[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  General
. . -> [Subject]  question with multiple line triggers

question with multiple line triggers

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by Guest1   USA  (256 posts)
Date Sun 09 Feb 2003 05:38 PM (UTC)

Amended on Sun 09 Feb 2003 05:39 PM (UTC) by Guest1

Message
Just playing around with an idea and needing a bit of help here since MUSHclient does not have the ability to recognise multiple line triggers (do any clients?)

Here's an example, for blinding mobs when in groups, the message you see on the mud I play is:

Playername utters the words, 'blindness'
Mobname seems to be blinded!

Now I know some people have worked out a way to do this and rather than grouptell 'mobname is blind', they are able to grouptell 'mobname blinded by playername' ..this is about the only way I can figure how to do it..

have a trigger which sets a playername as a variable whenever this line comes up:

Playername utters the words, 'blindness'

which means that the playername variable is going to be changing very rapidly as just about everyone in the group is going to be trying to blind the mob at the start.
Then have another trigger so that whenever this line comes up:

Mobname seems to be blinded!

it will take the current playername variable and grouptell 'mobname blinded by playername'

Now this sounds like it would work in theory, but is this how it's done?
Also, does the constant updating of playername variable lag you at all, and does it sometimes mess up and get the wrong playername when you have multiple players spamming blind spell in rapid succession after the mob is blind.. like:

Playername1 utters the words, 'blindness'

Playername2 utters the words, 'blindness'

Playername3 utters the words, 'blindness'
Mobname seems to be blinded!

Playername4 utters the words, 'blindness'

Playername5 utters the words, 'blindness'

and it picks up playername4 as the blinder, not playername3?
Any advice would be appreciated. :)
[Go to top] top

Posted by Guest1   USA  (256 posts)
Date Reply #1 on Sun 09 Feb 2003 05:44 PM (UTC)

Amended on Sun 09 Feb 2003 05:45 PM (UTC) by Guest1

Message
..and I'm guessing that (I use vbs) triggering on

* utters the words, 'blindness'\n* seems to be blinded!

does not work ( \n = newline ) ..or does MC now recognise \n? If not, will it ever Nick?
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Reply #2 on Sun 09 Feb 2003 07:07 PM (UTC)

Amended on Sun 09 Feb 2003 07:11 PM (UTC) by Magnum

Message
Your speculation in your first post is exactly correct.

Whenever a trigger fires, and calls script, that script is executed fully before any more lines from the mud are processed. Therefor, when your secondary trigger fires on the 'mob has been blinded' line, you can be sure that your script will run it's full course before the next line is processed.

Indeed, this is why we recommend to people that they do not try to script "stalling" routines that wait a period of time before acting (without using MUSHclient functions). The script runs, but nothing is processed in the meantime!

Regarding lag, I have noticed very mild lag from scripts. The main source of the lag is calls to MUSHclient functions, such as SetVariable and GetVariable. If I recall, Nick said this is because the script and MUSHclient have to make COM calls to each other, and there is some minor overhead in doing so. (Very minor).

For this reason, I avoid using MUSHclient variables arbitrarly. That is, I'll only use them when I want the value to persist through multiple sessions. (By far, the most function calls to MUSHclient are Set and GetVariable statements - Well, and Send statements, but those can't be avoided).

In your example, I wouldn't bother with MUSHclient variables. Instead, just use regular variables in your scripting language.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
[Go to top] top

Posted by Guest1   USA  (256 posts)
Date Reply #3 on Sun 09 Feb 2003 08:12 PM (UTC)
Message
Thanks Magnum I was with you all the way until the very last line..

"I wouldn't bother with MUSHclient variables. Instead, just use regular variables in your scripting language"

Pardon my ignorance, but can you expand on this a little? I was thinking of using the MC internal pop-up trigger box to send direct to variable for "Playername utters the words, 'blindness'", and the other trigger to work using @variable in the send box, but do you mean I should go nowhere near those and instead go into my .mcl script and code it there? Or in my .vbs script with a dim statement somehow?

