Equipment analyzer/sorting plugin/script help needed!

Posted by Sephiran on Fri 31 May 2019 06:04 PM — 31 posts, 106,049 views.

#0
I'm newbie at that this just trying to learn... problem is i can't figure it out why i came here for help/guidance. Trying to may a plugin or script that sorts eq in inv by three stats then wears the best one of each piece... i got something made that detects if a number is greater or lower than a certain number here is that trigger.. not the best but i am still learning... slowly getting better.. this is in lua... A and 10 was just used as a test to see if it would work it worked...
Now how would i take this and let's say compare it to another item in my inv? or even add another stat and compare two stats against each item? my goal is to have a script or plugin i can use to automatically sort 1000's of pieces of eq and wear the best of each slot... any help/advice will be much appreciated... thanks in advance sorry if this is a stupid question or something really simple to do i may just be over thinking it... the trigger part is all i have for right now slowly adding to it as i learn. Like i said i am very new to this... This is a example of the text in game i will use to match on: Affects spellpower by 420. i just choose to match on spellpower but could also match on the whole line and use a * or this (.*?) for the number?


<triggers>
  <trigger
   expand_variables="y"
   keep_evaluating="y"
   match="spellpower by (.*?)."
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>if x &gt; 10 then
  Send("a")
end</send>
  </trigger>
</triggers>
Amended on Fri 31 May 2019 07:09 PM by Fiendish
USA Global Moderator #1
Oof. That's quite a wall of text. I believe this is the salient question:
Quote:
Now how would i take this and let's say compare it to another item in my inv


Ok, so you made a trigger that looks at one item's spellpower value. The simplest way to do what you want would be to store that value in a variable, and then, when you subsequently look at another item, compare the value from the new item to the value that you stored. If the new item's value is better, wear that item and then store its value instead of the old one.
#2
thank you, Fiendish! But, that's beyond my knowledge right now could you be so kind to give a example of what you mean? storing a variable would be like what the targeting alias dose right? think i know what you mean just not how to go bout writing the code for it. Again thank you for your answer. what bout it being random value on every piece? could i make it so it just gets the highest one out of every item i compare, or would i have to have a set value for it to work? Plus how would i add another stat to be compared alone with spellpower? new trigger, or could i do it in the same one?
Australia Forum Administrator #3
The first thing you can do is take that wildcard (the thing in brackets) and use that in your code. For example:


if %1 > 10 then
  Send("Spellpower increased by more than 10!")
end


