Combat Systems

by Unknown

Back to Mechanic's Corner.

Unknown2006-10-05 22:56:09
I see a lot of thing about combat systems, and healing systems and other systems for things like zMUD etc.

How does one make them?

What I have in terms of stuff like that is just setting a particular target, then a quick click that punches in "CAST BLAST Target", which dysolis helped me with.

Aside from that, I have NOTHING.

I see people always talking about these great systems and such... How do they work? What is involved in them?

I mean for a healing system would it involve something like:
(forgive me for not knowing the language of Coding)
something on screen appears to the likes of:
Hmm, why must everything be so difficult to figure out? (just got stupidity)
somehow insert command: pulling pennyroyal from rift, keep sending comand until thing that appears "you pulled the pennyroyal"
next command involves EAT PENNYROAYL

I don't get how to write that.
With zMUD, which is what I have, what's the difference between aliases, triggers etc.?

To put it bluntly and plainly.
IT'S ALL GREEK TO ME!!

Now for the question:
How does one actually go about learning and making a system?

Basic tutorial is good.

Things are easier when given in step-by-step ways and examples.
Ashteru2006-10-05 23:08:07
Triggers are basically something that catch lines, and if they catch them, they react to it.
Aliases are things that can execute a command, like act does "abjure cosmicfire target"
Variable store values.

So, in your example, you could do


trigger: Hmm, why must everything be so difficult to figure out?
then, store it in a variable
afflictionlist = stupidity.
and then, after that, execute an alias
afflictionscan
in which you'd check for all afflictions (with ifs) and then react to it accordingly.
Laysus2006-10-06 00:46:38
Shorlen2006-10-06 05:17:59
QUOTE(Fireweaver @ Oct 5 2006, 06:56 PM) 339146
Question.

Well, first let me explain why they are hard.

An extremely basic system will eat pennyroyal the moment you get a stupidity afflict message, or apply mending the minute you break your legs. The problem with this is that if you just used a salve, you are "off salve balance," meaning, if you then break your leg again and try to apply mending, the salve won't work. A system like that won't realize it didn't successfully apply mending either, and so won't cure your broken leg. If you are hit by, say, a timed druidic demesne, you at afflicted with many things at once. If your system doesn't remember what you were hit with, it won't cure you of your afflicts as you regain the herb balance to do so.

Also, when you are aeoned or sapped, you do not want to spam cures as you are afflicted - you want to cure aeon/sap and the things that prevent them from being cured. You don't want your system to constantly mess you up while you are trying to do that. However, you also want to keep tracking what you are hit by, so the moment you cure aeon/sap, you can start curing everything else wrong with you. The same with being impaled, since you can't cure any (non-purgative) afflictions while impaled until you finish writhing.


Now, to explain how to code a system:

First of all, you have several balances to worry about: Potion, purgative, herb, salve, regeneration (kind of), and writhing (kind of). You also have focus mind, focus body (kind of), sparkleberry, and allheale balances, but you don't have to worry about them so much.

Potion balance is used when you sip health/mana/bromide potions, or when you apply health to cure deepwounds. Herb balance is used when you eat or smoke any herb, and when you apply arnica. Salve balance is used when you apply liniment, mending, regeneration, or melancholic.

All regeneration cures are delayed - when regeneration is applied, you also lose a hidden regeneration balance, which comes back when the cure finishes working. If you apply another regeneration salve before then, the affliction that was previously being cured by regeneration stops being cured. So, if you have your left leg tendon severed and your left arm amupated and you apply regeneration to your legs, nothing happens at first. If you then apply regeneration to your arms after you get your salve balance back but before your leg tendon reattaches itself, and then wait, your arm will grow back, but your leg tendon will still be severed. Sorry if that was confusing sad.gif

Writhing doesn't really have a balance, but if you writhe while writhing, it resets the writhe time. So, you need to keep track of what you need to writhe from, but wait to writhe until after you finish writhing whatever else you were writhing from. I treat writhe cures just the same way I treat herb, purgative, and salve cures.


Now, the best way that I've found to cure is to make a queue for each balance. So, you have an herb queue that contains all your afflictions cured by herbs, a salve queue that contains all of your afflictions cured by salves, etc. (The other way to handle this is to have a variable for each affliction and set them to true if you have that affliction. I'm not sure which runs faster.)

When you are hit by an affliction, run an alias based on the affliction. For example:

CODE
Pattern: ^Small motes of yellow pollen rise up from the wildflowers around you and drift
Value: asthma

