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

Gammon Software Solutions forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

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

Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?
(New message)
Subject: question with multiple line triggers
Name:
Your forum user name.
Register forum user name
Password:
Your forum password.
Forgotten password?
Message:
Message to be posted (in English, please).
Forum codes:
Check this if your message uses 'forum codes' or templates (auto-detected for new posts).
Forum codes Templates

Save this message ...


Subject review (reverse sequence)

Pages: 1  2 

Posted by Demonsurfer   USA  (256 posts)  [Biography] bio
Date Tue 11 Feb 2003 12:38 AM (UTC)  quote  ]
Message
Hey np Magnum :) I wasn't expecting anyone to write anything for me, just looking for advice and it's much appreciated.

I'll coast around the internet over the next week or two and see what I can dig up as well, that's basically how I figured out how to do the vbs for MC. Again, at this stage it's highly unlikely that playerstats will be kept long-term at all, so no biggie there, it's just to add a bit of fun to the groups and stop people botting.

*ack* dammit.. dwarven prince just killed me.. gotta go.
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Tue 11 Feb 2003 12:15 AM (UTC)  quote  ]
Message
Man, I should rush my latest plugin just so I can show it to you as an example. Although the nature of the data is completely different, you could see how I manage to work with arrays, and manage to write some efficient subroutines by using certain MUSHclient programming 'tricks' (such as having trigger names contain relevant data).

Anyway, you should definately put your data in an array. Don't use MUSHclient variables either.

Dim CombatMonitor(20, 5)  ' Number of Players, Number of items to track.

' CombatMonitor(PlayerNumber, 1) = Player_Name
' CombatMonitor(PlayerNumber, 2) = Player_Blinds
' CombatMonitor(PlayerNumber, 3) = Player_Trips
' CombatMonitor(PlayerNumber, 4) = Player_Chops
' CombatMonitor(PlayerNumber, 5) = Player_HeadChops

Because the number of players can vary, it's a bit tough to make the array flexible. You can probably use "ReDim", but I've had problems figuring out how to get that to work the way I wanted, but I'm sure it's workable once you figure out the syntax.

Using an array like that makes it MUCH easier to print 'charts' later. For example:

Sub Print_Stats (a, b, c)
  Dim x,y
  Dim OutputLine
  World.Send "title line."
  For x = 1 to NumberofPlayers
    OutputLine = ""
    For y = 1 to UBound(CombatMonitor, 2)
      OutputLine = OutputLine & CombatMonitor(x,y)
    Next
    World.Send OutputLine
  Next
End Sub

With a small subroutine like that, you could print out a large chart. (Of course, that code is rather raw, and would need cleaning to format the output nicely).

It's too much work for me to do everything for you. My home mud is down right now, so I can't even work on my project till it's back up. (Well, I could, but it's a pain in the ass). Sigh.

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 Demonsurfer   USA  (256 posts)  [Biography] bio
Date Mon 10 Feb 2003 11:11 PM (UTC)  quote  ]

Amended on Mon 10 Feb 2003 11:25 PM (UTC) by Demonsurfer

Message
hehe no probs, I had already started 'drawing' it out on notepad :) ..I have most of the messages I'll need to trigger on, although there's a few still missing which could take a few days or more to get depending if any groups are running when I am able to log on.

My basic idea atm is that a player will need to grouptell something like ADDME before I start tracking them, and when they do, it will create a variable for thier name (ie: player6 variable value = playername) and then for each player there will be a series of numerical variables for the differing actions.. so for each player there will be maybe 8 variables;

     var player1 = playername (text)
      var player1_blinds = x (integer)
      var player1_trips = x (integer)
      var player1_chops = x (integer)
      var player1_headchops = x (integer) etc..

     var player2 = playername (text)
      var player2_blinds = x (integer)
      var player2_trips = x (integer)
      var player2_chops = x (integer)
      var player2_headchops = x (integer) etc..

..and so on, all fed direct from the triggers like the one on this thread with a simple line added to get existing var and add 1 to it. Calling their stats would pull direct from the variables, and calculating a score would be an easy to code formula, along with sorting for group scores.. but again, if all of these are MC variables then I guess it will start effecting my gameplay with lags.. when it comes to using arrays/database, I know about --> <-- this much hehe.

At this stage I only envisage using it on a group duration basis only, so that when each mob is killed and the gold it has is split between the team members, a small percentage would be held back in a pot and given to the 'winner' at the end of the group and then all the stats would be wiped.
..but yeah, further down the track it may turn into keeping longer term stats for players if the interest is there. I'm in no big rush to complete this either, it's a project for me to do when I have the time, be it days, weeks or months in the process. :)
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Mon 10 Feb 2003 10:54 PM (UTC)  quote  ]
Message
Ah, now you're getting into some complex variable tracking, using arrays or databases of some kind. Building the triggers and output routines is fairly straight foward, but deciding exactly which data to track, and how you will track it is another matter completely.

