|
geniusclown Magician
Joined: 23 Apr 2003 Posts: 358 Location: USA
|
Posted: Sat Aug 21, 2004 4:56 pm
Multistate core (Dragonrealms) |
I'm working on a core multistate trigger to handle commands in DR (code quoted below). So far, it's got 3 queues:
"do_noRt" is a list of one-time commands that will not cause a roundtime (but I can't send more than 3 at a time, or the server says "Sorry, you may only type ahead 2 commands."). To prevent a long list from being sent all at once, it has a condition that triggers on %gsl(q), which is essentially a prompt.
"do_first" is a list of one-time commands that will cause roundtime, so it has a condition that waits for the roundtime (handled by another script using the variable @roundtime, which counts down).
"do_loop" is a single command that will cause roundtime, and is executed over and over.
After executing any command, the trigger resets itself to State 0, using the #STATE command, where it waits for one of the above three queues to have a value.
My problem is, when it does this, it doesn't immediately attempt to evaluate the expression of State 0, and hangs until I receive something from the MUD, or one of the 3 queues is altered. If the first 2 queues are empty and it executes do_loop, it resets itself because it runs out of states rather than executing a #STATE command, and State 0 evaluates itself like it should.
I'm looking for suggestions on how to get State 0 to evaluate itself automatically after being reset by the #STATE command. #SET won't do it, because that forces the trigger state to "true", regardless of if there's anything in the queues.
I tried tacking on a dummy state and going to it instead of State 0, but it would just hang on that State 8 the same as it does State 0, so that's not a solution.
Quote: |
#CLASS {Do}
#ALIAS que {#IF (%ismember( %1, @do_types)) {#IF (%1="loop") {do_loop = %2} {#VAR do_%1 %additem( %-2, @{do_%1})} {#ECHO {Syntax~: que ~{@do_types~} ~{command to que~}}}}}
#VAR do_noRt {}
#VAR do_first {}
#VAR do_loop {}
#VAR do_types {noRt|first|loop}
#TRIGGER "doit" {@do_noRt or @do_first or @do_loop} {} "" {exp}
#COND {@roundtime=0} {#IF (@do_noRt) {#STATE doit 2} {#IF (@do_first) {#STATE doit 4} {#IF (@do_loop) {#STATE doit 6}}}} {exp}
#COND {} {#EXEC %pop( do_noRt)} {wait|param=1}
#COND {q} {#STATE doit} {gsl}
#COND {} {#EXEC %pop( do_first)} {wait|param=1}
#COND {@roundtime>0} {#STATE doit} {exp}
#COND {} {#EXEC @do_loop} {wait|param=1}
#COND {@roundtime>0} {} {exp}
#BUTTON 50 {~[%state( doit)~] @do_noRt,@do_first,@do_loop} {#SET doit %state( doit)} {} {} {} {} {} {Size} {200} {22} {} {} {} {} {} {} {} "" {} {} {} |
|
|
_________________ .geniusclown |
|
|
|
geniusclown Magician
Joined: 23 Apr 2003 Posts: 358 Location: USA
|
Posted: Sun Sep 12, 2004 1:33 am |
I've been working on this script a bit, and made several modifications. Its purpose is the same, but the means are a little different. I've now set only 2 queues - 1 to execute immediately (@do), and 1 to loop (@loop). Here's the core multistate trigger:
Quote: |
#TRIGGER "doit" {@do or @loop} {} "" {exp}
#COND {@roundtime=0} {#IF (@do) {#EXEC %pop( do);#IF (%item( @do, 1)="noRt") {#NOOP %pop( do);#SET doit 2}} {#IF (@loop) {#STATE doit 4} {#STATE doit}}} {exp}
#COND {@roundtime>0} {} {exp}
#COND {} {#STATE doit} {wait|param=1}
#COND {} {#EXEC @loop} {wait|param=1}
#COND {@roundtime>0} {} {exp} |
It works very well, with one glaring exception. If @roundtime is already 0 when the first trigger fires (i.e. I put something in @do or @loop), the trigger will hang in state 1 until some variable changes, or I force it to move on via #SET. How can I guarantee that as soon as state 0 is true and it moves to state 1, it checks to see if the expression in state 1 is true? |
|
_________________ .geniusclown |
|
|
|
Vijilante SubAdmin
Joined: 18 Nov 2001 Posts: 5182
|
Posted: Sun Sep 12, 2004 4:04 am |
Use an alarm or wait state instead and simply test @roundtime in an #IF.
|
|
_________________ The only good questions are the ones we have never answered before.
Search the Forums |
|
|
|
LightBulb MASTER
Joined: 28 Nov 2000 Posts: 4817 Location: USA
|
Posted: Sun Sep 12, 2004 6:06 am |
If you have problems when roundtime is already zero, then make sure it isn't.
#TRIGGER "doit" {@do or @loop} {#IF (@roundtime = 0) {#VAR roundtime 1}} "" {exp} |
|
_________________ LightBulb
Senior member
Most scripts in this forum are written for Command Line entry.
Don't even open the Settings Editor unless its use is specified or obvious. |
|
|
|
geniusclown Magician
Joined: 23 Apr 2003 Posts: 358 Location: USA
|
Posted: Sun Sep 12, 2004 4:24 pm |
This works, but is more of a band-aid... it's not the best solution because I lose a second, which can be precious if I'm in combat. It also causes a delay if I have other stuff going on at the same time (again, usually in combat).
I still don't understand why the trigger wouldn't attempt to evaluate the expression as soon as it enters state 1. Can someone explain this for me, please? |
|
_________________ .geniusclown |
|
|
|
LightBulb MASTER
Joined: 28 Nov 2000 Posts: 4817 Location: USA
|
Posted: Mon Sep 13, 2004 5:33 am |
Because no variable changes value at the moment the trigger enters state 1. The help for the 'exp' option is quite explicit. The expression will be evaluated when a variable changes value (and not until then).
Type Category for detailed descriptions see: Trigger Types
exp expression trigger (expression is tested whenever a variable is changed)
Yes, the fix I suggested is a 'bandaid'. A real fix would be to check the expression before advancing the state, and execute the appropriate action when it is already true.
#TRIGGER "doit" {@do or @loop} {#IF (@roundtime = 0) {#IF (@do) {#EXEC %pop( do);#IF (%item( @do, 1)="noRt") {#NOOP %pop( do);#STATE doit 3}} {#STATE doit 4}}} "" {exp}
#COND {@roundtime=0} {#IF (@do) {#EXEC %pop( do);#IF (%item( @do, 1)="noRt") {#NOOP %pop( do);#SET doit 2}} {#IF (@loop) {#STATE doit 4} {#STATE doit}}} {exp}
#COND {@roundtime>0} {} {exp}
#COND {} {#STATE doit} {wait|param=1}
#COND {} {#EXEC @loop} {wait|param=1}
#COND {@roundtime>0} {} {exp}
Since either @do or @loop must be true for the trigger (state 0) to fire, when @do wasn't true there was no need to test @loop and I just went straight to state 4. I also altered the #SET 2 to #STATE 3 but I'm not sure this is correct, it might need to be #STATE 2. Depends on whether you meant to skip state 2 or advance to state 2, I assumed you meant to skip state 2. |
|
_________________ LightBulb
Senior member
Most scripts in this forum are written for Command Line entry.
Don't even open the Settings Editor unless its use is specified or obvious. |
|
|
|
geniusclown Magician
Joined: 23 Apr 2003 Posts: 358 Location: USA
|
Posted: Tue Sep 14, 2004 5:45 am |
I do realize that exp trigger states wait for variables to change, but I thought that they would check immediately when going into the state in the first place. I wonder if throwing in a line such as #ALA +0.01 do=@do could make it evaluate immediately?
Yes, I wanted to skip over state 2, which is where it waits for a roundtime... having the member "noRt" is intended to tell the trigger not to wait for roundtime before advancing. However, using #STATE doit 3 will accomplish the same thing.
Your solution seems a bit redundant, which is probably why I hadn't thought about it... my whole point of the core is to elimanate redundant code I have running rampant in my classes... It looks like it'll do what I need it to, so I'll try it out next time I'm in game.
You're living up to your namesake yet again, LightBulb, as always. I appreciate the insight. |
|
_________________ .geniusclown |
|
|
|
|
|