(In the future, such triggers will be written this way:)
CODE
#trigger {^Small motes of yellow pollen rise up from the wildflowers around you and drift} {asthma}

(If you enter the above code into the command line, the place where you type stuff to interact with the game, zMUD will add it as a trigger.)

This runs the "asthma" alias when you get the line "Small motes of yellow pollen..." The ^ means "match the beginning of the line" - $ means "match the end of the line." So, a triggerw ith the pattern ^test$ would fire if "test" was the only thing on a line, but wouldn't fire if someone said, "I'm testing something." It's important to catch the beginning and ends of lines when you can to help protect against illusions, and to avoid having your triggers fire unnecessarily. It's also very important to match the word "you" or "your" so you don't try to cure something when someone next to you is afflicted with it tongue.gif Remember though that triggers don't match past newline characters. Meaning, if an afflict line is really long like the example above and wraps around to a new line, you can't match the entire thing, only a portion of it. There are ways to match across the newline, but I won't get into them right now.

So, the above code runs the "asthma" alias when you are hit by pollen, a druidic demesne effect that causes asthma. My asthma alias:
CODE
#alias asthma {
  #echo %ansi( 79) Asthma afflict - cure: melc
  #if (@curesystem="on") {
    #additem salveafflicts asthma
    runac
  }
}

Salveafflicts is my list that contains all of my afflictions that are cured by salves. This adds asthma to that list, if my curesystem is on. It also echos to my screen that I've been afflicted with asthma, and tells me my manual cure for asthma (melc is my alias to apply melancholic to chest). Runac is my alias that looks through all my queues and cures the next thing in each queue if I have the balance for it. (It essentially just runs my runhc, runsc, runpc aliases, which go through the herb, salve, and purgative queues.) I run that alias whenever I am afflicted, whenever I regain a balance of any kind, whenever I am no longer stunned, whenever I cure aeon/sap/impale, whenever I am unafflicted with a delayed cure, and every 1.5 seconds just in case.


So, in other words, these two together are an example of how my system picks up that I've gained an affliction.

Once you know what afflictions you have, you can then either just cure them one by one from the queue, or you can use what's called a "priority queue" which cures the most devestating afflictions before the worthless ones. Here is an example of a priority queue (note, this is HARD TO READ):
CODE
#alias runsc {
#if (!@aeon) {
  #if (@curesystem="on" and @salvebalance="True" and @runscbalance="True" and (%numitems( @salveafflicts)>0) and !(%ismember( slickness, @herbafflicts))) {
    runscbalance=False
    #if (%ismember( slitthroat, @salveafflicts)) {menh} {#if (%ismember( asthma, @salveafflicts)) {melc} {#if (%ismember( blacklung, @salveafflicts)) {melc} {#if (%ismember( puncturedlung, @salveafflicts)) {melc} {#if (%ismember( sensitivity, @salveafflicts)) {melh} {#if (@regenbalance and %ismember( lostleg, @salveafflicts)) {regl} {#if (@regenbalance and %ismember( lostarm, @salveafflicts)) {rega} {#if (@regenbalance and %ismember( leftslicedtendon, @salveafflicts)) {regl} {#if (@regenbalance and %ismember( rightslicedtendon, @salveafflicts)) {regl} {#if (@regenbalance and %ismember( burstorgans, @salveafflicts)) {regg} {#if (@regenbalance and %ismember( crushedchest, @salveafflicts)) {regc} {#if (@regenbalance and %ismember( collapsedlungs, @salveafflicts)) {regc} {#if (@regenbalance and %ismember( disembowelment, @salveafflicts)) {regg} {#if (@regenbalance and %ismember( headtrauma, @salveafflicts)) {regh} {#if (%ismember( fracturedskull, @salveafflicts)) {menh} {#if (%ismember( vapors, @salveafflicts)) {melh} {#if (@regenbalance and %ismember( leftmangledleg, @salveafflicts)) {regl} {#if (@regenbalance and %ismember( rightmangledleg, @salveafflicts)) {regl} {#if (@regenbalance and %ismember( leftmangledarm, @salveafflicts)) {rega} {#if (@regenbalance and %ismember( rightmangledarm, @salveafflicts)) {rega} {#if (@regenbalance and %ismember( peckedeye, @salveafflicts)) {regh} {#if (@regenbalance and %ismember( brokenwrist, @salveafflicts)) {rega} {#if (%ismember( legbreak, @salveafflicts)) {menl} {#if (%ismember( rightlegbreak, @salveafflicts)) {menl} {#if (%ismember( leftlegbreak, @salveafflicts)) {menl} {#if (%ismember( armbreak, @salveafflicts)) {mena} {#if (%ismember( rightarmbreak, @salveafflicts)) {mena} {#if (%ismember( leftarmbreak, @salveafflicts)) {mena} {#if (%ismember( dizzy, @salveafflicts)) {melh} {#if (%ismember( break, @salveafflicts)) {menq} {#if (%ismember( scabies, @salveafflicts)) {lin} {#if (%ismember( sunallergy, @salveafflicts)) {lin} {#if (%ismember( pox, @salveafflicts)) {lin} {#if (@regenbalance and %ismember( leftcrackedelbow, @salveafflicts)) {rega} {#if (@regenbalance and %ismember( rightcrackedelbow, @salveafflicts)) {rega} {#if (@regenbalance and %ismember( leftcrackedkneecap, @salveafflicts)) {regl} {#if (@regenbalance and %ismember( rightcrackedkneecap, @salveafflicts)) {regl} {#if (%ismember( jawbreak, @salveafflicts)) {menh} {#if (@regenbalance and %ismember( damagedhead, @salveafflicts)) {regh} {#if (%ismember( maybeslick, @salveafflicts)) {menh} {#echo %ansi( 112)omgwtfsalve}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
    }
  #alarm +0.5 {runscbalance=True}
  }
}

