 |
Llohr Apprentice
Joined: 17 May 2005 Posts: 108
|
Posted: Fri Jun 22, 2012 2:36 am
Cleaning up a variable-heavy script with data base variables. |
I have recently decided to try cleaning up a rather variable intensive script with database variables,
and I'm having a little trouble figuring out where to go. I have a script currently that reads my affects
list, which looks like this:
Code: |
You are affected by:
1) Spell: swiftness modifies hitroll by 10 for 47 hours.
2) Spell: swiftness modifies ac by -25 for 47 hours.
3) Spell: wall of thorns modifies none by 0 for 47 hours.
4) Spell: shield modifies ac by -20 for 47 hours.
5) Spell: giant strength modifies strength by 4 for 47 hours.
6) Spell: barkskin modifies ac by -20 for 22 hours.
7) Spell: bless modifies saving-spell by -12 for 47 hours.
8) Spell: bless modifies hitroll by 12 for 47 hours.
9) Spell: divinity modifies saving-spell by -16 for 101 hours.
10) Spell: divinity modifies hitroll by 16 for 101 hours.
11) Spell: invis modifies none by 0 permanently.
12) Spell: enhanced strength modifies strength by 4 permanently.
13) Spell: mental barrier modifies ac by -20 permanently.
14) Spell: thought shield modifies ac by -20 permanently.
15) Spell: flesh armor modifies ac by -20 permanently.
16) Spell: detect bless modifies none by 0 permanently.
17) Spell: song of traveling modifies none by 0 permanently.
18) Spell: magic shelter modifies saving-spell by -300 permanently.
19) Spell: detect evil modifies none by 0 permanently.
20) Spell: detect good modifies none by 0 permanently.
21) Spell: stone skin modifies ac by -40 permanently.
22) Spell: heighten senses modifies none by 0 permanently.
23) Spell: heighten senses modifies none by 0 permanently.
24) Spell: heighten senses modifies none by 0 permanently.
25) Spell: heighten senses modifies none by 0 permanently.
26) Spell: biofeedback modifies none by 0 permanently.
27) Spell: energy containment modifies saving-spell by -20 permanently.
28) Spell: combat mind modifies hitroll by 12 permanently.
29) Spell: combat mind modifies ac by -38 permanently.
30) Spell: minstrelsy modifies hp by 400 permanently.
31) Spell: minstrelsy modifies mana by 400 permanently.
32) Spell: displacement modifies ac by -46 permanently.
33) Spell: story of safety modifies ac by -20 permanently. |
And creates a variable for each spell name, concatenating multiple words, and setting the value to 0, with
a default value of 1. The string "You are affected by~:" resets the class in which the script is contained,
setting all values to 1, and turns on a prompt trigger, which checks specific variables for non-zero values
and recasts the spells, in whatever manner I specify before turning itself off, like so:
Code: |
<trigger name="rsp" priority="290" enabled="false" id="425">
<pattern>~<%n~/%n~(%n~%~)Llohr~(%n~%~)</pattern>
<value>#if (@faeriefire) {} {biobreak Llohr 'faerie fire'}
#if (@pestilence) {} {biobreak Llohr pestilence}
#if (@egowhip) {} {biobreak Llohr ego}
#if (@curse) {} {biobreak Llohr curse}
#if (@blindness) {} {biobreak Llohr blind}
#if (@impairstrength) {} {biobreak Llohr impair}
#if (@aniseed) {} {biobreak Llohr aniseed}
#if (@poison) {} {biobreak Llohr poison}
#if (@banzai) {} {biobreak Llohr banzai}
#if (@biofeedback) {c biofeedback}
#if (@magicshelter) {c 'magic shelter'}
#if (@energycontainment) {c 'energy containment'}
#if (@flesharmor) {c 'flesh armor'}
#if (@thoughtshield) {c 'thought shield'}
#if (@mentalbarrier) {c 'mental barrier'}
#if (@combatmind) {c 'combat mind'}
#if (@displacement) {c displacement}
#if (@enhancedstrength) {c 'enhanced strength'}
#if (@adrenalinecontrol) {c 'adrenaline control'}
#if (@ectoplasmicform) {#if (@spiritform) {#if (@passdoor) {#if (@wraithform) {c 'ectoplasmic form'}}}}
#if (@inertialbarrier) {#if (@protection) {c 'inertial barrier'}}
#if (@intellectfortress) {c 'intellect fortress'}
#if (@neutralbarrier) {c neutral}
;#if (@unholybarrier) {remove cobra;wear cobra}
;#if (@fly) {remove figurine;wear figurine}
#if (@stoneskin) {remove neutron;wear neutron}
#if (@storyofsafety) {remove boots;wear boots}
;#if (@detectmagic) {wear light}
#if (@heightensenses) {heighten}
#if (@sneak) {~sneak}
#if (@shadowform) {sform}
#if (@haste) {#if (@flurry) {#if (@fervour) {#echo MARK}}}
#t- aff1
#t- aff2
#t- rsp
;#if (@auto) {wear ivory}</value>
</trigger> |
As you might imagine, this script creates scores of variables, and I thought it might all be a great deal neater if I used a database
variable. I've managed a trigger to set the values fairly easily, which looks like this:
Code: |
<trigger priority="4360" id="436">
<pattern>%n~) Spell~:%s([a-z ]) modifies</pattern>
<value>#addkey AffectsList %1 1
;#show affects recording fired</value>
</trigger>
|
And I believe I've found a way to check specific keys and recast as necessary, like so:
Code: |
<trigger name="ASC" priority="4390" enabled="false" id="439">
<pattern>~<%n~/%n~(%n~%~)Llohr~(%n~%~)%n~/%n</pattern>
<value>#if (@AffectsList."combat mind") {c combat} {#show Combat Mind is up~!}
#t- ASC</value>
</trigger> |
But I haven't figured out how I can set all the value of every key in a database variable at the same time.
I could fairly easily set the specific keys to 1 manually, but that seems like a lot of wasted keystrokes
when a single command should be able to do it. If anybody has a solution to that, any suggestions to
streamline the script, or sees a problem with what I have so far, I'd be happy to hear them! |
|
|
 |
