MUSHClient Plugin: Emote Preview

Talk about anything TI here! Also include suggestions for the game, website, and these forums.
User avatar
The_Last_Good_Dragon
Posts: 148
Joined: Sun Feb 14, 2016 1:08 am

MUSHClient Plugin: Emote Preview

Postby The_Last_Good_Dragon » Sun Jan 07, 2018 3:28 pm

I've been fiddling with making a script that will preview an emote before you send it, allowing you to review things like line spacing, quotation marks, targets, and stat/skill checks. While it's still rough around the edges, it works fairly well with emotes and rpechoes so I wanted to go ahead and share it.

I want to add support for any 'emote' command that isn't emote and rpecho, such as hemote, attack, safe, defend, surrender.

I also want to add language and color-code support so that it'll display those properly, but that's a whole different animal than expanding it to the other commands.

Hope you enjoy!

I totally copied these instructions from a Plugin Pixie posted, so if they don't work you can totally blame her!

Installation:

Go into Program FIles -> MUSHclient -> worlds -> plugins

Copy this into a fresh notepad file:

Code: Select all

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Friday, January 12, 2018, 2:37 PM -->
<!-- MuClient version 4.94 -->

<!-- Plugin "Emote_Preview" generated by Plugin Wizard -->

<muclient>
<plugin
   name="Emote_Preview"
   author="Last Good Dragon"
   id="2712720872c7eff575b6adb2"
   language="Lua"
   purpose="Preview an Emote Before Sending It"
   date_written="2018-01-12 14:34:51"
   requires="4.94"
   version="1.0"
   >

</plugin>


<!--  Get our standard constants -->

<include name="constants.lua"/>

<!--  Aliases  -->

<aliases>
  <alias
   match="attack *"
   enabled="y"
   group="Emote Preview"
   send_to="12"
   sequence="100"
  >
  <send>EPCreateWindow()
EPFormatEmote("attack", "%1")</send>
  </alias>
  <alias
   match="defend *"
   enabled="y"
   group="Emote Preview"
   send_to="12"
   sequence="100"
  >
  <send>EPCreateWindow()
EPFormatEmote("defend", "%1")</send>
  </alias>
  <alias
   match="emote *"
   enabled="y"
   group="Emote Preview"
   send_to="12"
   sequence="100"
  >
  <send>EPCreateWindow()
EPFormatEmote("emote", "%1")</send>
  </alias>
  <alias
   match="rpecho *"
   enabled="y"
   group="Emote Preview"
   send_to="12"
   sequence="100"
  >
  <send>EPCreateWindow()
EPFormatEmote("rpecho", "%1")</send>
  </alias>
  <alias
   match="safe *"
   enabled="y"
   group="Emote Preview"
   send_to="12"
   sequence="100"
  >
  <send>EPCreateWindow()
EPFormatEmote("safe", "%1")</send>
  </alias>
</aliases>

<!--  Script  -->


