Trigger Help Please

Posted by Eammon Wright on Wed 23 Sep 2020 06:20 PM — 29 posts, 102,708 views.

#0
Ok so I have tried this trigger out of combat and it works fine but only partially works in combat. I'm sure it's something simple but i'd like some help if possible.
the trigger out of combat is


     HP [ */* ]     SP [ */* ]     EP [ */* ]


and the if statements it runs are::


if %1 < 500 then Send "say heal"
if %3 < 300 then Send "say Mana"
if %5 < 200 then Send "vitalize"
end -- if
end -- if
end -- if


so if I type hp out of combat, I have the number very high so they will all execute, but they do all execute.

Now in combat the only difference is the trigger placement but here it is.


HP [ */* ]     SP [ */* ]     EP [ */* ]


Just no spacing prior to hp. each round of combat that hp bar come across the screen. the if statements to check those scores and perform what i want are:


if %1 < 100 then Send "heal me"
if %3 < 100 then Send "eat food"
if %5 < 30 then Send "vitalize"
end -- if
end -- if


only the heal me part will fire off. How should I rewrite this to work?

[EDIT] Used code tags for the trigger.
Amended on Thu 24 Sep 2020 03:58 AM by Nick Gammon
Australia Forum Administrator #1
In both cases your 2nd and 3rd tests are dependent on the first. Is that what you want? Indenting your code it looks like this:


if %1 < 100 then 
  Send "heal me"
  if %3 < 100 then 
    Send "eat food"
    if %5 < 30 then 
      Send "vitalize"
    end -- if
  end -- if
end -- if


In other words, it won't send "eat food" unless your HP is below 100 as well as your SP being lower than 100.

Assuming they are all independent you probably want:


if %1 < 100 then 
  Send "heal me"
end -- if

if %3 < 100 then 
  Send "eat food"
end -- if

if %5 < 30 then 
  Send "vitalize"
end -- if
#2
That worked great Thank you so much. I think I need to open a new thread for this but i'm also trying to figure out how to make a script for a beach im hunting on. basically if I see the monster I check my health energy and mana and if they are over a certain amount my character will start the fight. is that something a pure beginner like me could shoot for or would that be too complicated sir?

This will trigger when I see a sand lizard, to check my stats before i fight him. well thats the goal.

DoAfter (1, "hp")
if %1 > 200 then
if %3 > 100 then
if %5 < 75 then
Send "attack creature"
end -- if
end -- if
end -- if

This just doesnt work in any sense. Where can I improve on this sir?

I get this error
[string "Trigger: "]:2: unexpected symbol near '>'
Amended on Thu 24 Sep 2020 06:32 PM by Eammon Wright
Australia Forum Administrator #3
Can you show the whole thing, by following this guide:

Template:copying
For advice on how to copy aliases, timers or triggers from within MUSHclient, and paste them into a forum message, please see Copying XML.
#4
<triggers>
<trigger
enabled="y"
group="Cleric"
match=" sea lobster"
send_to="12"
sequence="100"
>
<send>DoAfter (1, "hp")
if %1 &gt; 200 then
if %3 &gt; 100 then
if %5 &gt; 75 then
Send "attack creature"
end -- if
end -- if
end -- if</send>
</trigger>
</triggers>


So basically I want to make it where when I see a creature it runs the hp command to show all my stats. if my stats in those if statements are all above those levels, then he would attack, if not, he would do nothing.
USA Global Moderator #5
What you've done will never work (of course).

You've just told MUSHclient: "Send the 'hp' command 1 second from now. Immediately (before the hp command is sent) look at a local variable that doesn't exist."

MUSHclient then does the following in order: Says "that variable doesn't exist", waits 1 second, then sends the hp command.


You need to...

Trigger when seeing the monste and request stats. Then you have to wait for the stats to show up and continue only after they arrive.

Probably the best way to do this is using the wait.lua module's wait.match function to wait for the stats to arrive before continuing.
Amended on Fri 25 Sep 2020 12:33 PM by Fiendish
#6
Ok I see what your saying. Im sorry guys im really new to programming.
<triggers>
<trigger
enabled="y"
group="Cleric"
match=" HP [ */* ] SP [ */* ] EP [ */* ]"
send_to="12"
sequence="100"
>
<send>if %1 &gt; 280 then
Send "DoAfter (1,"attack lobster")"
end -- if</send>
</trigger>
</triggers>