Llohr Apprentice
Joined: 17 May 2005 Posts: 108
|
Posted: Fri Jun 22, 2012 7:04 am |
Well, with some experimentation, I've come up with a (very) sloppy way to do what I want:
Code: |
<trigger priority="4370" id="437">
<pattern>You are affected by~:</pattern>
<value>$AffectsReset = %list(%expanddb(@AffectsList,",",","),",")
#forall $AffectsReset {#addkey AffectsList %i 1}
#t+ ASC
</trigger> |
This does set all of the values in the variable AffectsList to 1, but it also creates new keys, 0 and 1, and gives
them a value of 1. Actually, it sets those 2 keys to 1 over and over, since there are a lot of 0s and 1s in the
string list.
This is because nothing I tried was quite able to strip everything out of the string list except the keys from the
variable referenced. I've searched for some command to return all of the keys from a database variable, or a
command to set all of the values in a database variable simultaneously (without having to specify each individual
key) but have not managed to come up with anything. Even the ability--or proper syntax?--to use a wildcard in
place of a key in addkey or some other database modifying variable would make this simpler and cleaner.
So, I welcome any insights that will improve this script. Also welcome is any assurance that I'm not bound for
scripter's hell for writing something so very ugly.
After messing with syntax here for a while, trying to come up with something that would work, my "AffectsList"
variable suddenly took on the value held by $affectcheck (i.e. all of the spell names, with a 0 or 1 between each
and a few extra at the beginning, displayed as a valueless string list but still called a database). I'm going to
lean toward package corruption, as it's been nearly 24 hours since I exported and imported this session. |
|
|
 |