<script>
<![CDATA[
appendtext = ""
EPEmote = ""
CurrentColor = ColourNameToRGB("dimgray")
IsSpeach = false
wwidth = 800
wheight = 425

function EPCreateWindow()

   CurrentColor = ColourNameToRGB("dimgray")
   win = "EmotePreview"
   WindowCreate (win, 2, 2, wwidth, wheight, 12, 0, ColourNameToRGB("black"))
   WindowShow (win, true)
   WindowRectOp (win, miniwin.rect_fill, 0, 0, 0, 0, ColourNameToRGB("black"))
   WindowRectOp (win, miniwin.rect_frame, 0, 0, 0, 0, ColourNameToRGB("white"))
   lpoint = WindowInfo(win, 10)
   bpoint = WindowInfo(win, 13)
   WindowRectOp (win, 2, 1, wheight-50, wwidth/2, wheight-1, ColourNameToRGB("Green"))
   WindowRectOp (win, 2, wwidth/2, wheight-50, wwidth-1, wheight-1, ColourNameToRGB("Red"))
   WindowRectOp (win, 1, 0, 0, 800, 376, ColourNameToRGB("white"))
   WindowRectOp (win, 2, 0, 0, 800, 25, ColourNameToRGB("dimgray"))

   WindowAddHotspot(win, "submit", 1, wheight-50, wwidth/2, wheight-1, "", "", "", "", "EPSubmit", "Submit Emote As Is", miniwin.cursor_plus, 0)
   WindowAddHotspot(win, "cancel", wwidth/2, wheight-50, wwidth-1, wheight-1, "", "", "", "", "EPCancel", "Cancel And Return To Editing", miniwin.cursor_plus, 0)

   WindowFont (win, "title-font", "Courier", 10, true, false, true, false)
   WindowText (win, "title-font", "Farra's Emote Preview v0.2 - Line Breaks! Colors! Stats! Oh My!", 1, 1, 800, 25, ColourNameToRGB("Pink"), 0)
   WindowFont (win, "hotspot-font", "Courier", 28, true, false, true, false) -- define font
   WindowText (win, "hotspot-font", "SUBMIT", 150, 385, 350, 415, ColourNameToRGB("red"), 0)
   WindowText (win, "hotspot-font", "CANCEL", 550, 385, 750, 415, ColourNameToRGB("green"), 0)

   WindowFont (win, "output-font", "Courier", 5, false, false, false, false) -- define font
   appendtext = "NULL"

end -- CreateWindow

function EPHideWindow()
   win = "EmotePreview"
   WindowShow(win, false)
   WindowDelete(win)
end -- EPHideWindow()

function EPFormatEmote(etype, emote)

   EPEmote = etype .. " " .. emote
   text = emote
   height = 26
   IsSpeach = false

   -- Check for Combat Types, First Line should be this descriptor
   if (etype == "attack") or (etype == "safe") then
      name = string.sub(text, 0, string.find(text, " ")-1)
      if name ~= nil then
         text = string.sub(text, string.find(text, " ")+1)
         bodypart = string.sub(text, 0, string.find(text, " ")-1)
         if bodypart ~= nil then
            text = string.sub(text, string.find(text, " ")+1)
         else
            Note("EP Attack Error: Error With Emote (1)")
            return 0
         end
         
         -- Display the Attack Line
         
         if etype == "attack" then
            attacktext = "An ATTACK will be made against " .. name .. "'s " .. bodypart .. "."
         else
            attacktext = "A SAFE attack will be made against " .. name .. "'s " .. bodypart .. "."
         end
         WindowText (win, "output-font", attacktext, 1, height, 799, height + 13, ColourNameToRGB("red"), 0)
         height = height + 26 -- Line between this and the actual emote
         
         -- Check if the First word is /self, if not display that
         namestr = string.sub(text, 0, string.find(text, " ")-1)
         if namestr ~= nil then
            if ( namestr ~= "/self" ) then
               text = "/self " .. text
            end
         else
            Note("EP Attack Error: Error With Emote (2)")
            return 0
         end
      else
         Note("EP Attack Error: Error With Emote (3)")
         return 0
      end
   end

   -- Give Defend Mesage
   if etype == "defend" then
      WindowText (win, "output-font", "A combat DEFEND will be made.", 1, height, 799, height + 13, ColourNameToRGB("red"), 0)
      height = height + 26 -- Line between this and the actual emote
      
      namestr = string.sub(text, 0, string.find(text, " ")-1)
      if namestr ~= nil then
         if ( namestr ~= "/self" ) then
            text = "/self " .. text
         end
      else
         Note("EP Defend Error: Error With Emote (1)")
         return 0
      end
   end

   -- Check for Skill / Stat Checks
   if (string.find(text, "-") ~= nil) and (string.find(text, "-") == 1) and ( etype == "emote" or etype == "rpecho") then
      if string.find(text, "-") == 1 then
         loc = string.find(text, " ")
         if ( loc ~= nil ) then
            appendtext = "  A " .. string.sub(text, 2, loc-1) .. " skill check will be made."
            text = string.sub(text, loc+1)
         end
      end
   else
      if (string.find(text, "+") ~= nil) and (string.find(text, "+") == 1 ) then
         if string.find(text, "+") == 1 then
            loc = string.find(text, " ")
            if ( loc ~= nil ) then
               appendtext = "  A " .. string.sub(text, 2, loc-1) .. " stat check will be made."
               text = string.sub(text, loc+1)
            end
         end
      end
   end

   while EPShouldParse(text) do
      text = EPFormatLine(text, height, 1)
      height = height + 13
   end -- for
   EPFormatLine(text, height, 1)
   height = height + 13
   WindowText (win, "output-font", text, 1, height, 799, height+13, CurrentColor, 0)
   
   -- Display Appendtext properly
   if (appendtext ~= "NULL") then
      if (etype ~= "emote") then
         WindowText (win, "output-font", "Error: You Are Attempting A Stat/Skill Check Without Using Emote.", 1, height, 799, height+13, ColourNameToRGB("red"), 0)
      else
         WindowText (win, "output-font", appendtext, 1, height, 799, height+13, ColourNameToRGB("teal"), 0)
      end
      height = height + 13
   end

   -- type checks, ie used /self for emote, etc.
   if (etype == "emote") and (string.find(EPEmote, "/self") == nil) then
      height = height + 13
      WindowText (win, "output-font", "Error: using emote without /self detected. Consider using RPEcho.", 1, height, 799, height+13, ColourNameToRGB("red"), 0)
      height = height + 13
   end
   if (etype == "rpecho") and (string.find(EPEmote, "/self") ~= nil) then
      height = height + 13
      WindowText (win, "output-font", "Error: using rpecho with /self detected. Consider using Emote.", 1, height, 799, height+13, ColourNameToRGB("red"), 0)
      height = height + 13
   end
   if (etype == "attack" or etype == "safe") then
      -- Check if the bodypart is a valid location
      if not (bodypart == "head" or bodypart == "body" or bodypart == "arms" or bodypart == "legs" or bodypart == "hands" or bodypart == "feet") then
         height = height + 13
         WindowText (win, "output-font", "Error: Attack Location Is Invalid", 1, height, 799, height+13, ColourNameToRGB("red"), 0)
         height = height + 13
         WindowText (win, "output-font", "       Valid locations are head, body, arms, legs, hands and feet.", 1, height, 799, height+13, ColourNameToRGB("red"), 0)
         height = height + 13
      end
   end
   return 0
end -- EPFormatEmote

function EPShouldParse(text)

   str = text
   if (string.len(str) > 100) then
      return true
   end
   if ( string.find(str, "{/") ~= nil ) then
      return true
   end

   return false
end

function EPFormatLine(line, height, left)

   text = line

   if (string.len(text) > 100) then
      hardstop = string.sub(text, 0, 100)
      loc = string.find(hardstop, " ")
      nloc = string.find(hardstop, " ", tonumber(loc)+1)
      while ( nloc ~= nil ) do
         loc = nloc
         nloc = string.find(hardstop, " ", tonumber(loc)+1)
      end -- While
      if ( loc == nil ) then
         loc = string.len(text)
      end
   else
      loc = string.len(text)
   end
   newtext = string.sub(text, 0, loc) -- We have what we are going to display

   -- Line Break Parsing
   if ( string.find(newtext, "{/") ~= nil ) then
      loc = string.find(newtext, "{/")
      newtext = string.sub(text, 0, loc-1)
      text = string.sub(text, loc+2)
   else
      text = string.sub(text, loc+1)
   end -- Line Break Parsing

   -- Get Rid of Other {codes ... -- You know what, I don't even want to do this, it looks better this way, right?
   -- if ( string.find(newtext, "{") ~= nil ) then
   --   Note("Found { code")
   --   loc = string.find(newtext, "{")
   --   aftertext = string.sub (newtext, loc+2)
   --   Note(aftertext)
   --   beforetext = string.sub(newtext, 0, loc-1)
   --   Note(beforetext)
   --   newtext = beforetext .. aftertext
   --end


   -- Format Speach Coloring
   while ( string.find(newtext, '"') ~= nil ) do
      loc = string.find(newtext, '"')
      nloc = EPGetTargetLoc(newtext)
      while (nloc ~= nil) and (nloc < loc) and (not IsSpeach) do
         xloc = string.find(newtext, " ", nloc)
         if (nloc == nil) then
            xloc = string.len(newtext)
         end
         beforetext = string.sub (newtext, 0, nloc-1)
         targettext = string.sub (newtext, nloc, xloc)
         newtext = string.sub (newtext, xloc+1)
         left = left + WindowText (win, "output-font", beforetext, left, height, 799, height + 13, CurrentColor, 0)
         CurrentColor = ColourNameToRGB("orange")
         left = left + WindowText (win, "output-font", targettext, left, height, 799, height + 13, CurrentColor, 0)
         CurrentColor = ColourNameToRGB("dimgray")
         loc = string.find(newtext, '"')
         nloc = EPGetTargetLoc(newtext)
      end
      if ( IsSpeach ) then
         speachtext = string.sub (newtext, 0, loc)
         newtext = string.sub(newtext, loc+1)
         left = left + WindowText (win, "output-font", speachtext, left, height, 799, height + 13, CurrentColor, 0)
         CurrentColor = ColourNameToRGB("dimgray")
         IsSpeach = false
      else
         speachtext = string.sub (newtext, 0, loc-1)
         newtext = string.sub (newtext, loc+1)
         left = left + WindowText (win, "output-font", speachtext, left, height, 799, height + 13, CurrentColor, 0)
         CurrentColor = ColourNameToRGB("white")
         left = left + WindowText (win, "output-font", '"', left, height, 799, height + 13, CurrentColor, 0)
         IsSpeach = true
      end
   end
   nloc = EPGetTargetLoc(newtext)
   while (nloc ~= nil) and (not IsSpeach) do
      xloc = string.find(newtext, " ", nloc)
      if (xloc == nil) then
         xloc = string.len(newtext)
      end
      beforetext = string.sub (newtext, 0, nloc-1)
      targettext = string.sub (newtext, nloc, xloc)
      newtext = string.sub (newtext, xloc+1)
      left = left + WindowText (win, "output-font", beforetext, left, height, 799, height + 13, CurrentColor, 0)
      CurrentColor = ColourNameToRGB("orange")
      left = left + WindowText (win, "output-font", targettext, left, height, 799, height + 13, CurrentColor, 0)
      CurrentColor = ColourNameToRGB("dimgray")
      nloc = EPGetTargetLoc(newtext)
   end
   WindowText (win, "output-font", newtext, left, height, 799, height + 13, CurrentColor, 0)
   return text
   
end -- EPFormatLine

function EPGetTargetLoc (text)

   pLoc = EPGetTargetLocAid(text, "/")
   iLoc = EPGetTargetLocAid(text, "#")
   cLoc = EPGetTargetLocAid(text, "*")
   dLoc = EPGetTargetLocAid(text, "|")

   if (pLoc < iLoc) and (pLoc < cLoc) and (pLoc < dLoc) then
      return pLoc
   end
   if (iLoc < pLoc) and (iLoc < cLoc) and (iLoc < dLoc) then
      return iLoc
   end
   if (cLoc < pLoc) and (cLoc < iLoc) and (cLoc < dLoc) then
      return cLoc
   end
   if (dLoc < pLoc) and (dLoc < iLoc) and (dLoc < cLoc) then
      return dLoc
   end
   
   return nil

end -- EPGetRargetLoc

function EPGetTargetLocAid (text, str)

   vloc = string.find(text, str)
   if (vloc == nil) then
      vloc = string.len(text)
   end
   return vloc

end -- EPGetTargetLocAid
   
function EPSubmit (flags, hotspot_id)
   EPHideWindow()
   Send( EPEmote )
   EPEmote = ""
   return 0 -- needed for some languages
end -- EPSubmit

function EPCancel (flags, hotspot_id)
   EPHideWindow()
   return 0
end -- EPCancel

Note ("Last Good Dragon's Emote Preview Script Routine Loaded.")
Note ("Remember to RP Responsibily. For bug reports talk to Farra.")

Note ("Lua scripting enabled - script file processed")
]]>
</script>


</muclient>



Do "save as" and enter "Emote_Preview.xml". Close it. Place the file into the plugins folder.

Open up TI in MUSHclient. Go up to File -> Plugins. Click add, locate the plugin and open. The Emote_Preview plugin should now be listed there. Highlight it and install/enable.
Last edited by The_Last_Good_Dragon on Fri Jan 12, 2018 2:41 pm, edited 1 time in total.
~~ Team Farra'n'Stuff. ~~
User avatar
The_Last_Good_Dragon
Posts: 148
Joined: Sun Feb 14, 2016 1:08 am

Re: MUSHClient Plugin: Emote Preview

Postby The_Last_Good_Dragon » Sun Jan 07, 2018 3:32 pm

A picture of the plugin in use:
Image
~~ Team Farra'n'Stuff. ~~
User avatar
Niamh
Posts: 362
Joined: Wed Nov 30, 2016 9:04 pm
Discord Handle: Niamh#3824

Re: MUSHClient Plugin: Emote Preview

Postby Niamh » Fri Jan 12, 2018 5:44 am

Doing this:

Code: Select all

emote sdkjs dfh esufh weufh /self


I ran into this:

Code: Select all

Error number: 0
Event:        Run-time error
Description:  [string "Plugin"]:347: attempt to perform arithmetic on global 'xloc' (a nil value)

stack traceback:

   [string "Plugin"]:347: in function 'EPFormatLine'

   [string "Plugin"]:226: in function 'EPFormatEmote'

   [string "Alias: "]:2: in main chunk
Called by:    Immediate execution
User avatar
The_Last_Good_Dragon
Posts: 148
Joined: Sun Feb 14, 2016 1:08 am

Re: MUSHClient Plugin: Emote Preview

Postby The_Last_Good_Dragon » Fri Jan 12, 2018 2:43 pm

Updated to fix Naamah's bug; pesky xloc instead nloc's, they'll getchya every time!

Plugin now supports attack, defend, and safe commands — attempting to attack an invalid location displays a warning message.
On the list to add: hemote, display language colors when speaking, visibly preview color codes.
~~ Team Farra'n'Stuff. ~~

Return to “General Discussion”

Who is online

Users browsing this forum: No registered users and 9 guests