Raevnos' Demo Combat System

This is the start of a combat system that allows different attack and defense styles. It's geared towards a medieval set of weapons rather than hi-tech, because I work more with fantasy mushes than sci-fi ones.

Author: Raevnos
Category: Combat
Compatibility: PennMUSH.


Copy and paste the below code into a compatible MUSH or MUX.

MUSHCode for Raevnos' Demo Combat System

@dig/tel Raevnos' Demo Combat System
@DESCRIBE here=This is the start of a combat system that allows different attack and defense styles. It's geared towards a medieval set of weapons rather than hi-tech, because I work more with fantasy mushes than sci-fi ones.%r%rThere are two commands:%r [ansi(h, attack/<style> <target>)], where style is one of: stab, slice, and chop%r [ansi(h, defend\[/<style>\])], where style is one of: parry, shield, or dodge. Parry is the default style.%r%rIt obviously is just a framework of a real CS -- no weapons, stats, training, or damage. Just the basic mechanics for an attack command. Hopefully, it'll be useful as a starting point or for ideas.

@create CS Synchronizer
@lock/Basic CS Synchronizer==me
@lset CS Synchronizer/Basic=no_inherit
@set CS Synchronizer = VISUAL
@set CS Synchronizer = NO_COMMAND
&DESCRIBE CS Synchronizer=This object is used for the semaphores that control all the different combats.
@set CS Synchronizer/DESCRIBE=no_command visual public nearby
drop CS Synchronizer

@create CS Code
@lock/Basic CS Code==me
@lset CS Code/Basic=no_inherit
@set CS Code=VISUAL
@set CS Code=!NO_COMMAND
&ATTACK_CMD CS Code=$attack/* *:@break switch(0, member(v(attack_styles), lcstr(%0)), pemit(%#, '%0' isn't a valid attack style)1, isdbref(setr(0, pmatch(%1))), pemit(%#, '%1' isn't a player)1, nearby(%#, %q0), pemit(%#, You have to be closer to [name(%q0)] to attack [obj(%q0)])1, not(hasattrval(%vs, %#)), pemit(%#, You're being attacked. You should defend first)1, not(hasattrval(%vs, %q0)), pemit(%#, name(%q0) is already being attacked. One at a time!)1, 0); @pemit %#=You attack [name(%q0)] with a [lcstr(%0)]! Now [subj(%q0)] must choose a defense within 90 seconds.; @pemit %q0=%N is attacking you with what appears to be a [lcstr(%0)]. Use [ansi(h, defend\[/<style>\])] (Where <style> is one of parry, shield, or dodge) in the next 90 seconds or the default defense will be chosen for you.; @@ Now for the semaphore'd attack resolution code @@; @wait %vs/%q0/90={@remit %l=%N attacks [name(%q0)] with a [lcstr(%0)]! [name(%q0)] defends with a [default(%vs/%q0_defense, parry)]! The attack [if(gt(rand(1000), 500), succeeds, fails)]!; &%q0_defense %vs}
&ATTACK_STYLES CS Code=stab slice chop
&DEFEND_CMD CS Code=$defend*:@break switch(0, hasattrval(%vs, %#), pemit(%#, You're not being attacked!)1, strlen(%0), 0[setq(0, parry)], regmatchi(%0, ^/([v(defense_styles)])$, -1 0), pemit(%#, That's not a proper defense style.)1, 0); &%#_defense %vs=lcstr(%q0); @notify %vs/%#
&DEFENSE_STYLES CS Code=parry|shield|dodge
&DESCRIBE CS Code=This object holds the actual CS code.
@set CS Code/DESCRIBE=no_command visual public nearby
&LICENSE CS Code=All code on this object (Raevnos' Demo Combat System) is released under the Gnu Public License. A copy of that license if available at [tagwrap(a, href="http://www.gnu.org/copyleft/gpl.html", http://www.gnu.org/copyleft/gpl.html)]
@fo me=&VS CS Code=[num(CS Synchronizer)]
drop CS Code

@create Explanation
@lock/Basic Explanation==me
@lset Explanation/Basic=no_inherit
@set Explanation = VISUAL
@set Explanation = NO_COMMAND
&ATTACK_CMD Explanation=This contains the code for the attack command. It does error and permission checking using @break, and then @pemits messages and starts the semaphore on the defender's dbref, all in one queue cycle. Note that you can attack yourself. I left that check out so you can play with it when nobody else is around. The second part of the attack command is the timed semaphore that does the actual attack resolution. It is all in one action list instead of on another attribute and @triggered to help simplify timing issues and make it respond faster. The whole thing takes three queue cycles. One for the attack command, one for the defend command, and one for the semaphore.
&ATTACK_STYLES Explanation=The available attack styles, seperated by spaces.
&DEFEND_CMD Explanation=This is the code for the defend command. It does error and permission checking with @break (Instead of @switch, so it's one queue cycle), sets the defense style, and then @notifies the semaphore so that the actual attack gets resolved in the next queue cycle.
&DEFENSE_STYLES Explanation=The available defense styles, seperated by |'s.
&DESCRIBE Explanation=Each attribute on this object corresponds to one on CS Code (#3873) and explains what it does.
@set Explanation/DESCRIBE=no_command visual public nearby
&VS Explanation=This attribute holds the dbref of the CS Synchronizer object. The Synchronizer is used to @wait on for the attacks, using the dbref of the defender as the attribute to @wait on. This requires the named semaphores added in 1.7.3p13.
drop Explanation