MUSHClient Plugin: Emote Preview

Talk about anything TI here! Also include suggestions for the game, website, and these forums.

Moderators: Maeve, Maeve

Post Reply
User avatar
The_Last_Good_Dragon
Posts: 254
Joined: Sun Feb 14, 2016 1:08 am

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: 254
Joined: Sun Feb 14, 2016 1:08 am

Sun Jan 07, 2018 3:32 pm

A picture of the plugin in use:
Image
~~ Team Farra'n'Stuff. ~~

User avatar
Niamh
Posts: 1070
Joined: Wed Nov 30, 2016 9:04 pm
Discord Handle: Niamh#3824

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: 254
Joined: Sun Feb 14, 2016 1:08 am

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. ~~

Post Reply
  • Information
  • Who is online

    Users browsing this forum: No registered users and 58 guests