*scratches head* sorry, lack of sleep = lights are on but nobody's home.

Your help is much appreciated.
[Go to top] top

Posted by Meerclar   USA  (733 posts)  [Biography] bio
Date Reply #4 on Mon 10 Feb 2003 12:06 AM (UTC)
Message
I seem to remember a recent post that has /n as a name boundry marker in MC scripts rather than a new line designator. As for Magnums reference to regular variables instead of MC variables, it would be far easier to match

* utter's the words 'blindness'.
* is blinded.
grouptell %2 blinded by %1.

than to have MC store the player and mobname variables internally until they are cleared and have them change with each casting of the spell. Actually, if you had the script trigger on the "* is blinded" output it should be fairly simple to go back to the previous line and extract the playername for the grouptell.

Of course, my personal solution is to have designated casters for each spell I want on the mob in a fight that way everyone isn't burning mana on the same spell and the debuff goal is reached faster overall.

Meerclar - Lord of Cats
Coder, Builder, and Tormenter of Mortals
Stormbringer: Rebirth
storm-bringer.org:4500
www.storm-bringer.org
[Go to top] top

Posted by Neva   USA  (117 posts)  [Biography] bio
Date Reply #5 on Mon 10 Feb 2003 12:14 AM (UTC)
Message
The longstanding reply on why triggers can't match on multiple lines is usually that no, it's never going to happen. Which, personally, I'm not all that keen on, because there are plenty of cases of things like this where the two lines are always going to appear together. But I do recognize that it'd be difficult to do, and since I've never found any problem using scripting and multiple triggers to do what I need--with the major exception of trying to do multiple colourtells across different scripts--I don't think it's any big loss.

Scripting isn't that hard to learn to do, anyway, as I've discovered of late.
[Go to top] top

Posted by Guest1   USA  (256 posts)
Date Reply #6 on Mon 10 Feb 2003 12:49 AM (UTC)

Amended on Mon 10 Feb 2003 12:53 AM (UTC) by Guest1

Message
hmm.. and worse yet, if I'm the one who successfully blinds the mob, the message shows:

cast 'blindness' mobname
Ok.
mobname seems to be blinded!


so it's now a triple line match in this case.. *ack*


Meerclar thanks. Nods I was planning on only having a variable for playername, and then on the blind message of

Mobname seems to be blinded!

all I'd be doing is triggering it on

* seems to be blinded!

and sending

%1 blinded by @playername

but I'm not following what you mean when you said,

"As for Magnums reference to regular variables instead of MC variables, it would be far easier to match

* utter's the words 'blindness'.
* is blinded.
grouptell %2 blinded by %1.

than to have MC store the player and mobname variables internally..


I mean, yeah, if I could do that I would, but that is 2 lines it's matching on which can't be done on MC that easily.. right?

Also, "if you had the script trigger on the "* is blinded" output it should be fairly simple to go back to the previous line and extract the playername"

