Curing System Tutorial.

by Thorgal

Back to Combat Guide.

Thorgal2005-01-22 08:59:52
Here's a tutorial I wrote for building a queued curing from scratch, it's built to teach completely inexperienced people, so it doesn't use overcomplicated functions, however it's the base for a highly effective (and especially fast) curing. I focused on speed, cause I only got a P2 350mhz myself. But as said, it's just the basis, the foundation.

__________________________
--------------------------
Advanced Curing Magicks
__________________________
--------------------------





Introduction
-------------

This illustrous tome contends a guide to work with the advanced magicks designed to survive bombardments of afflictions without it hampering your offensive prowess.

I imagine many of you that fight, heard about curing magics that queue your afflictions, to make sure the most important ones are cured first. With this post, I will try to teach those interested how to make your own queued curing based on variables, because I am of the belief that a warrior can never become great if he did not make his own curing magicks.

Before you go on, make sure you turn off your reflexes.


Goals of Queueing
------------------

The goal and purpose of magics like this, is to have your subconsciousness store every affliction, every state and every defense and use that information to get rid of the negative states and afflictions as fast as possible, and pick the important ones first, working its way down to the least important ones. Not only will this make sure you cure all of your afflictions, but it enables you to choose which to cure first depending on your kind of attacks, or wether you want to cure defensively or offensively.


Different Curing Focuses
-------------------------

1) Offensive curing: This will make sure the afflictions that hamper your offense will be cured first, depending on the class, these will mostly be Paralysis, Peace, Confusion, Clumsiness, Vernalius, etc.

2) Defensive curing: This will prioritise the afflictions that endangerous your chance of survival, some examples are Masochism, Sunallergy, Sensitivity, Healthleech, various vomiting diseases, Recklessness, etc.

Depending on your fighting style and the enemies you mostly fight, you can choose either or create some sort of balance between them.


Simplicity and Speed
---------------------

If one wants to create his own curing magicks, he should remember, no matter how high his prowess is, he should always keep in mind to seek the most simple ways to solve a problem or create an automation. If you can get the wanted results in one line and with one variable, don't use more than one, just because it might look fancier. Another example, if you can do something with simple variables, don't use stringlists, though they will take less variables, the coding needed to use these stringlists will become extraordinarily messy and unecessarily complicated once you come to the actual curing and queueing. Thus we will keep to simple variables, which will work perfectly and faster, not to mention much simpler to use.

Then we come to reflexes, the more reflexes your mind has stored, the slower they will come into effect. One of your goals will be to capture events in the least reflexes possible, for this we will mainly use wildcards, indicted by and ONLY * or (*). we will never ever use insane stuff like %1, %2, %d, or %w IN THE PATTERN, it's fine to use in the value. These diabolic characters will slow down the processing of your mind to aeonic proportions. The "IF" function will also slow down your processing, but not by far in such an extend as reflexes. In many cases, it will cut down the amount of reflexes by such sheer amounts, that you will process 5 or even 10 times faster than when you would have used various reflexes.


Order of all Things
--------------------

Very important to prevent total chaos, is order in your classes. Your mind will contend settings for Offense, Defense, Traveling, Social, Curing, enchantments, etc. The way you want to organise your mind is up to you, but it is better to create too many classes than to little, especially at the start. For example you could start with making Curing folder, in that class you can make an Afflictions class, in which you place all your affliction variables (paralysis, peace, stupidity, etc). Then you can make another class in which you place all your defense variables (frost, fire, kafe, insomnia, etc).


First Steps and Basic Variables and Aliases.
---------------------------------------------

I will not babyfeed you exactly every piece of information needed to start working on it, less than teach it to you in rough lines, but I will still be clear enough so anyone that had never any experience in these magicks, can understand it and create it for himself.

1) Create a variable for every affliction you can think of, HELP AFFLICTIONS is a very good source for this, and set its default to 0. Place all these variables into a seperate class.

2) Create a variable for every defense: quicksilver, sixthsense, frost, fire, rebounding, insomnia, kafe, etc. Set its default to 0, and place these into a seperate class.

3) Create a variable for every state: sprawled, stunned, unconscious and asleep. Set their defaults to 0 and place them into a seperate class.

4) Create a variable for herbbalance, salvebalance and exlixirbalance...set their defaults to 1.

5) Create an alias for every herb, salve (mendarms, mendlegs, mendhead, regenarms, regenlegs, etc), pipe and elixir.


Needed Reflexes and Messages
-----------------------------

The next matter is more complicated, for as stated in a previous chapter, you have to capture every possibility in the smallest amount of reflexes possible, every of the above variables have to get set to true (1) or to false (0). In some cases, variables can have more than two states.

You will need to gather every single message even slightly relating to afflictions, states or defences and have those messages give the relating variable the correct value.

