Skip to content

Commit

Permalink
cgame - game: Implement melee feature and complete hit stun feature
Browse files Browse the repository at this point in the history
  • Loading branch information
LegendaryGuard committed May 31, 2024
1 parent 19eb1bc commit f9c05fb
Show file tree
Hide file tree
Showing 11 changed files with 315 additions and 41 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ A legendary 90s era Quake 3 Arena mod.
# TODO list:

- [x] ~~Toggeable flight (bind key). Hint: FLIGHT POWERUP~~
- [ ] Melee feature
- [x] ~~Melee feature~~
- [x] ~~Remove weapon visuals (models and stuff)~~
- [x] ~~Animations as listed on the old docs~~
- [x] ~~Bind key to recover ki energy~~
Expand All @@ -45,7 +45,7 @@ A legendary 90s era Quake 3 Arena mod.
- [x] ~~Third person traceable crosshair~~
- [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs
- [ ] Powerlevel and Power Tiers indicated on old docs
- [ ] Hit Stun (makes player can't use ki, melee, block and charge)
- [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~
- [ ] Power Struggles (when two beam attacks collide)
- [x] ~~Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)~~
- [ ] Short-Range Teleport (when pressing 2 times left or right)
Expand Down
9 changes: 5 additions & 4 deletions docs/bfp_cvars_task.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
- g_flightCostPct = "0"
- g_flightCost = "50"
- g_chargeDelay = "250"
- g_meleeRange = "32"
- g_meleeDiveRange = "700"
- g_meleeDamage = "10"

#### Cvar Gametypes:

Expand All @@ -29,7 +26,6 @@

## WIP:

- g_hitStun [0/1]: turn on or off the melee hit stun.

#### Cvar Gametypes:

Expand Down Expand Up @@ -72,6 +68,11 @@
- [x] ~~g_blockDelay~~
- [x] ~~g_blockCost~~
- [x] ~~g_blockCostPct~~
- [x] ~~g_hitStun~~
- [x] ~~g_meleeOnly~~
- [x] ~~g_meleeRange~~
- [x] ~~g_meleeDiveRange~~
- [x] ~~g_meleeDamage~~

#### Cvar Gametypes:

Expand Down
36 changes: 31 additions & 5 deletions source/cgame/cg_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,15 @@ static void CG_Obituary( entityState_t *ent ) {
case MOD_GRAPPLE:
message = "was caught by";
break;
// BFP - No gauntlet
#if 0
case MOD_GAUNTLET:
message = "was pummeled by";
break;
#endif
case MOD_MELEE: // BFP - Melee
message = "was beaten up by";
break;
case MOD_MACHINEGUN:
message = "was machinegunned by";
break;
Expand Down Expand Up @@ -677,14 +683,34 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
CG_FireWeapon( cent );
break;

case EV_MELEE_READY:
// DEBUGNAME("EV_MELEE_READY");
break;

// BFP - TODO: Implement EV_MELEE (when punching someone using Melee)
// BFP - Melee
case EV_MELEE:
{
int rndMeleeSnd = rand() % 5;
DEBUGNAME("EV_MELEE");
switch ( rndMeleeSnd ) {
case 0: {
trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit1.wav" ) );
break;
}
case 1: {
trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit2.wav" ) );
break;
}
case 2: {
trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit3.wav" ) );
break;
}
case 3: {
trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit4.wav" ) );
break;
}
default: {
trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit5.wav" ) );
}
}
break;
}

// BFP - TODO: Implement EV_TIER_0-4 (Tiers)
case EV_TIER_0:
Expand Down
95 changes: 84 additions & 11 deletions source/game/bg_pmove.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ float pm_spectatorfriction = 5.0f;
int c_pmove = 0;

// BFP - TODO: Macro for torso handling, since the code looked repetitive, so this macro makes the code a bit shorter
#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) ( pm->ps->pm_flags & PMF_BLOCK ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : PM_ContinueTorsoAnim( other_torsostatus )
#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) \
( pm->ps->pm_flags & PMF_BLOCK ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : \
( ( pm->cmd.buttons & BUTTON_MELEE ) && !( pm->ps->pm_flags & PMF_MELEE ) ) ? PM_ContinueTorsoAnim( TORSO_MELEE_READY ) : \
( pm->ps->pm_flags & PMF_MELEE ) ? PM_ContinueTorsoAnim( TORSO_MELEE_STRIKE ) : PM_ContinueTorsoAnim( other_torsostatus )

// BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter
#define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB )
Expand All @@ -59,6 +62,12 @@ int c_pmove = 0;
else if ( pm->cmd.forwardmove < 0 ) { TORSOSTATUS_ANIM_HANDLING( TORSO_FLYB ); PM_ContinueLegsAnim( LEGS_FLYB ); } \
else { TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); }

// BFP - Macro for melee strike handling, since the code looked repetitive, so this macro makes the code a bit shorter
#define CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING(condition) \
/* Keep moving the legs when the player is attacking to the target through melee. If the condition variable isn't used leave using this value: 1 */ \
if ( ( condition ) && ( pm->ps->pm_flags & PMF_MELEE ) \
&& !( pm->ps->pm_flags & PMF_HITSTUN ) && !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { PM_ContinueLegsAnim( LEGS_MELEE_STRIKE ); }

// BFP - Macro for movement handling in the slopes and when being near to the ground, since the code looked repetitive, so this macro makes the code a bit shorter
#define SLOPES_NEARGROUND_ANIM_HANDLING(is_slope) \
if (is_slope) { \
Expand All @@ -78,7 +87,8 @@ int c_pmove = 0;
return; \
} \
} \
if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { PM_ContinueLegsAnim( LEGS_IDLE ); return; } \
/* If it's very near to the other entity and the melee strike is executed, continue playing the melee strike legs animation */ \
if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { PM_ContinueLegsAnim( LEGS_IDLE ); CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) return; } \
if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { \
if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); } \
else if ( pm->cmd.forwardmove > 0 \
Expand All @@ -88,7 +98,8 @@ int c_pmove = 0;
else if ( pm->cmd.forwardmove > 0 \
|| ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALK ); } \
TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); \
}
} \
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 )