it probably is, but I have no idea how to do that either. :( do you?


I still think there's more to what Magnum said about "..use regular variables in your scripting.. .. but unfortunately dont understand the difference between MC variables and regular variables in this case, or how to write the vbscript..

....

hmm.. would an 'if' statement work? Like triggered on

Playername utters the words, 'blindness'

so that a script then doess something like

if next line = 'Mobname seems to be blinded!' then grouptell 'mobname blinded by playername'
end if

I just dont know how to script that, if it can be done.
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #7 on Mon 10 Feb 2003 04:06 AM (UTC)
Message
The way I would do it is something like:

Trigger: * utter's the words 'blindness'.
Name: BlindAttempt
Script: BlindTest

Trigger: * seems to be blinded!
Name: MobBlinded
Script: BlindTest

Script:
dim BlinderName

sub BlindTest (tname, output, wilds)
  select tname
    case "BlindAttempt"
      world.enabletrigger "MobBlinded", vbTrue
      BlinderName = wilds(1)
    case "MobBlinded"
      world.send "grouptell " & wilds(1) & " blinded by " & BlinderName & "."
      world.enabletrigger "MobBlinded", vbFalse
  end select
end sub

This keeps all the code together in one place and is basically the method used to capture more than one line in any case. Since it doesn't care what comes in between the attempt and the blinding, it will ignore any things like 'OK.' or the like.

One key element is enabling the capture of the second line(or for larger groups of lines, the last one) and disabling it to later to prevent it from triggering multiple times. It likely wouldn't in your case, but in one of mine it was necessary to use any line that wasn't indented as a disabling mechanism and I didn't exactly want it firing on 99% of all the lines the mud generated. ;) The other key factor is what Magnum hinted at. By creating the variable 'outside' of a sub it becomes a global variable and is accessable from all subs. It also means that unless something causes the entire script to reload or otherwise restart, thus clearing all variables, the value will persist until the world closes. It is probably best to place all such globals near the top of the script though, so you can avoid accidentally trying to reuse one someplace else.

You will also notice my using a case statement to allow a single sub to handle both triggers. This can be quite helpful in some cases and even more so with aliases that execute more than one set up events depending on the command you use. For instance: path mine or path village, where the command handles more than one speedwalk, instead of using multiple aliases.
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #8 on Mon 10 Feb 2003 04:18 AM (UTC)
Message
Actually Neva.. Look at it logistically.

Notes from a script can 'happen when they are generated' or 'only after a newline'.

So in the second case:
Problem - What if you have something that produces such output every 10 seconds, but the mud doesn't send anything for 30-40 seconds or longer?

Answer - Your script generated output doesn't work.

In the current way things are handled:
Problem - Output often arrives in the middle of lines, so how do you omit only the part of the line or multiple lines you intend to, without effecting the script generated output.

Answer - Without a serious redesign of how all the things work, that could break other more important things, you can't.

The only practical solution I could see is if you buffered script generated text and mud text seperately and only combined the two directly in output. However, doing so becomes an issue of whether you would prefer a slow client that actually supports multiline matching using such a method, or one that continues to be fast, because seperate buffering 'would' almost certainly slow things down noticably.
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Reply #9 on Mon 10 Feb 2003 07:11 AM (UTC)
Message
Ah, Shadowfyr offers some efficient code. The second trigger is enabled only when needed, then disabled afterwards. Because you said you sometimes do the casting yourself, I have modified Shadowfyr's code a little, and offer this updated version:

Alias: blind *
Name: BlindAttemptbyMe
Script: BlindTest

Trigger: * utter's the words 'blindness'.
Name: BlindAttemptbyOther
Script: BlindTest

Trigger: * seems to be blinded!
Name: MobBlinded
Script: BlindTest

Script:

dim BlinderName

sub BlindTest (tname, output, wilds)
  select tname
    case "BlindAttemptbyMe"
      world.enabletrigger "MobBlinded", vbTrue
      BlinderName = "Me"
      world.send "cast 'blindness' " & wilds(1)
    case "BlindAttemptbyOther"
      world.enabletrigger "MobBlinded", vbTrue
      BlinderName = wilds(1)
    case "MobBlinded"
      world.send "grouptell " & wilds(1) & " blinded by " & BlinderName & "."
      world.enabletrigger "MobBlinded", vbFalse
  end select
end sub

Both of your triggers, and your alias to cast the spell all call the same scripting subroutine. The subroutine uses a CASE statement (which works sort of like an IF statement) to check where it was called from, then acts accordingly.

In this new example, the "Ok." line you mentioned is ignored. I assume if you fail, "BlinderName" will be overwritten later when another attempt is made by yourself again, or some other player.

You will notice in the code, a lack of GetVariable and SetVariable function calls. Instead, we simply create a variable in Visual Basic, first declaring and ititializing in with the "DIM" statement. Because the "DIM" line is outside any subroutine, it will be executed immediately when your script is first loaded (or reset), and it will also be 'global' to all subroutines. In other words, any of the subroutines in your script file can interact with that variable.

If you had put the "DIM" statement inside a subroutine, then that particular variable would only remain in memory while that subroutine was being executed. Once the "End Sub" line is reached, the variable is discarded from memory.

VBS isn't really that hard. It's quite easy to learn, especially with the help file that Shadowfyr recently linked to in another thread.

Your original idea of just using two triggers, and no script at all, might have worked, but your alias complicated the matter too much, so you are forced to script to accomplish your goal.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
[Go to top] top

Posted by Guest1   USA  (256 posts)
Date Reply #10 on Mon 10 Feb 2003 07:59 AM (UTC)

Amended on Mon 10 Feb 2003 08:46 AM (UTC) by Guest1

Message
Thanks people! That's awesome. Learning new things is good :)

Due to a huge file I'm downloading atm, I wont be on the mud until tomorrow (lags), but I'll test it then. Thanks again :)


