Guarding/Free Attack Scripts
See also Special Abilities
The control of 'Free' attacks and 'Guard' attacks is entrusted to these scripts. Here is a possible outline of the process:
*/
Good Morning,
OK. Here is what I plan. This email message
will be copied verbatim into the C++ code as
comments as a reference.
Let me know if it seems wrong.
What follows here is a kind of "Pseudo-code"
as if it were being done by hook scripts)
and is applied to each combatants; PC, NPC,
or monster. I will attempt to code this
algorithm in such a way that hooks could
be inserted at any of these points in the
hard-coded algorithm. This may take a couple
of days and obviously will require more
extensive testing because there are so
many possibilities.
$VAR AttacksRemaining;
$VAR GuardingAttacksRemaining;
$VAR IsGuarding;
[Guarding-CanGuard]
$IF (is monster) $RETURN "N";
$IF (rangeWeapon) $RETURN "N";
$RETURN "Y";
[Guarding-BeginCombat]
GuardingAttacksRemaining = 0;
IsGuarding = false;
[Guarding-StartOfRound]
AttacksRemaining = <number of attacks allowed>;
[Guarding-Guard] // combatant enters 'guard' mode
GuardingAttacksRemaining = AttacksRemaining
IsGuarding = true;
[Guarding-StartOfTurn] // menu presented for combatant
IsGuarding = false;
GuardingAttacksRemaining = 0;
[Guarding-CanGuardAttack] // enemy approaches
$IF( !IsGuarding) $RETURN "N";
$IF (rangeWeapon) $RETURN "N";
$IF(GuardAttacksRemaining <=# 0) $RETURN "N";
$IF(AttacksRemaining <=#0) $RETURN "N";
$RETURN "Y";
[Guarding-AttackOver]
Decrement GuardAttacksRemaining;
$IF(GuardAttacksRemaining <=#0) IsGuarding = false;
Decrement AttacksRemaining
[FreeAttack-CanFreeAttack] // enemy departs
$IF(rangeWeapon) $RETURN "N";
$RETURN "Y";
[FreeAttack-AttackOver]
Decrement AttacksRemaining;
Decrement GuardAttacksRemaining;
$IF(GuardAttacksRemaining <=#0) IsGuarding = false;
[CanAttack]
$IF (IsGuarding) $RETURN "N";
$RETURN "Y";
Now I will attempt to apply this algorithm to your
examples.
On 10/17/2011 7:30 PM, Eric Cone wrote:
***> Good afternoon.
***>
***> First things first - terminology.
***>
***> Free attack: an attack that follows all the rules of regular
***> melee physical attacks (with or without weapon weapon, if
***> weapon only range of 1 counts as melee)
***> Guarding attack: a type of free attack that occurs when
***> a combatant moves adjacent to a combatant that is GUARDING.
***> As of this time, only***> combatants under player control
***> may GUARD.
Handled by $IF (is monster) in [Guarding-CanGuardAttack]
***> which may occur between a combatants consecutive turns is
***> equal to it's number of attacks per turn.
Handled by:
[Guarding-Guard]
[Guarding-StartOfTurn]
{Guarding-AttackOver]
***>
***> The other kind of free attack, occurs when a combatant moves
***> away from an adjacent square, once per monster moving away.
***>
***> With that in mind, let's use Tom's answers to the
***> questions - he was very thorough, and once the vocabulary
***> is straightened out, I completely agree. Here it is.
***>
***> -Eric
***>
***> On Sun, Oct 16, 2011 at 7:40 AM, <Nologgie@aol.com
***> <mailto:Nologgie@aol.com>> wrote:
***>
***> Good Morning Eric,
***>
***> Here are the answers I came up with for Paul's
***> questions.
***>
***> If an enemy is immediately adjacent and moves away
***> then he is subject to a free attack.
***>
***> If an enemy is not immediately adjacent and moves
***> so as to become immediately adjacent he is subject
***> to a 'guarding' attack, but not a free attack.
***>
***> The Exact Rules:
***>
***> Free Attacks
***>
***> 1. The 'free attack' is actually comprised of the
***> attacker's entire 'attack routine' for a combat
***> round. This is normally 1 or 2 attacks for
***> characters. For 'monsters', it may be 8 or more.
***>
***> 2. Free attacks will always occur if the target is
***> valid (IsValidTarget != "N") and the attacker is
***> able to execute a melee attack.
***> (IsCombatReady != "N", and a missile weapon is
***> not readied.)
Handled by [FreeAttack-CanFreeAttack]
***>
***> 3. If a free attack occurs before the attacker's
***> normal action for the round, any attacks executed
***> are deducted from the attacks available for that
***> round. If the attacks are depleted it constitutes
***> the combatant's action for the round, and the
***> combatant gets no 'turn'.
Handled by [FreeAttack-MakeFreeAttack]
You did not specify this so I made a guess
that a free attack should also reduce the
number of guard attacks remaining.
***>
***> 4. Free attacks are allowed against fleeing enemies
***> regardless of whether the attacker has any 'normal'
***> attacks remaining, so in that sense they are
***> unlimited.
***>
Handled by [FreeAttack-CanFreeAttack]
***> Guarding Attacks
***>
***> Combatants who do not have missile weapons readied
***> may select 'Guard' as a combat action. If a
***> non-adjacent enemy moves adjacent to a guarding
Handled by [Guarding-CanGuard]
***> combatant, the guarding combatant will execute its
***> attack routine. Any attacks made will be deducted
***> from those available to the attacker in the combat
***> round when guard was set. If the attacks are
***> depleted, guarding status is removed.
Handled by:
[MakeAttack]
[FreeAttack-AttackOver]
[Guarding-AttackOver]
***>
***> Example:
[StartOfCombat]
GuardAttacksRemaining=0;
***> A combatant selects Guard in round three. If an
***> enemy moves adjacent prior
[Guarding-StartOfRound] Round 3
AttacksRemaining = 3; // for example
[Guarding-Guard] round 3
GuardAttacksRemaining = AttacksRemaining = 3; //for example
[Guarding-AttackOver] round 3
Decrement GuardAttacksRemaining (now = 2)
***> to the guarding combatant's turn in round four,
***> the guarding combatant will
[GuardIng-StartOfRound] Round 4
AttacksRemaining = 3;
***> execute its attack routine, and the attacks will
***> be counted against the attacks available in round
***> three (when Guard was set). The combatant's round
***> four turn remains available.
[Guarding-AttackOver]
Decrement AttacksAvailable (now = 3)
Decrement GuardAttacksRemaining (now = 1)
The rest of your explanation assumed that
'free attacks' are completely separate from
'guard attacks' whereas my questions assumed
they were two different aspects of the same
thing. So the answers did not apply to the
intent of my questions.
PAul
*/
Combat Menu or Auto Movement terminated by max steps. |
Should the combatant enter 'Guard' mode |
Combatant / Guarding-CanGuard |
At Start of Combat Round |
Information Only |
Combatant / Guarding-StartOfRound |
When enemy approaches |
Should combatant 'Guard Attack'? |
Combatant / Guarding-CanGuardAttack |
When enemy retreats |
Should combatant 'Free Attack'? |
Combatant / FreeAttack-CanFreeAttack |
When Guard Attack Ends |
Reduce the number of attacks available |
Combatant / Guarding-AttackOver |
When Free Attack Ends |
Reduce the number of attacks available |
Combatant / FreeAttack-AttackOver |
When a combat begins |
Initialize combatant status |
Combatant / Guarding-BeginCombat |
See Special Abilities Scripts for some additional explanation
Additional GPDL functions
None
Context: Combatant
Parameters: Hook Parameter[5] = case number (1 or 2 – see below)
Result: If the first character of the result is 'Y' then the combatant is able to 'Guard'.
Default result: 'N'
Case 1:
When a combatant is in 'Auto' mode and is fleeing and exhausts his maximum number of steps.
Case 2:
When a combatant is in player control and the combat menu is about to be displayed. Answer the question: “Should “GUARD” be a combat option?”.
Context: Combatant, Character
Parameters:
HookParameter[5] = The current state of the combatant:
0 = ICS_None
1 = ICS_Casting,
2 = ICS_Attacking
3 = ICS_Guarding
4 = ICS_Bandaging,
5 = ICS_Using
6 = ICS_Moving
7 = ICS_Turning
8 = ICS_Fleeing
9 = ICS_Fled
10 = ICS_ContinueGuarding (into next round)
HookParameter[6] can be set to force a continuation of 'ICS_Guarding'. Normally at the start of each round, a combatant who is not in 'ICS_Casting' state and who is not in 'Auto' mode will have his state set to 'ICS_None'. If HookParameter[6] contains a 'G' then any non-Auto combatant who is in 'ICS_Guarding' state will be set to 'ICS_ContinueGuarding' and will remain in that state until his initiative arrives. He will then be set to 'ICS_None' and his combat menu will be displayed.
Result: Ignored. Probably best to return “” in case we augment this hook someday.
Default Result: “”
At the start of each combat round, this hook is called for each combatant. The hook “StartCombatRound” is also called under exactly the same circumstances but I added this so that 'Guarding' issues could be handled in their own private way and keep the scripts simpler. If it is important to you, you should know that “StartCombatRound is called first and Guarding-StartOfRound is called second.
Context: Attacker, Target
Parameters:
HookParameter[5] = attacker's number of available attacks
HookParameter[6] = “Y” if attacker is party member; else “N”
HookParameter[7] = “Y” if attacker is on 'Auto'. “N” if under player control.
Result: If the script returns a 'Y' as the first character then the Guarding attack can take place. The default result is an empty string and no guarding attack can occur.
This script is called whenever a combatant who is not adjacent to a potential 'Guarding Attacker' moves to a position that is adjacent to the potential 'Guarding Attacker'.
Context: Attacker, Target
Parameters:
HookParameter[5] = attacker's number of available attacks. This is generally the number of melee attacks remaining in this round of combat. It may be the number of attacks specified for a monster or it may be the Rate-of-Fire of a readied weapon. It will have been reduced by the number of attacks already taken in this round of combat.
HookParameter[6] = “Y” if attacker is party member; else “N”
HookParameter[7] = “Y” if attacker is on 'Auto'. “N” if under player control.
HookParameter[8] = The number of attacks allowed per turn for this combatant. It may be the number of attacks specified for a monster or it may be the Rate-of-Fire of a readied weapon.
Result: If the script returns a 'Y' as the first character then a Free Attack can take place. The number of Free Attacks will be one plus the number of available attacks (See HookParameter[5]). If the script returns a number greater than zero then it specifies the number of Free Attacks that can take place. The default result is an empty string and no free attack can occur.
This script is called whenever a combatant who is adjacent to a potential 'Free Attacker' moves to a position that is not adjacent to the potential 'Free Attacker'.
Context: Combatant
Parameters:
HookParameter[5] = Number of available attacks (before this guarding attack)
HookParameter[6] = Number of Guarding attacks against this one enemy (before this guarding attack). This is currently always 1.
HookParameter[7] = Minus one.
HookParameter[8] = Minus one.
Result: Ignored
After Guarding attack is complete we attempt to call this script. Then we use HookParameter[7] to modify the number of 'Normal' attacks that this combatant can use in this round. We use HookParameter[8] to modify the number of additional 'Guard' attacks that this combatant can execute against the same enemy combatant.
This script can modify HookParameter[7] and HookParameter[8].
The script should use this opportunity to update its own count of the number of 'Guard' attacks available to this combatant.
Exactly like “Guarding-AttackOver” except for 'Free Attacks' instead of 'Guard Attacks'.
Immediately after placing all combatants in the arena we search each combatant for a script named 'Guarding-BeginCombat'
Context: Combatant, Characters
Parameters: None
Result: ignored