Examples:

--> #trigger {Hmmmm. Why must everything be so difficult to figure out?} {stupidity=1}.
--> #trigger {You aren't such a complete idiot anymore.} {stupidity=0}.

--> #trigger {Your insomnia has cleared up.} {insomnia=0}.
--> #trigger {You clench your fists, grit your teeth, and banish all possibility of sleep.} {insomnia=1}.

--> #trigger {You sit yourself down.} {sprawled=1}.
--> #trigger {You stand up and stretch your arms out wide.} {sprawled=0}.

etc etc...

Now we come to wildcards, cause messages that are very similar to eachother, like limb-breaks would take up reflexes for each limb apart, so we stomp them together into one:

--> "You watch, in horror, as your (*) arm shrivels up and becomes useless." will execute:
#if ("%1"="left") {leftarm=1}
#if ("%1"="right") {rightarm=1}


--> "You stumble as your (*) leg shrivels into a useless appendage." will execute:
#if ("%1"="left") {leftleg=1}
#if ("%1"="right") {rightleg=1}

etc...

Herb-, Salve and Elixirbalance
------------------------------

Next you will need to keep track of your balances, for this, you just trigger the messages you see when eating a herb or applying a salve to "herbbalance=0" and "salvebalance=0", and trigger the messages you see when you regain either balances to "herbbalance=1" and "salveblance=1".
Next you make an alias for each herb that looks like this:

"yarrow" ->
outr yarrow
eat yarrow
herbbalance=0.5
#alarm +2 {#if @herbbalance="0.5" {herbbalance=1}}

"mendarms" ->
apply mending to arms
salvebalance=0.5
#alarm +2 {#if @salvebalance="0.5" {salvebalance=1}}

This will make sure the balances get reset to 1 when amnesia, stupidity or anything at all causes a failure of action. Because if the alias gets fired, the balance gets set to 0.5, when you eat it, it gets set to 0, if the eating does not go through cause of stupidity, amnesia, or anorexia, it'll get reset to 1, cause it's still 0.5, hence the alarm.

For stupidity we make something different:

"pennyroyal" ->
outr pennyroyal
eat pennyroyal
herbbalance=0.5
#alarm +1 {
#if @herbbalance="0.5" {
herbbalance=1
#if @stupidity=1 {herbqueue}
}
}

Here the queue gets checked again to make sure you keep trying to cure it untill it's cured.

etc...

Queueing Magicks
-----------------

Next comes the vital part of the curing, the heart and core of the system, the queues, the actual executing of the cures.

A queue is nothing more than an alias that checks each variable related to it and act accordingly to that, for example, it'll think: "Am I paralysed? Yes? I better focus body then!" or it'll think: "I'm paralysed, but I'm impatient as well, I cannot focus! The horror! -aaaaargh-"......-cough-.

Anyway, you will make a queue for every kind of balance, but let's start with just herbbalance, thus the herbqueue. For this, we use the IF-functions, which thinks like: "If paralysis is 1 -> focus body, if not, continue."

An example of a herbqueue would look like this:

#If (@herbbalance=1 and @anorexia=0 and @asleep=0 and @stunned=0 and @aeoned=0) {#if stupidity=1 {pennyroyal} {#if @peace=1 {reishi} {#if @lovers=1 {galingale} {etc..}}}}

Remember, for every bracket you open, you have to close it at the end of the queue, and this queue will think: If I'm not asleep, not anorexic, not stunned and not aeoned, I check for stupidity, if I'm stupid, I will eat pennyroyal, if I'm not stupid, I will check for peace, etc". That's how it will go down your entire queue, add a bracket and an IF for every affliction.

An example of a salvequeue would look like this:

#if (@salvebalance=1 and @slickness=0 and @asleep=0 and @stunned=0 and @aeoned=0) {#if @leftarm=1 {mendarms} {#if @leftarm=2 {resarms} {#if @leftleg=1 {mendlegs} {etc...}}}}

The process is the same as with the herbbalance.

A smokequeue would look different, because there is not balance to smoking a pipe:

#if @asthma=0 {
#if @masochism=1 {coltsfoot}
#if @anorexia=1 {coltsfoot}
etc...
}

But note, you cannot smoke coltsfoot off herbbalance. Tho it won't throw you off herbbalance when smoked.

You will fire these queues at every affliction message, balance regaining message and at every related cure message. When you wake up, get unstunned, become conscious again, you'll check all queues at once. When you cured anorexia you will check your herbqueue and elixirqueue, when you cured slickness you will check the salvequeue, when you cured asthma, you will check the smokequeue, etc.



Anti-illusion and Speeding up Performance
------------------------------------------