Llohr Apprentice
Joined: 17 May 2005 Posts: 108
|
Posted: Fri Jun 22, 2012 7:04 am |
Well, as long as I'm going on and on about this, I'd like to pose a related question.
I've created an alias:
Code: |
<alias name="check" id="442">
<value>#pr ./Affects/AffectsCheck.%-1 "What action would you like to take if this affect is missing?"</value>
</alias> |
And changed the trigger on my prompt to:
Code: |
#loopdb @AffectsList {%if(%iskey(@AffectsCheck,%key),%if(%val=1,@AffectsCheck.%key))} |
Which checks each key in AffectsList to see if it is both non-zero and has a matching key in AffectsCheck. If
both of those conditions are met, it sends the value of that key in AffectsCheck.
So I can type in "Check heighten senses" and when the dialog box prompts me to enter a value, I enter in
"heighten". Then, if "heighten senses" doesn't appear in my affects list, "heighten" is sent, effectively recasting
the spell.
This works, the problem is, I'm getting a blank line for every value in "AffectsList." So I see this:
Code: |
You are affected by:
1) Spell: renewal of the gladiator modifies ac by -50 for 20 hours.
2) Spell: renewal of the gladiator modifies hitroll by 15 for 20 hours.
3) Spell: renewal of the gladiator modifies damroll by 15 for 20 hours.
4) Spell: strength of superman modifies strength by 25 for 20 hours.
5) Spell: strength of superman modifies damroll by 50 for 20 hours.
6) Spell: song of freedom modifies none by 0 for 20 hours.
7) Spell: restoration of zandramas modifies none by 0 for 20 hours.
8) Spell: arcane focus modifies focus by 250 for 20 hours.
9) Spell: weed shield modifies ac by -20 for 50 hours.
10) Spell: crusade modifies damroll by 6 for 30 hours.
11) Spell: combat mind modifies ac by -38 permanently.
12) Spell: combat mind modifies hitroll by 12 permanently.
13) Spell: haste modifies none by 0 for 15 hours.
14) Spell: barkskin modifies ac by -20 for 75 hours.
15) Spell: pass door modifies none by 0 for 40 hours.
16) Spell: armor modifies ac by -20 for 50 hours.
17) Spell: immortal blessing modifies mana by 1000 for 50 hours.
18) Spell: immortal blessing modifies hp by 1000 for 50 hours.
19) Spell: heighten senses modifies none by 0 permanently.
20) Spell: heighten senses modifies none by 0 permanently.
21) Spell: heighten senses modifies none by 0 permanently.
22) Spell: heighten senses modifies none by 0 permanently.
23) Spell: fly modifies none by 0 permanently.
24) Spell: invis modifies none by 0 permanently.
25) Spell: star drain modifies mana by 4959 for 214 hours.
26) Spell: star drain modifies hp by -1983 for 214 hours.
27) Spell: swiftness modifies hitroll by 10 for 8 hours.
28) Spell: swiftness modifies ac by -25 for 8 hours.
29) Spell: wall of thorns modifies none by 0 for 8 hours.
30) Spell: divinity modifies saving-spell by -16 for 108 hours.
31) Spell: divinity modifies hitroll by 16 for 108 hours.
32) Spell: shield modifies ac by -20 for 8 hours.
33) Spell: giant strength modifies strength by 4 for 8 hours.
34) Spell: bless modifies saving-spell by -12 for 8 hours.
35) Spell: bless modifies hitroll by 12 for 8 hours.
36) Spell: enhanced strength modifies strength by 4 permanently.
37) Spell: mental barrier modifies ac by -20 permanently.
38) Spell: thought shield modifies ac by -20 permanently.
39) Spell: flesh armor modifies ac by -20 permanently.
40) Spell: detect bless modifies none by 0 permanently.
41) Spell: song of traveling modifies none by 0 permanently.
42) Spell: magic shelter modifies saving-spell by -300 permanently.
43) Spell: detect evil modifies none by 0 permanently.
44) Spell: detect good modifies none by 0 permanently.
45) Spell: stone skin modifies ac by -40 permanently.
46) Spell: biofeedback modifies none by 0 permanently.
47) Spell: energy containment modifies saving-spell by -20 permanently.
48) Spell: minstrelsy modifies hp by 400 permanently.
49) Spell: minstrelsy modifies mana by 400 permanently.
50) Spell: displacement modifies ac by -46 permanently.
51) Spell: story of safety modifies ac by -20 permanently.
<17832/17832(100%)Llohr(100%)24253/24253 DR/HR: 467/640 AC: -2543 Gold:433,336>
<17832/17832(100%)Llohr(100%)24253/24253 DR/HR: 467/640 AC: -2543 Gold:433,336> |
I can remove the blank lines with gagspace, but what can I do to prevent the sending of blank lines
entirely? Also, if I want to remove and rewear a piece of equipment, I can set the value of the corresponding
key to "remove eq;wear eq" but I can't make it parse the semicolon, it sends that exactly, but I have
to hit enter for the second part, "wear eq", to actually take effect. Is there any way around that short
of making a separate trigger? Is there any way to make the value being sent to the mud in this manner
function as an alias, assuming such an alias exists? |
|
|
 |
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Fri Jun 22, 2012 1:01 pm |
[edited]On your first question, you were looking for the %dbkeys() function. You may also want to know the %dbvalues() function for the future. And the best way to do the loop is with #LOOPDB
|
|
|
 |
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Fri Jun 22, 2012 1:11 pm |
The problem in your AffectsCheck script is that you are trying to execute %if() as a command. You can't start a command statement with a function or a variable (basically, anything that starts with % or @).
This code
Code: |
#loopdb @AffectsList {%if(%iskey(@AffectsCheck,%key),%if(%val=1,@AffectsCheck.%key))} |
should look more like
Code: |
#loopdb @AffectsList {#IF (%iskey(@AffectsCheck,%key) AND %val=1) {#SOMECOMMAND @AffectsCheck.%key}} |
What exactly do you want to do with the @AffectsCheck value? |
|
|
 |
