Evaluating MUSHClient, but trying to do some triggers from Zmud.

Posted by Buckleyp on Sun 07 Mar 2004 09:21 PM — 5 posts, 17,664 views.

#0
I've just started trying out MushClient and so far I like what I see. And think the scripting has a lot more power than the Zmud I am currently using. However I am having trouble working out how to do some things.

This is mainly to do with Maths and storing and using variables. For example I have the following trigger taken from Zmud and need to implement it.

____________

Trigger matches on "but you dodge"

#color 6
#ad enemyhits 1
#ad dodgedhits 1
#ad totalenemyhits 1
#math totaldefend @blockedhits+@dodgedhits
#math percentdefend @totaldefend*100
#math percentdefend @percentdefend/@totalenemyhits

____________

I need the values in these variables stored until I reset them with the alias that follows.

Alias: resetdef

#var blockedhits 0 _nodef fightcount
#var dodgedhits 0 _nodef fightcount
#var totalenemyhits 0 _nodef fightcount

____________

Can you please help.

Thanks in advance.

Buckleyp
USA #1
There are basically two methods for dealing with variables and storage. One option is MUSHclient's internal storage, which can be saved between sessions as part of the world file. These are accessed using the GetVariable and SetVariable commands. So for instance the line:

#math totaldefend @blockedhits+@dodgedhits

would become something like:

setvariable "totaldefend", blockedhits + dodgedhits

If blockedhits and dodgedhits must also be stored between script calls, then you may also need to make it:

setvariable "totaldefend", getvariable("blockedhits") + getvariable("dodgedhits")

Syntax will differ slightly depending on the script language you use, but not by much.

If the values do not need to be saved between sessions, but can be recreated each time the script is loaded (or you edit/manually reload it), then variable names work just like in any true programming language and have a "scope". This basically refers to *who* they actually belong to. Example:

dim MyVar1 '<--- Global scope, this is created when the script loads and
                 'will continue to exist until you reload the script. All parts
                 'of your script have direct access to this.
sub DoSomething(MyVar2)'<------ Local scope. These 'are owned by DoSomething.
  dim MyVar3           '<--/ |   The moment DoSomething is finished, these
  MyVar4 = "Hello"     '<----/   will be destroyed.
end sub


So, any variable defined outside of a Sub/End Sub or Function/End Function will continue to exist and keep the last value you gave them until something causes the script itself to change. Anything created inside such blocks cease to exist as soon as you leave them. In your case, you would do something like:

dim enemyhits, dodgehits, totalenemyhits
dim blockedhits, totaldefend, percentdefend

sub DoMath(TName, Output, Wildcards)
  enemyhits = enemyhits + 1
  dodgehits = dodgehits + 1
  totalenemyhits = totalenemyhits + 1
  totaldefend = blockedhits + dodgedhits
  percentdefend = int((totaldefend * 100) / totalenemyhits)
end sub

The 'dim' command lets you do as many definitions as you want on a line, so you could put all of them in one dim, but for readability... The above code is VBScript, so other languages use different commands to declare variables, but all of them include scope based automatic creation and destruction of them, so the same rule applies to how to make them last between calls to a sub, just declare them outside any functions or subs you use. ;) I am not sure what _nodef does in zMud, so can't comment on what if anything you need to duplicate it.

One thing to note... If you use the 'send to script' option to execute code, instead of using a call to a sub of function, then any variable you use in that script will exist in the global scope. It does exactly the same things as if you placed it in the main script file as a global. A side effect of this is that you must be very careful not to use temporary variables with the same name as something you need to be more permanent. In other words:

dim MyVar1
MyVar1 = "Hello"
sub DoStuff
  dim MyVar1
  MyVar1 = "Go Away"
  ...
end sub