These two topics overlap, because by protecting your messages against illusions in a special way, you will magnify your processing speed by an enormous amount. First of all you will gather all messages that are preceded by an attack into one large class and have your prompt "(*)h, (*)m, (*)" for example, disable the class as well. Like "#t- afflictionsclass". Next you will gather all assault messages, be it a slash, jab, swing, glyphs, runes, etc. Every of these messages will ENABLE the afflictions class, using "#t+ afflictionsclass".

Once you've done this, these messages will only become accepted when they are preceded by an attack, -AND- you will have a large reduce in always active reflexes, improving your processing greatly.

Create a failsafe, that if you've eaten a herb without effect, sets all the afflictions cured by that herb to 0. (not going into detail on this, very complicated, ask me personally if ya want to know).



Addendum
---------

All the previous information is basically all you need to start working on your curing, undoubtedly you will encounter many problems, but with the knowledge gained from succeedingly coding the above, you will be able to fix them, if not, there are many ways of getting solutions to your problems on forums or from friends. If you have any questions about this tome, leave me a message or send me a tell.
Unknown2005-01-22 09:14:17
Going
#VARIABLE VarName X
is a much better way than going
VarName=X
when specifying variable values. This is because sometimes, when you do the latter, it create another variable no matter if it already exists -- which renders systems relatively useless,
Unknown2005-01-22 10:24:14
Remember all you new system-builders, the #WAIT command is the devil. Stay far far away from it. It will devour your children.
Flow2005-01-22 10:25:19
They fixed it in 7.05. It just pauses the function it's in, not the whole thing.
Devris2005-01-22 10:54:53
Ok, lets try this...

reads the post - "make trigger for each affliction...set this....set that"

*head explodes*



j/k...will have to read more in depth I guess
Unknown2005-01-22 11:05:42
No Flow. #WAIT is fine for aliases. Do NOT put #WAIT into a trigger, ever, for any reason.

QUOTE
The #WAIT Command

Ahh, the dreaded #WAIT command.  This is probably the most heavily abused command in zMUD, and the cause of many scripting problems.  Early versions of zMUD did not have the #ALARM command, so only the #WAIT command could be used.  The general rule of thumb now is: DO NOT USE #WAIT UNLESS YOU MUST!  Repeat this to yourself 10 times.

OK, if you promise not to use the #WAIT command, I'll go ahead and tell you how it works and what it is really used for.  The #WAIT command is used for adding delays to loops in zMUD.  That's all.  Any other time delay can be accomplished using the #ALARM and Trigger Wait condition.

So, if you wanted to send the numbers 1-5 to the MUD with a one-second delay between each number, you would do this:

#LOOP 1,10 {%i;#WAIT 1000}

There is no easy way to do this using the #ALARM command, so you are allowed to use #WAIT for this.  Do NOT use #WAIT within a trigger!!

Repeat: DO NOT USE #WAIT WITHIN A TRIGGER!  Why?  Here is a simple example:

#TRIGGER {You lose concentration} {#WAIT 5000;recast spell}

Now, we all know you can do this using a Wait condition like this:

#TRIGGER {You lose concentration}
#CONDITION {} {recast spell} {Wait|Param=5000}

or you could use an alarm like this:

#TRIGGER {You lose concentration} {#ALARM +5 {recast spell}}

But, since we are talking about the evils of the #WAIT command, lets look at the #WAIT example.  If you run it, it seems to work.  So what is the problem?  What happens if you get the text twice before the 5 seconds is over.  For example:

You lose concentration
<3 seconds later>
You lose concentration