Llohr Apprentice
Joined: 17 May 2005 Posts: 108
|
Posted: Fri Jun 22, 2012 5:38 pm |
So using
Code: |
$AffectsReset = %list(%dbkeys(@AffectsList))
#forall $AffectsReset {#addkey ./Affects/AffectsList %i 1} |
is the most efficient way to reset all the keys in a variable to the same thing?
I guess I wasn't that far off then, which surprises me greatly, using %dbkeys
is certainly much cleaner than the code I'd mangled into place.
Or did you mean that I should use #loopdb to accomplish that somehow?
I really wanted to, but it seemed like most of the functions that deal with
db variables simply return keys or values, rather than changing them. I
assume that if I tried some form of #loopdb @AffectsList (%dbkeys/etc
I wouldn't get where I wanted to go.
I have not fully grasped the function vs command difference yet, as may be
obvious from my use of %if, I am quite surprised that it worked perfectly
considering that I'd done it wrong.
As to your question, I want to send the value of @AffectsCheck.%key to the mud,
it works as I had it, but I wondered if some other method would be more condign.
The @AffectsCheck variable contains all of the spells that I want to check my--
mud generated--affects list for, and the key of each value contains the action to
take if a particular spell or affect is missing from that list, the problem I am
having is that I haven't figured out a way to take multiple actions if necessary.
Say, instance, I have a key in AffectsCheck called "stone skin." The action I want
to take if that key in AffectsList = 1 is "remove neutron;wear neutron." I can set
the value of that key to "remove neutron;wear neutron," but it only executes the
first action, the mud requires another carriage return before the "wear neutron"
is processed. I can change the value if true to "#send @AffectsCheck.%key" but
that works exactly the same. I have on occasion wished for some way to get the
value of a variable to parse as an alias, but I haven't had any luck with that yet. |
|
|
 |
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Fri Jun 22, 2012 6:24 pm |
No...%dbkeys() already produces a stringlist so you don't even need %list. Instead of:
Code: |
$AffectsReset = %list(%dbkeys(@AffectsList))
#forall $AffectsReset {#addkey ./Affects/AffectsList %i 1} |
do this:
Code: |
#forall %dbkeys(@AffectsList) {#addkey ./Affects/AffectsList %i 1} |
Or, to do it with #LOOPDB:
Code: |
#LOOPDB @AffectsList {#addkey ./Affects/AffectsList %key 1} |
The reason your %if() worked is because it worked that way in Zmud, and Zugg mostly left that working just for backwards compatibility. But it does not always work, and it is not guaranteed to continue working in future releases of Cmud. A function is designed to return a value which can be used within some other command statement. Yes, the proper way to send the value of @AffectsCheck.%key to the mud is with the #SEND command. Simply putting the variable and expecting it to send a command to the mud may or may not work in every instance, and is a deprecated Zmud practice.
If the value of the key is "remove neutron;wear neutron", #SEND {@AffectsCheck.%key} should properly parse the key and send it to the mud as two commands. |
|
|
 |
