#include "data/scripts/vars/anims.h"
#include "data/scripts/vars/entity.h"
#include "data/scripts/com/ani0009.h"
#include "data/scripts/com/summ0001.h"
#define DC_PARRY_MP_GAIN_FACTOR 0.3
#define DC_PARRY_TARGET_FREEZE 30
#define DC_PARRY_OPPONENT_FREEZE 75
#define DC_PARRY_KEY_WINDOW 25
// dc_parry
// Caskey, Damon V.
// 2010-xx-xx
// Check opponent_pos_r block key timing and
// parry the attack accordingly.
int dc_parry(void target, void opponent){
float last_hit_X; // Last hit, X axis.
float last_hit_Y; // Last hit, Y axis.
float last_hit_Z; // Last hit, Z axis.
int MP_current; // MP, current value.
float MP_max = 0.0; // MP, maximum.
int animation_current; // Animation in use.
float opponent_pos_X; // Opponent position, X axis.
int elapsed_time; // Current elapsed time.
int key_time; // Time of last key press.
int target_next_time; // Elapsed time for next action (animations, toss, etc.), target.
int opponent_next_time; // Elapsed time for next action (animations, toss, etc.), opponent.
int pause_add; // Pause add value of attack to parry.
int target_pos_B; // Target position, base.
int target_pos_D; // Target position, direction.
float target_pos_X; // Target position, X axis.
float target_pos_Y; // Target position, Y axis.
int animation_parry; // Animation to use for parry.
if(!target)
{
target = getlocalvar("self");
}
key_time = getentityvar(target, KEY1SP); //Get time of last special press.
elapsed_time = openborvariant("elapsed_time"); //Get elapsed time.
animation_current = getentityproperty(target, "animationid"); //Get current animation.
// Player must press Special (block) inside of the parry window timing,
// and can't be attacking, in pain, or block stun.
if ((elapsed_time-key_time) <= DC_PARRY_KEY_WINDOW
&& (animation_current == openborconstant("ANI_BLOCK")
|| animation_current == AIRBLOCK
|| animation_current == PARRY
|| animation_current == APARRY))
{
// Reset last Special press time.
setentityvar(target, KEY1SP, 0);
// Get target position.
target_pos_B = getentityproperty(target, "base");
target_pos_Y = getentityproperty(target, "y");
// If target is on the ground, use ground parry
// animation (if available). If in the air, then
// use air parry (if available).
if(target_pos_Y == target_pos_B)
{
animation_parry = ani0009(target, PARRY, 0);
}
else
{
animation_parry = ani0009(target, APARRY, 0);
}
// Was a parry animation set? If so we will need to perform several
// actions to complete the parry effect.
//
// - Turn target toward the attack.
// - Apply parry animation to the target.
// - Add a short, static length freeze to the target.
// - Add a freeze effect to opponent, with a slightly
// longer static time than target's, plus the pause_add
// value of the attack that was parried.
//
// - Give target a small MP reward.
// - Spawn an appropriate flash effect.
// - Return a true value.
if(animation_parry)
{
// Get the screen position of the hit. We'll need this
// to spawn the flash correctly.
last_hit_X = openborvariant("lasthitx") - openborvariant("xpos");
last_hit_Y = openborvariant("lasthita");
last_hit_Z = openborvariant("lasthitz");
// Get target and opponent positions.
target_pos_X = getentityproperty(target, "x");
opponent_pos_X = getentityproperty(opponent, "x");
MP_current = getentityproperty(target, "mp");
MP_max += getentityproperty(target, "maxmp");
target_pos_D = getentityproperty(target, "direction");
// Get a direction facing attack.
if(target_pos_X > opponent_pos_X)
{
target_pos_D = openborconstant("DIRECTION_LEFT");
}
else if(target_pos_X < opponent_pos_X)
{
target_pos_D = openborconstant("DIRECTION_RIGHT");
}
// Face target toward attack.
changeentityproperty(target, "direction", target_pos_D);
// MP reward. Calculate a percentage of target's
// maximum MP and add it to current MP value.
MP_current = getentityproperty(target, "mp");
MP_current += (MP_max * DC_PARRY_MP_GAIN_FACTOR);
changeentityproperty(target, "mp", MP_current + (MP_max * DC_PARRY_MP_GAIN_FACTOR));
// Spawn the parry flash.
summ0001("pflash", "pflash", 0, 1, last_hit_X, last_hit_Y, last_hit_Z, target_pos_D, 0, 0, 1);
// Get the current nextanim times and attack pause add.
target_next_time = getentityproperty(target, "nextanim"); + DC_PARRY_TARGET_FREEZE;
opponent_next_time = getentityproperty(opponent, "nextanim"); + DC_PARRY_OPPONENT_FREEZE;
pause_add = getlocalvar("pauseadd");
// Add our additional freeze times to get a new nextanim
// to use. The opponent's should be slightly longer. This
// will "pause" both subjects, but the target is able to act
// first, just like the parry function in Street Fighter 3.
// For the opponent, we also add in pause_add value of the
// parried attack. This means that harder, heavier attacks
// have a longer recovery from getting parried than lighter
// attacks.
target_next_time += DC_PARRY_TARGET_FREEZE;
opponent_next_time += DC_PARRY_OPPONENT_FREEZE;
opponent_next_time += pause_add;
// Apply opponent's next times to its AI control flags.
changeentityproperty(opponent, "nextanim", opponent_next_time);
changeentityproperty(opponent, "nextthink", opponent_next_time);
changeentityproperty(opponent, "tosstime", opponent_next_time);
// Apply target's next times to its AI control flags.
changeentityproperty(target, "nextanim", target_next_time);
changeentityproperty(target, "nextthink", target_next_time);
changeentityproperty(target, "tosstime", target_next_time);
return 1;
}
}
return 0;
}