Skip to content

Commit

Permalink
game: Implement block, transfer health damage to ki and deflect some …
Browse files Browse the repository at this point in the history
…ki attacks
  • Loading branch information
LegendaryGuard committed Mar 24, 2024
1 parent d4f1568 commit b795755
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ A legendary 90s era Quake 3 Arena mod.
- [ ] Powerlevel and Power Tiers indicated on old docs
- [ ] Hit Stun (makes player can't use ki, melee, block and charge)
- [ ] Power Struggles (when two beam attacks collide)
- [ ] Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)
- [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)
- [ ] Transformations (related to Power Tiers)
- [ ] Attacksets (configurable for cfgs)
Expand Down
8 changes: 4 additions & 4 deletions docs/bfp_cvars_task.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@
## PENDING:

- g_basepl [1-999]: set the starting power level from one thousand to one mil.
- g_blockLength = "3"
- g_blockDelay = "2"
- g_kiChargePct = "15"
- g_kiCharge = "0"
- g_kiRegenPct = "0.6"
- g_kiRegen = "0"
- g_blockCostPct = "3"
- g_blockCost = "0"
- g_boostCostPct = "0"
- g_boostCost = "150"
- g_flightCostPct = "0"
Expand Down Expand Up @@ -72,6 +68,10 @@
- [x] ~~cg_polygonAura~~
- [x] ~~cg_highPolyAura~~
- [x] ~~g_noFlight (disables "fly" bind too, original BFP has a leak though)~~
- [x] ~~g_blockLength~~
- [x] ~~g_blockDelay~~
- [x] ~~g_blockCost~~
- [x] ~~g_blockCostPct~~

#### Cvar Gametypes:

Expand Down
4 changes: 2 additions & 2 deletions source/game/bg_pmove.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ 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_INVULEXPAND ) ? 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_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 Down Expand Up @@ -623,7 +623,7 @@ static void PM_FlyMove( void ) {

VectorCopy (wishvel, wishdir);
wishspeed = VectorNormalize(wishdir);
if ( !( pm->ps->pm_flags & PMF_INVULEXPAND ) // BFP - Don't increase the speed when blocking
if ( !( pm->ps->pm_flags & PMF_BLOCK ) // BFP - Don't increase the speed when blocking
&& ( pm->ps->powerups[PW_HASTE] > 0 || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) {
wishspeed *= scale;
}
Expand Down
2 changes: 2 additions & 0 deletions source/game/bg_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ typedef enum {
// pmove->pm_flags
#define PMF_DUCKED 1
#define PMF_JUMP_HELD 2
#define PMF_BLOCK 4 // BFP - Block
// BFP - PMF_BACKWARDS_JUMP is unused
// #define PMF_BACKWARDS_JUMP 8 // go into backwards land
#define PMF_NEARGROUND 8 // BFP - Near ground check
Expand Down Expand Up @@ -218,6 +219,7 @@ void Pmove (pmove_t *pmove);
typedef enum {
STAT_HEALTH,
STAT_KI, // BFP - KI amount
STAT_BLOCK, // BFP - Block amount treated as time
STAT_HOLDABLE_ITEM,
STAT_WEAPONS, // 16 bit fields
STAT_ARMOR,
Expand Down
79 changes: 79 additions & 0 deletions source/game/g_active.c
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ void ClientThink_real( gentity_t *ent ) {

// BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold
if ( !( client->ps.pm_flags & PMF_HITSTUN )
&& !( client->ps.pm_flags & PMF_BLOCK )
&& ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki
|| client->ps.powerups[PW_HASTE] > 0 ) ) { // BFP - When "kiusetoggle" is binded, enables/disables
if ( client->ps.powerups[PW_FLIGHT] <= 0 ) {
Expand All @@ -747,6 +748,84 @@ void ClientThink_real( gentity_t *ent ) {
}
}

// BFP - Block, reflect ki attacks and reduce health damage
// Block handling:
// Initialize the blocking and start the block length duration, specifically, ki boost and aura are disabled
if ( !( client->ps.pm_flags & PMF_BLOCK )
&& ( ucmd->buttons & BUTTON_BLOCK )
&& client->ps.stats[STAT_BLOCK] <= 0 ) {
client->ps.pm_flags |= PMF_BLOCK;
client->ps.powerups[PW_HASTE] = 0;
client->ps.eFlags &= ~EF_AURA;
ucmd->buttons &= ~BUTTON_KI_USE;
client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 100);
}

// Handle block status (it's like block time)
if ( client->ps.stats[STAT_BLOCK] >= 0 ) {
client->ps.stats[STAT_BLOCK]--;
// Print debug
#if 0
if ( ( client->ps.pm_flags & PMF_BLOCK ) && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) )
Com_Printf( "BLOCK LENGTH: %d\n", client->ps.stats[STAT_BLOCK] );
else if ( !( client->ps.pm_flags & PMF_BLOCK ) && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 100) )
Com_Printf( "BLOCK DELAY: %d\n", client->ps.stats[STAT_BLOCK] );
#endif
}

// BFP - Blocking status. Ki energy is being consumed and ki boost can't be used
if ( ( client->ps.pm_flags & PMF_BLOCK )
&& client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100)
&& client->ps.stats[STAT_BLOCK] >= 0 ) {

// BFP - NOTE: Approximate calculation of ki consumption while blocking
float blockCostPct = g_blockCostPct.integer * 0.1; // Percentage of ki consumed per millisecond
float bCost = g_blockCost.integer > 0 ? g_blockCost.integer : 1; // Absolute value of ki consumed per millisecond
float kiBlockConsume = bCost / (g_blockLength.integer * 1000.0);
float totalBlockConsume;
// Random variable to make an approximate calculation of the ki consumption while using block
float rndkiConsume = rand() % 2;

// BFP - TODO: Implement random calculations correctly?
if ( crandom() > 0.5 && crandom() < 0.8 ) {
rndkiConsume = rand() % 1;
} else if ( crandom() > 0.2 && crandom() < 0.5 ) {
rndkiConsume = random() + 0.38;
}

// Calculate total ki being consumed
totalBlockConsume = kiBlockConsume * (g_blockLength.integer * 1000.0) * rndkiConsume;

client->ps.stats[STAT_KI] -= totalBlockConsume;
}

// When the block length duration has been expired, then start the delay to avoid user
if ( ( client->ps.pm_flags & PMF_BLOCK )
&& client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100)
&& client->ps.stats[STAT_BLOCK] <= 0 ) {
client->ps.pm_flags &= ~PMF_BLOCK;
client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 100);
}

// If the block length duration hasn't been expired yet and
// pressing ki charge (if the aura is lighting) or attack buttons, then stop blocking and start the delay
if ( ( client->ps.pm_flags & PMF_BLOCK )
&& ( ( ucmd->buttons & BUTTON_MELEE )
|| ( ucmd->buttons & BUTTON_ATTACK )
|| ( client->ps.eFlags & EF_AURA ) ) ) {
client->ps.pm_flags &= ~PMF_BLOCK;
client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 100);
}

// Handle the delay and don't leave the user get away with it
if ( !( client->ps.pm_flags & PMF_BLOCK )
&& client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 100)
&& client->ps.stats[STAT_BLOCK] >= 0 ) {
client->ps.pm_flags &= ~PMF_BLOCK;
ucmd->buttons &= ~BUTTON_BLOCK; // If the user holds the key, when that ends, then immediately enters to this status again
}
// BFP - End of block handling