/*
===============
Expand Down Expand Up @@ -589,6 +600,9 @@ static void PM_WaterMove( void ) {
// BFP - Water animation handling, uses flying animation in that case
CONTINUEFLY_ANIM_HANDLING()

// BFP - Melee strike legs animation
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 )

PM_SlideMove( qfalse );
}

Expand Down Expand Up @@ -1055,16 +1069,32 @@ static void PM_CrashLand( void ) {
PM_CheckStuck
=============
*/
/*
void PM_CheckStuck(void) {
static void PM_CheckStuck(void) {
// BFP - NOTE: Curiously and originally, BFP uses this function to animate when the player is stuck,
// that can be tested when the player is pretty near to the other player
// or being stuck in the same origin as the other player, specially outside water.
// It has been implemented when melee animations were being used
trace_t trace;

pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask);
if (trace.allsolid) {
//int shit = qtrue;

// BFP - TODO: Ki attack animation handling (these are for torso animations)
// Try to handle the animations when the player is shooting

// BFP - Handle the animations when being stuck! (Only outside water)
if ( pm->waterlevel < 1 ) {
if ( pm->cmd.forwardmove < 0 ) {
PM_ContinueLegsAnim( LEGS_JUMPB );
} else {
PM_ContinueLegsAnim( LEGS_JUMP );
}
}
// BFP - Melee strike legs animation
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 )
}
}
*/

/*
=============
Expand Down Expand Up @@ -1438,8 +1468,10 @@ static void PM_Footsteps( void ) {
return;
}

// BFP - Avoid when flying
// BFP - Avoid when flying (for melee strike animation, that's applied)
if ( pm->ps->powerups[PW_FLIGHT] > 0 ) {
// BFP - Melee strike legs animation, don't apply if it's playing the starting jump animation in the flight status
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( pm->ps->pm_time <= 0 )
return;
}

Expand Down Expand Up @@ -1471,6 +1503,9 @@ static void PM_Footsteps( void ) {
PM_ContinueLegsAnim( LEGS_SWIM );
}
#endif
// BFP - PM_CheckStuck has been moved here, Q3 and the rest of mods hadn't used this
PM_CheckStuck();

return;
}

Expand All @@ -1487,6 +1522,8 @@ static void PM_Footsteps( void ) {
} else if ( !( pm->ps->pm_flags & PMF_DUCKED ) ) { // BFP - Handle the legs while it isn't doing nothing
PM_ContinueLegsAnim( LEGS_IDLE );
}
// BFP - Melee strike legs animation
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 )
return;
}

Expand Down Expand Up @@ -1539,6 +1576,9 @@ static void PM_Footsteps( void ) {
}
}

// BFP - Melee strike legs animation
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 )

// check for footstep / splash sounds
old = pm->ps->bobCycle;
pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255;
Expand Down Expand Up @@ -1670,7 +1710,7 @@ static void PM_TorsoAnimation( void ) {
trace_t trace;
vec3_t point;

// BFP - TODO: Melee and ki attack animation handling (these are for torso animations)
// BFP - TODO: Ki attack animation handling (these are for torso animations)
// Keep in mind about the implementations of the steep slopes,
// TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ) and
// !pm->cmd.forwardmove && !pm->cmd.rightmove && !pm->cmd.buttons thingies
Expand Down Expand Up @@ -1717,6 +1757,9 @@ static void PM_TorsoAnimation( void ) {
SLOPES_NEARGROUND_ANIM_HANDLING( 0 )
}

// BFP - Melee strike legs animation, don't apply if it isn't touching the ground
CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( pm->ps->groundEntityNum != ENTITYNUM_NONE )

#if 0
if ( pm->ps->weaponstate == WEAPON_READY ) {
if ( pm->ps->weapon == WP_GAUNTLET ) {
Expand Down Expand Up @@ -1853,6 +1896,20 @@ static void PM_HitStunAnimation( void ) { // BFP - Hit stun
}
}

/*
==============
PM_Melee
==============
*/
static void PM_Melee( void ) { // BFP - Melee
// Don't allow pressing ki attack and block buttons when melee is being used
if ( ( pm->ps->pm_flags & PMF_MELEE )
|| ( pm->cmd.buttons & BUTTON_MELEE ) ) {
pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_BLOCK );
}
}