To make sure you get a number (otherwise the comparison won't work) you could change your regular expression to:


spellpower by (\d+?)\.


I put a backslash in front of the final dot, because an unescaped dot matches any cahracter.

The \d matches a digit, and therefore \d+ matches one or more digits.




As for the rest of your question, you need to collect your inventory somehow. FAQ 37 might help.

Template:faq=37
Please read the MUSHclient FAQ - point 37.


There are ways of sorting in Lua, so you could find your entire inventory, and then sort it based on some criteria.

I suggest a bit of playing around with Lua to get more familiar with it.
#4
Thanks Nick! i'll look into tables... i thought bout them before but was hoping what i wanted could be done without them... i thought it would be something simple like for ex
lore/ID an item as soon as i pick it up then if the stats are over certain numbers put in bag... then i thought bout it. Realized even then i'd have to use a table for when it came time to actually wanting to equip the best pieces out of the ones i collected. The faq section you pointed me to will help out a lot. again, thanks.
USA Global Moderator #5
A quite good tutorial on Lua tables is http://www.phailed.me/2011/02/learn-lua-the-hard-way-tables/
#6
thanks fiendish, i'll be sure to check it out... guess it won't be as simple as what i thought going off a post in reddit i found i thought i could just do something like this
 (.*)Affects (spellpower|intelligence|damroll) by (.*?).


then just put this in to the send box:
 If ((%3 == "spellpower" or %3 == "intelligence" or %3 == "damroll")  and %4 > 17) then
    Send("put %1 in the bag")
else
    Send("drop %1")


guess it is little trickier then that post made it seem... Thanks again to both you for your help. I've learned quite a bit since i first started.
Amended on Sat 01 Jun 2019 02:22 AM by Sephiran
USA Global Moderator #7
That's very similar to what I suggested you do before. I only gave you the link on tables because you brought it up for some reason.

You'll need to put quotation marks around any of your %1, %2, etc that aren't numbers if you want them to be parsed properly. And checking for the words "spellpower", "intelligence", or "damroll" makes no sense because your pattern already only matched on those anyway. And you'd want to compare %3 (not %4 in that pattern) against some previously seen value, not 17.
Amended on Sat 01 Jun 2019 02:41 AM by Fiendish
#8
Ok thanks again fiendish. Only reason i brought up tables was because i thought that is what i would have to do at first, when i could not get what i posted that was like your idea you suggested i thought i would of needed a table to do what i wanted. Not sure i follow you with this line: "checking for the words "spellpower", "intelligence", or "damroll" makes no sense because your pattern already only matched on those anyway." i added them cause those are the other two stats i want to compare on items.. that's how the reddit post had the code i just switched the words to what i needed could not get it to work. I'll try what you said maybe i can get it to work, first time i tired it gave me an error of expected a = sign near >? and a few more i can't remember off the top of my head. this is the post where i got the code from: https://www.reddit.com/r/MUD/comments/6qis5r/help_with_mushclient_triggers/
USA Global Moderator #9
Quote:
Not sure i follow you with this line: "checking for the words "spellpower", "intelligence", or "damroll" makes no sense because your pattern already only matched on those anyway."


If your regular expression looks like:

 (.*)Affects (spellpower|intelligence|damroll) by (.*?).


Then by definition it will only match on lines where "%2" is one of "spellpower", "intelligence" or "damroll", so also putting

if (("%2" == "spellpower" or "%2" == "intelligence" or "%2" == "damroll")
is redundant.
Amended on Sat 01 Jun 2019 04:54 AM by Fiendish
#10
Maybe i've took away something i should not have here is the error i get with


<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="(.*)Affects (spellpower|intelligence|damroll) by (.*?)."
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>if (("%2" and "%2" and "%2") and %3 &gt; 100) then
    Send("a")
end</send>
  </trigger>
</triggers>


[string "Trigger: "]:1: attempt to compare number with string
stack traceback:
[string "Trigger: "]:1: in main chunk


this error i get if i have "" around the %3
[string "Trigger: "]:1: unexpected symbol near '>'

i even changed the match text to have (\d+?)\. at the end and still same two errors... I have a feeling maybe i'm over complicating this?
Amended on Sat 01 Jun 2019 08:09 AM by Sephiran
Australia Forum Administrator #11
Computer languages in general do not work like that. I know what you mean, but something like:


if Tom and Dick and Harry > 40 then ...


That isn't parsed how you might think. "and" is a boolean operation, so it reads as:

If Tom "is true" and Dick "is true" and Harry "is true" and if all that is true then if "true" > 40 then ...

You really want something like:


if Tom > 40 and Dick > 40 and Harry > 40 then ...
Amended on Sat 01 Jun 2019 10:23 AM by Nick Gammon
Australia Forum Administrator #12
You will find it much easier if, instead of trying to do complex triggers and regular expressions, you take a few days to learn the basics of programming, particularly in Lua.

I don't mean that in an insulting way, but getting comfortable with how the language works, and programming in general, will be easier if you take small steps with some tutorials.

I have a couple of posts about tables on this site:

http://www.gammon.com.au/forum/?id=4903

and:

http://www.gammon.com.au/forum/?id=6036
#13
thanks nick, and no i didn't take it as a insult and thank you for your words cause that is what i should of being doing from the start is the basic and simple stuff first to learn not complex like i jumped into. I'll do what u suggest that's my problem normally i tend to try complex things and just learn as i go. I'm the type to learn better if shown/video or trial and error... i don't know it seems strange but that's how i am.. thanks again to both you for your help and understanding.
Amended on Sat 01 Jun 2019 06:23 PM by Sephiran
#14
i got it working had to remove (.*) from start of trigger

is there a way to make it so it only puts the item that's lored in to something or dropped? by name or something? i tried to just have put 1. box but if an item matches on more the one stat it puts not only the item that i'm loring into a box but the other two after it that is in my inv. ex from game:

 if an item has two like this Affects intelligence by 402.
put 1. love
Affects damroll by 1251.
put 1. love


then it puts the item i IDed into a box like: You put (Spiffed) A Wyldfae's chilled polearm of rain calling in BRoM'S SaCK oF LoVe.

but then it also put the next item that became first in my inv into box: You put (Spiffed) Soratami Seer's glittery sword of crack in BRoM'S SaCK oF LoVe.

not all of my eq is going have the same name..
Amended on Sat 01 Jun 2019 08:38 PM by Sephiran
USA Global Moderator #15
That's a tricky scenario. What you need to do is wait until you know that all of the messages are done for the thing that you're looking at before you put anything in the box.

You will need to plan out a logical sequence of events between
  1. an alias or trigger that captures the name of the thing that you're using lore on
  2. then one or more triggers that capture the stat lines
  3. then some way of detecting that you're done receiving stat lines so that you can safely put just the one item in the box
Amended on Sat 01 Jun 2019 08:28 PM by Fiendish
#16
thanks fiendish for ur answer i will work on that. also wanted to know if i have different numbers set for all three like
 if "%1" >= "300" and "%1" >= "400" and "%1" >= "1000" then
    Send("put 1. love")
end
...nvm that still matches on all three.. if i set damroll to %3 and spellpower to %2 and intelligence to %1 in variables it wont fire at all.. would i have to use like a,b,c for variables? i tried to just use a set value of 3000 for variable named damroll (damroll can go over 3k)... but again matched on all three stats... thinking i may need three separate triggers for each stat i want to compare instead of one for all three? there are "" around 300,400,1000 had to put them or else i get this error: string "Trigger: "]:1: attempt to compare number with string
Amended on Sat 01 Jun 2019 08:59 PM by Sephiran
Australia Forum Administrator #17
If %1 is a number then you should be able to write:


if %1 >= 300 then


If you write:


if "%1" >= "300" then


Then you can (will) get problems with certain numbers. As strings, for example, "4" is greater then "300", because strings compare from the left.

It might be easier if you switch to putting code in a script file. There is provision in the Scripting configuration tab for making or selecting a script file. Then put the name of the script function in the trigger and leave the Send box blank. The function looks like this:


function myTrigger (name, line, wildcards, styles)

-- put your code here

end -- myTrigger


Inside such a function the wildards are table entries in the wildcards variable. eg.


local weaponstats = tonumber (wildcards [1])  -- first wildcard, convert to number

if weaponstats == nil then
  return -- not a number
end -- if

if weaponstats >= 300 then

-- do something

end -- if


Now you don't have to muck around with %1 style wildcards.

You might also find it easier to name your wildcards, like this:



match="(.*)Affects (?<whichstat>(spellpower|intelligence|damroll)) by (?<statvalue>.*?)\."


Now the whole function can look like this:


function myTrigger (name, line, wildcards, styles)

  local whichstat = wildcards.whichstat             -- which stat, eg. spellpower, intelligence etc.
  local statvalue = tonumber (wildcards.statvalue)  -- what the value is, convert to number

  if statvalue == nil then  -- tonumber returns nil if the string cannot be converted to a number
    return -- not a number
  end -- if

  if statvalue >= 300 then

    -- do something

  end -- if

end -- myTrigger


See my video about scripting: http://www.gammon.com.au/forum/?id=10212
Direct link to video: Vimeo: MUSHclient scripting tutorial




Also see this: http://www.gammon.com.au/scripting

That explains about putting scripts into a script file.
Amended on Sat 01 Jun 2019 11:19 PM by Nick Gammon
#18
thanks nick, that may help out a lot.. question however looking at what you posted it seems like i will need a wildcard for each stat i have to compare?, some item will have none others just 1 & some maybe just 2 others could have all 3. Would I need a wildcard for each stat i am comparing? like 1 for damroll one for spellpower and one for intelligence? the statvalue will always be a random number. I just want values for the stats on the items to be equal to or greater then certain numbers.. like if damroll is >= 3000 and intelligence >= 400 and spellpower >= 400 then it would do something ... .... sorry maybe i am just confused or confusing my self.. being starting at ur post trying to figure it out. it makes sense but... Maybe it's cause i am hang up on this line here :
if statvalue >= 300 then

    -- do something
i have no clue why
ex of an item in game
Object 'unique Soratami Seer glittery sword of crack elite epic' is type weapon
Extra flags nolocate unique.
Extra2 flags elite epic
put epic love
Weight is 1, value is 0, level is 466.
Weapon type is sword.
Damage is 40d33(average 680).
Base critical chance is   5.00%.
Damage noun is hit.
Affects constitution by 893.
Affects spellpower by 469.
Affects hp by 11891.
Affects move by 32617.
Affects mana by 12605.
Affects hitroll by 1033.
Affects damroll by 1292.
Affects wisdom by 402.
Affects intelligence by 324.
Affects critical chance by   1.31% percent.


if damnroll was 300o or more and intelligence was 400 or more it would put this in a bag... only on items that have all three stats...
Amended on Sun 02 Jun 2019 02:52 AM by Sephiran
Australia Forum Administrator #19
I was doing a simplified example. I could answer better if you showed examples of the MUD output, with the various stats (you said you might have one, two or three of them).

Maybe show the whole thing you are trying to analyze? I am having to guess from your descriptions. This sort of stuff isn't very clear:

Quote:

is there a way to make it so it only puts the item that's lored in to something or dropped? by name or something? i tried to just have put 1. box but if an item matches on more the one stat it puts not only the item that i'm loring into a box but the other two after it that is in my inv. ex from game


Before you even start to code you want to have in your head a clear logic flow.

[EDIT] I note you added an example while I was typing. Thanks! Perhaps a few more?
Amended on Sun 02 Jun 2019 02:57 AM by Nick Gammon
Australia Forum Administrator #20

What would you get after those lines? In other words, what sort of line indicates the end of those attributes?

Australia Forum Administrator #21
Based on your example, this is the general idea:


<triggers>
  <trigger
   enabled="y"
   match="*"
   name="end_of_affects"
   send_to="12"
   sequence="110"
  >
  <send>

-- turn off most of the triggers
EnableTrigger ("affects", false)
EnableTrigger ("end_of_affects", false)
EnableTriggerGroup ("attributes_group", false)

-- show results

if objectDamage then
  print ("Damage is", objectDamage)
  print ("Average damage is", objectAverageDamage)
end -- if

local damroll      = tonumber (objectStats ['damroll'])
local constitution = tonumber (objectStats ['constitution'])
local spellpower   = tonumber (objectStats ['spellpower'])

-- check if good enough
if damroll and constitution and spellpower then  -- if attributes exist

  if damroll &gt;= 1000 and constitution &gt;= 500 and spellpower  &gt;= 100 then
     print (string.format ("Putting %s in the bag", objectName))
  else
     print (string.format ("Object %s isn't good enough", objectName))
  end -- if

end -- if

</send>
  </trigger>


  <trigger
   match="Affects * by *."
   name="affects"
   send_to="12"
   sequence="100"
  >
  <send>

objectStats ["%1"] = "%2"  -- remember the affect
EnableTrigger ("end_of_affects", true)  -- enable a trigger that matches anything

</send>
  </trigger>


  <trigger
   group="attributes_group"
   match="Damage is *(average *)."
   send_to="12"
   sequence="100"
  >
  <send>

objectDamage = "%1"  -- remember damage
objectAverageDamage  = "%2"  -- and average damage

</send>
  </trigger>

  <trigger
   enabled="y"
   match="Object '*' is type *"
   name="NewObject"
   send_to="12"
   sequence="100"
  >
  <send>

objectStats = {}  -- no stats yet
objectName = "%1" -- remember name
objectType = "%2" -- remember type
EnableTrigger ("affects", true)  -- get ready to receive affects
EnableTriggerGroup ("attributes_group", true)  -- get ready to receive other attributes

</send>
  </trigger>


  <trigger
   group="attributes_group"
   match="Weight is *, value is *, level is *."
   send_to="12"
   sequence="100"
  >
  <send>

-- an example of collecting attributes

objectWeight = "%1" 
objectValue  = "%2"
objectLevel  = "%3"
</send>
  </trigger>

</triggers>


Template:pasting
For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.


What this does is wait for the line "Object '*' is type *" which enables a trigger and a trigger group. Those triggers start matching the incoming attributes (how ever many of them there are) and putting them in a table. Then when the final line comes (a line NOT starting with "Affects") then it can analyze what it found and make a decision.

In this particular case:


Damage is 40d33
Average damage is 680
Putting unique Soratami Seer glittery sword of crack elite epic in the bag
Amended on Sun 02 Jun 2019 03:26 AM by Nick Gammon
#22
Edit sorry i was slow in posting this just realized you posted again before i posted this thanks nick, here is a screenshot of an item that has only two of the stats i want on it so.. i would just drop this one... being lored in game... the best way i could explain what is after all the stats i was not sure how to explain it myself...

https://imgur.com/a/8d9v1lB

Edit sorry if this is a dumb question... confused your last post nick is all triggers? so each one will go under one trigger or all in one? or do i do the script file route? cause i tried that and got
 
Immediate execution
[string "Script file"]:3: unexpected symbol near '<'
Error context in script:
   1 : function myTrigger (name, line, wildcards, styles)
   2 : 
   3*: <triggers>
   4 :   
   5 :   <trigger
   6 :    enabled="y"
   7 :    match="*" 
Amended on Sun 02 Jun 2019 04:12 AM by Sephiran
Australia Forum Administrator #23
Yes, for compactness it is just triggers. I put a link how to use it:

Template:pasting
For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.
Australia Forum Administrator #24
Rather than posting screenshots (which I can't copy and test) please copy/paste the actual text from the window like you did before.
#25
i understand that what i was confused about is for ex:


<triggers>
  <trigger
   enabled="y"
   match="*"
   name="end_of_affects"
   send_to="12"
   sequence="110"
  >
  <send>

-- turn off most of the triggers
EnableTrigger ("affects", false)
EnableTrigger ("end_of_affects", false)
EnableTriggerGroup ("attributes_group", false)

-- show results

if objectDamage then
  print ("Damage is", objectDamage)
  print ("Average damage is", objectAverageDamage)
end -- if

local damroll      = tonumber (objectStats ['damroll'])
local constitution = tonumber (objectStats ['constitution'])
local spellpower   = tonumber (objectStats ['spellpower'])

-- check if good enough
if damroll and constitution and spellpower then  -- if attributes exist

  if damroll &gt;= 1000 and constitution &gt;= 500 and spellpower  &gt;= 100 then
     print (string.format ("Putting %s in the bag", objectName))
  else
     print (string.format ("Object %s isn't good enough", objectName))
  end -- if

end -- if

</send>
  </trigger>


would go in to one trigger alone? or paste all into one trigger? sorry again if this is a dumb question i know this is a simple matter, But simple and me always turns in to complicated... i tried pasting it all under one
 trigger set it to match lore but got this string ["Trigger: "]:1: unexpected symbol near '<'


just seen that u posted before i posted this so here is what the screenshot was of

lore 1.
Object 'unique A citizen autumn pendant of flowering elite epic' is type armor
Extra flags nolocate unique.
Extra2 flags elite epic
Weight is 1, value is 0, level is 463.
Worn on: take neck
Armor class is 13177 pierce, 13137 bash, 13126 slash, and 13177 vs. magic.
Affects dexterity by 420.
Affects constitution by 346.
Affects wisdom by 1116.
Affects intelligence by 962.
Affects strength by 339.
Affects move by 13193.
Affects spellpower by 259.
Affects mana by 10428.

[EX:NESWU][Align: -994][ETL: 35000]
<802574/802574Hp 409832/411332M 462674/462674Mv> 
Australia Forum Administrator #26
Would you please look at that link that I posted twice and follow it? You seem to be ignoring that and trying to guess what to do. There are multiple triggers there and following that link will make all triggers be imported in one operation.

Here it is again:

Template:pasting
For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.
Amended on Sun 02 Jun 2019 04:56 AM by Nick Gammon
#27
it works thanks nick had to lore the sword for some reason before it started working bout my last post i'm sorry that was my bad i was trying load from file but clipboard solve my issue
Amended on Sun 02 Jun 2019 05:45 AM by Sephiran
#28
would it be possible to edit this https://github.com/Aardurel/aard-plugins/blob/master/aard_inventory.xml for other muds? asking for a friend cause i didn't know if it could be done myself... i don't think he means the whole thing just certain parts of it only.. think he is trying to add it to other scripts he has.
USA Global Moderator #29
Oof. Everything is possible within the limits of what other muds support, but Durel's inventory plugin for Aardwolf is 23000 lines long. Even just reading through it to figure out what would need to be changed would take more work than is reasonable if it's not your full time job.
#30
damn did not realize it was that long... might be better to tell him to make his own then if he really wants one... that would be a lot of work 23000 lines long.. wonder how long that took him to make.... jeez