So now when I see the lobster I have a trigger to run the hp command. if my HP is above 280 it should, after 1 second, attack. but this just throws an error. I have tried a single quote before and after the DoAfter statement but that just literally prints DoAfter (1,"attack lobster") on the screen. Also couldnt figure our how to check for more than just the HP being a certain level before the attack.
USA Global Moderator #7
First, if you're nesting quotation marks, they can't be the same type. The Lua parser doesn't know that when you say "A"B"C" you really mean for the interal ones to be literal if you don't escape them.

Second, you don't Send DoAfter. You either Send _or_ you DoAfter. Not both.

Also, doing your trigger that way will send "attack lobster" literally every time you check your stats if your HP is high enough, which is not what you want. I recommend looking into my suggestion of using wait.match inside of the sea lobster trigger instead of a new second trigger. Otherwise you'll have to separately manage when to activate and deactivate this stats trigger.
Amended on Fri 25 Sep 2020 01:29 PM by Fiendish
#8
I definitely see what your saying, the way i'm doing it is not very functional. However, I am unable to understand just yet how to make the wait.match work with it. Like I said this is my first time trying to write scripts. My end goal is to automate this guy so he walks a certain path and fights and waits along the way. I figured this would be a good way to learn a programming language.

Also Thank you guys for being so friendly and actually offering support and advice. It's refreshing.

Just to show what I had tried prior to this though.

<triggers>
<trigger
group="Cleric"
match=" HP [ */* ] SP [ */* ] EP [ */* ]"
send_to="12"
sequence="100"
>
<send>if %1 &gt; 280 and %3 &gt; 280 and %5 &gt; 100 then
DoAfter (1,"attack lobster")
else
DoAfter (60,"look")
end -- if</send>
</trigger>
</triggers>

So when I checked hp it would attack lobster, if one wasnt present it would just wait and look again, so I added a trigger for the 3 types of monsters on the beach, lobster, crab, and gull. so if I attacked lobster and there was not one there it would trigger attack crab, then gull...problem was it was some infinite loop that just kept cycling through them. I think that would work if I could figure out how to make it only fire off once each.
Amended on Fri 25 Sep 2020 01:46 PM by Eammon Wright
USA Global Moderator #9
Quote:
if one wasnt present it would

That's not what that does. Nowhere does it evaluate presence.

Another thing you can do which might be simpler to understand is to have your HP/SP/EP trigger just store the values to variables and then check those variables for whatever was stored in them last whenever your monster triggers fire. Of course it will depend on you constantly updating those values in between.
Amended on Fri 25 Sep 2020 08:46 PM by Fiendish
#10
Yea. I'm going to dig around online and try and find an easy to follow example that I can tweak. I'm sure I can figure it out at that point. Thanks for all the advice, i'll be back if I can not figure it out though for sure :)
USA Global Moderator #11
But anyway, using wait.match isn't hard per se (though it does require you to manually invoke a coroutine wrapper, which I hate). It's just apparently not documented anywhere.

You want your sea lobster trigger to do something like...


require "wait"
wait.make (function ()
   Send("hp")
   local line, wildcards = wait.match(" HP [ */* ] SP [ */* ] EP [ */* ]")
   -- here you check your hp/sp/ep using wildcards[1], wildcards[2], etc instead of %1 %2 etc.
end)

Amended on Fri 25 Sep 2020 09:07 PM by Fiendish
Australia Forum Administrator #12
It's documented here: http://www.gammon.com.au/modules

Scroll down to the "wait.lua" section.
Australia Forum Administrator #13
Quote:


<triggers>
  <trigger
   enabled="y"
   group="Cleric"
   match="   sea lobster"
   send_to="12"
   sequence="100"
  >
  <send>
DoAfter (1, "hp")
if %1 &gt; 200 then
  if %3 &gt; 100 then
    if %5 &gt; 75 then
      Send "attack creature"
    end -- if
  end -- if
end -- if
  </send>
  </trigger>
</triggers>



As Fiendish was explaining, the use of %1 here is meaningless because what you are matching on (the "match" part) doesn't have any wildcards, hence %1, %3 and %5 will just be empty strings.