Because you declare a *local* version of MyVar1 in the sub, a 'new' variable is created and given the value "Go Away", but the *global* version will continue to contain "Hello". In full languages it is often possible to use something like Parent:MyVar1 to access the global version, however Python is probably the only script engine that allows it. As long as you remember to use dim, var or whatever method the language you choose uses to make local variables, the global value will be untouched. This makes life a lot safer and easier, since you can use identical names without worrying about how they may screw up some other piece of your code. However, because 'send to script' executes as global it is very important to make sure you don't use a global variable like 'Count' to keep track of some value, then accidently reuse it in a for-next loop in your trigger.

Using the option to imbed your script directly in the triggers output with 'send to script' is a convenient trick, but it isn't as **safe** as letting the trigger call a sub or function you specify, which is the default method of using scripts. You need to be a bit more careful when using it.
Amended on Sun 07 Mar 2004 10:18 PM by Shadowfyr
#2
Ahh thats great with that help I managed to make a nice new script file with the following :-

dim enemyhits
dim dodgedhits
dim parriedhits
dim blockedhits
dim totalenemyhits
dim totaldefend
dim percentdefend

sub dodgecount (name, output, wildcards)
enemyhits = enemyhits + 1
dodgedhits = dodgedhits + 1
totalenemyhits = totalenemyhits + 1
call UpdateStatus (name, output, wildcards)
end sub

sub parrycount (name, output, wildcards)
enemyhits = enemyhits + 1
parriedhits = parriedhits + 1
totalenemyhits = totalenemyhits + 1
call UpdateStatus (name, output, wildcards)
end sub

sub blockcount (name, output, wildcards)
enemyhits = enemyhits + 1
blockedhits = blockedhits + 1
totalenemyhits = totalenemyhits + 1
call UpdateStatus (name, output, wildcards)
end sub

sub hitcount (name, output, wildcards)
enemyhits = enemyhits + 1
totalenemyhits = totalenemyhits + 1
call updatestatus()
end sub

sub updateStatus (name, output, wildcards)
totaldefend = blockedhits + dodgedhits + parriedhits
percentdefend = int((totaldefend * 100) / totalenemyhits)
world.setstatus "Parry: " & Parriedhits & " Dodge: " & DodgedHits & " Blocked: " & BlockedHits & "(" & TotalEnemyHits & " / " & PercentDefend &"%)"
end sub

sub resetvars(name, output, wildcards)
enemyhits = 0
dodgedhits = 0
parriedhits = 0
blockedhits = 0
totalenemyhits = 0
totaldefend = 0
percentdefend = 0
end sub

Next I need to patern match Hp: *(*) Gp: *(*) Xp: * and store each one into an already defined variable. HPCurrent, HPMax, GpCurrent, GPMax, and XP Current. Would it be best to do this in the trigger, or in a script. If so how on either one?

I managed to do what took 50 triggers in zmud in 4 in mush.. Very impressed so far.

Thanks again.

buckleyp
Australia Forum Administrator #3
A trigger matching on:

Hp: *(*) Gp: *(*) Xp: *

would work pretty well. It can do "send to script" to quickly set up variables, eg.

SetVariable "HPCurrent", "%1"
SetVariable "HPMax", "%2"
SetVariable "GpCurrent", "%3"
SetVariable "GPMax", "%4"
SetVariable "XP ", "%5"

By doing "send to script" in the trigger you can execute VBscript code (or whatever your main scripting language is) directly from the trigger "send" box.
Australia Forum Administrator #4
With your function "UpdateStatus" you don't need those extra arguments unless it is called from a trigger or alias. Triggers or aliases send three arguments automatically, however an internal sub like that may just as well be:


sub updateStatus
totaldefend = blockedhits + dodgedhits + parriedhits
percentdefend = int((totaldefend * 100) / totalenemyhits)
world.setstatus "Parry: " & Parriedhits & " Dodge: " & DodgedHits & " Blocked: " & BlockedHits & "(" & TotalEnemyHits & " / " & PercentDefend &"%)"
end sub


Then just call it as:

call updateStatus

... which you have already done in one place.