Llohr Apprentice
Joined: 17 May 2005 Posts: 108
|
Posted: Fri Jun 22, 2012 7:04 pm |
I'd have sworn I tried that #loopdb method exactly, without success, but I imagine I simply mangled the syntax.
The #SEND {@AffectsCheck.%key} is still sending the single line "remove neutron;wear neutron" which requires
a carriage return to complete. Also tried #send (AffectsCheck.%key) mostly out of curiosity, it behaved exactly
the same.
Script XML so far:
Code: |
<class name="Affects" id="435">
<trigger priority="4360" id="436">
<pattern>%n~) Spell~:%s([a-z ]) modifies</pattern>
<value>#addkey ./Affects/AffectsList %1 0
</value>
</trigger>
<trigger priority="4370" id="437">
<pattern>You are affected by~:</pattern>
<value>#forall %dbkeys(@AffectsList) {#addkey ./Affects/AffectsList %i 1}
#t+ afreset</value>
</trigger>
<trigger name="afreset" priority="4390" enabled="false" id="439">
<pattern>~<%n~/%n~(%n~%~)Llohr~(%n~%~)%n~/%n</pattern>
<value>#loopdb @AffectsList {#if (%iskey(AffectsCheck,%key) AND %val=1) {#SEND {@AffectsCheck.%key}}}
#t- afreset</value>
</trigger>
<alias name="check" id="442">
<value>#pr ./Affects/AffectsCheck.%-1 "What action would you like to take if this affect is missing?"</value>
</alias>
<var name="AffectsList" type="Record" sorted="1" id="449">
<value>arcane focus=1|armor=1|barkskin=0|biofeedback=0|bless=0|combat mind=0|crusade=1|detect bless=0|detect evil=0|detect good=0|displacement=0|divinity=0|energy containment=0|enhanced strength=0|flesh armor=0|fly=0|giant strength=0|haste=1|heighten senses=0|immortal blessing=1|invis=1|magic shelter=0|mental barrier=0|minstrelsy=0|pass door=1|renewal of the gladiator=1|restoration of zandramas=1|shadow form=0|shield=0|sneak=0|song of freedom=1|song of traveling=0|star drain=1|stone skin=1|story of safety=0|strength of superman=1|swiftness=0|thought shield=0|wall of thorns=0|weed shield=1</value>
<json>{"arcane focus":1,"armor":1,"barkskin":0,"biofeedback":0,"bless":0,"combat mind":0,"crusade":1,"detect bless":0,"detect evil":0,"detect good":0,"displacement":0,"divinity":0,"energy containment":0,"enhanced strength":0,"flesh armor":0,"fly":0,"giant strength":0,"haste":1,"heighten senses":0,"immortal blessing":1,"invis":1,"magic shelter":0,"mental barrier":0,"minstrelsy":0,"pass door":1,"renewal of the gladiator":1,"restoration of zandramas":1,"shadow form":0,"shield":0,"sneak":0,"song of freedom":1,"song of traveling":0,"star drain":1,"stone skin":1,"story of safety":0,"strength of superman":1,"swiftness":0,"thought shield":0,"wall of thorns":0,"weed shield":1}</json>
</var>
<var name="AffectsCheck" type="Record" id="450">
<value>combat mind=c combat|heighten senses=heighten|mental barrier=c mental|shadow form=sform|sneak=sneak|stone skin=remove neutron ; wear neutron</value>
<json>{"stone skin":"remove neutron;wear neutron","mental barrier":"c mental","shadow form":"sform","sneak":"sneak","heighten senses":"heighten","combat mind":"c combat"}</json>
</var>
</class>
|
I suppose I could just add
Code: |
#if (@AffectsList."stone skin") {remove neutron;wear neutron} |
to my prompt trigger, but I'm attempting to put together a very user-friendly package that doesn't require manual trigger editing by people who don't know much about triggers.
I also forgot to mention that changing the incorrect %if to #if got rid of the extra blank lines being sent. Huge thanks for all the help! |
|
|
 |
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Fri Jun 22, 2012 7:39 pm |
#SEND just sends the text directly to the mud. If you want the semi-colons to be parsed you need to use #EXECUTE.
|
|
|
 |
Llohr Apprentice
Joined: 17 May 2005 Posts: 108
|
Posted: Fri Jun 22, 2012 8:37 pm |
Awesome, that works perfectly. Thank you both!
|
|
|
 |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|