A more logical approach would be to capture your prompt, and "remember" your current hp, mana etc. in variables. Then when you see the sea lobster you decide whether to attack it or not depending on the saved variables.
#14
<triggers>
<trigger
enabled="y"
group="Cleric"
match=" sea lobster"
send_to="12"
sequence="100"
>
<send>require "wait"
wait.make (function ()
Send("hp")
local line, wildcards = wait.match(" HP [ */* ] SP [ */* ] EP [ */* ]")
end)

if wildcard[1] &gt; 280 and wildcard[3] &gt; 280 and wildcard [5] &gt; 100

Send "attack lobster"
end -- if</send>
</trigger>
</triggers>


Ok so, This is how I understood what you guys are saying. Still not working but am I getting closer?
USA Global Moderator #15
In Lua, every "if" needs a "then".
#16
[string "Trigger: "]:7: attempt to index global 'wildcard' (a nil value)
stack traceback:
[string "Trigger: "]:7: in main chunk

Ok so this is the error im getting now. and this is what my code looks like.

<triggers>
<trigger
enabled="y"
group="Cleric"
match=" sea lobster"
send_to="12"
sequence="100"
>
<send>require "wait"
wait.make (function ()
Send("hp")
local line, wildcards = wait.match(" HP [ */* ] SP [ */* ] EP [ */* ]")
end)

if wildcard[1] &gt; 280 and wildcard[3] &gt; 280 and wildcard [5] &gt; 100 then

Send "attack lobster"

else
DoAfter (180,"look")
end -- if</send>
</trigger>
</triggers>

Ok so the point was to see the lobsterm have it run hp, if my stats are all over a ceertain level I attack else i wait 180 then look which will start the process all over again.
USA Global Moderator #17
First you declared "wildcards" with an s, and then tried to access "wildcard" without an s. They must be the same.

Also I think you will need to move your lines around. Put your if/else stuff before the "end)" line that closes out the "wait.make(function()" line. Otherwise I'm pretty sure the waiting won't work.


Quote:
Ok so the point was to see the lobsterm have it run hp, if my stats are all over a ceertain level I attack else i wait 180 then look which will start the process all over again.

Isn't 180 a long time?
Amended on Mon 28 Sep 2020 06:10 PM by Fiendish
#18

<triggers>
  <trigger
   enabled="y"
   group="Cleric"
   match="   sea lobster"
   send_to="12"
   sequence="100"
  >
  <send>require "wait"
wait.make (function ()
   Send("hp")
   local line, wildcards = wait.match(" HP [ */* ] SP [ */* ] EP [ */* ]")
   if wildcards[1] &gt; 280 and wildcards[3] &gt; 280 and wildcards [5] &gt; 100 then

Send "attack lobster"

else
   DoAfter (60,"look")
end -- if
end)</send>
  </trigger>
</triggers>


Ok, See what your saying aboutthe placement and syntax. I get no errors now, however, it doesnt attack either. I see the lobster, it check hp then does nothing. Any thoughts?

EDIT: thought it might have been a spacing issue with the HP out put so I added the proper output spacing and it through this error.


hp
>      HP [ 288/288 ]     SP [ 289/289 ]     EP [ 114/114 ]
Error raised in trigger function (in wait module)
stack traceback:
        [string "Trigger: "]: in function <[string "Trigger: "]:2>
>


[EDIT] Added code blocks.
Amended on Tue 29 Sep 2020 07:06 AM by Nick Gammon
Australia Forum Administrator #19
Inside the "wait" block you shouldn't use DoAfter. You should use wait.time. So, instead of:


   DoAfter (60,"look")


do:


  wait.time (60)
  Send ("look")
Australia Forum Administrator #20
Template:codetag
To make your code more readable please use [code] tags as described here.
#21

require "wait"
wait.make (function ()
   Send("hp")
   local line, wildcards = wait.match(">      HP [ */* ]     SP [ */* ]     EP [ */* ]")
   if wildcards[1] > 280 and wildcards[3] > 280 and wildcards [5] > 100 then

Send "attack lobster"

else
    wait.time (60)
    Send ("look")
end -- if
end)


There we go. Ok. So fixed the wait.time look, and that all works fine. However, it is not firing the attack command even though the wildcard parameters have been met. Any thoughts?