// BFP - Ki Charge
if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0
&& ( client->ps.pm_flags & PMF_KI_CHARGE ) ) {
Expand Down
9 changes: 6 additions & 3 deletions source/game/g_combat.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
// add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
if ( attacker->client && targ != attacker && targ->health > 0
&& targ->s.eType != ET_MISSILE
&& targ->s.eType != ET_GENERAL) {
&& targ->s.eType != ET_GENERAL
&& !( client->ps.pm_flags & PMF_BLOCK ) ) { // BFP - When blocking, don't receive any hit
if ( OnSameTeam( targ, attacker ) ) {
attacker->client->ps.persistant[PERS_HITS]--;
} else {
Expand Down Expand Up @@ -808,7 +809,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
// add to the damage inflicted on a player this frame
// the total will be turned into screen blends and view angle kicks
// at the end of the frame
if ( client ) {
if ( client
&& !( client->ps.pm_flags & PMF_BLOCK ) ) { // BFP - When blocking, don't receive screams of pain
if ( attacker ) {
client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
} else {
Expand Down Expand Up @@ -838,7 +840,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
}

// do the damage
if (take) {
if (take
&& !( client->ps.pm_flags & PMF_BLOCK )) { // BFP - When blocking, don't receive damage
targ->health = targ->health - take;
if ( targ->client ) {
targ->client->ps.stats[STAT_HEALTH] = targ->health;
Expand Down
10 changes: 6 additions & 4 deletions source/game/g_cvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,17 @@ G_CVAR( g_maxSpawnPL, "g_maxSpawnPL", "999", 0, 0, qtrue ) // BFP - Max spawn po
G_CVAR( g_flightCost, "g_flightCost", "50", 0, 0, qtrue ) // BFP - Flight cost
G_CVAR( g_flightCostPct, "g_flightCostPct", "0", 0, 0, qtrue ) // BFP - Flight cost percentage
G_CVAR( g_boostCost, "g_boostCost", "350", 0, 0, qtrue ) // BFP - Boost cost
G_CVAR( g_boostCostPct, "g_boostCostPct", "3", 0, 0, qtrue ) // BFP - Boost cost percentage
G_CVAR( g_boostCostPct, "g_boostCostPct", "0", 0, 0, qtrue ) // BFP - Boost cost percentage

G_CVAR( g_blockCost, "g_blockCost", "2", 0, 0, qtrue ) // BFP - Block cost
G_CVAR( g_blockCostPct, "g_blockCostPct", "3", 0, 0, qtrue ) // BFP - Block cost percentage
G_CVAR( g_blockCostPct, "g_blockCostPct", "0", 0, 0, qtrue ) // BFP - Block cost percentage
G_CVAR( g_blockDelay, "g_blockDelay", "2", 0, 0, qtrue ) // BFP - Block delay
G_CVAR( g_blockLength, "g_blockLength", "2", 0, 0, qtrue ) // BFP - Block length

G_CVAR( g_kiRegen, "g_kiRegen", "0", 0, 0, qtrue ) // BFP - Ki regeneration
G_CVAR( g_kiRegenPct, "g_kiRegenPct", "0.6", 0, 0, qtrue ) // BFP - Ki regeneration percentage
G_CVAR( g_kiCharge, "g_kiCharge", "0", 0, 0, qtrue ) // BFP - Ki charge
G_CVAR( g_kiChargePct, "g_kiChargePct", "15", 0, 0, qtrue ) // BFP - Ki charge percentage
G_CVAR( g_blockDelay, "g_blockDelay", "2", 0, 0, qtrue ) // BFP - Block delay
G_CVAR( g_blockLength, "g_blockLength", "3", 0, 0, qtrue ) // BFP - Block length

G_CVAR( g_podiumDist, "g_podiumDist", "80", 0, 0, qfalse )
G_CVAR( g_podiumDrop, "g_podiumDrop", "70", 0, 0, qfalse )
Expand Down
16 changes: 16 additions & 0 deletions source/game/g_missile.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
if ( ent->damage ) {
vec3_t velocity;

// BFP - When blocking... Deflect the projectile!
if ( other->client->ps.pm_flags & PMF_BLOCK ) {
// PUSH!
BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
if ( VectorLength( velocity ) == 0 ) {
velocity[2] = 1;
}
G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
ent->s.origin, ent->damage,
0, ent->methodOfDeath);

// DEFLECT!
G_BounceMissile( ent, trace );
return;
}

if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
g_entities[ent->r.ownerNum].client->accuracy_hits++;
hitClient = qtrue;
Expand Down

0 comments on commit b795755

Please sign in to comment.