diff --git a/code/game/g_combat.c b/code/game/g_combat.c index 6302035e..f8bb9fd1 100644 --- a/code/game/g_combat.c +++ b/code/game/g_combat.c @@ -829,7 +829,24 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int self->s.loopSound = 0; - self->r.maxs[2] = -8; + if (!g_shotgunGibFix.integer) { + // Executing this line causes a bug where the shotgun doesn't gib + // unless you aim at the feet. + // See https://github.com/ioquake/ioq3/issues/794. + // + // Not executing this line makes is so that the corpse + // doesn't get shorter immediately on death + // and instead can still take up other pellets + // from the same shotgun shot. + // + // The purpose and the effect of this line is not entirely clear. + // Maybe it's to transition the player hitbox + // into the "lying down dead" state, make it shorter. + // But this is already handled in `PM_CheckDuck`, + // so maybe it's just leftover code. + // So let's keep this line for now, but put behind a cvar. + self->r.maxs[2] = -8; + } // don't allow respawn until the death anim is done // g_forcerespawn may force spawning at some later time diff --git a/code/game/g_local.h b/code/game/g_local.h index b9931c55..940eab55 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -1068,6 +1068,7 @@ extern vmCvar_t g_votecustom; extern vmCvar_t g_warmup; extern vmCvar_t g_doWarmup; extern vmCvar_t g_blood; +extern vmCvar_t g_shotgunGibFix; extern vmCvar_t g_allowVote; extern vmCvar_t g_teamAutoJoin; extern vmCvar_t g_teamForceBalance; diff --git a/code/game/g_main.c b/code/game/g_main.c index e9e9cf17..5181b5a6 100644 --- a/code/game/g_main.c +++ b/code/game/g_main.c @@ -79,6 +79,7 @@ vmCvar_t g_restarted; vmCvar_t g_logfile; vmCvar_t g_logfileSync; vmCvar_t g_blood; +vmCvar_t g_shotgunGibFix; vmCvar_t g_podiumDist; vmCvar_t g_podiumDrop; vmCvar_t g_allowVote; @@ -261,6 +262,7 @@ static cvarTable_t gameCvarTable[] = { { &g_motd, "g_motd", "", 0, 0, qfalse }, { &g_motdfile, "g_motdfile", "motd.cfg", 0, 0, qfalse }, { &g_blood, "com_blood", "1", 0, 0, qfalse }, + { &g_shotgunGibFix, "g_shotgunGibFix", "1", CVAR_ARCHIVE, 0, qfalse }, { &g_podiumDist, "g_podiumDist", "80", 0, 0, qfalse }, { &g_podiumDrop, "g_podiumDrop", "70", 0, 0, qfalse }, diff --git a/code/game/g_weapon.c b/code/game/g_weapon.c index bedc90ae..001df7d6 100644 --- a/code/game/g_weapon.c +++ b/code/game/g_weapon.c @@ -377,6 +377,25 @@ qboolean ShotgunPellet( vec3_t start, vec3_t end, gentity_t *ent ) } continue; } + + // When shooting through a corpse, gib it, + // but don't "absorb" the pellet, i.e. allow to hit a player + // through a corpse. + // This is mostly to compensate for the balance changes + // that are introduced by the removal of the `self->r.maxs[2] = -8;` + // line in `player_die` when `g_shotgunGibFix` is enabled. + // But it's probably also sensible otherwise that corpses + // affect "more serious" gameplay less. + // See + // - https://github.com/ioquake/ioq3/issues/794 + // - https://github.com/OpenArena/gamecode/pull/349 + if ( g_shotgunGibFix.integer && traceEnt->client && traceEnt->client->ps.pm_type == PM_DEAD ) { + G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_SHOTGUN ); + passent = traceEnt->s.number; + VectorCopy( tr.endpos, tr_start ); + continue; + } + if( LogAccuracyHit( traceEnt, ent ) ) { hitClient = qtrue; }