/*
==============
PM_Weapon
Expand Down Expand Up @@ -1907,6 +1964,11 @@ static void PM_Weapon( void ) {
pm->ps->weaponTime -= pml.msec;
}

// BFP - Hit stun melee delay time
if ( pm->ps->stats[STAT_HITSTUN_MELEE_DELAY] > 0 ) {
pm->ps->stats[STAT_HITSTUN_MELEE_DELAY] -= pml.msec;
}

// check for weapon change
// can't change if weapon is firing, but can change
// again if lowering or raising
Expand All @@ -1926,6 +1988,16 @@ static void PM_Weapon( void ) {
return;
}

// BFP - Melee, avoid shooting if the player is in this status
if ( pm->cmd.buttons & BUTTON_MELEE ) {
// Melee fight handling
if ( pm->gauntletHit && pm->ps->weaponTime <= 0 ) {
pm->ps->weaponTime += 300;
pm->ps->pm_flags |= PMF_MELEE;
}
return;
}

// BFP - No weapon raising handling
#if 0
if ( pm->ps->weaponstate == WEAPON_RAISING ) {
Expand Down Expand Up @@ -2422,6 +2494,9 @@ void PmoveSingle (pmove_t *pmove) {
// BFP - Block
PM_BlockTime();

// BFP - Melee
PM_Melee();

PM_DropTimers();

// BFP - Flight
Expand Down Expand Up @@ -2532,14 +2607,12 @@ void Pmove (pmove_t *pmove) {
pmove->cmd.upmove = 20;
}
}

//PM_CheckStuck();

}

// BFP - Undefine the macros
#undef TORSOSTATUS_ANIM_HANDLING
#undef FORCEJUMP_ANIM_HANDLING
#undef CONTINUEFLY_ANIM_HANDLING
#undef CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING
#undef SLOPES_NEARGROUND_ANIM_HANDLING

3 changes: 3 additions & 0 deletions source/game/bg_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ typedef enum {
#define PMF_NEARGROUND 8 // BFP - Near ground check
// BFP - PMF_BACKWARDS_RUN is unused
// #define PMF_BACKWARDS_RUN 16 // coast down to backwards run
#define PMF_MELEE 16 // BFP - Melee
// BFP - PMF_TIME_LAND is unused
// #define PMF_TIME_LAND 32 // pm_time is time before rejump
#define PMF_FALLING 32 // BFP - Falling status
Expand Down Expand Up @@ -220,6 +221,7 @@ typedef enum {
STAT_HEALTH,
STAT_KI, // BFP - KI amount
STAT_BLOCK, // BFP - Block amount treated as time
STAT_HITSTUN_MELEE_DELAY, // BFP - Hitstun delay time status
STAT_HOLDABLE_ITEM,
STAT_WEAPONS, // 16 bit fields
STAT_ARMOR,
Expand Down Expand Up @@ -680,6 +682,7 @@ typedef enum {
typedef enum {
MOD_UNKNOWN,
MOD_SHOTGUN,
MOD_MELEE, // BFP - Melee
MOD_GAUNTLET,
MOD_MACHINEGUN,
MOD_GRENADE,
Expand Down
15 changes: 15 additions & 0 deletions source/game/g_active.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,11 @@ void ClientThink_real( gentity_t *ent ) {
}
// BFP - End of block handling

// BFP - Melee handling
if ( !( ucmd->buttons & BUTTON_MELEE ) ) {
client->ps.pm_flags &= ~PMF_MELEE;
}

// BFP - Ki Charge
if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0
&& ( client->ps.pm_flags & PMF_KI_CHARGE ) ) {
Expand Down Expand Up @@ -845,12 +850,22 @@ void ClientThink_real( gentity_t *ent ) {

memset (&pm, 0, sizeof(pm));

// BFP - No gauntlet hit check
#if 0
// check for the hit-scan gauntlet, don't let the action
// go through as an attack unless it actually hits something
if ( client->ps.weapon == WP_GAUNTLET && !( ucmd->buttons & BUTTON_TALK ) &&
( ucmd->buttons & BUTTON_ATTACK ) && client->ps.weaponTime <= 0 ) {
pm.gauntletHit = CheckGauntletAttack( ent );
}
#endif

// BFP - Melee
if ( !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_MELEE )
&& !( client->ps.pm_flags & PMF_KI_CHARGE )
&& client->ps.weaponTime <= 0 ) {
pm.gauntletHit = CheckMeleeAttack( ent );
}

if ( ent->flags & FL_FORCE_GESTURE ) {
ent->flags &= ~FL_FORCE_GESTURE;
Expand Down
Loading

0 comments on commit f9c05fb

Please sign in to comment.