Perhaps you tried to execute a spell twice?  Now, if Windows was a perfect system, what we expect to happen is that the command "recast spell" is sent 5 seconds after the first text, then sent again 5 seconds after the second text.  But this isn't what happens.  Because of how Windows works (as we'll see in a minute), you get the command "recast spell" sent twice, 8 seconds after the initial text (the 3 second delay between the text plus the 5 second delay in the #WAIT command).

So what happened?  Why did the #WAIT command from the first text get displayed 8 seconds later along with the second one?  Well, the #WAIT command tells Windows to pause for the given amount of time.  But Windows continues to process messages (to avoid freezing the application).  3 seconds later you get the second message, and this causes the #WAIT command to run again, pausing Windows for 5 seconds.  But Windows only has a single execution thread by default.  So, while that second command is waiting for 5 seconds, the original wait command is also waiting.  When the second command is done, it then returns to the first command, which notices that more than 5 seconds is up and executes.  So, both triggers wait the full 8 seconds.

If zMUD was multi-threaded, this wouldn't be a problem.  Each #WAIT command could run in a separate thread and then they wouldn't interfere.  But multi-threaded programs are *very* complex to write, and zMUD was originally written before threads were available.  In particular, different threads cannot access the same resource without complex locking and synchronization, and the screen output is one of these resources.  Trying to resolve the synchronization problem so that each thread could write to the screen would be enormously difficult.

So, just don't worry about any of this technical jargon.  Just stop using the #WAIT command and start using #ALARM and Trigger Wait states instead.  You're scripts will work a lot better then!

Thorgal2005-01-22 11:23:05
QUOTE(Zaltan @ Jan 22 2005, 11:14 AM)
Going
#VARIABLE VarName X
is a much better way than going
VarName=X
when specifying variable values. This is because sometimes, when you do the latter, it create another variable no matter if it already exists -- which renders systems relatively useless,
33520



Nope, never creates new variables unless the existing variable is placed into a disabled class, to which of course is no point to do, but it doesn't really matter, I just use varname=blah cause it's shorter and simpler.
Lisaera2005-01-22 11:58:01
I like it. I'm pinning it.

Down with the #WAIT devil!
Unknown2005-01-22 14:13:02
QUOTE(Thorgal @ Jan 22 2005, 06:23 AM)
Nope, never creates new variables unless the existing variable is placed into a disabled class, to which of course is no point to do, but it doesn't really matter, I just use varname=blah cause it's shorter and simpler.
33562



I agree with Zaltan. Happens to me a lot, even when the folder isn't disabled. I switched to the #VAR syntax and have had a lot fewer problems with it. It's one of zMUD's many little quirks.
Thorgal2005-01-22 14:58:25
-shrug- In nearly three years I've never had any problems with that.
Unknown2005-01-22 15:38:12
My GOD man. You're a genius! Thank you so much!

Daniel
Unknown2005-01-23 10:02:48
QUOTE(Thorgal @ Jan 23 2005, 03:58 AM)
-shrug- In nearly three years I've never had any problems with that.
33616


Maybe it just happens to some zMUDs, depending on certain enviroments or something.
Devris2005-01-31 14:57:19
I'm a bit confused.

I set up the various alias for the afflictions and then for the status's/cures. All set to make up my herbque and such, but stuck there.


How do I set it up so the queue is actually in game, and fires off at each times I need it to check for afflictions. I typed up the entire order I want in word (set up the whole #IF statement) but how do I import to zmud?
Thorgal2005-01-31 15:38:48
Just make an alias called herbqueue, copy the stuff from word, and paste it into the value of that alias. Then trigger the various messages to that alias.
Unknown2005-02-12 16:25:53
nice tutorial!
medheriadh2005-02-18 14:25:27
Nice and simple tutorial. You explained the basics very well, and the way to control herb and salve balance is very elegant (that alarm to set it back to 1 is cool).

However, just one observation:

QUOTE(Thorgal @ Jan 22 2005, 09:59 AM)
An example of a herbqueue would look like this:

#If (@herbbalance=1 and @anorexia=0 and @asleep=0 and @stunned=0 and @aeoned=0) {#if stupidity=1 {pennyroyal} {#if @peace=1 {reishi} {#if @lovers=1 {galingale} {etc..}}}}



This is *not* a queue. This is just a set of nested if-then-else clauses, even though it works equally fine. The downside of this approach is that if a new affliction is created, you have to edit your "herbqueue" alias to include it.

A standard queue can be implemented by keeping all aliases to cure your afflictions in a string list, ordered by priority, and creating aliases to put something in the list and remove them.

Whenever a new affliction is created in Lusternia, you just create a new alias for the cure; you don't need to edit your "herbqueue" alias, which can be dangerous and produce new bugs.

Also, you forgot to mention a "diagnose backup", in which your affliction variables are updated whenever you do DIAG. Very handy for things like angel or demon afflictions, because you don't know what you have been aflicted with until secondary symptoms appear (and some afflictions won't give that).
Thorgal2005-02-18 16:42:23
I could give two shits smile.gif, a queue is a row, in IRE's case, the definition of a queue is simple: tracking your afflictions, and curing them in priority. Your example is exactly what it is, a stringlist, just happens to be a queue if you use it to cure afflictions.
Unknown2005-02-25 17:20:59
Yes after you read this post you can all snicker or laugh out loud. I won't feel bad as it's probably a stupid question but here goes.


In the tutorial you say

QUOTE
5) Create an alias for every herb, salve (mendarms, mendlegs, mendhead, regenarms, regenlegs, etc), pipe and elixir.


My question is this. That confuses the hell out of me. do I make an alias mendarms and so forth? Secondly for the pipes do I make an alias saying Pipe89826 or whatever it is or?

Yes it's probably a stupid question but as i've said on other topics, I'm like a blind idiot trying to get out of a room with no doors when it comes to this stuff.
Soll2005-02-25 17:33:11
read wrong. tongue.gif
Laysus2005-02-25 19:06:25
Useful for ironing out a few kinks in my own system, even if I have to convert everything to it's nearest equivalent in AL biggrin.gif

Thanks muchly.