-- add on --

ok here's something to throw a spanner in the works possibly. When in a group, the leader always sets the target (via a grouptell) before the group hits it, so I have a trigger that sets that target as a variable, then when we hit the target I normally use an alias bt (=blind target) which sends to the mud cast 'blindness' @target with expand variable selected for the alias.

Now with the script you gave me Magnum, in the case "BlindAttemptbyMe" on the line where it sends
world.send "cast 'blindness' " & wilds(1)
I will need that to be calling a variable rather than a wildcard.. hehe fun huh? note: I think you forgot the & "" at the end of that line in your script there, right?
Does this look right then for the script then?



dim BlinderName

sub BlindTest (tname, output, wilds)
dim target
target = World.GetVariable("target")
select tname
case "BlindAttemptbyMe"
world.enabletrigger "MobBlinded", vbTrue
BlinderName = "Me"
world.send "cast 'blindness' " & target & ""
case "BlindAttemptbyOther"
world.enabletrigger "MobBlinded", vbTrue
BlinderName = wilds(1)
case "MobBlinded"
world.send "grouptell " & wilds(1) & " blinded by " & BlinderName & "."
world.enabletrigger "MobBlinded", vbFalse
end select
end sub


Looks right, but I can't get on to test it atm. I wont use this script when soloing, so I don't need to be covered for when there is no target variable already set that is called on, if you get what I mean.

FYI this is just a small part of a much bigger script I'm writing to make groups a bit more fun, and also to hopefully keep sponging bots to a minimum. Group members will gain points when they blind a mob, trip it, chop off a limb, decapitate it, and lose points for chopping off other group members heads accidentally, or breaking their weapon etc. Most of the mud prompts it will work off are single lines and nice and straight forward, it was just the blinding spells that need the 2-lines to match. Eventually I'll have to add to this script to make it add a point to the playernames cumulative total etc, ..but I'll cross that bridge when I get to it.

hmm there's another thought.. can I set triggers to fire on what I grouptell? For example when the above script fires, I'd see on the mud

You grouptell: 'mobname blinded by playername'

which I could then use to award the point to their cumulative total.. yeah, I think I can, that's easier.
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #11 on Mon 10 Feb 2003 09:02 PM (UTC)

Amended on Mon 10 Feb 2003 09:11 PM (UTC) by Shadowfyr

Message
That should work.

Note however that you don't need the & "" in there. Doing so is like saying 'Add these two strings together and then add nothing to the end'. In general "" is only useful if you want to force a variable to be a string and empty, such as where you are building a complex set of things to send and you need to start with an empty one like so:

a = "" 'Force it to be an empty string.
a = a & "add some stuff"
a = a & "add more stuff"

Also, another good thing to note about "", if you try to use it with world.note or world.colournote, won't work. You have to use at least a single space or it generates an error.

As for keeping a track record of who blinded what. It doesn't make much sense to use another trigger for that. One option is to add something like:

world.setvariable "Score_" & wilds(1), world.getvariable ("Score_" & wilds(1)) + 1

to the MobBlinded section. However this uses mushclient variables, which in turn slows things down a bit.

However, you can later retrieve a list of all triggers, search that list for anything with 'Score_{name}' in it and read the values from there to display them.

The alternative is to use an array, but doing that requires more complex code. You can simplify the actual case statement and the difficulty of later changes for it a bit if you make it like:
dim BlinderName
  'We Redim them instead of using dim, because Redim lets us do {redim preserve BNames(newsize)}
  'if the number of names goes over 10. ;) While 'preserve' keeps the current contents. Ones using
  'Dim can't be resized. NOTE: Arrays created using the Split command will resize, but won't
  'keep the original contents
redim BNames (10) 
redim BScores (10)

sub BlindTest (tname, output, wilds)
  case "MobBlinded"
  world.send "grouptell " & wilds(1) & " blinded by " & BlinderName & "."
  world.enabletrigger "MobBlinded", vbFalse
  Update_BScore (BlinderName)
...

sub Update_BScore (Name)
  'Put the code to handle the name and score arrays here.
end sub


That way the code to handle the arrays is seperated from the main routine, which only gets one new line added to it, making it easier to edit both of them.

P.S. There is a check box that says 'Forum codes:'. If you click that then place [code] and [/code] around the script stuff you post it won't collapse against the edge like it did to you. ;)
[Go to top] top

Posted by Guest1   USA  (256 posts)
Date Reply #12 on Mon 10 Feb 2003 09:57 PM (UTC)

Amended on Mon 10 Feb 2003 10:02 PM (UTC) by Guest1

Message
Excellent, thanks Shadowfyr for the advice. I'm glad this board is here, I've learnt a lot from you and others, so thanks again :)

I'm bookmarking this page as this group individual scoring feature is likely to take some time, as there are a hell of a lot of different things to score on and in most cases several different mud generated messages possible for each action. Eventually I'd like to have the admin approve a bot that a group leader can summon that follows the group around and does all this for them.

That redim is handy - groups can go from as few as 4 people to as many as 15-20 (or more) so I will definitely need something that can handle it.

For the moment I wont go too full on until after v3.33 comes out as I'll be rewriting a lot of my characters existing scripts.. just needed to get over these initial obstacles that we have discussed here.

Oh, and yeah, I did click the forum codes box, I just forgot the code tags hehe (kinda defeats the purpose but ya get that on the big jobs)
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Reply #13 on Mon 10 Feb 2003 10:06 PM (UTC)
Message
Just in case you opt for simpler stuff for now, the direct answer to your question would be to use this line:

  world.send "cast 'blindness' " & World.GetVariable("target")

Since you set the value of "target" with a MUSHclient trigger, the value is stored in a MUSHclient variable; you must use the appropriate MUSHclient scripting function to fetch it.

As Shadowfyr pointed out, there is no sense in using & "" to simply add an empty string to the line.

Shadowfyr offers some interesting hints on how you could use scripting to track the 'score' for each member of your group.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Reply #14 on Mon 10 Feb 2003 10:12 PM (UTC)
Message
Quote:

For the moment I wont go too full on until after v3.33 comes out as I'll be rewriting a lot of my characters existing scripts.. just needed to get over these initial obstacles that we have discussed here.

I highly recommend putting such projects in plugins. Use a different 'world' file for each character, and have them share code by installing the same plugins for each character. Only use your main script file for stuff that is specific to one character only.

I could say that advice would have helped me greatly, but I was around before plugins anyway, so I am forced to adapt. I'm slowly moving stuff from my main script out to plugins. The nice thing is, once each 'project' is done, I can share the plugins simply with other people too.

Get my plugins here: http://www.magnumsworld.com/muds/

Constantly proving I don't know what I am doing...
Magnum.
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


50,190 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]