Error:
...son\Desktop\Misc\Passport Backup\MUSHclient\lua\wait.lua:67: [string "Trigger: "]:5: attempt to compare number with string
stack traceback:
[C]: in function 'error'
...son\Desktop\Misc\Passport Backup\MUSHclient\lua\wait.lua:67: in function <...son\Desktop\Misc\Passport Backup\MUSHclient\lua\wait.lua:59>

Error raised in trigger function (in wait module)
stack traceback:
[string "Trigger: "]: in function <[string "Trigger: "]:2>

Now if you notice that the hp trigger has a > and a large space before the stats are parsed, that's the exact output when hp is ran. It seems that the '>' is throwing the error, it's trying to use that as an operator instead of the text output. Also, i'm assuming that they d this to prevent triggers and scripts, but sometimes that '>' is there, and sometimes it's not. Is there a way around that also with this script? Any thoughts on that one as well?
Amended on Tue 29 Sep 2020 12:20 PM by Eammon Wright
USA Global Moderator #22
Quote:
It seems that the '>' is throwing the error, it's trying to use that as an operator instead of the text output.

No. wait.match wildcard results don't work the same way as %1, %2 pattern replacement does. You have to convert wildcards[1] etc to numbers with tonumber if you want them to be treated as numbers.

You do still have to be careful about the XML parser though. The <triggers><trigger><send></send></trigger></triggers> block gets parsed as XML first before being sent to the Lua engine, which is why you'll often see &gt; and &lt; inside there instead of > and <. But the parser will usually only care about < and not about > for technical reasons.

Quote:
sometimes that '>' is there, and sometimes it's not. Is there a way around that also with this script?

Either switch from wait.match to wait.regex and use a regular expression pattern instead or replace the leading > with another wildcard capture and shift your index numbers up one.
Amended on Tue 29 Sep 2020 12:42 PM by Fiendish
#23

require "wait"
wait.make (function ()
   Send("hp")
   local line, wildcards = wait.match("*      HP [ */* ]     SP [ */* ]     EP [ */* ]")
   if wildcards[2] > 280 and wildcards[4] > 280 and wildcards [6] > 100 then

        Send "attack lobster"

    else
        wait.time (60)
        Send ("look")
    end -- if
end)


I'm assuming that's what you meant about the '>' problem. But I am unsure how to use tonumber here. I have read through the function file on it here ont he forums. Would you please be able to show me an example maybe?
Amended on Tue 29 Sep 2020 01:15 PM by Fiendish
USA Global Moderator #24
Quote:
I'm assuming that's what you meant about the '>' problem.

Yup. Keep in mind that doing it this way will also match if the line starts with "ASDasdfasdfSDFSDFSDFSD" or "SomePlayer says ". To avoid that, you'd need to switch to a regular expression pattern and use wait.regex instead. But get this working first before you worry about that.

Quote:
Would you please be able to show me an example maybe?

tonumber(wildcards[2]) > 280

etc
Amended on Tue 29 Sep 2020 01:20 PM by Fiendish
#25

require "wait"
wait.make (function ()
   Send("hp")
   local line, wildcards = wait.match("*      HP [ */* ]     SP [ */* ]     EP [ */* ]")
   if tonumber(wildcards[2]) > 280 and tonumber(wildcards[4]) > 280 and tonumber(wildcards [6]) > 100 then

        Send "attack lobster"

    else
        wait.time (60)
        Send ("look")
    end -- if
end)


Works great. Now when it sees the creature, it checks my stats, if their above those levels it attacks, if not it waits 60 seconds while i regen and looks again.

So what was the next problem you were saying with my code sir?

EDIT: Actually I'm running across a small but annoying problem. There are 3 creatures on the beach I have that script for. Lobster, Crab, and Gull. Sometimes when I see one, it will try and attack a different one instead. Any htoughts on that?
Amended on Tue 29 Sep 2020 05:50 PM by Eammon Wright
Australia Forum Administrator #26
You need to detect which one you see, eg. trigger on "A * is here" and remember (save as a variable) which mob is there.
#27
I either trigger on the crab, lobster, or gull, depending on which is on the screen. I was afraid if I set a generic * and made it a variable and attacked the variable that could bite me. If someone were to walk on the screen I would attack them. Other than that though the script seems to work fine. I have to find a way to put it into my array loop once I get it working.
Australia Forum Administrator #28
Well, with a regexp you can do:


^A (lobster|crab|gull) is here\.$


That only matches on those 3 words.