This makes sure I'm not in aeon mode, then checks if I have salve balance, that I have a salve-cured affliction, that I am not slick, and then checks to make sure I'm not running this code too often (so if it is run twice in rapid succession, I don't want to apply a cure twice, only once, so it gives .5 seconds before allowing the code to be run a second time - that's what the stuff with "runscbalance" does), and then if it's all set right, I cure the worst thing wrong with me that can be cured with a salve. The aliases menh, regh, melc, et cetera are my "apply something to somewhere" aliases.


In other words, this section is what decides what I can cure given what I'm afflicted with, and what should be cured first.

Lastly, you need to know what you've cured, or the system won't know to stop trying to cure it. For this, you need to catch the "unafflict" message and then remove it from the queue. Here is the example for asthma:
CODE
#trigger {^Your bronchial tubes open up and your asthma is cured.$} {#echo %ansi( 31) Asthma unafflict caught;#delitem salveafflicts asthma}

This should be pretty obvious by this point - it just removes asthma from the list of salve-cured afflictions. If you are using the other method of having variables you set and unset, you would just unset the variable here. So, asthma=0 (or #var asthma 0, or #var salveafflictions.asthma 0, or whatever syntax you are using) instead of the #delitem line.


This just tells the system "I cured asthma, so you don't have to keep trying! Go on to the next thing!"

Of course, you need a simple trigger that catches ^You may apply another salve to yourself.$ and sets your salve balance to true, and a trigger for ^You take out some salve and quickly rub it on your (%w).$ that sets your salve balance to false when you apply a salve. The trick is figuring out how to make the latter not fire when you apply health potion to yourself and not fire when you apply mending or melancholic to yourself while not afflicted, since those two salves don't take balance unless you actually cure something. Arnica is the same way with herb balance - it only takes it if it cures something.


So! If you're still with me, there is still one thing missing from all this. What if you think you are afflicted, but you aren't (due to an illusion or a faulty trigger)? Then, when you do something that should cure you of something, and it doesn't cure anything at all, it needs to remove all afflictions it should have cured from your queues. This is easy enough for herbs, but for salves and potions, this is not trivial to do by any means, since drinking one potion looks much the same as drinking another - the same for applying salves. Also, applying health potion looks just like a salve, and drinking health, mana, bromide, and quicksilver looks just like drinking a purgative (quicksilver is on no balance at all, by the way). My system seems to do it rather well, but it's a bit complicated.


This isn't even getting into how you handle warrior afflictions and deepwounds, autosipping (I think I posted my autosipper code somewhere already, though that might have been before I took into account burstvessels), diagnosing (which is actually quite simple), writhing/focusbody (which are both quite similar, and not terribly complicated if you want some code for them), or aeon/sap (which can be so horrendously complicated, I don't bother dealing with them at all).


Now, I'm sure I lost you somewhere, but hopefully you can ask better questions now with an idea of how a curing system works and why it's complicated? Feel free to ask anything! Procrastination is fun smile.gif
Acrune2006-10-06 13:20:59
QUOTE(Shorlen @ Oct 6 2006, 01:17 AM) 339382

Procrastination is fun smile.gif


blink.gif

It must be tongue.gif
Kaalak2006-10-12 18:17:59
clap_1.gif Very helpful Shorlen. I'll direct my novices to this post. Thanks.