What I do for projects of this magnitude, is to actually draw up on paper a chart of all the data I want to track. I try to determine what values I need stored on an ongoing basis (between MUSHclient sessions), and which ones I don't. How is the data related? etc... What is the most efficient way to interact with the data?

As your project becomes more complex, you're going to have to rely on yourself to do the programming. Frankly, from my own perspective, I have too much work for my own projects (that I have been putting off) that needs doing, before I write for someone else. Fortunately, we've got a budding community here, so you should be able to get help whenever you are stuck, and many of us try and provide snippets from time to time, or even share our own work, which you can learn from by example.

The project I am currently working on might be useful, but I don't think I'll finish it for a few weeks, 'cause I only take stabs at it once it a while. It's main functionality relies on a large multi-dimensional array.

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 Demonsurfer   USA  (256 posts)  [Biography] bio
Date Mon 10 Feb 2003 10:30 PM (UTC)  quote  ]

Amended on Mon 10 Feb 2003 10:37 PM (UTC) by Demonsurfer

Message
Thanks Magnum, yes that line is even easier stiil :)

The score function is going to take some thinking as I'd like to be able to give the scores as both a single 'total points' value (easily done), but also have it able to be broken down, so I may end up having a lot of variables.

Ideally there will be a variety of options so that if a player grouptells SCORES, I'd respond with a triggered grouptell reply of

     playername1 = x points
     playername2 = x points
     playername3 = x points
     playername4 = x points

in value order, and if they type just SCORE, they would only get their personal score, not everyone elses. The additional things would be something like a team member grouptelling STAT to get a breakdown of their score.. like

     playername3 has 12 blinds, 6 trips, 8 mobchops etc 

and in turn STATS would give everyones stats

     playername1 = x blinds, x trips, x mobchops etc 
     playername2 = x blinds, x trips, x mobchops etc 
     playername3 = x blinds, x trips, x mobchops etc 
     playername4 = x blinds, x trips, x mobchops etc

and of course LOSER would state who is coming last, and EVIL would show who has chopped the most other players (it's a side effect that happens sometimes on the mud I play on that in a chop group you sometimes miss the mob and hit one of the other team members instead) so in other words there will be a lot more detail required than purely just a points total score.


..and yup I always have had different world files for each character :) In fact I'm still using vers3.26 and haven't upgraded yet because I'm hoping Nick will add in the suggestions I wrote an another thread before I change everything to trigger groups and plugins etc

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=2274

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=2111
[Go to top] top

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Mon 10 Feb 2003 10:12 PM (UTC)  quote  ]
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

Posted by Magnum   Canada  (580 posts)  [Biography] bio
Date Mon 10 Feb 2003 10:06 PM (UTC)  quote  ]
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 Demonsurfer   USA  (256 posts)  [Biography] bio
Date Mon 10 Feb 2003 09:57 PM (UTC)  quote  ]

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

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 Shadowfyr   USA  (1,774 posts)  [Biography] bio
Date Mon 10 Feb 2003 09:02 PM (UTC)  quote  ]

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. ;)

main {
__if (Schrodinger_Cat is Alive or version >= "XP"){
____if version = "Vista" then Performance /= Number_of_Cores;
____call Functional_Code();}
__else
____call Crash_Windows();}
[Go to top] top

Posted by Demonsurfer   USA  (256 posts)  [Biography] bio
Date Mon 10 Feb 2003 07:59 AM (UTC)  quote  ]

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

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 Magnum   Canada  (580 posts)  [Biography] bio
Date Mon 10 Feb 2003 07:11 AM (UTC)  quote  ]
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 Shadowfyr   USA  (1,774 posts)  [Biography] bio
Date Mon 10 Feb 2003 04:18 AM (UTC)  quote  ]
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.

main {
__if (Schrodinger_Cat is Alive or version >= "XP"){
____if version = "Vista" then Performance /= Number_of_Cores;
____call Functional_Code();}
__else
____call Crash_Windows();}
[Go to top] top

Posted by Shadowfyr   USA  (1,774 posts)  [Biography] bio
Date Mon 10 Feb 2003 04:06 AM (UTC)  quote  ]
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.

main {
__if (Schrodinger_Cat is Alive or version >= "XP"){
____if version = "Vista" then Performance /= Number_of_Cores;
____call Functional_Code();}
__else
____call Crash_Windows();}
[Go to top] top

Posted by Demonsurfer   USA  (256 posts)  [Biography] bio
Date Mon 10 Feb 2003 12:49 AM (UTC)  quote  ]

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

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 Neva   USA  (117 posts)  [Biography] bio
Date Mon 10 Feb 2003 12:14 AM (UTC)  quote  ]
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

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.


7,048 views.

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

[Reply to this subject]  Reply to this subject   [New subject]  Start a new subject   [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

[Home]

Written by Nick Gammon - 5K

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

[Best viewed with any browser - 2K]    [Internet Contents Rating Association (ICRA) - 2K]    [Web site powered by FutureQuest.Net]