2013-04-19 02:52:48 +00:00
# include "q_shared.h"
# include "bg_public.h"
# include "bg_local.h"
# include "w_saber.h"
# include "../namespace_begin.h"
extern qboolean BG_SabersOff ( playerState_t * ps ) ;
saberInfo_t * BG_MySaber ( int clientNum , int saberNum ) ;
int PM_irand_timesync ( int val1 , int val2 )
{
int i ;
i = ( val1 - 1 ) + ( Q_random ( & pm - > cmd . serverTime ) * ( val2 - val1 ) ) + 1 ;
if ( i < val1 )
{
i = val1 ;
}
if ( i > val2 )
{
i = val2 ;
}
return i ;
}
void BG_ForcePowerDrain ( playerState_t * ps , forcePowers_t forcePower , int overrideAmt )
{
//take away the power
int drain = overrideAmt ;
/*
if ( ps - > powerups [ PW_FORCE_BOON ] )
{
return ;
}
*/
//No longer grant infinite force with boon.
if ( ! drain )
{
drain = forcePowerNeeded [ ps - > fd . forcePowerLevel [ forcePower ] ] [ forcePower ] ;
}
if ( ! drain )
{
return ;
}
if ( forcePower = = FP_LEVITATION )
{ //special case
int jumpDrain = 0 ;
if ( ps - > velocity [ 2 ] > 250 )
{
jumpDrain = 20 ;
}
else if ( ps - > velocity [ 2 ] > 200 )
{
jumpDrain = 16 ;
}
else if ( ps - > velocity [ 2 ] > 150 )
{
jumpDrain = 12 ;
}
else if ( ps - > velocity [ 2 ] > 100 )
{
jumpDrain = 8 ;
}
else if ( ps - > velocity [ 2 ] > 50 )
{
jumpDrain = 6 ;
}
else if ( ps - > velocity [ 2 ] > 0 )
{
jumpDrain = 4 ;
}
if ( jumpDrain )
{
if ( ps - > fd . forcePowerLevel [ FP_LEVITATION ] )
{ //don't divide by 0!
jumpDrain / = ps - > fd . forcePowerLevel [ FP_LEVITATION ] ;
}
}
ps - > fd . forcePower - = jumpDrain ;
if ( ps - > fd . forcePower < 0 )
{
ps - > fd . forcePower = 0 ;
}
return ;
}
ps - > fd . forcePower - = drain ;
if ( ps - > fd . forcePower < 0 )
{
ps - > fd . forcePower = 0 ;
}
}
qboolean BG_EnoughForcePowerForMove ( int cost )
{
if ( pm - > ps - > fd . forcePower < cost )
{
PM_AddEvent ( EV_NOAMMO ) ;
return qfalse ;
}
return qtrue ;
}
// Silly, but I'm replacing these macros so they are shorter!
# define AFLAG_IDLE (SETANIM_FLAG_NORMAL)
# define AFLAG_ACTIVE (SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD | SETANIM_FLAG_HOLDLESS)
# define AFLAG_WAIT (SETANIM_FLAG_HOLD | SETANIM_FLAG_HOLDLESS)
# define AFLAG_FINISH (SETANIM_FLAG_HOLD)
//FIXME: add the alternate anims for each style?
saberMoveData_t saberMoveData [ LS_MOVE_MAX ] = { // NB:randomized
// name anim(do all styles?)startQ endQ setanimflag blend, blocking chain_idle chain_attack trailLen
{ " None " , BOTH_STAND1 , Q_R , Q_R , AFLAG_IDLE , 350 , BLK_NO , LS_NONE , LS_NONE , 0 } , // LS_NONE = 0,
// General movements with saber
{ " Ready " , BOTH_STAND2 , Q_R , Q_R , AFLAG_IDLE , 350 , BLK_WIDE , LS_READY , LS_S_R2L , 0 } , // LS_READY,
{ " Draw " , BOTH_STAND1TO2 , Q_R , Q_R , AFLAG_FINISH , 350 , BLK_NO , LS_READY , LS_S_R2L , 0 } , // LS_DRAW,
{ " Putaway " , BOTH_STAND2TO1 , Q_R , Q_R , AFLAG_FINISH , 350 , BLK_NO , LS_READY , LS_S_R2L , 0 } , // LS_PUTAWAY,
// Attacks
//UL2LR
{ " TL2BR Att " , BOTH_A1_TL_BR , Q_TL , Q_BR , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_R_TL2BR , LS_R_TL2BR , 200 } , // LS_A_TL2BR
//SLASH LEFT
{ " L2R Att " , BOTH_A1__L__R , Q_L , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_R_L2R , LS_R_L2R , 200 } , // LS_A_L2R
//LL2UR
{ " BL2TR Att " , BOTH_A1_BL_TR , Q_BL , Q_TR , AFLAG_ACTIVE , 50 , BLK_TIGHT , LS_R_BL2TR , LS_R_BL2TR , 200 } , // LS_A_BL2TR
//LR2UL
{ " BR2TL Att " , BOTH_A1_BR_TL , Q_BR , Q_TL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_R_BR2TL , LS_R_BR2TL , 200 } , // LS_A_BR2TL
//SLASH RIGHT
{ " R2L Att " , BOTH_A1__R__L , Q_R , Q_L , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_R_R2L , LS_R_R2L , 200 } , // LS_A_R2L
//UR2LL
{ " TR2BL Att " , BOTH_A1_TR_BL , Q_TR , Q_BL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_R_TR2BL , LS_R_TR2BL , 200 } , // LS_A_TR2BL
//SLASH DOWN
{ " T2B Att " , BOTH_A1_T__B_ , Q_T , Q_B , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_R_T2B , LS_R_T2B , 200 } , // LS_A_T2B
//special attacks
{ " Back Stab " , BOTH_A2_STABBACK1 , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_A_BACKSTAB
{ " Back Att " , BOTH_ATTACK_BACK , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_A_BACK
{ " CR Back Att " , BOTH_CROUCHATTACKBACK1 , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_A_BACK_CR
{ " RollStab " , BOTH_ROLL_STAB , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_ROLL_STAB
{ " Lunge Att " , BOTH_LUNGE2_B__T_ , Q_B , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_A_LUNGE
{ " Jump Att " , BOTH_FORCELEAP2_T__B_ , Q_T , Q_B , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_A_JUMP_T__B_
{ " Flip Stab " , BOTH_JUMPFLIPSTABDOWN , Q_R , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1_T___R , 200 } , // LS_A_FLIP_STAB
{ " Flip Slash " , BOTH_JUMPFLIPSLASHDOWN1 , Q_L , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1__R_T_ , 200 } , // LS_A_FLIP_SLASH
{ " DualJump Atk " , BOTH_JUMPATTACK6 , Q_R , Q_BL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1_BL_TR , 200 } , // LS_JUMPATTACK_DUAL
{ " DualJumpAtkL_A " , BOTH_ARIAL_LEFT , Q_R , Q_TL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_A_TL2BR , 200 } , // LS_JUMPATTACK_ARIAL_LEFT
{ " DualJumpAtkR_A " , BOTH_ARIAL_RIGHT , Q_R , Q_TR , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_A_TR2BL , 200 } , // LS_JUMPATTACK_ARIAL_RIGHT
{ " DualJumpAtkL_A " , BOTH_CARTWHEEL_LEFT , Q_R , Q_TL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1_TL_BR , 200 } , // LS_JUMPATTACK_CART_LEFT
{ " DualJumpAtkR_A " , BOTH_CARTWHEEL_RIGHT , Q_R , Q_TR , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1_TR_BL , 200 } , // LS_JUMPATTACK_CART_RIGHT
{ " DualJumpAtkLStaff " , BOTH_BUTTERFLY_FL1 , Q_R , Q_L , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1__L__R , 200 } , // LS_JUMPATTACK_STAFF_LEFT
{ " DualJumpAtkRStaff " , BOTH_BUTTERFLY_FR1 , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1__R__L , 200 } , // LS_JUMPATTACK_STAFF_RIGHT
{ " ButterflyLeft " , BOTH_BUTTERFLY_LEFT , Q_R , Q_L , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1__L__R , 200 } , // LS_BUTTERFLY_LEFT
{ " ButterflyRight " , BOTH_BUTTERFLY_RIGHT , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1__R__L , 200 } , // LS_BUTTERFLY_RIGHT
{ " BkFlip Atk " , BOTH_JUMPATTACK7 , Q_B , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_T1_T___R , 200 } , // LS_A_BACKFLIP_ATK
{ " DualSpinAtk " , BOTH_SPINATTACK6 , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_SPINATTACK_DUAL
{ " StfSpinAtk " , BOTH_SPINATTACK7 , Q_L , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_SPINATTACK
{ " LngLeapAtk " , BOTH_FORCELONGLEAP_ATTACK , Q_R , Q_L , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_LEAP_ATTACK
{ " SwoopAtkR " , BOTH_VS_ATR_S , Q_R , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_SWOOP_ATTACK_RIGHT
{ " SwoopAtkL " , BOTH_VS_ATL_S , Q_L , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_SWOOP_ATTACK_LEFT
{ " TauntaunAtkR " , BOTH_VT_ATR_S , Q_R , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_TAUNTAUN_ATTACK_RIGHT
{ " TauntaunAtkL " , BOTH_VT_ATL_S , Q_L , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_TAUNTAUN_ATTACK_LEFT
{ " StfKickFwd " , BOTH_A7_KICK_F , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_F
{ " StfKickBack " , BOTH_A7_KICK_B , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_B
{ " StfKickRight " , BOTH_A7_KICK_R , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_R
{ " StfKickLeft " , BOTH_A7_KICK_L , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_L
{ " StfKickSpin " , BOTH_A7_KICK_S , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_S_R2L , 200 } , // LS_KICK_S
{ " StfKickBkFwd " , BOTH_A7_KICK_BF , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_S_R2L , 200 } , // LS_KICK_BF
{ " StfKickSplit " , BOTH_A7_KICK_RL , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_S_R2L , 200 } , // LS_KICK_RL
{ " StfKickFwdAir " , BOTH_A7_KICK_F_AIR , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_F_AIR
{ " StfKickBackAir " , BOTH_A7_KICK_B_AIR , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_B_AIR
{ " StfKickRightAir " , BOTH_A7_KICK_R_AIR , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_R_AIR
{ " StfKickLeftAir " , BOTH_A7_KICK_L_AIR , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_KICK_L_AIR
{ " StabDown " , BOTH_STABDOWN , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_STABDOWN
{ " StabDownStf " , BOTH_STABDOWN_STAFF , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_STABDOWN_STAFF
{ " StabDownDual " , BOTH_STABDOWN_DUAL , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_S_R2L , 200 } , // LS_STABDOWN_DUAL
{ " dualspinprot " , BOTH_A6_SABERPROTECT , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 500 } , // LS_DUAL_SPIN_PROTECT
{ " StfSoulCal " , BOTH_A7_SOULCAL , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 500 } , // LS_STAFF_SOULCAL
{ " specialfast " , BOTH_A1_SPECIAL , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 2000 } , // LS_A1_SPECIAL
{ " specialmed " , BOTH_A2_SPECIAL , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 2000 } , // LS_A2_SPECIAL
{ " specialstr " , BOTH_A3_SPECIAL , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 2000 } , // LS_A3_SPECIAL
{ " upsidedwnatk " , BOTH_FLIP_ATTACK7 , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_UPSIDE_DOWN_ATTACK
{ " pullatkstab " , BOTH_PULL_IMPALE_STAB , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_PULL_ATTACK_STAB
{ " pullatkswing " , BOTH_PULL_IMPALE_SWING , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_PULL_ATTACK_SWING
{ " AloraSpinAtk " , BOTH_ALORA_SPIN_SLASH , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_SPINATTACK_ALORA
{ " Dual FB Atk " , BOTH_A6_FB , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_DUAL_FB
{ " Dual LR Atk " , BOTH_A6_LR , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_DUAL_LR
{ " StfHiltBash " , BOTH_A7_HILT , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_HILT_BASH
//starts
{ " TL2BR St " , BOTH_S1_S1_TL , Q_R , Q_TL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_TL2BR , LS_A_TL2BR , 200 } , // LS_S_TL2BR
{ " L2R St " , BOTH_S1_S1__L , Q_R , Q_L , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_L2R , LS_A_L2R , 200 } , // LS_S_L2R
{ " BL2TR St " , BOTH_S1_S1_BL , Q_R , Q_BL , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_BL2TR , LS_A_BL2TR , 200 } , // LS_S_BL2TR
{ " BR2TL St " , BOTH_S1_S1_BR , Q_R , Q_BR , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_BR2TL , LS_A_BR2TL , 200 } , // LS_S_BR2TL
{ " R2L St " , BOTH_S1_S1__R , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_R2L , LS_A_R2L , 200 } , // LS_S_R2L
{ " TR2BL St " , BOTH_S1_S1_TR , Q_R , Q_TR , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_TR2BL , LS_A_TR2BL , 200 } , // LS_S_TR2BL
{ " T2B St " , BOTH_S1_S1_T_ , Q_R , Q_T , AFLAG_ACTIVE , 100 , BLK_TIGHT , LS_A_T2B , LS_A_T2B , 200 } , // LS_S_T2B
//returns
{ " TL2BR Ret " , BOTH_R1_BR_S1 , Q_BR , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_TL2BR
{ " L2R Ret " , BOTH_R1__R_S1 , Q_R , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_L2R
{ " BL2TR Ret " , BOTH_R1_TR_S1 , Q_TR , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_BL2TR
{ " BR2TL Ret " , BOTH_R1_TL_S1 , Q_TL , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_BR2TL
{ " R2L Ret " , BOTH_R1__L_S1 , Q_L , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_R2L
{ " TR2BL Ret " , BOTH_R1_BL_S1 , Q_BL , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_TR2BL
{ " T2B Ret " , BOTH_R1_B__S1 , Q_B , Q_R , AFLAG_FINISH , 100 , BLK_TIGHT , LS_READY , LS_READY , 200 } , // LS_R_T2B
//Transitions
{ " BR2R Trans " , BOTH_T1_BR__R , Q_BR , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_A_R2L , 150 } , //# Fast arc bottom right to right
{ " BR2TR Trans " , BOTH_T1_BR_TR , Q_BR , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_TR2BL , 150 } , //# Fast arc bottom right to top right (use: BOTH_T1_TR_BR)
{ " BR2T Trans " , BOTH_T1_BR_T_ , Q_BR , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_T2B , 150 } , //# Fast arc bottom right to top (use: BOTH_T1_T__BR)
{ " BR2TL Trans " , BOTH_T1_BR_TL , Q_BR , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_A_TL2BR , 150 } , //# Fast weak spin bottom right to top left
{ " BR2L Trans " , BOTH_T1_BR__L , Q_BR , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_A_L2R , 150 } , //# Fast weak spin bottom right to left
{ " BR2BL Trans " , BOTH_T1_BR_BL , Q_BR , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_A_BL2TR , 150 } , //# Fast weak spin bottom right to bottom left
{ " R2BR Trans " , BOTH_T1__R_BR , Q_R , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_A_BR2TL , 150 } , //# Fast arc right to bottom right (use: BOTH_T1_BR__R)
{ " R2TR Trans " , BOTH_T1__R_TR , Q_R , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_TR2BL , 150 } , //# Fast arc right to top right
{ " R2T Trans " , BOTH_T1__R_T_ , Q_R , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_T2B , 150 } , //# Fast ar right to top (use: BOTH_T1_T___R)
{ " R2TL Trans " , BOTH_T1__R_TL , Q_R , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_A_TL2BR , 150 } , //# Fast arc right to top left
{ " R2L Trans " , BOTH_T1__R__L , Q_R , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_A_L2R , 150 } , //# Fast weak spin right to left
{ " R2BL Trans " , BOTH_T1__R_BL , Q_R , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_A_BL2TR , 150 } , //# Fast weak spin right to bottom left
{ " TR2BR Trans " , BOTH_T1_TR_BR , Q_TR , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_A_BR2TL , 150 } , //# Fast arc top right to bottom right
{ " TR2R Trans " , BOTH_T1_TR__R , Q_TR , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_A_R2L , 150 } , //# Fast arc top right to right (use: BOTH_T1__R_TR)
{ " TR2T Trans " , BOTH_T1_TR_T_ , Q_TR , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_T2B , 150 } , //# Fast arc top right to top (use: BOTH_T1_T__TR)
{ " TR2TL Trans " , BOTH_T1_TR_TL , Q_TR , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_A_TL2BR , 150 } , //# Fast arc top right to top left
{ " TR2L Trans " , BOTH_T1_TR__L , Q_TR , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_A_L2R , 150 } , //# Fast arc top right to left
{ " TR2BL Trans " , BOTH_T1_TR_BL , Q_TR , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_A_BL2TR , 150 } , //# Fast weak spin top right to bottom left
{ " T2BR Trans " , BOTH_T1_T__BR , Q_T , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_A_BR2TL , 150 } , //# Fast arc top to bottom right
{ " T2R Trans " , BOTH_T1_T___R , Q_T , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_A_R2L , 150 } , //# Fast arc top to right
{ " T2TR Trans " , BOTH_T1_T__TR , Q_T , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_TR2BL , 150 } , //# Fast arc top to top right
{ " T2TL Trans " , BOTH_T1_T__TL , Q_T , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_A_TL2BR , 150 } , //# Fast arc top to top left
{ " T2L Trans " , BOTH_T1_T___L , Q_T , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_A_L2R , 150 } , //# Fast arc top to left
{ " T2BL Trans " , BOTH_T1_T__BL , Q_T , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_A_BL2TR , 150 } , //# Fast arc top to bottom left
{ " TL2BR Trans " , BOTH_T1_TL_BR , Q_TL , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_A_BR2TL , 150 } , //# Fast weak spin top left to bottom right
{ " TL2R Trans " , BOTH_T1_TL__R , Q_TL , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_A_R2L , 150 } , //# Fast arc top left to right (use: BOTH_T1__R_TL)
{ " TL2TR Trans " , BOTH_T1_TL_TR , Q_TL , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_TR2BL , 150 } , //# Fast arc top left to top right (use: BOTH_T1_TR_TL)
{ " TL2T Trans " , BOTH_T1_TL_T_ , Q_TL , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_T2B , 150 } , //# Fast arc top left to top (use: BOTH_T1_T__TL)
{ " TL2L Trans " , BOTH_T1_TL__L , Q_TL , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_A_L2R , 150 } , //# Fast arc top left to left (use: BOTH_T1__L_TL)
{ " TL2BL Trans " , BOTH_T1_TL_BL , Q_TL , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_A_BL2TR , 150 } , //# Fast arc top left to bottom left
{ " L2BR Trans " , BOTH_T1__L_BR , Q_L , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_A_BR2TL , 150 } , //# Fast weak spin left to bottom right
{ " L2R Trans " , BOTH_T1__L__R , Q_L , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_A_R2L , 150 } , //# Fast weak spin left to right
{ " L2TR Trans " , BOTH_T1__L_TR , Q_L , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_TR2BL , 150 } , //# Fast arc left to top right (use: BOTH_T1_TR__L)
{ " L2T Trans " , BOTH_T1__L_T_ , Q_L , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_T2B , 150 } , //# Fast arc left to top (use: BOTH_T1_T___L)
{ " L2TL Trans " , BOTH_T1__L_TL , Q_L , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_A_TL2BR , 150 } , //# Fast arc left to top left
{ " L2BL Trans " , BOTH_T1__L_BL , Q_L , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_A_BL2TR , 150 } , //# Fast arc left to bottom left (use: BOTH_T1_BL__L)
{ " BL2BR Trans " , BOTH_T1_BL_BR , Q_BL , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_A_BR2TL , 150 } , //# Fast weak spin bottom left to bottom right
{ " BL2R Trans " , BOTH_T1_BL__R , Q_BL , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_A_R2L , 150 } , //# Fast weak spin bottom left to right
{ " BL2TR Trans " , BOTH_T1_BL_TR , Q_BL , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_TR2BL , 150 } , //# Fast weak spin bottom left to top right
{ " BL2T Trans " , BOTH_T1_BL_T_ , Q_BL , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_A_T2B , 150 } , //# Fast arc bottom left to top (use: BOTH_T1_T__BL)
{ " BL2TL Trans " , BOTH_T1_BL_TL , Q_BL , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_A_TL2BR , 150 } , //# Fast arc bottom left to top left (use: BOTH_T1_TL_BL)
{ " BL2L Trans " , BOTH_T1_BL__L , Q_BL , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_A_L2R , 150 } , //# Fast arc bottom left to left
//Bounces
{ " Bounce BR " , BOTH_B1_BR___ , Q_BR , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_T1_BR_TR , 150 } ,
{ " Bounce R " , BOTH_B1__R___ , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_T1__R__L , 150 } ,
{ " Bounce TR " , BOTH_B1_TR___ , Q_TR , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_T1_TR_TL , 150 } ,
{ " Bounce T " , BOTH_B1_T____ , Q_T , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_T1_T__BL , 150 } ,
{ " Bounce TL " , BOTH_B1_TL___ , Q_TL , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_T1_TL_TR , 150 } ,
{ " Bounce L " , BOTH_B1__L___ , Q_L , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_T1__L__R , 150 } ,
{ " Bounce BL " , BOTH_B1_BL___ , Q_BL , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_T1_BL_TR , 150 } ,
//Deflected attacks (like bounces, but slide off enemy saber, not straight back)
{ " Deflect BR " , BOTH_D1_BR___ , Q_BR , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TL2BR , LS_T1_BR_TR , 150 } ,
{ " Deflect R " , BOTH_D1__R___ , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_L2R , LS_T1__R__L , 150 } ,
{ " Deflect TR " , BOTH_D1_TR___ , Q_TR , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_T1_TR_TL , 150 } ,
{ " Deflect T " , BOTH_B1_T____ , Q_T , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_T1_T__BL , 150 } ,
{ " Deflect TL " , BOTH_D1_TL___ , Q_TL , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BR2TL , LS_T1_TL_TR , 150 } ,
{ " Deflect L " , BOTH_D1__L___ , Q_L , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_R2L , LS_T1__L__R , 150 } ,
{ " Deflect BL " , BOTH_D1_BL___ , Q_BL , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_TR2BL , LS_T1_BL_TR , 150 } ,
{ " Deflect B " , BOTH_D1_B____ , Q_B , Q_B , AFLAG_ACTIVE , 100 , BLK_NO , LS_R_BL2TR , LS_T1_T__BL , 150 } ,
//Reflected attacks
{ " Reflected BR " , BOTH_V1_BR_S1 , Q_BR , Q_BR , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1_BR
{ " Reflected R " , BOTH_V1__R_S1 , Q_R , Q_R , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1__R
{ " Reflected TR " , BOTH_V1_TR_S1 , Q_TR , Q_TR , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1_TR
{ " Reflected T " , BOTH_V1_T__S1 , Q_T , Q_T , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1_T_
{ " Reflected TL " , BOTH_V1_TL_S1 , Q_TL , Q_TL , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1_TL
{ " Reflected L " , BOTH_V1__L_S1 , Q_L , Q_L , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1__L
{ " Reflected BL " , BOTH_V1_BL_S1 , Q_BL , Q_BL , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1_BL
{ " Reflected B " , BOTH_V1_B__S1 , Q_B , Q_B , AFLAG_ACTIVE , 100 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_V1_B_
// Broken parries
{ " BParry Top " , BOTH_H1_S1_T_ , Q_T , Q_B , AFLAG_ACTIVE , 50 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_PARRY_UP,
{ " BParry UR " , BOTH_H1_S1_TR , Q_TR , Q_BL , AFLAG_ACTIVE , 50 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_PARRY_UR,
{ " BParry UL " , BOTH_H1_S1_TL , Q_TL , Q_BR , AFLAG_ACTIVE , 50 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_PARRY_UL,
{ " BParry LR " , BOTH_H1_S1_BL , Q_BL , Q_TR , AFLAG_ACTIVE , 50 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_PARRY_LR,
{ " BParry Bot " , BOTH_H1_S1_B_ , Q_B , Q_T , AFLAG_ACTIVE , 50 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_PARRY_LL
{ " BParry LL " , BOTH_H1_S1_BR , Q_BR , Q_TL , AFLAG_ACTIVE , 50 , BLK_NO , LS_READY , LS_READY , 150 } , // LS_PARRY_LL
// Knockaways
{ " Knock Top " , BOTH_K1_S1_T_ , Q_R , Q_T , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BL2TR , LS_T1_T__BR , 150 } , // LS_PARRY_UP,
{ " Knock UR " , BOTH_K1_S1_TR , Q_R , Q_TR , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BL2TR , LS_T1_TR__R , 150 } , // LS_PARRY_UR,
{ " Knock UL " , BOTH_K1_S1_TL , Q_R , Q_TL , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BR2TL , LS_T1_TL__L , 150 } , // LS_PARRY_UL,
{ " Knock LR " , BOTH_K1_S1_BL , Q_R , Q_BL , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_TL2BR , LS_T1_BL_TL , 150 } , // LS_PARRY_LR,
{ " Knock LL " , BOTH_K1_S1_BR , Q_R , Q_BR , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_TR2BL , LS_T1_BR_TR , 150 } , // LS_PARRY_LL
// Parry
{ " Parry Top " , BOTH_P1_S1_T_ , Q_R , Q_T , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BL2TR , LS_A_T2B , 150 } , // LS_PARRY_UP,
{ " Parry UR " , BOTH_P1_S1_TR , Q_R , Q_TL , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BL2TR , LS_A_TR2BL , 150 } , // LS_PARRY_UR,
{ " Parry UL " , BOTH_P1_S1_TL , Q_R , Q_TR , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BR2TL , LS_A_TL2BR , 150 } , // LS_PARRY_UL,
{ " Parry LR " , BOTH_P1_S1_BL , Q_R , Q_BR , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_TL2BR , LS_A_BR2TL , 150 } , // LS_PARRY_LR,
{ " Parry LL " , BOTH_P1_S1_BR , Q_R , Q_BL , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_TR2BL , LS_A_BL2TR , 150 } , // LS_PARRY_LL
// Reflecting a missile
{ " Reflect Top " , BOTH_P1_S1_T_ , Q_R , Q_T , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BL2TR , LS_A_T2B , 300 } , // LS_PARRY_UP,
{ " Reflect UR " , BOTH_P1_S1_TL , Q_R , Q_TR , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BR2TL , LS_A_TL2BR , 300 } , // LS_PARRY_UR,
{ " Reflect UL " , BOTH_P1_S1_TR , Q_R , Q_TL , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_BL2TR , LS_A_TR2BL , 300 } , // LS_PARRY_UL,
{ " Reflect LR " , BOTH_P1_S1_BR , Q_R , Q_BL , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_TR2BL , LS_A_BL2TR , 300 } , // LS_PARRY_LR
{ " Reflect LL " , BOTH_P1_S1_BL , Q_R , Q_BR , AFLAG_ACTIVE , 50 , BLK_WIDE , LS_R_TL2BR , LS_A_BR2TL , 300 } , // LS_PARRY_LL,
} ;
int transitionMove [ Q_NUM_QUADS ] [ Q_NUM_QUADS ] =
{
LS_NONE , //Can't transition to same pos!
LS_T1_BR__R , //40
LS_T1_BR_TR ,
LS_T1_BR_T_ ,
LS_T1_BR_TL ,
LS_T1_BR__L ,
LS_T1_BR_BL ,
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1__R_BR , //46
LS_NONE , //Can't transition to same pos!
LS_T1__R_TR ,
LS_T1__R_T_ ,
LS_T1__R_TL ,
LS_T1__R__L ,
LS_T1__R_BL ,
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1_TR_BR , //52
LS_T1_TR__R ,
LS_NONE , //Can't transition to same pos!
LS_T1_TR_T_ ,
LS_T1_TR_TL ,
LS_T1_TR__L ,
LS_T1_TR_BL ,
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1_T__BR , //58
LS_T1_T___R ,
LS_T1_T__TR ,
LS_NONE , //Can't transition to same pos!
LS_T1_T__TL ,
LS_T1_T___L ,
LS_T1_T__BL ,
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1_TL_BR , //64
LS_T1_TL__R ,
LS_T1_TL_TR ,
LS_T1_TL_T_ ,
LS_NONE , //Can't transition to same pos!
LS_T1_TL__L ,
LS_T1_TL_BL ,
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1__L_BR , //70
LS_T1__L__R ,
LS_T1__L_TR ,
LS_T1__L_T_ ,
LS_T1__L_TL ,
LS_NONE , //Can't transition to same pos!
LS_T1__L_BL ,
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1_BL_BR , //76
LS_T1_BL__R ,
LS_T1_BL_TR ,
LS_T1_BL_T_ ,
LS_T1_BL_TL ,
LS_T1_BL__L ,
LS_NONE , //Can't transition to same pos!
LS_NONE , //No transitions to bottom, and no anims start there, so shouldn't need any
LS_T1_BL_BR , //NOTE: there are no transitions from bottom, so re-use the bottom right transitions
LS_T1_BR__R ,
LS_T1_BR_TR ,
LS_T1_BR_T_ ,
LS_T1_BR_TL ,
LS_T1_BR__L ,
LS_T1_BR_BL ,
LS_NONE //No transitions to bottom, and no anims start there, so shouldn't need any
} ;
saberMoveName_t PM_AttackMoveForQuad ( int quad )
{
switch ( quad )
{
case Q_B :
case Q_BR :
return LS_A_BR2TL ;
break ;
case Q_R :
return LS_A_R2L ;
break ;
case Q_TR :
return LS_A_TR2BL ;
break ;
case Q_T :
return LS_A_T2B ;
break ;
case Q_TL :
return LS_A_TL2BR ;
break ;
case Q_L :
return LS_A_L2R ;
break ;
case Q_BL :
return LS_A_BL2TR ;
break ;
}
return LS_NONE ;
}
qboolean PM_SaberKataDone ( int curmove , int newmove ) ;
int PM_SaberAnimTransitionAnim ( int curmove , int newmove )
{
int retmove = newmove ;
if ( curmove = = LS_READY )
{ //just standing there
switch ( newmove )
{
case LS_A_TL2BR :
case LS_A_L2R :
case LS_A_BL2TR :
case LS_A_BR2TL :
case LS_A_R2L :
case LS_A_TR2BL :
case LS_A_T2B :
//transition is the start
retmove = LS_S_TL2BR + ( newmove - LS_A_TL2BR ) ;
break ;
}
}
else
{
switch ( newmove )
{
//transitioning to ready pose
case LS_READY :
switch ( curmove )
{
//transitioning from an attack
case LS_A_TL2BR :
case LS_A_L2R :
case LS_A_BL2TR :
case LS_A_BR2TL :
case LS_A_R2L :
case LS_A_TR2BL :
case LS_A_T2B :
//transition is the return
retmove = LS_R_TL2BR + ( newmove - LS_A_TL2BR ) ;
break ;
}
break ;
//transitioning to an attack
case LS_A_TL2BR :
case LS_A_L2R :
case LS_A_BL2TR :
case LS_A_BR2TL :
case LS_A_R2L :
case LS_A_TR2BL :
case LS_A_T2B :
if ( newmove = = curmove )
{
//going into an attack
if ( PM_SaberKataDone ( curmove , newmove ) )
{ //done with this kata, must return to ready before attack again
retmove = LS_R_TL2BR + ( newmove - LS_A_TL2BR ) ;
}
else
{ //okay to chain to another attack
retmove = transitionMove [ saberMoveData [ curmove ] . endQuad ] [ saberMoveData [ newmove ] . startQuad ] ;
}
}
else if ( saberMoveData [ curmove ] . endQuad = = saberMoveData [ newmove ] . startQuad )
{ //new move starts from same quadrant
retmove = newmove ;
}
else
{
switch ( curmove )
{
//transitioning from an attack
case LS_A_TL2BR :
case LS_A_L2R :
case LS_A_BL2TR :
case LS_A_BR2TL :
case LS_A_R2L :
case LS_A_TR2BL :
case LS_A_T2B :
case LS_D1_BR :
case LS_D1__R :
case LS_D1_TR :
case LS_D1_T_ :
case LS_D1_TL :
case LS_D1__L :
case LS_D1_BL :
case LS_D1_B_ :
retmove = transitionMove [ saberMoveData [ curmove ] . endQuad ] [ saberMoveData [ newmove ] . startQuad ] ;
break ;
//transitioning from a return
case LS_R_TL2BR :
case LS_R_L2R :
case LS_R_BL2TR :
case LS_R_BR2TL :
case LS_R_R2L :
case LS_R_TR2BL :
case LS_R_T2B :
//transitioning from a bounce
/*
case LS_BOUNCE_UL2LL :
case LS_BOUNCE_LL2UL :
case LS_BOUNCE_L2LL :
case LS_BOUNCE_L2UL :
case LS_BOUNCE_UR2LR :
case LS_BOUNCE_LR2UR :
case LS_BOUNCE_R2LR :
case LS_BOUNCE_R2UR :
case LS_BOUNCE_TOP :
case LS_OVER_UR2UL :
case LS_OVER_UL2UR :
case LS_BOUNCE_UR :
case LS_BOUNCE_UL :
case LS_BOUNCE_LR :
case LS_BOUNCE_LL :
*/
//transitioning from a parry/reflection/knockaway/broken parry
case LS_PARRY_UP :
case LS_PARRY_UR :
case LS_PARRY_UL :
case LS_PARRY_LR :
case LS_PARRY_LL :
case LS_REFLECT_UP :
case LS_REFLECT_UR :
case LS_REFLECT_UL :
case LS_REFLECT_LR :
case LS_REFLECT_LL :
case LS_K1_T_ :
case LS_K1_TR :
case LS_K1_TL :
case LS_K1_BR :
case LS_K1_BL :
case LS_V1_BR :
case LS_V1__R :
case LS_V1_TR :
case LS_V1_T_ :
case LS_V1_TL :
case LS_V1__L :
case LS_V1_BL :
case LS_V1_B_ :
case LS_H1_T_ :
case LS_H1_TR :
case LS_H1_TL :
case LS_H1_BR :
case LS_H1_BL :
retmove = transitionMove [ saberMoveData [ curmove ] . endQuad ] [ saberMoveData [ newmove ] . startQuad ] ;
break ;
//NB: transitioning from transitions is fine
}
}
break ;
//transitioning to any other anim is not supported
}
}
if ( retmove = = LS_NONE )
{
return newmove ;
}
return retmove ;
}
extern qboolean BG_InKnockDown ( int anim ) ;
saberMoveName_t PM_CheckStabDown ( void )
{
vec3_t faceFwd , facingAngles ;
vec3_t fwd ;
bgEntity_t * ent = NULL ;
trace_t tr ;
//yeah, vm's may complain, but.. who cares!
vec3_t trmins = { - 15 , - 15 , - 15 } ;
vec3_t trmaxs = { 15 , 15 , 15 } ;
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber1
& & ( saber1 - > saberFlags & SFL_NO_STABDOWN ) )
{
return LS_NONE ;
}
if ( saber2
& & ( saber2 - > saberFlags & SFL_NO_STABDOWN ) )
{
return LS_NONE ;
}
if ( pm - > ps - > groundEntityNum = = ENTITYNUM_NONE )
{ //sorry must be on ground!
return LS_NONE ;
}
if ( pm - > ps - > clientNum < MAX_CLIENTS )
{ //player
pm - > ps - > velocity [ 2 ] = 0 ;
pm - > cmd . upmove = 0 ;
}
VectorSet ( facingAngles , 0 , pm - > ps - > viewangles [ YAW ] , 0 ) ;
AngleVectors ( facingAngles , faceFwd , NULL , NULL ) ;
//FIXME: need to only move forward until we bump into our target...?
VectorMA ( pm - > ps - > origin , 164.0f , faceFwd , fwd ) ;
pm - > trace ( & tr , pm - > ps - > origin , trmins , trmaxs , fwd , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
if ( tr . entityNum < ENTITYNUM_WORLD )
{
ent = PM_BGEntForNum ( tr . entityNum ) ;
}
if ( ent & &
( ent - > s . eType = = ET_PLAYER | | ent - > s . eType = = ET_NPC ) & &
BG_InKnockDown ( ent - > s . legsAnim ) )
{ //guy is on the ground below me, do a top-down attack
if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
return LS_STABDOWN_DUAL ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
return LS_STABDOWN_STAFF ;
}
else
{
return LS_STABDOWN ;
}
}
return LS_NONE ;
}
int PM_SaberMoveQuadrantForMovement ( usercmd_t * ucmd )
{
if ( ucmd - > rightmove > 0 )
{ //moving right
if ( ucmd - > forwardmove > 0 )
{ //forward right = TL2BR slash
return Q_TL ;
}
else if ( ucmd - > forwardmove < 0 )
{ //backward right = BL2TR uppercut
return Q_BL ;
}
else
{ //just right is a left slice
return Q_L ;
}
}
else if ( ucmd - > rightmove < 0 )
{ //moving left
if ( ucmd - > forwardmove > 0 )
{ //forward left = TR2BL slash
return Q_TR ;
}
else if ( ucmd - > forwardmove < 0 )
{ //backward left = BR2TL uppercut
return Q_BR ;
}
else
{ //just left is a right slice
return Q_R ;
}
}
else
{ //not moving left or right
if ( ucmd - > forwardmove > 0 )
{ //forward= T2B slash
return Q_T ;
}
else if ( ucmd - > forwardmove < 0 )
{ //backward= T2B slash //or B2T uppercut?
return Q_T ;
}
else
{ //Not moving at all
return Q_R ;
}
}
}
//===================================================================
qboolean PM_SaberInBounce ( int move )
{
if ( move > = LS_B1_BR & & move < = LS_B1_BL )
{
return qtrue ;
}
if ( move > = LS_D1_BR & & move < = LS_D1_BL )
{
return qtrue ;
}
return qfalse ;
}
qboolean PM_SaberInTransition ( int move ) ;
int saberMoveTransitionAngle [ Q_NUM_QUADS ] [ Q_NUM_QUADS ] =
{
0 , //Q_BR,Q_BR,
45 , //Q_BR,Q_R,
90 , //Q_BR,Q_TR,
135 , //Q_BR,Q_T,
180 , //Q_BR,Q_TL,
215 , //Q_BR,Q_L,
270 , //Q_BR,Q_BL,
45 , //Q_BR,Q_B,
45 , //Q_R,Q_BR,
0 , //Q_R,Q_R,
45 , //Q_R,Q_TR,
90 , //Q_R,Q_T,
135 , //Q_R,Q_TL,
180 , //Q_R,Q_L,
215 , //Q_R,Q_BL,
90 , //Q_R,Q_B,
90 , //Q_TR,Q_BR,
45 , //Q_TR,Q_R,
0 , //Q_TR,Q_TR,
45 , //Q_TR,Q_T,
90 , //Q_TR,Q_TL,
135 , //Q_TR,Q_L,
180 , //Q_TR,Q_BL,
135 , //Q_TR,Q_B,
135 , //Q_T,Q_BR,
90 , //Q_T,Q_R,
45 , //Q_T,Q_TR,
0 , //Q_T,Q_T,
45 , //Q_T,Q_TL,
90 , //Q_T,Q_L,
135 , //Q_T,Q_BL,
180 , //Q_T,Q_B,
180 , //Q_TL,Q_BR,
135 , //Q_TL,Q_R,
90 , //Q_TL,Q_TR,
45 , //Q_TL,Q_T,
0 , //Q_TL,Q_TL,
45 , //Q_TL,Q_L,
90 , //Q_TL,Q_BL,
135 , //Q_TL,Q_B,
215 , //Q_L,Q_BR,
180 , //Q_L,Q_R,
135 , //Q_L,Q_TR,
90 , //Q_L,Q_T,
45 , //Q_L,Q_TL,
0 , //Q_L,Q_L,
45 , //Q_L,Q_BL,
90 , //Q_L,Q_B,
270 , //Q_BL,Q_BR,
215 , //Q_BL,Q_R,
180 , //Q_BL,Q_TR,
135 , //Q_BL,Q_T,
90 , //Q_BL,Q_TL,
45 , //Q_BL,Q_L,
0 , //Q_BL,Q_BL,
45 , //Q_BL,Q_B,
45 , //Q_B,Q_BR,
90 , //Q_B,Q_R,
135 , //Q_B,Q_TR,
180 , //Q_B,Q_T,
135 , //Q_B,Q_TL,
90 , //Q_B,Q_L,
45 , //Q_B,Q_BL,
0 //Q_B,Q_B,
} ;
int PM_SaberAttackChainAngle ( int move1 , int move2 )
{
if ( move1 = = - 1 | | move2 = = - 1 )
{
return - 1 ;
}
return saberMoveTransitionAngle [ saberMoveData [ move1 ] . endQuad ] [ saberMoveData [ move2 ] . startQuad ] ;
}
qboolean PM_SaberKataDone ( int curmove , int newmove )
{
if ( pm - > ps - > m_iVehicleNum )
{ //never continue kata on vehicle
if ( pm - > ps - > saberAttackChainCount > 0 )
{
return qtrue ;
}
}
if ( pm - > ps - > fd . saberAnimLevel = = SS_DESANN | | pm - > ps - > fd . saberAnimLevel = = SS_TAVION )
{ //desann and tavion can link up as many attacks as they want
return qfalse ;
}
if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
//TEMP: for now, let staff attacks infinitely chain
return qfalse ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
//TEMP: for now, let staff attacks infinitely chain
return qfalse ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = FORCE_LEVEL_3 )
{
if ( curmove = = LS_NONE | | newmove = = LS_NONE )
{
if ( pm - > ps - > fd . saberAnimLevel > = FORCE_LEVEL_3 & & pm - > ps - > saberAttackChainCount > PM_irand_timesync ( 0 , 1 ) )
{
return qtrue ;
}
}
else if ( pm - > ps - > saberAttackChainCount > PM_irand_timesync ( 2 , 3 ) )
{
return qtrue ;
}
else if ( pm - > ps - > saberAttackChainCount > 0 )
{
int chainAngle = PM_SaberAttackChainAngle ( curmove , newmove ) ;
if ( chainAngle < 135 | | chainAngle > 215 )
{ //if trying to chain to a move that doesn't continue the momentum
return qtrue ;
}
else if ( chainAngle = = 180 )
{ //continues the momentum perfectly, allow it to chain 66% of the time
if ( pm - > ps - > saberAttackChainCount > 1 )
{
return qtrue ;
}
}
else
{ //would continue the movement somewhat, 50% chance of continuing
if ( pm - > ps - > saberAttackChainCount > 2 )
{
return qtrue ;
}
}
}
}
else
{ //Perhaps have chainAngle influence fast and medium chains as well? For now, just do level 3.
if ( newmove = = LS_A_TL2BR | |
newmove = = LS_A_L2R | |
newmove = = LS_A_BL2TR | |
newmove = = LS_A_BR2TL | |
newmove = = LS_A_R2L | |
newmove = = LS_A_TR2BL )
{ //lower chaining tolerance for spinning saber anims
int chainTolerance ;
if ( pm - > ps - > fd . saberAnimLevel = = FORCE_LEVEL_1 )
{
chainTolerance = 5 ;
}
else
{
chainTolerance = 3 ;
}
if ( pm - > ps - > saberAttackChainCount > = chainTolerance & & PM_irand_timesync ( 1 , pm - > ps - > saberAttackChainCount ) > chainTolerance )
{
return qtrue ;
}
}
if ( pm - > ps - > fd . saberAnimLevel = = FORCE_LEVEL_2 & & pm - > ps - > saberAttackChainCount > PM_irand_timesync ( 2 , 5 ) )
{
return qtrue ;
}
}
return qfalse ;
}
void PM_SetAnimFrame ( playerState_t * gent , int frame , qboolean torso , qboolean legs )
{
gent - > saberLockFrame = frame ;
}
int PM_SaberLockWinAnim ( qboolean victory , qboolean superBreak )
{
int winAnim = - 1 ;
switch ( pm - > ps - > torsoAnim )
{
/*
default :
# ifndef FINAL_BUILD
Com_Printf ( S_COLOR_RED " ERROR-PM_SaberLockBreak: %s not in saberlock anim, anim = (%d)%s \n " , pm - > gent - > NPC_type , pm - > ps - > torsoAnim , animTable [ pm - > ps - > torsoAnim ] . name ) ;
# endif
*/
case BOTH_BF2LOCK :
if ( superBreak )
{
winAnim = BOTH_LK_S_S_T_SB_1_W ;
}
else if ( ! victory )
{
winAnim = BOTH_BF1BREAK ;
}
else
{
pm - > ps - > saberMove = LS_A_T2B ;
winAnim = BOTH_A3_T__B_ ;
}
break ;
case BOTH_BF1LOCK :
if ( superBreak )
{
winAnim = BOTH_LK_S_S_T_SB_1_W ;
}
else if ( ! victory )
{
winAnim = BOTH_KNOCKDOWN4 ;
}
else
{
pm - > ps - > saberMove = LS_K1_T_ ;
winAnim = BOTH_K1_S1_T_ ;
}
break ;
case BOTH_CWCIRCLELOCK :
if ( superBreak )
{
winAnim = BOTH_LK_S_S_S_SB_1_W ;
}
else if ( ! victory )
{
pm - > ps - > saberMove = LS_V1_BL ; //pm->ps->saberBounceMove =
pm - > ps - > saberBlocked = BLOCKED_PARRY_BROKEN ;
winAnim = BOTH_V1_BL_S1 ;
}
else
{
winAnim = BOTH_CWCIRCLEBREAK ;
}
break ;
case BOTH_CCWCIRCLELOCK :
if ( superBreak )
{
winAnim = BOTH_LK_S_S_S_SB_1_W ;
}
else if ( ! victory )
{
pm - > ps - > saberMove = LS_V1_BR ; //pm->ps->saberBounceMove =
pm - > ps - > saberBlocked = BLOCKED_PARRY_BROKEN ;
winAnim = BOTH_V1_BR_S1 ;
}
else
{
winAnim = BOTH_CCWCIRCLEBREAK ;
}
break ;
default :
//must be using new system:
break ;
}
if ( winAnim ! = - 1 )
{
PM_SetAnim ( SETANIM_BOTH , winAnim , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD , 0 ) ;
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ;
pm - > ps - > saberBlocked = BLOCKED_NONE ;
pm - > ps - > weaponstate = WEAPON_FIRING ;
/*
if ( superBreak
& & winAnim ! = BOTH_LK_ST_DL_T_SB_1_W )
{ //going to attack with saber, do a saber trail
pm - > ps - > SaberActivateTrail ( 200 ) ;
}
*/
}
return winAnim ;
}
// Need to avoid nesting namespaces!
# include "../namespace_end.h"
# ifdef QAGAME //including game headers on cgame is FORBIDDEN ^_^
# include "g_local.h"
extern void NPC_SetAnim ( gentity_t * ent , int setAnimParts , int anim , int setAnimFlags ) ;
extern gentity_t g_entities [ ] ;
# elif defined CGAME
2013-04-19 03:47:29 +00:00
# include "../cgame/cg_local.h" //ahahahahhahahaha@$!$!
2013-04-19 02:52:48 +00:00
# endif
# include "../namespace_begin.h"
int PM_SaberLockLoseAnim ( playerState_t * genemy , qboolean victory , qboolean superBreak )
{
int loseAnim = - 1 ;
switch ( genemy - > torsoAnim )
{
/*
default :
# ifndef FINAL_BUILD
Com_Printf ( S_COLOR_RED " ERROR-PM_SaberLockBreak: %s not in saberlock anim, anim = (%d)%s \n " , genemy - > NPC_type , genemy - > client - > ps . torsoAnim , animTable [ genemy - > client - > ps . torsoAnim ] . name ) ;
# endif
*/
case BOTH_BF2LOCK :
if ( superBreak )
{
loseAnim = BOTH_LK_S_S_T_SB_1_L ;
}
else if ( ! victory )
{
loseAnim = BOTH_BF1BREAK ;
}
else
{
if ( ! victory )
{ //no-one won
genemy - > saberMove = LS_K1_T_ ;
loseAnim = BOTH_K1_S1_T_ ;
}
else
{ //FIXME: this anim needs to transition back to ready when done
loseAnim = BOTH_BF1BREAK ;
}
}
break ;
case BOTH_BF1LOCK :
if ( superBreak )
{
loseAnim = BOTH_LK_S_S_T_SB_1_L ;
}
else if ( ! victory )
{
loseAnim = BOTH_KNOCKDOWN4 ;
}
else
{
if ( ! victory )
{ //no-one won
genemy - > saberMove = LS_A_T2B ;
loseAnim = BOTH_A3_T__B_ ;
}
else
{
loseAnim = BOTH_KNOCKDOWN4 ;
}
}
break ;
case BOTH_CWCIRCLELOCK :
if ( superBreak )
{
loseAnim = BOTH_LK_S_S_S_SB_1_L ;
}
else if ( ! victory )
{
genemy - > saberMove = LS_V1_BL ; //genemy->saberBounceMove =
genemy - > saberBlocked = BLOCKED_PARRY_BROKEN ;
loseAnim = BOTH_V1_BL_S1 ;
}
else
{
if ( ! victory )
{ //no-one won
loseAnim = BOTH_CCWCIRCLEBREAK ;
}
else
{
genemy - > saberMove = LS_V1_BL ; //genemy->saberBounceMove =
genemy - > saberBlocked = BLOCKED_PARRY_BROKEN ;
loseAnim = BOTH_V1_BL_S1 ;
/*
genemy - > client - > ps . saberMove = genemy - > client - > ps . saberBounceMove = LS_H1_BR ;
genemy - > client - > ps . saberBlocked = BLOCKED_PARRY_BROKEN ;
loseAnim = BOTH_H1_S1_BL ;
*/
}
}
break ;
case BOTH_CCWCIRCLELOCK :
if ( superBreak )
{
loseAnim = BOTH_LK_S_S_S_SB_1_L ;
}
else if ( ! victory )
{
genemy - > saberMove = LS_V1_BR ; //genemy->saberBounceMove =
genemy - > saberBlocked = BLOCKED_PARRY_BROKEN ;
loseAnim = BOTH_V1_BR_S1 ;
}
else
{
if ( ! victory )
{ //no-one won
loseAnim = BOTH_CWCIRCLEBREAK ;
}
else
{
genemy - > saberMove = LS_V1_BR ; //genemy->saberBounceMove =
genemy - > saberBlocked = BLOCKED_PARRY_BROKEN ;
loseAnim = BOTH_V1_BR_S1 ;
/*
genemy - > client - > ps . saberMove = genemy - > client - > ps . saberBounceMove = LS_H1_BL ;
genemy - > client - > ps . saberBlocked = BLOCKED_PARRY_BROKEN ;
loseAnim = BOTH_H1_S1_BR ;
*/
}
}
break ;
}
if ( loseAnim ! = - 1 )
{
# ifdef QAGAME
NPC_SetAnim ( & g_entities [ genemy - > clientNum ] , SETANIM_BOTH , loseAnim , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ) ;
genemy - > weaponTime = genemy - > torsoTimer ; // + 250;
# endif
genemy - > saberBlocked = BLOCKED_NONE ;
genemy - > weaponstate = WEAPON_READY ;
}
return loseAnim ;
}
int PM_SaberLockResultAnim ( playerState_t * duelist , qboolean superBreak , qboolean won )
{
int baseAnim = duelist - > torsoAnim ;
switch ( baseAnim )
{
case BOTH_LK_S_S_S_L_2 : //lock if I'm using single vs. a single and other intitiated
baseAnim = BOTH_LK_S_S_S_L_1 ;
break ;
case BOTH_LK_S_S_T_L_2 : //lock if I'm using single vs. a single and other initiated
baseAnim = BOTH_LK_S_S_T_L_1 ;
break ;
case BOTH_LK_DL_DL_S_L_2 : //lock if I'm using dual vs. dual and other initiated
baseAnim = BOTH_LK_DL_DL_S_L_1 ;
break ;
case BOTH_LK_DL_DL_T_L_2 : //lock if I'm using dual vs. dual and other initiated
baseAnim = BOTH_LK_DL_DL_T_L_1 ;
break ;
case BOTH_LK_ST_ST_S_L_2 : //lock if I'm using staff vs. a staff and other initiated
baseAnim = BOTH_LK_ST_ST_S_L_1 ;
break ;
case BOTH_LK_ST_ST_T_L_2 : //lock if I'm using staff vs. a staff and other initiated
baseAnim = BOTH_LK_ST_ST_T_L_1 ;
break ;
}
//what kind of break?
if ( ! superBreak )
{
baseAnim - = 2 ;
}
else if ( superBreak )
{
baseAnim + = 1 ;
}
else
{ //WTF? Not a valid result
return - 1 ;
}
//win or lose?
if ( won )
{
baseAnim + = 1 ;
}
//play the anim and hold it
# ifdef QAGAME
//server-side: set it on the other guy, too
if ( duelist - > clientNum = = pm - > ps - > clientNum )
{ //me
PM_SetAnim ( SETANIM_BOTH , baseAnim , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD , 0 ) ;
}
else
{ //other guy
NPC_SetAnim ( & g_entities [ duelist - > clientNum ] , SETANIM_BOTH , baseAnim , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD ) ;
}
# else
PM_SetAnim ( SETANIM_BOTH , baseAnim , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD , 0 ) ;
# endif
if ( superBreak
& & ! won )
{ //if you lose a superbreak, you're defenseless
/*
//Taken care of in SetSaberBoxSize()
//make saberent not block
gentity_t * saberent = & g_entities [ duelist - > client - > ps . saberEntityNum ] ;
if ( saberent )
{
VectorClear ( saberent - > mins ) ;
VectorClear ( saberent - > maxs ) ;
G_SetOrigin ( saberent , duelist - > currentOrigin ) ;
}
*/
# ifdef QAGAME
if ( 1 )
# else
if ( duelist - > clientNum = = pm - > ps - > clientNum )
# endif
{
//set sabermove to none
duelist - > saberMove = LS_NONE ;
//Hold the anim a little longer than it is
duelist - > torsoTimer + = 250 ;
}
}
# ifdef QAGAME
if ( 1 )
# else
if ( duelist - > clientNum = = pm - > ps - > clientNum )
# endif
{
//no attacking during this anim
duelist - > weaponTime = duelist - > torsoTimer ;
duelist - > saberBlocked = BLOCKED_NONE ;
/*
if ( superBreak
& & won
& & baseAnim ! = BOTH_LK_ST_DL_T_SB_1_W )
{ //going to attack with saber, do a saber trail
duelist - > client - > ps . SaberActivateTrail ( 200 ) ;
}
*/
}
return baseAnim ;
}
void PM_SaberLockBreak ( playerState_t * genemy , qboolean victory , int strength )
{
int winAnim = BOTH_STAND1 , loseAnim = BOTH_STAND1 ;
//qboolean punishLoser = qfalse;
qboolean noKnockdown = qfalse ;
qboolean singleVsSingle = qtrue ;
qboolean superBreak = ( strength + pm - > ps - > saberLockHits > Q_irand ( 2 , 4 ) ) ;
winAnim = PM_SaberLockWinAnim ( victory , superBreak ) ;
if ( winAnim ! = - 1 )
{ //a single vs. single break
loseAnim = PM_SaberLockLoseAnim ( genemy , victory , superBreak ) ;
}
else
{ //must be a saberlock that's not between single and single...
singleVsSingle = qfalse ;
winAnim = PM_SaberLockResultAnim ( pm - > ps , superBreak , qtrue ) ;
pm - > ps - > weaponstate = WEAPON_FIRING ;
loseAnim = PM_SaberLockResultAnim ( genemy , superBreak , qfalse ) ;
genemy - > weaponstate = WEAPON_READY ;
}
if ( victory )
{ //someone lost the lock, so punish them by knocking them down
if ( pm - > ps - > saberLockHits & & ! superBreak )
{ //there was some over-power in the win, but not enough to superbreak
vec3_t oppDir ;
int strength = 8 ;
VectorSubtract ( genemy - > origin , pm - > ps - > origin , oppDir ) ;
VectorNormalize ( oppDir ) ;
if ( noKnockdown )
{
if ( ! genemy - > saberEntityNum )
{ //if he has already lost his saber then just knock him down
noKnockdown = qfalse ;
}
}
if ( ! noKnockdown & & BG_KnockDownable ( genemy ) )
{
genemy - > forceHandExtend = HANDEXTEND_KNOCKDOWN ;
genemy - > forceHandExtendTime = pm - > cmd . serverTime + 1100 ;
genemy - > forceDodgeAnim = 0 ; //this toggles between 1 and 0, when it's 1 we should play the get up anim
genemy - > otherKiller = pm - > ps - > clientNum ;
genemy - > otherKillerTime = pm - > cmd . serverTime + 5000 ;
genemy - > otherKillerDebounceTime = pm - > cmd . serverTime + 100 ;
//genemy->otherKillerMOD = MOD_UNKNOWN;
//genemy->otherKillerVehWeapon = 0;
//genemy->otherKillerWeaponType = WP_NONE;
genemy - > velocity [ 0 ] = oppDir [ 0 ] * ( strength * 40 ) ;
genemy - > velocity [ 1 ] = oppDir [ 1 ] * ( strength * 40 ) ;
genemy - > velocity [ 2 ] = 100 ;
}
pm - > checkDuelLoss = genemy - > clientNum + 1 ;
pm - > ps - > saberEventFlags | = SEF_LOCK_WON ;
}
}
else
{ //If no one lost, then shove each player away from the other
vec3_t oppDir ;
int strength = 4 ;
VectorSubtract ( genemy - > origin , pm - > ps - > origin , oppDir ) ;
VectorNormalize ( oppDir ) ;
genemy - > velocity [ 0 ] = oppDir [ 0 ] * ( strength * 40 ) ;
genemy - > velocity [ 1 ] = oppDir [ 1 ] * ( strength * 40 ) ;
genemy - > velocity [ 2 ] = 150 ;
VectorSubtract ( pm - > ps - > origin , genemy - > origin , oppDir ) ;
VectorNormalize ( oppDir ) ;
pm - > ps - > velocity [ 0 ] = oppDir [ 0 ] * ( strength * 40 ) ;
pm - > ps - > velocity [ 1 ] = oppDir [ 1 ] * ( strength * 40 ) ;
pm - > ps - > velocity [ 2 ] = 150 ;
genemy - > forceHandExtend = HANDEXTEND_WEAPONREADY ;
}
pm - > ps - > weaponTime = 0 ;
genemy - > weaponTime = 0 ;
pm - > ps - > saberLockTime = genemy - > saberLockTime = 0 ;
pm - > ps - > saberLockFrame = genemy - > saberLockFrame = 0 ;
pm - > ps - > saberLockEnemy = genemy - > saberLockEnemy = 0 ;
pm - > ps - > forceHandExtend = HANDEXTEND_WEAPONREADY ;
PM_AddEvent ( EV_JUMP ) ;
if ( ! victory )
{ //no-one won
BG_AddPredictableEventToPlayerstate ( EV_JUMP , 0 , genemy ) ;
}
else
{
if ( PM_irand_timesync ( 0 , 1 ) )
{
BG_AddPredictableEventToPlayerstate ( EV_JUMP , PM_irand_timesync ( 0 , 75 ) , genemy ) ;
}
}
}
qboolean BG_CheckIncrementLockAnim ( int anim , int winOrLose )
{
qboolean increment = qfalse ; //???
//RULE: if you are the first style in the lock anim, you advance from LOSING position to WINNING position
// if you are the second style in the lock anim, you advance from WINNING position to LOSING position
switch ( anim )
{
//increment to win:
case BOTH_LK_DL_DL_S_L_1 : //lock if I'm using dual vs. dual and I initiated
case BOTH_LK_DL_DL_S_L_2 : //lock if I'm using dual vs. dual and other initiated
case BOTH_LK_DL_DL_T_L_1 : //lock if I'm using dual vs. dual and I initiated
case BOTH_LK_DL_DL_T_L_2 : //lock if I'm using dual vs. dual and other initiated
case BOTH_LK_DL_S_S_L_1 : //lock if I'm using dual vs. a single
case BOTH_LK_DL_S_T_L_1 : //lock if I'm using dual vs. a single
case BOTH_LK_DL_ST_S_L_1 : //lock if I'm using dual vs. a staff
case BOTH_LK_DL_ST_T_L_1 : //lock if I'm using dual vs. a staff
case BOTH_LK_S_S_S_L_1 : //lock if I'm using single vs. a single and I initiated
case BOTH_LK_S_S_T_L_2 : //lock if I'm using single vs. a single and other initiated
case BOTH_LK_ST_S_S_L_1 : //lock if I'm using staff vs. a single
case BOTH_LK_ST_S_T_L_1 : //lock if I'm using staff vs. a single
case BOTH_LK_ST_ST_T_L_1 : //lock if I'm using staff vs. a staff and I initiated
case BOTH_LK_ST_ST_T_L_2 : //lock if I'm using staff vs. a staff and other initiated
if ( winOrLose = = SABERLOCK_WIN )
{
increment = qtrue ;
}
else
{
increment = qfalse ;
}
break ;
//decrement to win:
case BOTH_LK_S_DL_S_L_1 : //lock if I'm using single vs. a dual
case BOTH_LK_S_DL_T_L_1 : //lock if I'm using single vs. a dual
case BOTH_LK_S_S_S_L_2 : //lock if I'm using single vs. a single and other intitiated
case BOTH_LK_S_S_T_L_1 : //lock if I'm using single vs. a single and I initiated
case BOTH_LK_S_ST_S_L_1 : //lock if I'm using single vs. a staff
case BOTH_LK_S_ST_T_L_1 : //lock if I'm using single vs. a staff
case BOTH_LK_ST_DL_S_L_1 : //lock if I'm using staff vs. dual
case BOTH_LK_ST_DL_T_L_1 : //lock if I'm using staff vs. dual
case BOTH_LK_ST_ST_S_L_1 : //lock if I'm using staff vs. a staff and I initiated
case BOTH_LK_ST_ST_S_L_2 : //lock if I'm using staff vs. a staff and other initiated
if ( winOrLose = = SABERLOCK_WIN )
{
increment = qfalse ;
}
else
{
increment = qtrue ;
}
break ;
default :
break ;
}
return increment ;
}
extern qboolean ValidAnimFileIndex ( int index ) ;
void PM_SaberLocked ( void )
{
int remaining = 0 ;
playerState_t * genemy ;
bgEntity_t * eGenemy = PM_BGEntForNum ( pm - > ps - > saberLockEnemy ) ;
if ( ! eGenemy )
{
return ;
}
genemy = eGenemy - > playerState ;
if ( ! genemy )
{
return ;
}
/*if ( ( (pm->ps->torsoAnim) == BOTH_BF2LOCK ||
( pm - > ps - > torsoAnim ) = = BOTH_BF1LOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_CWCIRCLELOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_CCWCIRCLELOCK )
& & ( ( genemy - > torsoAnim ) = = BOTH_BF2LOCK | |
( genemy - > torsoAnim ) = = BOTH_BF1LOCK | |
( genemy - > torsoAnim ) = = BOTH_CWCIRCLELOCK | |
( genemy - > torsoAnim ) = = BOTH_CCWCIRCLELOCK )
)
*/ //yeah..
if ( pm - > ps - > saberLockFrame & &
genemy - > saberLockFrame & &
BG_InSaberLock ( pm - > ps - > torsoAnim ) & &
BG_InSaberLock ( genemy - > torsoAnim ) )
{
float dist = 0 ;
pm - > ps - > torsoTimer = 0 ;
pm - > ps - > weaponTime = 0 ;
genemy - > torsoTimer = 0 ;
genemy - > weaponTime = 0 ;
dist = DistanceSquared ( pm - > ps - > origin , genemy - > origin ) ;
if ( dist < 64 | | dist > 6400 )
{ //between 8 and 80 from each other
PM_SaberLockBreak ( genemy , qfalse , 0 ) ;
return ;
}
/*
//NOTE: time-out is handled around where PM_SaberLocked is called
if ( pm - > ps - > saberLockTime < = pm - > cmd . serverTime + 500 )
{ //lock just ended
PM_SaberLockBreak ( genemy , qfalse , 0 ) ;
return ;
}
*/
if ( pm - > ps - > saberLockAdvance )
{ //holding attack
animation_t * anim ;
float currentFrame ;
int curFrame ;
int strength = 1 ;
pm - > ps - > saberLockAdvance = qfalse ;
anim = & pm - > animations [ pm - > ps - > torsoAnim ] ;
currentFrame = pm - > ps - > saberLockFrame ;
strength = pm - > ps - > fd . forcePowerLevel [ FP_SABER_OFFENSE ] + 1 ;
//advance/decrement my frame number
if ( BG_InSaberLockOld ( pm - > ps - > torsoAnim ) )
{ //old locks
if ( ( pm - > ps - > torsoAnim ) = = BOTH_CCWCIRCLELOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_BF2LOCK )
{
curFrame = floor ( currentFrame ) - strength ;
//drop my frame one
if ( curFrame < = anim - > firstFrame )
{ //I won! Break out
PM_SaberLockBreak ( genemy , qtrue , strength ) ;
return ;
}
else
{
PM_SetAnimFrame ( pm - > ps , curFrame , qtrue , qtrue ) ;
remaining = curFrame - anim - > firstFrame ;
}
}
else
{
curFrame = ceil ( currentFrame ) + strength ;
//advance my frame one
if ( curFrame > = anim - > firstFrame + anim - > numFrames )
{ //I won! Break out
PM_SaberLockBreak ( genemy , qtrue , strength ) ;
return ;
}
else
{
PM_SetAnimFrame ( pm - > ps , curFrame , qtrue , qtrue ) ;
remaining = anim - > firstFrame + anim - > numFrames - curFrame ;
}
}
}
else
{ //new locks
if ( BG_CheckIncrementLockAnim ( pm - > ps - > torsoAnim , SABERLOCK_WIN ) )
{
curFrame = ceil ( currentFrame ) + strength ;
//advance my frame one
if ( curFrame > = anim - > firstFrame + anim - > numFrames )
{ //I won! Break out
PM_SaberLockBreak ( genemy , qtrue , strength ) ;
return ;
}
else
{
PM_SetAnimFrame ( pm - > ps , curFrame , qtrue , qtrue ) ;
remaining = anim - > firstFrame + anim - > numFrames - curFrame ;
}
}
else
{
curFrame = floor ( currentFrame ) - strength ;
//drop my frame one
if ( curFrame < = anim - > firstFrame )
{ //I won! Break out
PM_SaberLockBreak ( genemy , qtrue , strength ) ;
return ;
}
else
{
PM_SetAnimFrame ( pm - > ps , curFrame , qtrue , qtrue ) ;
remaining = curFrame - anim - > firstFrame ;
}
}
}
if ( ! PM_irand_timesync ( 0 , 2 ) )
{
PM_AddEvent ( EV_JUMP ) ;
}
//advance/decrement enemy frame number
anim = & pm - > animations [ ( genemy - > torsoAnim ) ] ;
if ( BG_InSaberLockOld ( genemy - > torsoAnim ) )
{
if ( ( genemy - > torsoAnim ) = = BOTH_CWCIRCLELOCK | |
( genemy - > torsoAnim ) = = BOTH_BF1LOCK )
{
if ( ! PM_irand_timesync ( 0 , 2 ) )
{
BG_AddPredictableEventToPlayerstate ( EV_PAIN , floor ( ( float ) 80 / 100 * 100.0f ) , genemy ) ;
}
PM_SetAnimFrame ( genemy , anim - > firstFrame + remaining , qtrue , qtrue ) ;
}
else
{
PM_SetAnimFrame ( genemy , anim - > firstFrame + anim - > numFrames - remaining , qtrue , qtrue ) ;
}
}
else
{ //new locks
if ( BG_CheckIncrementLockAnim ( genemy - > torsoAnim , SABERLOCK_LOSE ) )
{
if ( ! PM_irand_timesync ( 0 , 2 ) )
{
BG_AddPredictableEventToPlayerstate ( EV_PAIN , floor ( ( float ) 80 / 100 * 100.0f ) , genemy ) ;
}
PM_SetAnimFrame ( genemy , anim - > firstFrame + anim - > numFrames - remaining , qtrue , qtrue ) ;
}
else
{
PM_SetAnimFrame ( genemy , anim - > firstFrame + remaining , qtrue , qtrue ) ;
}
}
}
}
else
{ //something broke us out of it
PM_SaberLockBreak ( genemy , qfalse , 0 ) ;
}
}
qboolean PM_SaberInBrokenParry ( int move )
{
if ( move > = LS_V1_BR & & move < = LS_V1_B_ )
{
return qtrue ;
}
if ( move > = LS_H1_T_ & & move < = LS_H1_BL )
{
return qtrue ;
}
return qfalse ;
}
int PM_BrokenParryForParry ( int move )
{
switch ( move )
{
case LS_PARRY_UP :
return LS_H1_T_ ;
break ;
case LS_PARRY_UR :
return LS_H1_TR ;
break ;
case LS_PARRY_UL :
return LS_H1_TL ;
break ;
case LS_PARRY_LR :
return LS_H1_BL ;
break ;
case LS_PARRY_LL :
return LS_H1_BR ;
break ;
case LS_READY :
return LS_H1_B_ ;
break ;
}
return LS_NONE ;
}
# define BACK_STAB_DISTANCE 128
qboolean PM_CanBackstab ( void )
{
trace_t tr ;
vec3_t flatAng ;
vec3_t fwd , back ;
vec3_t trmins = { - 15 , - 15 , - 8 } ;
vec3_t trmaxs = { 15 , 15 , 8 } ;
VectorCopy ( pm - > ps - > viewangles , flatAng ) ;
flatAng [ PITCH ] = 0 ;
AngleVectors ( flatAng , fwd , 0 , 0 ) ;
back [ 0 ] = pm - > ps - > origin [ 0 ] - fwd [ 0 ] * BACK_STAB_DISTANCE ;
back [ 1 ] = pm - > ps - > origin [ 1 ] - fwd [ 1 ] * BACK_STAB_DISTANCE ;
back [ 2 ] = pm - > ps - > origin [ 2 ] - fwd [ 2 ] * BACK_STAB_DISTANCE ;
pm - > trace ( & tr , pm - > ps - > origin , trmins , trmaxs , back , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
if ( tr . fraction ! = 1.0 & & tr . entityNum > = 0 & & tr . entityNum < ENTITYNUM_NONE )
{
bgEntity_t * bgEnt = PM_BGEntForNum ( tr . entityNum ) ;
if ( bgEnt & & ( bgEnt - > s . eType = = ET_PLAYER | | bgEnt - > s . eType = = ET_NPC ) )
{
return qtrue ;
}
}
return qfalse ;
}
saberMoveName_t PM_SaberFlipOverAttackMove ( void )
{
vec3_t fwdAngles , jumpFwd ;
// float zDiff = 0;
// playerState_t *psData;
// bgEntity_t *bgEnt;
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
//see if we have an overridden (or cancelled) lunge move
if ( saber1
& & saber1 - > jumpAtkFwdMove ! = LS_INVALID )
{
if ( saber1 - > jumpAtkFwdMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber1 - > jumpAtkFwdMove ;
}
}
if ( saber2
& & saber2 - > jumpAtkFwdMove ! = LS_INVALID )
{
if ( saber2 - > jumpAtkFwdMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber2 - > jumpAtkFwdMove ;
}
}
//no overrides, cancelled?
if ( saber1
& & saber1 - > jumpAtkFwdMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
if ( saber2
& & saber2 - > jumpAtkFwdMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
//just do it
VectorCopy ( pm - > ps - > viewangles , fwdAngles ) ;
fwdAngles [ PITCH ] = fwdAngles [ ROLL ] = 0 ;
AngleVectors ( fwdAngles , jumpFwd , NULL , NULL ) ;
VectorScale ( jumpFwd , 150 , pm - > ps - > velocity ) ; //was 50
pm - > ps - > velocity [ 2 ] = 400 ;
/*
bgEnt = PM_BGEntForNum ( tr - > entityNum ) ;
if ( ! bgEnt )
{
return LS_A_FLIP_STAB ;
}
psData = bgEnt - > playerState ;
//go higher for enemies higher than you, lower for those lower than you
if ( psData )
{
zDiff = psData - > origin [ 2 ] - pm - > ps - > origin [ 2 ] ;
}
else
{
zDiff = 0 ;
}
pm - > ps - > velocity [ 2 ] + = ( zDiff ) * 1.5f ;
//clamp to decent-looking values
if ( zDiff < = 0 & & pm - > ps - > velocity [ 2 ] < 200 )
{ //if we're on same level, don't let me jump so low, I clip into the ground
pm - > ps - > velocity [ 2 ] = 200 ;
}
else if ( pm - > ps - > velocity [ 2 ] < 100 )
{
pm - > ps - > velocity [ 2 ] = 100 ;
}
else if ( pm - > ps - > velocity [ 2 ] > 400 )
{
pm - > ps - > velocity [ 2 ] = 400 ;
}
*/
PM_SetForceJumpZStart ( pm - > ps - > origin [ 2 ] ) ; //so we don't take damage if we land at same height
PM_AddEvent ( EV_JUMP ) ;
pm - > ps - > fd . forceJumpSound = 1 ;
pm - > cmd . upmove = 0 ;
/*
if ( PM_irand_timesync ( 0 , 1 ) )
{
return LS_A_FLIP_STAB ;
}
else
*/
{
return LS_A_FLIP_SLASH ;
}
}
int PM_SaberBackflipAttackMove ( void )
{
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
//see if we have an overridden (or cancelled) lunge move
if ( saber1
& & saber1 - > jumpAtkBackMove ! = LS_INVALID )
{
if ( saber1 - > jumpAtkBackMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber1 - > jumpAtkBackMove ;
}
}
if ( saber2
& & saber2 - > jumpAtkBackMove ! = LS_INVALID )
{
if ( saber2 - > jumpAtkBackMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber2 - > jumpAtkBackMove ;
}
}
//no overrides, cancelled?
if ( saber1
& & saber1 - > jumpAtkBackMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
if ( saber2
& & saber2 - > jumpAtkBackMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
//just do it
pm - > cmd . upmove = 127 ;
pm - > ps - > velocity [ 2 ] = 500 ;
return LS_A_BACKFLIP_ATK ;
}
int PM_SaberDualJumpAttackMove ( void )
{
//FIXME: to make this move easier to execute, should be allowed to do it
// after you've already started your jump... but jump is delayed in
// this anim, so how do we undo the jump?
pm - > cmd . upmove = 0 ; //no jump just yet
return LS_JUMPATTACK_DUAL ;
}
# define FLIPHACK_DISTANCE 200
qboolean PM_SomeoneInFront ( trace_t * tr )
{ //Also a very simplified version of the sp counterpart
vec3_t flatAng ;
vec3_t fwd , back ;
vec3_t trmins = { - 15 , - 15 , - 8 } ;
vec3_t trmaxs = { 15 , 15 , 8 } ;
VectorCopy ( pm - > ps - > viewangles , flatAng ) ;
flatAng [ PITCH ] = 0 ;
AngleVectors ( flatAng , fwd , 0 , 0 ) ;
back [ 0 ] = pm - > ps - > origin [ 0 ] + fwd [ 0 ] * FLIPHACK_DISTANCE ;
back [ 1 ] = pm - > ps - > origin [ 1 ] + fwd [ 1 ] * FLIPHACK_DISTANCE ;
back [ 2 ] = pm - > ps - > origin [ 2 ] + fwd [ 2 ] * FLIPHACK_DISTANCE ;
pm - > trace ( tr , pm - > ps - > origin , trmins , trmaxs , back , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
if ( tr - > fraction ! = 1.0 & & tr - > entityNum > = 0 & & tr - > entityNum < ENTITYNUM_NONE )
{
bgEntity_t * bgEnt = PM_BGEntForNum ( tr - > entityNum ) ;
if ( bgEnt & & ( bgEnt - > s . eType = = ET_PLAYER | | bgEnt - > s . eType = = ET_NPC ) )
{
return qtrue ;
}
}
return qfalse ;
}
saberMoveName_t PM_SaberLungeAttackMove ( qboolean noSpecials )
{
vec3_t fwdAngles , jumpFwd ;
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
//see if we have an overridden (or cancelled) lunge move
if ( saber1
& & saber1 - > lungeAtkMove ! = LS_INVALID )
{
if ( saber1 - > lungeAtkMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber1 - > lungeAtkMove ;
}
}
if ( saber2
& & saber2 - > lungeAtkMove ! = LS_INVALID )
{
if ( saber2 - > lungeAtkMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber2 - > lungeAtkMove ;
}
}
//no overrides, cancelled?
if ( saber1
& & saber1 - > lungeAtkMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
if ( saber2
& & saber2 - > lungeAtkMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
//just do it
if ( pm - > ps - > fd . saberAnimLevel = = SS_FAST )
{
VectorCopy ( pm - > ps - > viewangles , fwdAngles ) ;
fwdAngles [ PITCH ] = fwdAngles [ ROLL ] = 0 ;
//do the lunge
AngleVectors ( fwdAngles , jumpFwd , NULL , NULL ) ;
VectorScale ( jumpFwd , 150 , pm - > ps - > velocity ) ;
PM_AddEvent ( EV_JUMP ) ;
return LS_A_LUNGE ;
}
else if ( ! noSpecials & & pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
return LS_SPINATTACK ;
}
else if ( ! noSpecials )
{
return LS_SPINATTACK_DUAL ;
}
return LS_A_T2B ;
}
saberMoveName_t PM_SaberJumpAttackMove2 ( void )
{
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
//see if we have an overridden (or cancelled) lunge move
if ( saber1
& & saber1 - > jumpAtkFwdMove ! = LS_INVALID )
{
if ( saber1 - > jumpAtkFwdMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber1 - > jumpAtkFwdMove ;
}
}
if ( saber2
& & saber2 - > jumpAtkFwdMove ! = LS_INVALID )
{
if ( saber2 - > jumpAtkFwdMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber2 - > jumpAtkFwdMove ;
}
}
//no overrides, cancelled?
if ( saber1
& & saber1 - > jumpAtkFwdMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
if ( saber2
& & saber2 - > jumpAtkFwdMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
//just do it
if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
return PM_SaberDualJumpAttackMove ( ) ;
}
else
{
//rwwFIXMEFIXME I don't like randomness for this sort of thing, gives people reason to
//complain combat is unpredictable. Maybe do something more clever to determine
//if we should do a left or right?
/*
if ( PM_irand_timesync ( 0 , 1 ) )
{
newmove = LS_JUMPATTACK_STAFF_LEFT ;
}
else
*/
{
return LS_JUMPATTACK_STAFF_RIGHT ;
}
}
return LS_A_T2B ;
}
saberMoveName_t PM_SaberJumpAttackMove ( void )
{
vec3_t fwdAngles , jumpFwd ;
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
//see if we have an overridden (or cancelled) lunge move
if ( saber1
& & saber1 - > jumpAtkFwdMove ! = LS_INVALID )
{
if ( saber1 - > jumpAtkFwdMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber1 - > jumpAtkFwdMove ;
}
}
if ( saber2
& & saber2 - > jumpAtkFwdMove ! = LS_INVALID )
{
if ( saber2 - > jumpAtkFwdMove ! = LS_NONE )
{
return ( saberMoveName_t ) saber2 - > jumpAtkFwdMove ;
}
}
//no overrides, cancelled?
if ( saber1
& & saber1 - > jumpAtkFwdMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
if ( saber2
& & saber2 - > jumpAtkFwdMove = = LS_NONE )
{
return LS_A_T2B ; //LS_NONE;
}
//just do it
VectorCopy ( pm - > ps - > viewangles , fwdAngles ) ;
fwdAngles [ PITCH ] = fwdAngles [ ROLL ] = 0 ;
AngleVectors ( fwdAngles , jumpFwd , NULL , NULL ) ;
VectorScale ( jumpFwd , 300 , pm - > ps - > velocity ) ;
pm - > ps - > velocity [ 2 ] = 280 ;
PM_SetForceJumpZStart ( pm - > ps - > origin [ 2 ] ) ; //so we don't take damage if we land at same height
PM_AddEvent ( EV_JUMP ) ;
pm - > ps - > fd . forceJumpSound = 1 ;
pm - > cmd . upmove = 0 ;
return LS_A_JUMP_T__B_ ;
}
float PM_GroundDistance ( void )
{
trace_t tr ;
vec3_t down ;
VectorCopy ( pm - > ps - > origin , down ) ;
down [ 2 ] - = 4096 ;
pm - > trace ( & tr , pm - > ps - > origin , pm - > mins , pm - > maxs , down , pm - > ps - > clientNum , MASK_SOLID ) ;
VectorSubtract ( pm - > ps - > origin , tr . endpos , down ) ;
return VectorLength ( down ) ;
}
float PM_WalkableGroundDistance ( void )
{
trace_t tr ;
vec3_t down ;
VectorCopy ( pm - > ps - > origin , down ) ;
down [ 2 ] - = 4096 ;
pm - > trace ( & tr , pm - > ps - > origin , pm - > mins , pm - > maxs , down , pm - > ps - > clientNum , MASK_SOLID ) ;
if ( tr . plane . normal [ 2 ] < MIN_WALK_NORMAL )
{ //can't stand on this plane
return 4096 ;
}
VectorSubtract ( pm - > ps - > origin , tr . endpos , down ) ;
return VectorLength ( down ) ;
}
qboolean BG_SaberInTransitionAny ( int move ) ;
static qboolean PM_CanDoDualDoubleAttacks ( void )
{
if ( pm - > ps - > weapon = = WP_SABER )
{
saberInfo_t * saber = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
if ( saber
& & ( saber - > saberFlags & SFL_NO_MIRROR_ATTACKS ) )
{
return qfalse ;
}
saber = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber
& & ( saber - > saberFlags & SFL_NO_MIRROR_ATTACKS ) )
{
return qfalse ;
}
}
if ( BG_SaberInSpecialAttack ( pm - > ps - > torsoAnim ) | |
BG_SaberInSpecialAttack ( pm - > ps - > legsAnim ) )
{
return qfalse ;
}
return qtrue ;
}
static qboolean PM_CheckEnemyPresence ( int dir , float radius )
{ //anyone in this dir?
vec3_t angles ;
vec3_t checkDir ;
vec3_t tTo ;
vec3_t tMins , tMaxs ;
trace_t tr ;
const float tSize = 12.0f ;
//sp uses a bbox ent list check, but.. that's not so easy/fast to
//do in predicted code. So I'll just do a single box trace in the proper direction,
//and take whatever is first hit.
VectorSet ( tMins , - tSize , - tSize , - tSize ) ;
VectorSet ( tMaxs , tSize , tSize , tSize ) ;
VectorCopy ( pm - > ps - > viewangles , angles ) ;
angles [ PITCH ] = 0.0f ;
switch ( dir )
{
case DIR_RIGHT :
AngleVectors ( angles , NULL , checkDir , NULL ) ;
break ;
case DIR_LEFT :
AngleVectors ( angles , NULL , checkDir , NULL ) ;
VectorScale ( checkDir , - 1 , checkDir ) ;
break ;
case DIR_FRONT :
AngleVectors ( angles , checkDir , NULL , NULL ) ;
break ;
case DIR_BACK :
AngleVectors ( angles , checkDir , NULL , NULL ) ;
VectorScale ( checkDir , - 1 , checkDir ) ;
break ;
}
VectorMA ( pm - > ps - > origin , radius , checkDir , tTo ) ;
pm - > trace ( & tr , pm - > ps - > origin , tMins , tMaxs , tTo , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
if ( tr . fraction ! = 1.0f & & tr . entityNum < ENTITYNUM_WORLD )
{ //let's see who we hit
bgEntity_t * bgEnt = PM_BGEntForNum ( tr . entityNum ) ;
if ( bgEnt & &
( bgEnt - > s . eType = = ET_PLAYER | | bgEnt - > s . eType = = ET_NPC ) )
{ //this guy can be considered an "enemy"... if he is on the same team, oh well. can't bg-check that (without a whole lot of hassle).
return qtrue ;
}
}
//no one in the trace
return qfalse ;
}
# define SABER_ALT_ATTACK_POWER 50 //75?
# define SABER_ALT_ATTACK_POWER_LR 10 //30?
# define SABER_ALT_ATTACK_POWER_FB 25 //30/50?
extern qboolean PM_SaberInReturn ( int move ) ; //bg_panimate.c
saberMoveName_t PM_CheckPullAttack ( void )
{
#if 0 //disabling these for MP, they aren't useful
if ( ! ( pm - > cmd . buttons & BUTTON_ATTACK ) )
{
return LS_NONE ;
}
if ( ( pm - > ps - > saberMove = = LS_READY | | PM_SaberInReturn ( pm - > ps - > saberMove ) | | PM_SaberInReflect ( pm - > ps - > saberMove ) ) //ready
//&& (pm->ps->clientNum < MAX_CLIENTS||PM_ControlledByPlayer())//PLAYER ONLY
& & pm - > ps - > fd . saberAnimLevel > = SS_FAST //single saber styles - FIXME: Tavion?
& & pm - > ps - > fd . saberAnimLevel < = SS_STRONG //single saber styles - FIXME: Tavion?
//&& G_TryingPullAttack( pm->gent, &pm->cmd, qfalse )
//&& pm->ps->fd.forcePowerLevel[FP_PULL]
//rwwFIXMEFIXME: rick has the damn msg.cpp file checked out exclusively so I can't update the bloody psf to send this for prediction
& & pm - > ps - > powerups [ PW_DISINT_4 ] > pm - > cmd . serverTime
& & ! ( pm - > ps - > fd . forcePowersActive & ( 1 < < FP_GRIP ) )
& & pm - > ps - > powerups [ PW_PULL ] > pm - > cmd . serverTime
//&& pm->cmd.forwardmove<0//pulling back
& & ( pm - > cmd . buttons & BUTTON_ATTACK ) //attacking
& & BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) ) //pm->ps->forcePower >= SABER_ALT_ATTACK_POWER_FB//have enough power
{ //FIXME: some NPC logic to do this?
qboolean doMove = qtrue ;
// if ( g_saberNewControlScheme->integer
// || g_crosshairEntNum < ENTITYNUM_WORLD )//in old control scheme, there has to be someone there
{
saberMoveName_t pullAttackMove = LS_NONE ;
if ( pm - > ps - > fd . saberAnimLevel = = SS_FAST )
{
pullAttackMove = LS_PULL_ATTACK_STAB ;
}
else
{
pullAttackMove = LS_PULL_ATTACK_SWING ;
}
/*
if ( g_crosshairEntNum < ENTITYNUM_WORLD
& & pm - > gent & & pm - > gent - > client )
{
gentity_t * targEnt = & g_entities [ g_crosshairEntNum ] ;
if ( targEnt - > client
& & targEnt - > health > 0
//FIXME: check other things like in knockdown, saberlock, uninterruptable anims, etc.
& & ! PM_InOnGroundAnim ( & targEnt - > client - > ps )
& & ! PM_LockedAnim ( targEnt - > client - > ps . legsAnim )
& & ! PM_SuperBreakLoseAnim ( targEnt - > client - > ps . legsAnim )
& & ! PM_SuperBreakWinAnim ( targEnt - > client - > ps . legsAnim )
& & targEnt - > client - > ps . saberLockTime < = 0
& & WP_ForceThrowable ( targEnt , targEnt , pm - > gent , qtrue , 1.0f , 0.0f , NULL ) )
{
if ( ! g_saberNewControlScheme - > integer )
{ //in old control scheme, make sure they're close or far enough away for the move we'll be doing
float targDist = Distance ( targEnt - > currentOrigin , pm - > ps - > origin ) ;
if ( pullAttackMove = = LS_PULL_ATTACK_STAB )
{ //must be closer than 512
if ( targDist > 384.0f )
{
return LS_NONE ;
}
}
else //if ( pullAttackMove == LS_PULL_ATTACK_SWING )
{ //must be farther than 256
if ( targDist > 512.0f )
{
return LS_NONE ;
}
if ( targDist < 192.0f )
{
return LS_NONE ;
}
}
}
vec3_t targAngles = { 0 , targEnt - > client - > ps . viewangles [ YAW ] , 0 } ;
if ( InFront ( pm - > ps - > origin , targEnt - > currentOrigin , targAngles ) )
{
NPC_SetAnim ( targEnt , SETANIM_BOTH , BOTH_PULLED_INAIR_F , SETANIM_FLAG_OVERRIDE , SETANIM_FLAG_HOLD ) ;
}
else
{
NPC_SetAnim ( targEnt , SETANIM_BOTH , BOTH_PULLED_INAIR_B , SETANIM_FLAG_OVERRIDE , SETANIM_FLAG_HOLD ) ;
}
//hold the anim until I'm with done pull anim
targEnt - > client - > ps . legsAnimTimer = targEnt - > client - > ps . torsoAnimTimer = PM_AnimLength ( pm - > gent - > client - > clientInfo . animFileIndex , ( animNumber_t ) saberMoveData [ pullAttackMove ] . animToUse ) ;
//set pullAttackTime
pm - > gent - > client - > ps . pullAttackTime = targEnt - > client - > ps . pullAttackTime = level . time + targEnt - > client - > ps . legsAnimTimer ;
//make us know about each other
pm - > gent - > client - > ps . pullAttackEntNum = g_crosshairEntNum ;
targEnt - > client - > ps . pullAttackEntNum = pm - > ps - > clientNum ;
//do effect and sound on me
pm - > ps - > powerups [ PW_FORCE_PUSH ] = level . time + 1000 ;
if ( pm - > gent )
{
G_Sound ( pm - > gent , G_SoundIndex ( " sound/weapons/force/pull.wav " ) ) ;
}
doMove = qtrue ;
}
}
*/
if ( doMove )
{
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
return pullAttackMove ;
}
}
}
# endif
return LS_NONE ;
}
qboolean PM_InSecondaryStyle ( void )
{
if ( pm - > ps - > fd . saberAnimLevelBase = = SS_STAFF
| | pm - > ps - > fd . saberAnimLevelBase = = SS_DUAL )
{
if ( pm - > ps - > fd . saberAnimLevel ! = pm - > ps - > fd . saberAnimLevelBase )
{
return qtrue ;
}
}
return qfalse ;
}
saberMoveName_t PM_SaberAttackForMovement ( saberMoveName_t curmove )
{
saberMoveName_t newmove = LS_NONE ;
qboolean noSpecials = PM_InSecondaryStyle ( ) ;
qboolean allowCartwheels = qtrue ;
saberMoveName_t overrideJumpRightAttackMove = LS_INVALID ;
saberMoveName_t overrideJumpLeftAttackMove = LS_INVALID ;
if ( pm - > ps - > weapon = = WP_SABER )
{
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber1
& & saber1 - > jumpAtkRightMove ! = LS_INVALID )
{
if ( saber1 - > jumpAtkRightMove ! = LS_NONE )
{ //actually overriding
overrideJumpRightAttackMove = ( saberMoveName_t ) saber1 - > jumpAtkRightMove ;
}
else if ( saber2
& & saber2 - > jumpAtkRightMove > LS_NONE )
{ //would be cancelling it, but check the second saber, too
overrideJumpRightAttackMove = ( saberMoveName_t ) saber2 - > jumpAtkRightMove ;
}
else
{ //nope, just cancel it
overrideJumpRightAttackMove = LS_NONE ;
}
}
else if ( saber2
& & saber2 - > jumpAtkRightMove ! = LS_INVALID )
{ //first saber not overridden, check second
overrideJumpRightAttackMove = ( saberMoveName_t ) saber2 - > jumpAtkRightMove ;
}
if ( saber1
& & saber1 - > jumpAtkLeftMove ! = LS_INVALID )
{
if ( saber1 - > jumpAtkLeftMove ! = LS_NONE )
{ //actually overriding
overrideJumpLeftAttackMove = ( saberMoveName_t ) saber1 - > jumpAtkLeftMove ;
}
else if ( saber2
& & saber2 - > jumpAtkLeftMove > LS_NONE )
{ //would be cancelling it, but check the second saber, too
overrideJumpLeftAttackMove = ( saberMoveName_t ) saber2 - > jumpAtkLeftMove ;
}
else
{ //nope, just cancel it
overrideJumpLeftAttackMove = LS_NONE ;
}
}
else if ( saber2
& & saber2 - > jumpAtkLeftMove ! = LS_INVALID )
{ //first saber not overridden, check second
overrideJumpLeftAttackMove = ( saberMoveName_t ) saber1 - > jumpAtkLeftMove ;
}
if ( saber1
& & ( saber1 - > saberFlags & SFL_NO_CARTWHEELS ) )
{
allowCartwheels = qfalse ;
}
if ( saber2
& & ( saber2 - > saberFlags & SFL_NO_CARTWHEELS ) )
{
allowCartwheels = qfalse ;
}
}
if ( pm - > cmd . rightmove > 0 )
{ //moving right
if ( ! noSpecials
& & overrideJumpRightAttackMove ! = LS_NONE
& & pm - > ps - > velocity [ 2 ] > 20.0f //pm->ps->groundEntityNum != ENTITYNUM_NONE//on ground
& & ( pm - > cmd . buttons & BUTTON_ATTACK ) //hitting attack
& & PM_GroundDistance ( ) < 70.0f //not too high above ground
& & ( pm - > cmd . upmove > 0 | | ( pm - > ps - > pm_flags & PMF_JUMP_HELD ) ) //focus-holding player
& & BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_LR ) ) //have enough power
{ //cartwheel right
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_LR ) ;
if ( overrideJumpRightAttackMove ! = LS_INVALID )
{ //overridden with another move
return overrideJumpRightAttackMove ;
}
else
{
vec3_t right , fwdAngles ;
VectorSet ( fwdAngles , 0.0f , pm - > ps - > viewangles [ YAW ] , 0.0f ) ;
AngleVectors ( fwdAngles , NULL , right , NULL ) ;
pm - > ps - > velocity [ 0 ] = pm - > ps - > velocity [ 1 ] = 0.0f ;
VectorMA ( pm - > ps - > velocity , 190.0f , right , pm - > ps - > velocity ) ;
if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
newmove = LS_BUTTERFLY_RIGHT ;
pm - > ps - > velocity [ 2 ] = 350.0f ;
}
else if ( allowCartwheels )
{
//PM_SetJumped( JUMP_VELOCITY, qtrue );
PM_AddEvent ( EV_JUMP ) ;
pm - > ps - > velocity [ 2 ] = 300.0f ;
//if ( !Q_irand( 0, 1 ) )
//if (PM_GroundDistance() >= 25.0f)
if ( 1 )
{
newmove = LS_JUMPATTACK_ARIAL_RIGHT ;
}
else
{
newmove = LS_JUMPATTACK_CART_RIGHT ;
}
}
}
}
else if ( pm - > cmd . forwardmove > 0 )
{ //forward right = TL2BR slash
newmove = LS_A_TL2BR ;
}
else if ( pm - > cmd . forwardmove < 0 )
{ //backward right = BL2TR uppercut
newmove = LS_A_BL2TR ;
}
else
{ //just right is a left slice
newmove = LS_A_L2R ;
}
}
else if ( pm - > cmd . rightmove < 0 )
{ //moving left
if ( ! noSpecials
& & overrideJumpLeftAttackMove ! = LS_NONE
& & pm - > ps - > velocity [ 2 ] > 20.0f //pm->ps->groundEntityNum != ENTITYNUM_NONE//on ground
& & ( pm - > cmd . buttons & BUTTON_ATTACK ) //hitting attack
& & PM_GroundDistance ( ) < 70.0f //not too high above ground
& & ( pm - > cmd . upmove > 0 | | ( pm - > ps - > pm_flags & PMF_JUMP_HELD ) ) //focus-holding player
& & BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_LR ) ) //have enough power
{ //cartwheel left
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_LR ) ;
if ( overrideJumpLeftAttackMove ! = LS_INVALID )
{ //overridden with another move
return overrideJumpLeftAttackMove ;
}
else
{
vec3_t right , fwdAngles ;
VectorSet ( fwdAngles , 0.0f , pm - > ps - > viewangles [ YAW ] , 0.0f ) ;
AngleVectors ( fwdAngles , NULL , right , NULL ) ;
pm - > ps - > velocity [ 0 ] = pm - > ps - > velocity [ 1 ] = 0.0f ;
VectorMA ( pm - > ps - > velocity , - 190.0f , right , pm - > ps - > velocity ) ;
if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
newmove = LS_BUTTERFLY_LEFT ;
pm - > ps - > velocity [ 2 ] = 250.0f ;
}
else if ( allowCartwheels )
{
//PM_SetJumped( JUMP_VELOCITY, qtrue );
PM_AddEvent ( EV_JUMP ) ;
pm - > ps - > velocity [ 2 ] = 350.0f ;
//if ( !Q_irand( 0, 1 ) )
//if (PM_GroundDistance() >= 25.0f)
if ( 1 )
{
newmove = LS_JUMPATTACK_ARIAL_LEFT ;
}
else
{
newmove = LS_JUMPATTACK_CART_LEFT ;
}
}
}
}
else if ( pm - > cmd . forwardmove > 0 )
{ //forward left = TR2BL slash
newmove = LS_A_TR2BL ;
}
else if ( pm - > cmd . forwardmove < 0 )
{ //backward left = BR2TL uppercut
newmove = LS_A_BR2TL ;
}
else
{ //just left is a right slice
newmove = LS_A_R2L ;
}
}
else
{ //not moving left or right
if ( pm - > cmd . forwardmove > 0 )
{ //forward= T2B slash
if ( ! noSpecials & &
( pm - > ps - > fd . saberAnimLevel = = SS_DUAL | | pm - > ps - > fd . saberAnimLevel = = SS_STAFF ) & &
pm - > ps - > fd . forceRageRecoveryTime < pm - > cmd . serverTime & &
//pm->ps->fd.forcePowerLevel[FP_LEVITATION] > FORCE_LEVEL_1 &&
( pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE | | PM_GroundDistance ( ) < = 40 ) & &
pm - > ps - > velocity [ 2 ] > = 0 & &
( pm - > cmd . upmove > 0 | | pm - > ps - > pm_flags & PMF_JUMP_HELD ) & &
! BG_SaberInTransitionAny ( pm - > ps - > saberMove ) & &
! BG_SaberInAttack ( pm - > ps - > saberMove ) & &
pm - > ps - > weaponTime < = 0 & &
pm - > ps - > forceHandExtend = = HANDEXTEND_NONE & &
( pm - > cmd . buttons & BUTTON_ATTACK ) & &
BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) )
{ //DUAL/STAFF JUMP ATTACK
newmove = PM_SaberJumpAttackMove2 ( ) ;
if ( newmove ! = LS_A_T2B
& & newmove ! = LS_NONE )
{
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
}
}
else if ( ! noSpecials & &
pm - > ps - > fd . saberAnimLevel = = SS_MEDIUM & &
pm - > ps - > velocity [ 2 ] > 100 & &
PM_GroundDistance ( ) < 32 & &
! BG_InSpecialJump ( pm - > ps - > legsAnim ) & &
! BG_SaberInSpecialAttack ( pm - > ps - > torsoAnim ) & &
BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) )
{ //FLIP AND DOWNWARD ATTACK
//trace_t tr;
//if (PM_SomeoneInFront(&tr))
{
newmove = PM_SaberFlipOverAttackMove ( ) ;
if ( newmove ! = LS_A_T2B
& & newmove ! = LS_NONE )
{
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
}
}
}
else if ( ! noSpecials & &
pm - > ps - > fd . saberAnimLevel = = SS_STRONG & &
pm - > ps - > velocity [ 2 ] > 100 & &
PM_GroundDistance ( ) < 32 & &
! BG_InSpecialJump ( pm - > ps - > legsAnim ) & &
! BG_SaberInSpecialAttack ( pm - > ps - > torsoAnim ) & &
BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) )
{ //DFA
//trace_t tr;
//if (PM_SomeoneInFront(&tr))
{
newmove = PM_SaberJumpAttackMove ( ) ;
if ( newmove ! = LS_A_T2B
& & newmove ! = LS_NONE )
{
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
}
}
}
else if ( ( pm - > ps - > fd . saberAnimLevel = = SS_FAST | | pm - > ps - > fd . saberAnimLevel = = SS_DUAL | | pm - > ps - > fd . saberAnimLevel = = SS_STAFF ) & &
pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE & &
( pm - > ps - > pm_flags & PMF_DUCKED ) & &
pm - > ps - > weaponTime < = 0 & &
! BG_SaberInSpecialAttack ( pm - > ps - > torsoAnim ) & &
BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) )
{ //LUNGE (weak)
newmove = PM_SaberLungeAttackMove ( noSpecials ) ;
if ( newmove ! = LS_A_T2B
& & newmove ! = LS_NONE )
{
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
}
}
else if ( ! noSpecials )
{
saberMoveName_t stabDownMove = PM_CheckStabDown ( ) ;
if ( stabDownMove ! = LS_NONE
& & BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) )
{
newmove = stabDownMove ;
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
}
else
{
newmove = LS_A_T2B ;
}
}
}
else if ( pm - > cmd . forwardmove < 0 )
{ //backward= T2B slash//B2T uppercut?
if ( ! noSpecials & &
pm - > ps - > fd . saberAnimLevel = = SS_STAFF & &
pm - > ps - > fd . forceRageRecoveryTime < pm - > cmd . serverTime & &
pm - > ps - > fd . forcePowerLevel [ FP_LEVITATION ] > FORCE_LEVEL_1 & &
( pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE | | PM_GroundDistance ( ) < = 40 ) & &
pm - > ps - > velocity [ 2 ] > = 0 & &
( pm - > cmd . upmove > 0 | | pm - > ps - > pm_flags & PMF_JUMP_HELD ) & &
! BG_SaberInTransitionAny ( pm - > ps - > saberMove ) & &
! BG_SaberInAttack ( pm - > ps - > saberMove ) & &
pm - > ps - > weaponTime < = 0 & &
pm - > ps - > forceHandExtend = = HANDEXTEND_NONE & &
( pm - > cmd . buttons & BUTTON_ATTACK ) )
{ //BACKFLIP ATTACK
newmove = PM_SaberBackflipAttackMove ( ) ;
}
else if ( PM_CanBackstab ( ) & & ! BG_SaberInSpecialAttack ( pm - > ps - > torsoAnim ) )
{ //BACKSTAB (attack varies by level)
if ( pm - > ps - > fd . saberAnimLevel > = FORCE_LEVEL_2 & & pm - > ps - > fd . saberAnimLevel ! = SS_STAFF )
{ //medium and higher attacks
if ( ( pm - > ps - > pm_flags & PMF_DUCKED ) | | pm - > cmd . upmove < 0 )
{
newmove = LS_A_BACK_CR ;
}
else
{
newmove = LS_A_BACK ;
}
}
else
{ //weak attack
newmove = LS_A_BACKSTAB ;
}
}
else
{
newmove = LS_A_T2B ;
}
}
else if ( PM_SaberInBounce ( curmove ) )
{ //bounces should go to their default attack if you don't specify a direction but are attacking
newmove = saberMoveData [ curmove ] . chain_attack ;
if ( PM_SaberKataDone ( curmove , newmove ) )
{
newmove = saberMoveData [ curmove ] . chain_idle ;
}
else
{
newmove = saberMoveData [ curmove ] . chain_attack ;
}
}
else if ( curmove = = LS_READY )
{ //Not moving at all, shouldn't have gotten here...?
//for now, just pick a random attack
//newmove = Q_irand( LS_A_TL2BR, LS_A_T2B );
//rww - If we don't seed with a "common" value, the client and server will get mismatched
//prediction values. Under laggy conditions this will cause the appearance of rapid swing
//sequence changes.
newmove = LS_A_T2B ; //decided we don't like random attacks when idle, use an overhead instead.
}
}
if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
if ( ( newmove = = LS_A_R2L | | newmove = = LS_S_R2L
| | newmove = = LS_A_L2R | | newmove = = LS_S_L2R )
& & PM_CanDoDualDoubleAttacks ( )
& & PM_CheckEnemyPresence ( DIR_RIGHT , 100.0f )
& & PM_CheckEnemyPresence ( DIR_LEFT , 100.0f ) )
{ //enemy both on left and right
newmove = LS_DUAL_LR ;
//probably already moved, but...
pm - > cmd . rightmove = 0 ;
}
else if ( ( newmove = = LS_A_T2B | | newmove = = LS_S_T2B
| | newmove = = LS_A_BACK | | newmove = = LS_A_BACK_CR )
& & PM_CanDoDualDoubleAttacks ( )
& & PM_CheckEnemyPresence ( DIR_FRONT , 100.0f )
& & PM_CheckEnemyPresence ( DIR_BACK , 100.0f ) )
{ //enemy both in front and back
newmove = LS_DUAL_FB ;
//probably already moved, but...
pm - > cmd . forwardmove = 0 ;
}
}
return newmove ;
}
int PM_KickMoveForConditions ( void )
{
int kickMove = - 1 ;
//FIXME: only if FP_SABER_OFFENSE >= 3
if ( pm - > cmd . rightmove )
{ //kick to side
if ( pm - > cmd . rightmove > 0 )
{ //kick right
kickMove = LS_KICK_R ;
}
else
{ //kick left
kickMove = LS_KICK_L ;
}
pm - > cmd . rightmove = 0 ;
}
else if ( pm - > cmd . forwardmove )
{ //kick front/back
if ( pm - > cmd . forwardmove > 0 )
{ //kick fwd
/*
if ( pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE & &
PM_CheckEnemyPresence ( DIR_FRONT , 64.0f ) )
{
kickMove = LS_HILT_BASH ;
}
else
*/
{
kickMove = LS_KICK_F ;
}
}
else
{ //kick back
kickMove = LS_KICK_B ;
}
pm - > cmd . forwardmove = 0 ;
}
else
{
//if (pm->cmd.buttons & BUTTON_ATTACK)
//if (pm->ps->pm_flags & PMF_JUMP_HELD)
if ( 0 )
{ //ok, let's try some fancy kicks
//qboolean is actually of type int anyway, but just for safeness.
int front = ( int ) PM_CheckEnemyPresence ( DIR_FRONT , 100.0f ) ;
int back = ( int ) PM_CheckEnemyPresence ( DIR_BACK , 100.0f ) ;
int right = ( int ) PM_CheckEnemyPresence ( DIR_RIGHT , 100.0f ) ;
int left = ( int ) PM_CheckEnemyPresence ( DIR_LEFT , 100.0f ) ;
int numEnemy = front + back + right + left ;
if ( numEnemy > = 3 | |
( ( ! right | | ! left ) & & numEnemy > = 2 ) )
{ //> 2 enemies near, or, >= 2 enemies near and they are not to the right and left.
kickMove = LS_KICK_S ;
}
else if ( right & & left )
{ //enemies on both sides
kickMove = LS_KICK_RL ;
}
else
{ //oh well, just do a forward kick
kickMove = LS_KICK_F ;
}
pm - > cmd . upmove = 0 ;
}
}
return kickMove ;
}
qboolean BG_InSlopeAnim ( int anim ) ;
qboolean PM_RunningAnim ( int anim ) ;
qboolean PM_SaberMoveOkayForKata ( void )
{
if ( pm - > ps - > saberMove = = LS_READY
| | PM_SaberInStart ( pm - > ps - > saberMove ) )
{
return qtrue ;
}
else
{
return qfalse ;
}
}
qboolean PM_CanDoKata ( void )
{
if ( PM_InSecondaryStyle ( ) )
{
return qfalse ;
}
if ( ! pm - > ps - > saberInFlight //not throwing saber
& & PM_SaberMoveOkayForKata ( )
& & ! BG_SaberInKata ( pm - > ps - > saberMove )
& & ! BG_InKataAnim ( pm - > ps - > legsAnim )
& & ! BG_InKataAnim ( pm - > ps - > torsoAnim )
/*
& & pm - > ps - > saberAnimLevel > = SS_FAST //fast, med or strong style
& & pm - > ps - > saberAnimLevel < = SS_STRONG //FIXME: Tavion, too?
*/
& & pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE //not in the air
& & ( pm - > cmd . buttons & BUTTON_ATTACK ) //pressing attack
& & ( pm - > cmd . buttons & BUTTON_ALT_ATTACK ) //pressing alt attack
& & ! pm - > cmd . forwardmove //not moving f/b
& & ! pm - > cmd . rightmove //not moving r/l
& & pm - > cmd . upmove < = 0 //not jumping...?
& & BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER ) ) // have enough power
{ //FIXME: check rage, etc...
saberInfo_t * saber = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
if ( saber
& & saber - > kataMove = = LS_NONE )
{ //kata move has been overridden in a way that should stop you from doing it at all
return qfalse ;
}
saber = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber
& & saber - > kataMove = = LS_NONE )
{ //kata move has been overridden in a way that should stop you from doing it at all
return qfalse ;
}
return qtrue ;
}
return qfalse ;
}
qboolean PM_CheckAltKickAttack ( void )
{
if ( pm - > ps - > weapon = = WP_SABER )
{
saberInfo_t * saber = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
if ( saber
& & ( saber - > saberFlags & SFL_NO_KICKS ) )
{
return qfalse ;
}
saber = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber
& & ( saber - > saberFlags & SFL_NO_KICKS ) )
{
return qfalse ;
}
}
if ( ( pm - > cmd . buttons & BUTTON_ALT_ATTACK )
//&& (!(pm->ps->pm_flags&PMF_ALT_ATTACK_HELD)||PM_SaberInReturn(pm->ps->saberMove))
& & ( ! BG_FlippingAnim ( pm - > ps - > legsAnim ) | | pm - > ps - > legsTimer < = 250 )
& & ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF /*||!pm->ps->saber[0].throwable*/ ) & & ! pm - > ps - > saberHolstered )
{
return qtrue ;
}
return qfalse ;
}
int bg_parryDebounce [ NUM_FORCE_POWER_LEVELS ] =
{
500 , //if don't even have defense, can't use defense!
300 ,
150 ,
50
} ;
qboolean PM_SaberPowerCheck ( void )
{
if ( pm - > ps - > saberInFlight )
{ //so we don't keep doing stupid force out thing while guiding saber.
if ( pm - > ps - > fd . forcePower > forcePowerNeeded [ pm - > ps - > fd . forcePowerLevel [ FP_SABERTHROW ] ] [ FP_SABERTHROW ] )
{
return qtrue ;
}
}
else
{
return BG_EnoughForcePowerForMove ( forcePowerNeeded [ pm - > ps - > fd . forcePowerLevel [ FP_SABERTHROW ] ] [ FP_SABERTHROW ] ) ;
}
return qfalse ;
}
qboolean PM_CanDoRollStab ( void )
{
if ( pm - > ps - > weapon = = WP_SABER )
{
saberInfo_t * saber = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
if ( saber
& & ( saber - > saberFlags & SFL_NO_ROLL_STAB ) )
{
return qfalse ;
}
saber = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber
& & ( saber - > saberFlags & SFL_NO_ROLL_STAB ) )
{
return qfalse ;
}
}
return qtrue ;
}
/*
= = = = = = = = = = = = = = = = =
PM_WeaponLightsaber
Consults a chart to choose what to do with the lightsaber .
While this is a little different than the Quake 3 code , there is no clean way of using the Q3 code for this kind of thing .
= = = = = = = = = = = = = = = = =
*/
// Ultimate goal is to set the sabermove to the proper next location
// Note that if the resultant animation is NONE, then the animation is essentially "idle", and is set in WP_TorsoAnim
qboolean PM_WalkingAnim ( int anim ) ;
qboolean PM_SwimmingAnim ( int anim ) ;
int PM_SaberBounceForAttack ( int move ) ;
qboolean BG_SuperBreakLoseAnim ( int anim ) ;
qboolean BG_SuperBreakWinAnim ( int anim ) ;
void PM_WeaponLightsaber ( void )
{
int addTime , amount ;
qboolean delayed_fire = qfalse ;
int anim = - 1 , curmove , newmove = LS_NONE ;
qboolean checkOnlyWeap = qfalse ;
if ( PM_InKnockDown ( pm - > ps ) | | BG_InRoll ( pm - > ps , pm - > ps - > legsAnim ) )
{ //in knockdown
// make weapon function
if ( pm - > ps - > weaponTime > 0 ) {
pm - > ps - > weaponTime - = pml . msec ;
if ( pm - > ps - > weaponTime < = 0 )
{
pm - > ps - > weaponTime = 0 ;
}
}
if ( pm - > ps - > legsAnim = = BOTH_ROLL_F
& & pm - > ps - > legsTimer < = 250 )
{
if ( ( pm - > cmd . buttons & BUTTON_ATTACK ) )
{
if ( BG_EnoughForcePowerForMove ( SABER_ALT_ATTACK_POWER_FB ) & & ! pm - > ps - > saberInFlight )
{
if ( PM_CanDoRollStab ( ) )
{
//make sure the saber is on for this move!
if ( pm - > ps - > saberHolstered = = 2 )
{ //all the way off
pm - > ps - > saberHolstered = 0 ;
PM_AddEvent ( EV_SABER_UNHOLSTER ) ;
}
PM_SetSaberMove ( LS_ROLL_STAB ) ;
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER_FB ) ;
}
}
}
}
return ;
}
if ( pm - > ps - > saberLockTime > pm - > cmd . serverTime )
{
pm - > ps - > saberMove = LS_NONE ;
PM_SaberLocked ( ) ;
return ;
}
else
{
if ( /*( (pm->ps->torsoAnim) == BOTH_BF2LOCK ||
( pm - > ps - > torsoAnim ) = = BOTH_BF1LOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_CWCIRCLELOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_CCWCIRCLELOCK | | */
pm - > ps - > saberLockFrame
)
{
if ( pm - > ps - > saberLockEnemy < ENTITYNUM_NONE & &
pm - > ps - > saberLockEnemy > = 0 )
{
bgEntity_t * bgEnt ;
playerState_t * en ;
bgEnt = PM_BGEntForNum ( pm - > ps - > saberLockEnemy ) ;
if ( bgEnt )
{
en = bgEnt - > playerState ;
if ( en )
{
PM_SaberLockBreak ( en , qfalse , 0 ) ;
return ;
}
}
}
if ( /* ( (pm->ps->torsoAnim) == BOTH_BF2LOCK ||
( pm - > ps - > torsoAnim ) = = BOTH_BF1LOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_CWCIRCLELOCK | |
( pm - > ps - > torsoAnim ) = = BOTH_CCWCIRCLELOCK | | */
pm - > ps - > saberLockFrame
)
{
pm - > ps - > torsoTimer = 0 ;
PM_SetAnim ( SETANIM_TORSO , BOTH_STAND1 , SETANIM_FLAG_OVERRIDE , 100 ) ;
pm - > ps - > saberLockFrame = 0 ;
}
}
}
if ( BG_KickingAnim ( pm - > ps - > legsAnim ) | |
BG_KickingAnim ( pm - > ps - > torsoAnim ) )
{
if ( pm - > ps - > legsTimer > 0 )
{ //you're kicking, no interruptions
return ;
}
//done? be immeditately ready to do an attack
pm - > ps - > saberMove = LS_READY ;
pm - > ps - > weaponTime = 0 ;
}
if ( BG_SuperBreakLoseAnim ( pm - > ps - > torsoAnim )
| | BG_SuperBreakWinAnim ( pm - > ps - > torsoAnim ) )
{
if ( pm - > ps - > torsoTimer > 0 )
{ //never interrupt these
return ;
}
}
if ( BG_SabersOff ( pm - > ps ) )
{
if ( pm - > ps - > saberMove ! = LS_READY )
{
PM_SetSaberMove ( LS_READY ) ;
}
if ( ( pm - > ps - > legsAnim ) ! = ( pm - > ps - > torsoAnim ) & & ! BG_InSlopeAnim ( pm - > ps - > legsAnim ) & &
pm - > ps - > torsoTimer < = 0 )
{
PM_SetAnim ( SETANIM_TORSO , ( pm - > ps - > legsAnim ) , SETANIM_FLAG_OVERRIDE , 100 ) ;
}
else if ( BG_InSlopeAnim ( pm - > ps - > legsAnim ) & & pm - > ps - > torsoTimer < = 0 )
{
PM_SetAnim ( SETANIM_TORSO , PM_GetSaberStance ( ) , SETANIM_FLAG_OVERRIDE , 100 ) ;
}
if ( pm - > ps - > weaponTime < 1 & & ( ( pm - > cmd . buttons & BUTTON_ALT_ATTACK ) | | ( pm - > cmd . buttons & BUTTON_ATTACK ) ) )
{
if ( pm - > ps - > duelTime < pm - > cmd . serverTime )
{
if ( ! pm - > ps - > m_iVehicleNum )
{ //don't let em unholster the saber by attacking while on vehicle
pm - > ps - > saberHolstered = 0 ;
PM_AddEvent ( EV_SABER_UNHOLSTER ) ;
}
else
{
pm - > cmd . buttons & = ~ BUTTON_ALT_ATTACK ;
pm - > cmd . buttons & = ~ BUTTON_ATTACK ;
}
}
}
if ( pm - > ps - > weaponTime > 0 )
{
pm - > ps - > weaponTime - = pml . msec ;
}
checkOnlyWeap = qtrue ;
goto weapChecks ;
}
if ( ! pm - > ps - > saberEntityNum & & pm - > ps - > saberInFlight )
{ //this means our saber has been knocked away
/*
if ( pm - > ps - > saberMove ! = LS_READY )
{
PM_SetSaberMove ( LS_READY ) ;
}
if ( ( pm - > ps - > legsAnim ) ! = ( pm - > ps - > torsoAnim ) & & ! BG_InSlopeAnim ( pm - > ps - > legsAnim ) )
{
PM_SetAnim ( SETANIM_TORSO , ( pm - > ps - > legsAnim ) , SETANIM_FLAG_OVERRIDE , 100 ) ;
}
if ( BG_InSaberStandAnim ( pm - > ps - > torsoAnim ) | | pm - > ps - > torsoAnim = = BOTH_SABERPULL )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_STAND1 , SETANIM_FLAG_OVERRIDE , 100 ) ;
}
return ;
*/
//Old method, don't want to do this now because we want to finish up reflected attacks and things
//if our saber is pried out of our hands from one.
if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
if ( pm - > ps - > saberHolstered > 1 )
{
pm - > ps - > saberHolstered = 1 ;
}
}
else
{
pm - > cmd . buttons & = ~ BUTTON_ATTACK ;
}
pm - > cmd . buttons & = ~ BUTTON_ALT_ATTACK ;
}
if ( ( pm - > cmd . buttons & BUTTON_ALT_ATTACK ) )
{ //might as well just check for a saber throw right here
if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{ //kick instead of doing a throw
//if in a saber attack return anim, can interrupt it with a kick
if ( pm - > ps - > weaponTime > 0 //can't fire yet
& & PM_SaberInReturn ( pm - > ps - > saberMove ) //in a saber return move - FIXME: what about transitions?
//&& pm->ps->weaponTime <= 250//should be able to fire soon
//&& pm->ps->torsoTimer <= 250//torso almost done
& & pm - > ps - > saberBlocked = = BLOCKED_NONE //not interacting with any other saber
& & ! ( pm - > cmd . buttons & BUTTON_ATTACK ) ) //not trying to swing the saber
{
if ( ( pm - > cmd . forwardmove | | pm - > cmd . rightmove ) //trying to kick in a specific direction
& & PM_CheckAltKickAttack ( ) ) //trying to do a kick
{ //allow them to do the kick now!
int kickMove = PM_KickMoveForConditions ( ) ;
if ( kickMove ! = - 1 )
{
pm - > ps - > weaponTime = 0 ;
PM_SetSaberMove ( kickMove ) ;
return ;
}
}
}
}
else if ( pm - > ps - > weaponTime < 1 & &
pm - > ps - > saberCanThrow & &
//pm->ps->fd.forcePower >= forcePowerNeeded[pm->ps->fd.forcePowerLevel[FP_SABERTHROW]][FP_SABERTHROW] &&
! BG_HasYsalamiri ( pm - > gametype , pm - > ps ) & &
BG_CanUseFPNow ( pm - > gametype , pm - > ps , pm - > cmd . serverTime , FP_SABERTHROW ) & &
pm - > ps - > fd . forcePowerLevel [ FP_SABERTHROW ] > 0 & &
PM_SaberPowerCheck ( ) )
{
trace_t sabTr ;
vec3_t fwd , minFwd , sabMins , sabMaxs ;
VectorSet ( sabMins , SABERMINS_X , SABERMINS_Y , SABERMINS_Z ) ;
VectorSet ( sabMaxs , SABERMAXS_X , SABERMAXS_Y , SABERMAXS_Z ) ;
AngleVectors ( pm - > ps - > viewangles , fwd , NULL , NULL ) ;
VectorMA ( pm - > ps - > origin , SABER_MIN_THROW_DIST , fwd , minFwd ) ;
pm - > trace ( & sabTr , pm - > ps - > origin , sabMins , sabMaxs , minFwd , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
if ( sabTr . allsolid | | sabTr . startsolid | | sabTr . fraction < 1.0f )
{ //not enough room to throw
}
else
{ //throw it
//This will get set to false again once the saber makes it back to its owner game-side
if ( ! pm - > ps - > saberInFlight )
{
pm - > ps - > fd . forcePower - = forcePowerNeeded [ pm - > ps - > fd . forcePowerLevel [ FP_SABERTHROW ] ] [ FP_SABERTHROW ] ;
}
pm - > ps - > saberInFlight = qtrue ;
}
}
}
if ( pm - > ps - > saberInFlight & & pm - > ps - > saberEntityNum )
{ //guiding saber
if ( ( pm - > ps - > fd . saberAnimLevel ! = SS_DUAL //not using 2 sabers
| | pm - > ps - > saberHolstered //left one off - FIXME: saberHolstered 1 should be left one off, 0 should be both on, 2 should be both off
| | ( ! ( pm - > cmd . buttons & BUTTON_ATTACK ) //not trying to start an attack AND...
& & ( pm - > ps - > torsoAnim = = BOTH_SABERDUAL_STANCE //not already attacking
| | pm - > ps - > torsoAnim = = BOTH_SABERPULL //not already attacking
| | pm - > ps - > torsoAnim = = BOTH_STAND1 //not already attacking
| | PM_RunningAnim ( pm - > ps - > torsoAnim ) //not already attacking
| | PM_WalkingAnim ( pm - > ps - > torsoAnim ) //not already attacking
| | PM_JumpingAnim ( pm - > ps - > torsoAnim ) //not already attacking
| | PM_SwimmingAnim ( pm - > ps - > torsoAnim ) ) //not already attacking
)
)
)
{
PM_SetAnim ( SETANIM_TORSO , BOTH_SABERPULL , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD , 100 ) ;
pm - > ps - > torsoTimer = 1 ;
return ;
}
}
// don't allow attack until all buttons are up
//This is bad. It freezes the attack state and the animations if you hold the button after respawning, and it looks strange.
/*
if ( pm - > ps - > pm_flags & PMF_RESPAWNED ) {
return ;
}
*/
// check for dead player
if ( pm - > ps - > stats [ STAT_HEALTH ] < = 0 ) {
return ;
}
/*
if ( pm - > ps - > weaponstate = = WEAPON_READY | |
pm - > ps - > weaponstate = = WEAPON_IDLE )
{
if ( pm - > ps - > saberMove ! = LS_READY & & pm - > ps - > weaponTime < = 0 & & ! pm - > ps - > saberBlocked )
{
PM_SetSaberMove ( LS_READY ) ;
}
}
if ( PM_RunningAnim ( pm - > ps - > torsoAnim ) )
{
if ( ( pm - > ps - > torsoAnim ) ! = ( pm - > ps - > legsAnim ) )
{
PM_SetAnim ( SETANIM_TORSO , ( pm - > ps - > legsAnim ) , SETANIM_FLAG_OVERRIDE , 100 ) ;
}
}
*/
// make weapon function
if ( pm - > ps - > weaponTime > 0 )
{
//check for special pull move while busy
saberMoveName_t pullmove = PM_CheckPullAttack ( ) ;
if ( pullmove ! = LS_NONE )
{
pm - > ps - > weaponTime = 0 ;
pm - > ps - > torsoTimer = 0 ;
pm - > ps - > legsTimer = 0 ;
pm - > ps - > forceHandExtend = HANDEXTEND_NONE ;
pm - > ps - > weaponstate = WEAPON_READY ;
PM_SetSaberMove ( pullmove ) ;
return ;
}
pm - > ps - > weaponTime - = pml . msec ;
//This was stupid and didn't work right. Looks like things are fine without it.
// if (pm->ps->saberBlocked && pm->ps->torsoAnim != saberMoveData[pm->ps->saberMove].animToUse)
// { //rww - keep him in the blocking pose until he can attack again
// PM_SetAnim(SETANIM_TORSO,saberMoveData[pm->ps->saberMove].animToUse,saberMoveData[pm->ps->saberMove].animSetFlags|SETANIM_FLAG_HOLD, saberMoveData[pm->ps->saberMove].blendTime);
// return;
// }
}
else
{
pm - > ps - > weaponstate = WEAPON_READY ;
}
// Now we react to a block action by the player's lightsaber.
if ( pm - > ps - > saberBlocked )
{
if ( pm - > ps - > saberBlocked > = BLOCKED_UPPER_RIGHT
& & pm - > ps - > saberBlocked < BLOCKED_UPPER_RIGHT_PROJ )
{ //hold the parry for a bit
pm - > ps - > weaponTime = bg_parryDebounce [ pm - > ps - > fd . forcePowerLevel [ FP_SABER_DEFENSE ] ] + 200 ;
}
switch ( pm - > ps - > saberBlocked )
{
case BLOCKED_BOUNCE_MOVE :
{ //act as a bounceMove and reset the saberMove instead of using a seperate value for it
pm - > ps - > torsoTimer = 0 ;
PM_SetSaberMove ( pm - > ps - > saberMove ) ;
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ;
pm - > ps - > saberBlocked = 0 ;
}
break ;
case BLOCKED_PARRY_BROKEN :
//whatever parry we were is in now broken, play the appropriate knocked-away anim
{
int nextMove ;
if ( PM_SaberInBrokenParry ( pm - > ps - > saberMove ) )
{ //already have one...?
nextMove = pm - > ps - > saberMove ;
}
else
{
nextMove = PM_BrokenParryForParry ( pm - > ps - > saberMove ) ;
}
if ( nextMove ! = LS_NONE )
{
PM_SetSaberMove ( nextMove ) ;
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ;
}
else
{ //Maybe in a knockaway?
}
}
break ;
case BLOCKED_ATK_BOUNCE :
// If there is absolutely no blocked move in the chart, don't even mess with the animation.
// OR if we are already in a block or parry.
if ( pm - > ps - > saberMove > = LS_T1_BR__R )
{ //an actual bounce? Other bounces before this are actually transitions?
pm - > ps - > saberBlocked = BLOCKED_NONE ;
}
else
{
int bounceMove ;
if ( PM_SaberInBounce ( pm - > ps - > saberMove ) | | ! BG_SaberInAttack ( pm - > ps - > saberMove ) )
{
if ( pm - > cmd . buttons & BUTTON_ATTACK )
{ //transition to a new attack
int newQuad = PM_SaberMoveQuadrantForMovement ( & pm - > cmd ) ;
while ( newQuad = = saberMoveData [ pm - > ps - > saberMove ] . startQuad )
{ //player is still in same attack quad, don't repeat that attack because it looks bad,
//FIXME: try to pick one that might look cool?
//newQuad = Q_irand( Q_BR, Q_BL );
newQuad = PM_irand_timesync ( Q_BR , Q_BL ) ;
//FIXME: sanity check, just in case?
} //else player is switching up anyway, take the new attack dir
bounceMove = transitionMove [ saberMoveData [ pm - > ps - > saberMove ] . startQuad ] [ newQuad ] ;
}
else
{ //return to ready
if ( saberMoveData [ pm - > ps - > saberMove ] . startQuad = = Q_T )
{
bounceMove = LS_R_BL2TR ;
}
else if ( saberMoveData [ pm - > ps - > saberMove ] . startQuad < Q_T )
{
bounceMove = LS_R_TL2BR + saberMoveData [ pm - > ps - > saberMove ] . startQuad - Q_BR ;
}
else // if ( saberMoveData[pm->ps->saberMove].startQuad > Q_T )
{
bounceMove = LS_R_BR2TL + saberMoveData [ pm - > ps - > saberMove ] . startQuad - Q_TL ;
}
}
}
else
{ //start the bounce
bounceMove = PM_SaberBounceForAttack ( ( saberMoveName_t ) pm - > ps - > saberMove ) ;
}
PM_SetSaberMove ( bounceMove ) ;
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ; //+saberMoveData[bounceMove].blendTime+SABER_BLOCK_DUR;
}
break ;
case BLOCKED_UPPER_RIGHT :
PM_SetSaberMove ( LS_PARRY_UR ) ;
break ;
case BLOCKED_UPPER_RIGHT_PROJ :
PM_SetSaberMove ( LS_REFLECT_UR ) ;
break ;
case BLOCKED_UPPER_LEFT :
PM_SetSaberMove ( LS_PARRY_UL ) ;
break ;
case BLOCKED_UPPER_LEFT_PROJ :
PM_SetSaberMove ( LS_REFLECT_UL ) ;
break ;
case BLOCKED_LOWER_RIGHT :
PM_SetSaberMove ( LS_PARRY_LR ) ;
break ;
case BLOCKED_LOWER_RIGHT_PROJ :
PM_SetSaberMove ( LS_REFLECT_LR ) ;
break ;
case BLOCKED_LOWER_LEFT :
PM_SetSaberMove ( LS_PARRY_LL ) ;
break ;
case BLOCKED_LOWER_LEFT_PROJ :
PM_SetSaberMove ( LS_REFLECT_LL ) ;
break ;
case BLOCKED_TOP :
PM_SetSaberMove ( LS_PARRY_UP ) ;
break ;
case BLOCKED_TOP_PROJ :
PM_SetSaberMove ( LS_REFLECT_UP ) ;
break ;
default :
pm - > ps - > saberBlocked = BLOCKED_NONE ;
break ;
}
if ( pm - > ps - > saberBlocked > = BLOCKED_UPPER_RIGHT
& & pm - > ps - > saberBlocked < BLOCKED_UPPER_RIGHT_PROJ )
{ //hold the parry for a bit
if ( pm - > ps - > torsoTimer < pm - > ps - > weaponTime )
{
pm - > ps - > torsoTimer = pm - > ps - > weaponTime ;
}
}
//what the? I don't know why I was doing this.
/*
if ( pm - > ps - > saberBlocked ! = BLOCKED_ATK_BOUNCE & & pm - > ps - > saberBlocked ! = BLOCKED_PARRY_BROKEN & & pm - > ps - > weaponTime < 1 )
{
pm - > ps - > torsoTimer = SABER_BLOCK_DUR ;
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ;
}
*/
//clear block
pm - > ps - > saberBlocked = 0 ;
// Charging is like a lead-up before attacking again. This is an appropriate use, or we can create a new weaponstate for blocking
pm - > ps - > weaponstate = WEAPON_READY ;
// Done with block, so stop these active weapon branches.
return ;
}
weapChecks :
if ( pm - > ps - > saberEntityNum )
{ //only check if we have our saber with us
// check for weapon change
// can't change if weapon is firing, but can change again if lowering or raising
//if ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) {
if ( pm - > ps - > weaponTime < = 0 & & pm - > ps - > torsoTimer < = 0 )
{
if ( pm - > ps - > weapon ! = pm - > cmd . weapon ) {
PM_BeginWeaponChange ( pm - > cmd . weapon ) ;
}
}
}
if ( PM_CanDoKata ( ) )
{
saberMoveName_t overrideMove = LS_INVALID ;
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
//see if we have an overridden (or cancelled) kata move
if ( saber1 & & saber1 - > kataMove ! = LS_INVALID )
{
if ( saber1 - > kataMove ! = LS_NONE )
{
overrideMove = ( saberMoveName_t ) saber1 - > kataMove ;
}
}
if ( overrideMove = = LS_INVALID )
{ //not overridden by first saber, check second
if ( saber2
& & saber2 - > kataMove ! = LS_INVALID )
{
if ( saber2 - > kataMove ! = LS_NONE )
{
overrideMove = ( saberMoveName_t ) saber2 - > kataMove ;
}
}
}
//no overrides, cancelled?
if ( overrideMove = = LS_INVALID )
{
if ( saber2
& & saber2 - > kataMove = = LS_NONE )
{
overrideMove = LS_NONE ;
}
else if ( saber2
& & saber2 - > kataMove = = LS_NONE )
{
overrideMove = LS_NONE ;
}
}
if ( overrideMove = = LS_INVALID )
{ //not overridden
//FIXME: make sure to turn on saber(s)!
switch ( pm - > ps - > fd . saberAnimLevel )
{
case SS_FAST :
case SS_TAVION :
PM_SetSaberMove ( LS_A1_SPECIAL ) ;
break ;
case SS_MEDIUM :
PM_SetSaberMove ( LS_A2_SPECIAL ) ;
break ;
case SS_STRONG :
case SS_DESANN :
PM_SetSaberMove ( LS_A3_SPECIAL ) ;
break ;
case SS_DUAL :
PM_SetSaberMove ( LS_DUAL_SPIN_PROTECT ) ; //PM_CheckDualSpinProtect();
break ;
case SS_STAFF :
PM_SetSaberMove ( LS_STAFF_SOULCAL ) ;
break ;
}
pm - > ps - > weaponstate = WEAPON_FIRING ;
//G_DrainPowerForSpecialMove( pm->gent, FP_SABER_OFFENSE, SABER_ALT_ATTACK_POWER );//FP_SPEED, SINGLE_SPECIAL_POWER );
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER ) ;
}
else if ( overrideMove ! = LS_NONE )
{
PM_SetSaberMove ( overrideMove ) ;
pm - > ps - > weaponstate = WEAPON_FIRING ;
BG_ForcePowerDrain ( pm - > ps , FP_GRIP , SABER_ALT_ATTACK_POWER ) ;
}
if ( overrideMove ! = LS_NONE )
{ //not cancelled
return ;
}
}
if ( pm - > ps - > weaponTime > 0 )
{
return ;
}
// *********************************************************
// WEAPON_DROPPING
// *********************************************************
// change weapon if time
if ( pm - > ps - > weaponstate = = WEAPON_DROPPING ) {
PM_FinishWeaponChange ( ) ;
return ;
}
// *********************************************************
// WEAPON_RAISING
// *********************************************************
if ( pm - > ps - > weaponstate = = WEAPON_RAISING )
{ //Just selected the weapon
pm - > ps - > weaponstate = WEAPON_IDLE ;
if ( ( pm - > ps - > legsAnim ) = = BOTH_WALK1 )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_WALK1 , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( ( pm - > ps - > legsAnim ) = = BOTH_RUN1 )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_RUN1 , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( ( pm - > ps - > legsAnim ) = = BOTH_RUN2 )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_RUN2 , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( pm - > ps - > legsAnim = = BOTH_RUN_STAFF )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_RUN_STAFF , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( pm - > ps - > legsAnim = = BOTH_RUN_DUAL )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_RUN_DUAL , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( ( pm - > ps - > legsAnim ) = = BOTH_WALK1 )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_WALK1 , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( pm - > ps - > legsAnim = = BOTH_WALK2 )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_WALK2 , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( pm - > ps - > legsAnim = = BOTH_WALK_STAFF )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_WALK_STAFF , SETANIM_FLAG_NORMAL , 100 ) ;
}
else if ( pm - > ps - > legsAnim = = BOTH_WALK_DUAL )
{
PM_SetAnim ( SETANIM_TORSO , BOTH_WALK_DUAL , SETANIM_FLAG_NORMAL , 100 ) ;
}
else
{
PM_SetAnim ( SETANIM_TORSO , PM_GetSaberStance ( ) , SETANIM_FLAG_NORMAL , 100 ) ;
}
if ( pm - > ps - > weaponstate = = WEAPON_RAISING )
{
return ;
}
}
if ( checkOnlyWeap )
{
return ;
}
// *********************************************************
// Check for WEAPON ATTACK
// *********************************************************
if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF & &
( pm - > cmd . buttons & BUTTON_ALT_ATTACK ) )
{ //ok, try a kick I guess.
int kickMove = - 1 ;
if ( ! BG_KickingAnim ( pm - > ps - > torsoAnim ) & &
! BG_KickingAnim ( pm - > ps - > legsAnim ) & &
! BG_InRoll ( pm - > ps , pm - > ps - > legsAnim ) & &
// !BG_KickMove( pm->ps->saberMove )//not already in a kick
pm - > ps - > saberMove = = LS_READY
& & ! ( pm - > ps - > pm_flags & PMF_DUCKED ) //not ducked
& & ( pm - > cmd . upmove > = 0 ) //not trying to duck
) //&& pm->ps->groundEntityNum != ENTITYNUM_NONE)
{ //player kicks
kickMove = PM_KickMoveForConditions ( ) ;
}
if ( kickMove ! = - 1 )
{
if ( pm - > ps - > groundEntityNum = = ENTITYNUM_NONE )
{ //if in air, convert kick to an in-air kick
float gDist = PM_GroundDistance ( ) ;
//let's only allow air kicks if a certain distance from the ground
//it's silly to be able to do them right as you land.
//also looks wrong to transition from a non-complete flip anim...
if ( ( ! BG_FlippingAnim ( pm - > ps - > legsAnim ) | | pm - > ps - > legsTimer < = 0 ) & &
gDist > 64.0f & & //strict minimum
gDist > ( - pm - > ps - > velocity [ 2 ] ) - 64.0f //make sure we are high to ground relative to downward velocity as well
)
{
switch ( kickMove )
{
case LS_KICK_F :
kickMove = LS_KICK_F_AIR ;
break ;
case LS_KICK_B :
kickMove = LS_KICK_B_AIR ;
break ;
case LS_KICK_R :
kickMove = LS_KICK_R_AIR ;
break ;
case LS_KICK_L :
kickMove = LS_KICK_L_AIR ;
break ;
default : //oh well, can't do any other kick move while in-air
kickMove = - 1 ;
break ;
}
}
else
{ //leave it as a normal kick unless we're too high up
if ( gDist > 128.0f | | pm - > ps - > velocity [ 2 ] > = 0 )
{ //off ground, but too close to ground
kickMove = - 1 ;
}
}
}
if ( kickMove ! = - 1 )
{
PM_SetSaberMove ( kickMove ) ;
return ;
}
}
}
//this is never a valid regular saber attack button
pm - > cmd . buttons & = ~ BUTTON_ALT_ATTACK ;
if ( ! delayed_fire )
{
// Start with the current move, and cross index it with the current control states.
if ( pm - > ps - > saberMove > LS_NONE & & pm - > ps - > saberMove < LS_MOVE_MAX )
{
curmove = pm - > ps - > saberMove ;
}
else
{
curmove = LS_READY ;
}
if ( curmove = = LS_A_JUMP_T__B_ | | pm - > ps - > torsoAnim = = BOTH_FORCELEAP2_T__B_ )
{ //must transition back to ready from this anim
newmove = LS_R_T2B ;
}
// check for fire
else if ( ! ( pm - > cmd . buttons & ( BUTTON_ATTACK | BUTTON_ALT_ATTACK ) ) )
{ //not attacking
pm - > ps - > weaponTime = 0 ;
if ( pm - > ps - > weaponTime > 0 )
{ //Still firing
pm - > ps - > weaponstate = WEAPON_FIRING ;
}
else if ( pm - > ps - > weaponstate ! = WEAPON_READY )
{
pm - > ps - > weaponstate = WEAPON_IDLE ;
}
//Check for finishing an anim if necc.
if ( curmove > = LS_S_TL2BR & & curmove < = LS_S_T2B )
{ //started a swing, must continue from here
newmove = LS_A_TL2BR + ( curmove - LS_S_TL2BR ) ;
}
else if ( curmove > = LS_A_TL2BR & & curmove < = LS_A_T2B )
{ //finished an attack, must continue from here
newmove = LS_R_TL2BR + ( curmove - LS_A_TL2BR ) ;
}
else if ( PM_SaberInTransition ( curmove ) )
{ //in a transition, must play sequential attack
newmove = saberMoveData [ curmove ] . chain_attack ;
}
else if ( PM_SaberInBounce ( curmove ) )
{ //in a bounce
newmove = saberMoveData [ curmove ] . chain_idle ; //oops, not attacking, so don't chain
}
else
{ //FIXME: what about returning from a parry?
//PM_SetSaberMove( LS_READY );
//if ( pm->ps->saberBlockingTime > pm->cmd.serverTime )
{
PM_SetSaberMove ( LS_READY ) ;
}
return ;
}
}
// ***************************************************
// Pressing attack, so we must look up the proper attack move.
if ( pm - > ps - > weaponTime > 0 )
{ // Last attack is not yet complete.
pm - > ps - > weaponstate = WEAPON_FIRING ;
return ;
}
else
{
int both = qfalse ;
if ( pm - > ps - > torsoAnim = = BOTH_FORCELONGLEAP_ATTACK
| | pm - > ps - > torsoAnim = = BOTH_FORCELONGLEAP_LAND )
{ //can't attack in these anims
return ;
}
else if ( pm - > ps - > torsoAnim = = BOTH_FORCELONGLEAP_START )
{ //only 1 attack you can do from this anim
if ( pm - > ps - > torsoTimer > = 200 )
{ //hit it early enough to do the attack
PM_SetSaberMove ( LS_LEAP_ATTACK ) ;
}
return ;
}
if ( curmove > = LS_PARRY_UP & & curmove < = LS_REFLECT_LL )
{ //from a parry or reflection, can go directly into an attack
switch ( saberMoveData [ curmove ] . endQuad )
{
case Q_T :
newmove = LS_A_T2B ;
break ;
case Q_TR :
newmove = LS_A_TR2BL ;
break ;
case Q_TL :
newmove = LS_A_TL2BR ;
break ;
case Q_BR :
newmove = LS_A_BR2TL ;
break ;
case Q_BL :
newmove = LS_A_BL2TR ;
break ;
//shouldn't be a parry that ends at L, R or B
}
}
if ( newmove ! = LS_NONE )
{ //have a valid, final LS_ move picked, so skip findingt he transition move and just get the anim
anim = saberMoveData [ newmove ] . animToUse ;
}
//FIXME: diagonal dirs use the figure-eight attacks from ready pose?
if ( anim = = - 1 )
{
//FIXME: take FP_SABER_OFFENSE into account here somehow?
if ( PM_SaberInTransition ( curmove ) )
{ //in a transition, must play sequential attack
newmove = saberMoveData [ curmove ] . chain_attack ;
}
else if ( curmove > = LS_S_TL2BR & & curmove < = LS_S_T2B )
{ //started a swing, must continue from here
newmove = LS_A_TL2BR + ( curmove - LS_S_TL2BR ) ;
}
else if ( PM_SaberInBrokenParry ( curmove ) )
{ //broken parries must always return to ready
newmove = LS_READY ;
}
else //if ( pm->cmd.buttons&BUTTON_ATTACK && !(pm->ps->pm_flags&PMF_ATTACK_HELD) )//only do this if just pressed attack button?
{ //get attack move from movement command
/*
if ( PM_SaberKataDone ( ) )
{ //we came from a bounce and cannot chain to another attack because our kata is done
newmove = saberMoveData [ curmove ] . chain_idle ;
}
else */
newmove = PM_SaberAttackForMovement ( curmove ) ;
if ( ( PM_SaberInBounce ( curmove ) | | PM_SaberInBrokenParry ( curmove ) )
& & saberMoveData [ newmove ] . startQuad = = saberMoveData [ curmove ] . endQuad )
{ //this attack would be a repeat of the last (which was blocked), so don't actually use it, use the default chain attack for this bounce
newmove = saberMoveData [ curmove ] . chain_attack ;
}
if ( PM_SaberKataDone ( curmove , newmove ) )
{ //cannot chain this time
newmove = saberMoveData [ curmove ] . chain_idle ;
}
}
/*
if ( newmove = = LS_NONE )
{ //FIXME: should we allow this? Are there some anims that you should never be able to chain into an attack?
//only curmove that might get in here is LS_NONE, LS_DRAW, LS_PUTAWAY and the LS_R_ returns... all of which are in Q_R
newmove = PM_AttackMoveForQuad ( saberMoveData [ curmove ] . endQuad ) ;
}
*/
if ( newmove ! = LS_NONE )
{
//Now get the proper transition move
newmove = PM_SaberAnimTransitionAnim ( curmove , newmove ) ;
anim = saberMoveData [ newmove ] . animToUse ;
}
}
if ( anim = = - 1 )
{ //not side-stepping, pick neutral anim
// Add randomness for prototype?
newmove = saberMoveData [ curmove ] . chain_attack ;
anim = saberMoveData [ newmove ] . animToUse ;
if ( ! pm - > cmd . forwardmove & & ! pm - > cmd . rightmove & & pm - > cmd . upmove > = 0 & & pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE )
{ //not moving at all, so set the anim on entire body
both = qtrue ;
}
}
if ( anim = = - 1 )
{
switch ( pm - > ps - > legsAnim )
{
case BOTH_WALK1 :
case BOTH_WALK2 :
case BOTH_WALK_STAFF :
case BOTH_WALK_DUAL :
case BOTH_WALKBACK1 :
case BOTH_WALKBACK2 :
case BOTH_WALKBACK_STAFF :
case BOTH_WALKBACK_DUAL :
case BOTH_RUN1 :
case BOTH_RUN2 :
case BOTH_RUN_STAFF :
case BOTH_RUN_DUAL :
case BOTH_RUNBACK1 :
case BOTH_RUNBACK2 :
case BOTH_RUNBACK_STAFF :
anim = pm - > ps - > legsAnim ;
break ;
default :
anim = PM_GetSaberStance ( ) ;
break ;
}
// if (PM_RunningAnim(anim) && !pm->cmd.forwardmove && !pm->cmd.rightmove)
// { //semi-hacky (if not moving on x-y and still playing the running anim, force the player out of it)
// anim = PM_GetSaberStance();
// }
newmove = LS_READY ;
}
PM_SetSaberMove ( newmove ) ;
if ( both & & pm - > ps - > torsoAnim = = anim )
{
PM_SetAnim ( SETANIM_LEGS , anim , SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD , 100 ) ;
}
//don't fire again until anim is done
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ;
}
}
// *********************************************************
// WEAPON_FIRING
// *********************************************************
pm - > ps - > weaponstate = WEAPON_FIRING ;
amount = weaponData [ pm - > ps - > weapon ] . energyPerShot ;
addTime = pm - > ps - > weaponTime ;
pm - > ps - > saberAttackSequence = pm - > ps - > torsoAnim ;
if ( ! addTime )
{
addTime = weaponData [ pm - > ps - > weapon ] . fireTime ;
}
pm - > ps - > weaponTime = addTime ;
}
void PM_SetSaberMove ( short newMove )
{
unsigned int setflags = saberMoveData [ newMove ] . animSetFlags ;
int anim = saberMoveData [ newMove ] . animToUse ;
int parts = SETANIM_TORSO ;
if ( newMove = = LS_READY | | newMove = = LS_A_FLIP_STAB | | newMove = = LS_A_FLIP_SLASH )
{ //finished with a kata (or in a special move) reset attack counter
pm - > ps - > saberAttackChainCount = 0 ;
}
else if ( BG_SaberInAttack ( newMove ) )
{ //continuing with a kata, increment attack counter
pm - > ps - > saberAttackChainCount + + ;
}
if ( pm - > ps - > saberAttackChainCount > 16 )
{ //for the sake of being able to send the value over the net within a reasonable bit count
pm - > ps - > saberAttackChainCount = 16 ;
}
if ( newMove = = LS_DRAW )
{
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber1
& & saber1 - > drawAnim ! = - 1 )
{
anim = saber1 - > drawAnim ;
}
else if ( saber2
& & saber2 - > drawAnim ! = - 1 )
{
anim = saber2 - > drawAnim ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
anim = BOTH_S1_S7 ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
anim = BOTH_S1_S6 ;
}
}
else if ( newMove = = LS_PUTAWAY )
{
saberInfo_t * saber1 = BG_MySaber ( pm - > ps - > clientNum , 0 ) ;
saberInfo_t * saber2 = BG_MySaber ( pm - > ps - > clientNum , 1 ) ;
if ( saber1
& & saber1 - > putawayAnim ! = - 1 )
{
anim = saber1 - > putawayAnim ;
}
else if ( saber2
& & saber2 - > putawayAnim ! = - 1 )
{
anim = saber2 - > putawayAnim ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF )
{
anim = BOTH_S7_S1 ;
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL )
{
anim = BOTH_S6_S1 ;
}
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_STAFF & & newMove > = LS_S_TL2BR & & newMove < LS_REFLECT_LL )
{ //staff has an entirely new set of anims, besides special attacks
//FIXME: include ready and draw/putaway?
//FIXME: get hand-made bounces and deflections?
if ( newMove > = LS_V1_BR & & newMove < = LS_REFLECT_LL )
{ //there aren't 1-7, just 1, 6 and 7, so just set it
anim = BOTH_P7_S7_T_ + ( anim - BOTH_P1_S1_T_ ) ; //shift it up to the proper set
}
else
{ //add the appropriate animLevel
anim + = ( pm - > ps - > fd . saberAnimLevel - FORCE_LEVEL_1 ) * SABER_ANIM_GROUP_SIZE ;
}
}
else if ( pm - > ps - > fd . saberAnimLevel = = SS_DUAL & & newMove > = LS_S_TL2BR & & newMove < LS_REFLECT_LL )
{ //akimbo has an entirely new set of anims, besides special attacks
//FIXME: include ready and draw/putaway?
//FIXME: get hand-made bounces and deflections?
if ( newMove > = LS_V1_BR & & newMove < = LS_REFLECT_LL )
{ //there aren't 1-7, just 1, 6 and 7, so just set it
anim = BOTH_P6_S6_T_ + ( anim - BOTH_P1_S1_T_ ) ; //shift it up to the proper set
}
else
{ //add the appropriate animLevel
anim + = ( pm - > ps - > fd . saberAnimLevel - FORCE_LEVEL_1 ) * SABER_ANIM_GROUP_SIZE ;
}
}
/*
else if ( newMove = = LS_DRAW & & pm - > ps - > SaberStaff ( ) )
{ //hold saber out front as we turn it on
//FIXME: need a real "draw" anim for this (and put-away)
anim = BOTH_SABERSTAFF_STANCE ;
}
*/
else if ( pm - > ps - > fd . saberAnimLevel > FORCE_LEVEL_1 & &
! BG_SaberInIdle ( newMove ) & & ! PM_SaberInParry ( newMove ) & & ! PM_SaberInKnockaway ( newMove ) & & ! PM_SaberInBrokenParry ( newMove ) & & ! PM_SaberInReflect ( newMove ) & & ! BG_SaberInSpecial ( newMove ) )
{ //readies, parries and reflections have only 1 level
anim + = ( pm - > ps - > fd . saberAnimLevel - FORCE_LEVEL_1 ) * SABER_ANIM_GROUP_SIZE ;
}
// If the move does the same animation as the last one, we need to force a restart...
if ( saberMoveData [ pm - > ps - > saberMove ] . animToUse = = anim & & newMove > LS_PUTAWAY )
{
setflags | = SETANIM_FLAG_RESTART ;
}
//saber torso anims should always be highest priority (4/12/02 - for special anims only)
if ( ! pm - > ps - > m_iVehicleNum )
{ //if not riding a vehicle
if ( BG_SaberInSpecial ( newMove ) )
{
setflags | = SETANIM_FLAG_OVERRIDE ;
}
/*
if ( newMove = = LS_A_LUNGE
| | newMove = = LS_A_JUMP_T__B_
| | newMove = = LS_A_BACKSTAB
| | newMove = = LS_A_BACK
| | newMove = = LS_A_BACK_CR
| | newMove = = LS_A_FLIP_STAB
| | newMove = = LS_A_FLIP_SLASH
| | newMove = = LS_JUMPATTACK_DUAL
| | newMove = = LS_A_BACKFLIP_ATK )
{
setflags | = SETANIM_FLAG_OVERRIDE ;
}
*/
}
if ( BG_InSaberStandAnim ( anim ) | | anim = = BOTH_STAND1 )
{
anim = ( pm - > ps - > legsAnim ) ;
if ( ( anim > = BOTH_STAND1 & & anim < = BOTH_STAND4TOATTACK2 ) | |
( anim > = TORSO_DROPWEAP1 & & anim < = TORSO_WEAPONIDLE10 ) )
{ //If standing then use the special saber stand anim
anim = PM_GetSaberStance ( ) ;
}
if ( pm - > ps - > pm_flags & PMF_DUCKED )
{ //Playing torso walk anims while crouched makes you look like a monkey
anim = PM_GetSaberStance ( ) ;
}
if ( anim = = BOTH_WALKBACK1 | | anim = = BOTH_WALKBACK2 | | anim = = BOTH_WALK1 )
{ //normal stance when walking backward so saber doesn't look like it's cutting through leg
anim = PM_GetSaberStance ( ) ;
}
if ( BG_InSlopeAnim ( anim ) )
{
anim = PM_GetSaberStance ( ) ;
}
parts = SETANIM_TORSO ;
}
if ( ! pm - > ps - > m_iVehicleNum )
{ //if not riding a vehicle
if ( newMove = = LS_JUMPATTACK_ARIAL_RIGHT | |
newMove = = LS_JUMPATTACK_ARIAL_LEFT )
{ //force only on legs
parts = SETANIM_LEGS ;
}
else if ( newMove = = LS_A_LUNGE
| | newMove = = LS_A_JUMP_T__B_
| | newMove = = LS_A_BACKSTAB
| | newMove = = LS_A_BACK
| | newMove = = LS_A_BACK_CR
| | newMove = = LS_ROLL_STAB
| | newMove = = LS_A_FLIP_STAB
| | newMove = = LS_A_FLIP_SLASH
| | newMove = = LS_JUMPATTACK_DUAL
| | newMove = = LS_JUMPATTACK_ARIAL_LEFT
| | newMove = = LS_JUMPATTACK_ARIAL_RIGHT
| | newMove = = LS_JUMPATTACK_CART_LEFT
| | newMove = = LS_JUMPATTACK_CART_RIGHT
| | newMove = = LS_JUMPATTACK_STAFF_LEFT
| | newMove = = LS_JUMPATTACK_STAFF_RIGHT
| | newMove = = LS_A_BACKFLIP_ATK
| | newMove = = LS_STABDOWN
| | newMove = = LS_STABDOWN_STAFF
| | newMove = = LS_STABDOWN_DUAL
| | newMove = = LS_DUAL_SPIN_PROTECT
| | newMove = = LS_STAFF_SOULCAL
| | newMove = = LS_A1_SPECIAL
| | newMove = = LS_A2_SPECIAL
| | newMove = = LS_A3_SPECIAL
| | newMove = = LS_UPSIDE_DOWN_ATTACK
| | newMove = = LS_PULL_ATTACK_STAB
| | newMove = = LS_PULL_ATTACK_SWING
| | BG_KickMove ( newMove ) )
{
parts = SETANIM_BOTH ;
}
else if ( BG_SpinningSaberAnim ( anim ) )
{ //spins must be played on entire body
parts = SETANIM_BOTH ;
}
else if ( ( ! pm - > cmd . forwardmove & & ! pm - > cmd . rightmove & & ! pm - > cmd . upmove ) )
{ //not trying to run, duck or jump
if ( ! BG_FlippingAnim ( pm - > ps - > legsAnim ) & &
! BG_InRoll ( pm - > ps , pm - > ps - > legsAnim ) & &
! PM_InKnockDown ( pm - > ps ) & &
! PM_JumpingAnim ( pm - > ps - > legsAnim ) & &
! BG_InSpecialJump ( pm - > ps - > legsAnim ) & &
anim ! = PM_GetSaberStance ( ) & &
pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE & &
! ( pm - > ps - > pm_flags & PMF_DUCKED ) )
{
parts = SETANIM_BOTH ;
}
else if ( ! ( pm - > ps - > pm_flags & PMF_DUCKED )
& & ( newMove = = LS_SPINATTACK_DUAL | | newMove = = LS_SPINATTACK ) )
{
parts = SETANIM_BOTH ;
}
}
PM_SetAnim ( parts , anim , setflags , saberMoveData [ newMove ] . blendTime ) ;
if ( parts ! = SETANIM_LEGS & &
( pm - > ps - > legsAnim = = BOTH_ARIAL_LEFT | |
pm - > ps - > legsAnim = = BOTH_ARIAL_RIGHT ) )
{
if ( pm - > ps - > legsTimer > pm - > ps - > torsoTimer )
{
pm - > ps - > legsTimer = pm - > ps - > torsoTimer ;
}
}
}
if ( ( pm - > ps - > torsoAnim ) = = anim )
{ //successfully changed anims
//special check for *starting* a saber swing
//playing at attack
if ( BG_SaberInAttack ( newMove ) | | BG_SaberInSpecialAttack ( anim ) )
{
if ( pm - > ps - > saberMove ! = newMove )
{ //wasn't playing that attack before
if ( newMove ! = LS_KICK_F
& & newMove ! = LS_KICK_B
& & newMove ! = LS_KICK_R
& & newMove ! = LS_KICK_L
& & newMove ! = LS_KICK_F_AIR
& & newMove ! = LS_KICK_B_AIR
& & newMove ! = LS_KICK_R_AIR
& & newMove ! = LS_KICK_L_AIR )
{
PM_AddEvent ( EV_SABER_ATTACK ) ;
}
if ( pm - > ps - > brokenLimbs )
{ //randomly make pain sounds with a broken arm because we are suffering.
int iFactor = - 1 ;
if ( pm - > ps - > brokenLimbs & ( 1 < < BROKENLIMB_RARM ) )
{ //You're using it more. So it hurts more.
iFactor = 5 ;
}
else if ( pm - > ps - > brokenLimbs & ( 1 < < BROKENLIMB_LARM ) )
{
iFactor = 10 ;
}
if ( iFactor ! = - 1 )
{
if ( ! PM_irand_timesync ( 0 , iFactor ) )
{
BG_AddPredictableEventToPlayerstate ( EV_PAIN , PM_irand_timesync ( 1 , 100 ) , pm - > ps ) ;
}
}
}
}
}
if ( BG_SaberInSpecial ( newMove ) & &
pm - > ps - > weaponTime < pm - > ps - > torsoTimer )
{ //rww 01-02-03 - I think this will solve the issue of special attacks being interruptable, hopefully without side effects
pm - > ps - > weaponTime = pm - > ps - > torsoTimer ;
}
pm - > ps - > saberMove = newMove ;
pm - > ps - > saberBlocking = saberMoveData [ newMove ] . blocking ;
pm - > ps - > torsoAnim = anim ;
if ( pm - > ps - > weaponTime < = 0 )
{
pm - > ps - > saberBlocked = BLOCKED_NONE ;
}
}
}
saberInfo_t * BG_MySaber ( int clientNum , int saberNum )
{
//returns a pointer to the requested saberNum
# ifdef QAGAME
gentity_t * ent = & g_entities [ clientNum ] ;
if ( ent - > inuse & & ent - > client )
{
if ( ! ent - > client - > saber [ saberNum ] . model
| | ! ent - > client - > saber [ saberNum ] . model [ 0 ] )
{ //don't have saber anymore!
return NULL ;
}
return & ent - > client - > saber [ saberNum ] ;
}
# elif defined CGAME
clientInfo_t * ci = NULL ;
if ( clientNum < MAX_CLIENTS )
{
ci = & cgs . clientinfo [ clientNum ] ;
}
else
{
centity_t * cent = & cg_entities [ clientNum ] ;
if ( cent - > npcClient )
{
ci = cent - > npcClient ;
}
}
if ( ci
& & ci - > infoValid )
{
if ( ! ci - > saber [ saberNum ] . model
| | ! ci - > saber [ saberNum ] . model [ 0 ] )
{ //don't have sabers anymore!
return NULL ;
}
return & ci - > saber [ saberNum ] ;
}
# endif
return NULL ;
}
# include "../namespace_end.h"