Hello, I'm trying to get sounds to work with my client, I have the plugin installed, and the sounds installed, and the plugin pointing to the proper location, but I don't think that Mushclient is reading the tag properly. In the MXP debug window, I get:
A 20000: ( 239) MXP element: <sound FName="mm_door_open.*" V=100 L=1 P=50 T="misc">
W 5012: ( 239) MXP tag <sound> is not implemented
W 5015: ( 239) Unused argument for <sound>: fname="mm_door_open.*"
W 5015: ( 239) Unused argument for <sound>: v="100"
W 5015: ( 239) Unused argument for <sound>: l="1"
W 5015: ( 239) Unused argument for <sound>: p="50"
W 5015: ( 239) Unused argument for <sound>: t="misc"
Yes, you can do this. You need to add a script routine to your world script file, here is an example:
function OnMXPStartTag (name, args, mylist)
dim i
dim fn
dim arg
'
' only proces sound tags
'
if name <> "sound" then
exit function
end if
'
' find the sound file name
'
if not IsEmpty (mylist) then
for i = lbound (mylist) to ubound (mylist)
arg = split (mylist (i), "=")
if arg (0) = "fname" then
fn = arg (1)
end if
next
End If
'
' play sound
'
if fn <> "" then
fn = Replace (fn, "*", "wav")
Sound "c:\mysounds" & fn
end if
' suppress sound tags (handle them ourselves)
OnMXPStartTag = 1
end function
What you will then need to do is add "OnMXPStartTag" as the "Opening Tag" script file in the scripting configuration page (click the "MXP" button).
What is happening here is that when MUSHclient gets the MXP start tag "sound" it calls the script. The script gets passed all the sound arguments (FName="mm_door_open.*" V=100 L=1 P=50 T="misc") in an array.
It walks the array looking for the "FName" argument and then saves the filename.
Then it uses the "Sound" script command to play that sound.
In your example it cannot play the sound "mm_door_open.*" so I have replaced the "*" with "wav".
You may also need change the directory where it is looking for the sounds. I used "c:\mysounds".
Finally this line stops the line from being processed by MUSHclient and thus giving an error message:
Umm. I'm trying to wrap this all into a plugin, but the OnMXPStartTag isn't calling the plugin, it only works if I insert the code into my main script. Can you address the tag to a plugin?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE muclient>
<!-- Saved on Friday, September 12, 2003, 12:23 AM -->
<!-- MuClient version 3.24 -->
<!-- Plugin "msp" generated by Plugin Wizard -->
<muclient>
<plugin
name="MM_MSP_Emulation"
author="Nick Gammon with alterations by ****** for use with MateriaMagica IEN"
id="74c06c730af9e17ac98dc126"
language="VBscript"
purpose="Emulates MSP (MUD Sound Protocol) on MateriaMagica"
save_state="y"
date_written="2003-09-11 12:12:11"
requires="3.24"
version="1.0"
>
<description trim="y">
<![CDATA[
Type: "msp:help" to see this help.
See:
You will need to get the sound files manually (ie. from the
MUD) and install them before using this. The plugin is
configured to look for them in C:\Program Files\MUSHclient\msp,
but you can change that by typing:
set_msp_path new_path
eg.
set_msp_path C:\Program Files\MUSHclient\msp
This does require sound to be enabled, so type:
set sound on
Also, this requires you to manually set a few things.
Set MXP/Pueblo on, follow these steps:
1.) Press Ctrl+Alt+U, or use Game -> Configure -> MXP / Pueblo
2.) Set "Use MXP/Pueblo to "On Command"
3.) Uncheck all other options.
Now we need to add something to the scripting interface.
1.) Press Shift+Ctrl+6 or use Game -> Configure -> Scripting
2.) Press the MXP button
3.) In the Opening Tag box, insert "OnMXPStartTag", without the quotes.
And finally, you need to specify either .wav files, or .mp3 files,
type:
set_msp_type (file type)
eg.
set_msp_type wav
or
set_msp_type mp3
Any questions, feel free to contact ******* in game.
<script>
<![CDATA[
'
' Script to emulate MSP on MateriaMagica.
'
Sub On_set_MSP_type (strName, strLine, arrWildCards)
dim sType
sType = arrWildCards (1)
'
' ensure either "wav" or "mp3" was specified
'
Select Case sType
Case "wav"
world.setvariable "msp_type", sType
world.note "MSP will now use the .wav extension"
Case "mp3"
world.setvariable "msp_type", sType
world.note "MSP will now use the .mp3 extension"
Case Else
World.Note "You must specify either 'wav' or 'mp3' for sound file extension."
End Select
End Sub
sub On_set_MSP_path (strName, strLine, aryWildcards)
dim sPath
sPath = aryWildcards (1)
'
' ensure trailing backslash
'
if right (sPath, 1) <> "\" then
sPath = sPath & "\"
end if
world.setvariable "msp_path", sPath
world.note "MSP sound files will be obtained from " & _
sPath
end sub
Function OnMXPStartTag (name, args, mylist)
dim i
dim fn
dim arg
'
' only process sound tags
'
if name <> "sound" then
exit function
end if
'
' find the sound file name
'
if not IsEmpty (mylist) then
for i = lbound (mylist) to ubound (mylist)
arg = split (mylist (i), "=")
if arg (0) = "fname" then
fn = arg (1)
end if
next
End If
'
' play sound
'
if fn <> "" then
fn = Replace (fn, "*", world.getvariable ("msp_type"))
world.Sound msp_Path & fn
end if
<script>
<![CDATA[
Sub OnHelp (sName, sLine, wildcards)
World.Note World.GetPluginInfo (World.GetPluginID, 3)
End Sub
]]>
</script>
</muclient>
I'm trying to make a portable plugin for sounds with my mud. The only things that are hanging me up are the (on_mxp_open_tag="OnMXPStartTag" ), since I can't think of a way to automate that refrence to be installed into the world file (found under " <world " in the .mcl file, and the plugin doesn't work because theres no connection between "OnMXPStartTag" and the plugin. The script itself works fine if I add all the aliases and stuff to the regular world alias/trigger/script, but not as an independent standalone plugin.
I thought about adding a OnMXPStartTag sub and refrencing it to the plugin, but that kind of negates the portablility and automatic installation. Again, I'm shooting for ease of use and portablility, since this is going to be availible for download from the mud's web page. Is there an easy way to point OnMXPStartTag to the plugin?
The problem here is basically the same as why there is a CallPlugin command, instead of a way to directly call a sub in a plugin script. I think it is a serious flaw and has made numerous plugin desigs impossible. I am not sure of the precise reason for it, but it mostly comes down to mushclient not knowing before hand what subs to expect in a script. Since the main script executes in a global namespace, the client can make direct calls too it, but plugins each exist in a seperate thread of something, in order to prevent conflicts with variables and things of that sort. MXP subs can't call using a plugin ID, so they have no way to know 'where' to look for the block of code that needs to be executed, even if they do have a name to look for.
There has got to be a better way imho. Being able to tell the world file the ID of a plugin to execute MXP stuff would help, with a blank ID defaulting to the main world, but calling plugins is still a pain. It would have been much better imho to do this:
set Handle = GetPluginHandle(BSTR Plugin ID)
Handle.SomeSubName(Arguement1, Arguement2, ...)
The method used now is inconvenient and requires complicated code to be added into one special sub, where everything has to be broken up and passed on to what you intended to call in the first place. This is not only unecessarily complicated, but confusing from the stand point of trying to call anything in a plugin. Especially since it doesn't even reflect the standard way that all other objects, commands and code is used for anything else in a script.
In theory.. If you get a world handle, so that you are executing global calls with it, instead of plugin calls, you might be able to set the names used for the scripts, then use ImportXML to 'import' the blocks of code containing those into the main world. They could either perform the actual commands or use CallPlugin to pass the needed information to your plugin and have that do the job. This is 'theory' though, I don't know if creating a handle to mushclient in the script will actually give you direct control over the main world, or if you would just be giving your script a roundabout way to talk to itself. lol
Hmm. Thinking on it, I am not sure it is even possible. Maybe if you used python and a Mushclient 'wrapper' to give the script information on the internals, but you would need to do something like this in VBScript:
a = getworldid(worldname)
dim b as object 'Create a generic object type.
'???? b = a ???? I have no idea what is needed here to have it work...,
'but you have to make the generic object 'become' your world some how.
b.inportXML("Your code here")
In Python, *with the wrapper*, it would be much easier, but it is still rediculous to have to do this sort of thing imho. Someone that understood COM better and had a lot more patience than me could probably make it work, but not me.
There is another alternative though. It would be reading the world file itself in to your script, checking to see if the code is there already and if not, then writing the entire file back in, including the code you needed to add. This is dangerous, nearly as complicated and still quite insane to have to do. :p
It'd be nice if we can do custom distributions. I've sort of solved it by making a .mcl file and a vb script file for download. But a whole custom distribution would be pretty nice. It'd allow me to make all the appropriate settings availible for users.
Well, hopefully Nick will find a way to use the plugins like objects, instead of the currect insane way. That would help some.
The second things is some means to import XML permanently into the world file and save it, or even a direct way to respond to MXP stuff in plugins, either one of which would solve your problem. It gets frustrating when such basic things require either a very unfriendly non-distributable solution or wrapping your mind around some convaluted and insane solution like the one I suggested, which would probably never work anyway....
Feels like traversing a bloody mazer without a flashlight sometimes. lol
So Nick.. Why is it exactly that plugins can't use the Object.Command method for calling plugins, aside from you not implimenting such? It seems to me to be far more consistent, considering what we try and would like to do with them. Even scripts calling other 'external' scripts would use this method, but not being able to use it 'in' a script running within Mushclient. :p
Hmm.. Here is an idea though Johnathan. Under the file menu is an option for 'Import'. You may be able to create an mcl file that only has the options you specifically need and possibly some script code (or an 'include' directive that imports the needed scripts). It isn't elegant, but if the importer doesn't complain about things that are missing from the file (i.e. you left out to prevent it from overriding the settings), it 'may' work. It isn't A) safe or B) the best solution, but it may actually work.
Apparently, I don't. This is awesome. Now to fiddle with the script. So far, I have this:
Function OnPluginMXPopenTag (strArgs)
Dim fn
Dim mylist
Dim arrType
dim i
dim arg
mylist = Cstr(strArgs)
arrType = Split(mylist, ",", -1, 1)
if arrType(0) <> "sound" then
exit function
end if
mylist = arrType (1)
arg = split (mylist, "=", -1)
fn = arg (1)
fn = Replace(fn, "' v", "")
fn = Replace(fn, "'", "")
msp_path = world.GetVariable ("msp_path")
msp_type = world.GetVariable ("msp_type")
if fn <> "" then
fn = Replace (fn, "*", world.getvariable ("msp_type"))
world.Sound msp_path & fn
end if
OnPluginMXPopenTag = 1
End Function
It's pretty sloppy, but its 3 am here :P
I'd like to get rid of some variables. The first split is to get rid of the 'sound' precurser, the second split is to isolate the filename, but I kept getting something along the lines of:
'mm_sound1.*' v
..So, I had to do two replaces to get rid of the "'" and the "' v". I'm not sure of a better way to do that.
So, if you have a better suggestion, feel free. I'll be burning the midnight oil over here.
Anything for plugins (or regular scripts) for mxp definitions?
From the MXP Debug screen:
I 20002: ( 3623) Got Definition: !en MaxHp 3495
I 20002: ( 3623) Got Definition: !en MaxSp 1992
I 20002: ( 3623) Got Definition: !en MaxSt 2138
What I'm trying to do is adapt the super health bar plugin to my mud, but again, things are being done differently. I'm trying to extract the variables and entities from my prompt, but its kinda funky:
I've got the !EN tags working okay, I used the OnMXPError function and split down the arguments to isolate the Hp/Sp/St and set them to variables (for testing purposes), but I still can't read the stuff between the <V> tags. Using the MXP start tag and end tag routines, I get nothing. As for debug, I get:
A 20000: ( 4994) MXP element: <V Hp>
E 1023: ( 4994) Unknown MXP element: <v>
A 20000: ( 4994) MXP element: </V>
W 5005: ( 4994) Closing MXP tag </v> does not have corresponding opening tag
That sort of signifies to me that its reading the start and end tags, but doing nothing with them. I'm guessing because the text actually resides between the opening and closing tags, and neither routine is designed to handle this. The mxp start tag is for arguments residing within the first tag, and mxp end tag is looking for a "<V Hp>" and a "</V Hp>", which isn't being used. I suppose I could do this with two sets of triggers, one for the !EN definitions, and another one just to read the prompt off the screen, but that introduces about a round of 'lag' between updates (i.e. the meter displays the last rounds statistics instead of the current one). I really don't know how to grab all the info I need in one fell swoop.
I thought <V> tags didn't need to be defined, according to the MXP specs on zugg's website.
Quote:
<VAR> <V>
<VAR Name [DESC=description] [PRIVATE] [PUBLISH] [DELETE] [ADD] [REMOVE]>Value</VAR>
The <!ENTITY> tag allows the MUD server to set the value of a variable without displaying the value to the user. The <VAR> tag is just like the <!ENTITY> tag, except that the value of the variable is placed between the <VAR> and </VAR> tags, and this value is displayed to the user.
Hp: <VAR Hp>100</Var>
would display: "Hp: 100" to the user, and would set the entity hp to 100.
Grrrr, he has amended the spec since I did it. MUSHclient supports <var> not <v>.
For some reason Zugg has thrown in synonyms into the MXP specs, for instance <i> and <italic> are the same. When I did the MXP implementation there was only <var> but I see from your quote he has added <v> as well.