From 06f671d8e163d7b594d07162d2adb44d14746bc7 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Mon, 10 Nov 2025 10:43:14 -0500 Subject: [PATCH 1/4] Add cg_damagePlums Shows a quake live style damage plum on damage when set to 1. --- code/cgame/cg_cvar.h | 1 + code/cgame/cg_effects.c | 50 +++++++++++++++++- code/cgame/cg_event.c | 4 ++ code/cgame/cg_local.h | 2 + code/cgame/cg_localents.c | 108 ++++++++++++++++++++++++++++++++++++++ code/game/bg_events.h | 4 +- code/game/g_active.c | 6 +++ code/game/g_combat.c | 51 ++++++++++++++++++ code/game/g_local.h | 9 ++++ code/game/g_main.c | 1 + 10 files changed, 233 insertions(+), 3 deletions(-) diff --git a/code/cgame/cg_cvar.h b/code/cgame/cg_cvar.h index 46811af9..96375280 100644 --- a/code/cgame/cg_cvar.h +++ b/code/cgame/cg_cvar.h @@ -111,6 +111,7 @@ CG_CVAR( cg_timescaleFadeEnd, "cg_timescaleFadeEnd", "1", 0 ) CG_CVAR( cg_timescaleFadeSpeed, "cg_timescaleFadeSpeed", "0", 0 ) CG_CVAR( cg_timescale, "timescale", "1", 0 ) CG_CVAR( cg_scorePlum, "cg_scorePlums", "1", CVAR_USERINFO | CVAR_ARCHIVE ) +CG_CVAR( cg_damagePlums, "cg_damagePlums", "0", CVAR_USERINFO | CVAR_ARCHIVE ) CG_CVAR( cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE ) CG_CVAR( cg_cameraMode, "com_cameraMode", "0", CVAR_CHEAT ) CG_CVAR( cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE ) diff --git a/code/cgame/cg_effects.c b/code/cgame/cg_effects.c index 115c309f..894e5864 100644 --- a/code/cgame/cg_effects.c +++ b/code/cgame/cg_effects.c @@ -407,10 +407,10 @@ void CG_ScorePlum( int client, const vec3_t origin, int score ) { le->endTime = cg.time + 4000; le->lifeRate = 1.0 / ( le->endTime - le->startTime ); - + le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0; le->radius = score; - + VectorCopy( origin, le->pos.trBase ); if ( origin[2] >= lastPos[2] - 20 && origin[2] <= lastPos[2] + 20 ) { le->pos.trBase[2] -= 20; @@ -428,6 +428,52 @@ void CG_ScorePlum( int client, const vec3_t origin, int score ) { AnglesToAxis( angles, re->axis ); } +/* +================== +CG_DamagePlum +================== +*/ +void CG_DamagePlum( vec3_t org, int damage ) { + localEntity_t *le; + refEntity_t *re; + vec3_t angles; + float random_x, random_y; + + if ( cg_damagePlums.integer == 0 ) { + return; + } + + le = CG_AllocLocalEntity(); + le->leFlags = 0; + le->leType = LE_DAMAGEPLUM; + le->startTime = cg.time; + le->endTime = cg.time + 1000; + le->lifeRate = 1.0 / ( le->endTime - le->startTime ); + + le->color[0] = 1.0; + le->color[1] = 0.5; + le->color[2] = 0.0; + le->color[3] = 1.0; + le->radius = damage; + + VectorCopy( org, le->pos.trBase ); + + random_x = (random() * 2.0 - 1.0); + random_y = (random() * 2.0 - 1.0); + + le->pos.trDelta[0] = random_x; + le->pos.trDelta[1] = random_y; + le->pos.trDelta[2] = 0.5 + random() * 0.5; + + re = &le->refEntity; + + re->reType = RT_SPRITE; + re->radius = 16; + + VectorClear(angles); + AnglesToAxis( angles, re->axis ); +} + /* ==================== diff --git a/code/cgame/cg_event.c b/code/cgame/cg_event.c index 67319e7f..7ff63303 100644 --- a/code/cgame/cg_event.c +++ b/code/cgame/cg_event.c @@ -963,6 +963,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position, int entityNum ) { CG_ScorePlum( cent->currentState.otherEntityNum, cent->lerpOrigin, cent->currentState.time ); break; + case EV_DAMAGEPLUM: + CG_DamagePlum( cent->lerpOrigin, cent->currentState.time ); + break; + // // missile impacts // diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 240f6ed1..b67c8530 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -232,6 +232,7 @@ typedef enum { LE_FADE_RGB, LE_SCALE_FADE, LE_SCOREPLUM, + LE_DAMAGEPLUM, #ifdef MISSIONPACK LE_KAMIKAZE, LE_INVULIMPACT, @@ -1405,6 +1406,7 @@ void CG_InvulnerabilityJuiced( vec3_t org ); void CG_LightningBoltBeam( vec3_t start, vec3_t end ); #endif void CG_ScorePlum( int client, const vec3_t origin, int score ); +void CG_DamagePlum( vec3_t org, int damage ); void CG_GibPlayer( const vec3_t playerOrigin ); void CG_BigExplode( vec3_t playerOrigin ); diff --git a/code/cgame/cg_localents.c b/code/cgame/cg_localents.c index 45535ab7..9160e068 100644 --- a/code/cgame/cg_localents.c +++ b/code/cgame/cg_localents.c @@ -870,6 +870,110 @@ void CG_AddScorePlum( localEntity_t *le ) { } } +/* +=================== +CG_AddDamagePlum +=================== +*/ +void CG_AddDamagePlum( localEntity_t *le ) { + refEntity_t *re; + vec3_t origin, delta, dir, vec, up = {0, 0, 1}; + float c, len; + int i, damage, digits[10], numdigits, negative; + float progress, fade; + float spread_x, spread_y; + float vertical_offset, peak_height; + float rise_progress, fall_progress; + + re = &le->refEntity; + + c = ( le->endTime - cg.time ) * le->lifeRate; + + damage = le->radius; + + // Color based on damage amount - gradient from white to red + if (damage >= 50) { + re->shaderRGBA[0] = 0xff; + re->shaderRGBA[1] = 0x00; + re->shaderRGBA[2] = 0x00; + } else if (damage >= 25) { + re->shaderRGBA[0] = 0xff; + re->shaderRGBA[1] = 0x80; + re->shaderRGBA[2] = 0x00; + } else if (damage >= 10) { + re->shaderRGBA[0] = 0xff; + re->shaderRGBA[1] = 0xff; + re->shaderRGBA[2] = 0x00; + } else { + re->shaderRGBA[0] = 0xff; + re->shaderRGBA[1] = 0xff; + re->shaderRGBA[2] = 0xff; + } + + // Fade out after 250ms (after peak at 25% progress) + progress = 1.0 - c; // 0.0 at start, 1.0 at end + if (progress < 0.25) { + fade = 1.0; // Full opacity for first 250ms + } else { + fade = 1.0 - ((progress - 0.25) / 0.75); // Fade out over remaining 750ms + } + re->shaderRGBA[3] = 0xff * fade; + + re->radius = NUMBER_SIZE / 2; + + VectorCopy(le->pos.trBase, origin); + + spread_x = le->pos.trDelta[0] * 70.0 * progress; + spread_y = le->pos.trDelta[1] * 70.0 * progress; + origin[0] += spread_x; + origin[1] += spread_y; + + peak_height = 30.0 * le->pos.trDelta[2]; + + if (progress < 0.25) { + rise_progress = progress / 0.25; + vertical_offset = peak_height * (1.0 - (1.0 - rise_progress) * (1.0 - rise_progress)); + } else { + fall_progress = (progress - 0.25) / 0.75; + vertical_offset = peak_height - (peak_height + 48.0) * fall_progress * fall_progress; + } + origin[2] += vertical_offset; + + VectorSubtract(cg.refdef.vieworg, origin, dir); + CrossProduct(dir, up, vec); + VectorNormalize(vec); + + // if the view would be "inside" the sprite, kill the sprite + VectorSubtract( origin, cg.refdef.vieworg, delta ); + len = VectorLength( delta ); + if ( len < 20 ) { + CG_FreeLocalEntity( le ); + return; + } + + negative = qfalse; + if (damage < 0) { + negative = qtrue; + damage = -damage; + } + + for (numdigits = 0; !(numdigits && !damage); numdigits++) { + digits[numdigits] = damage % 10; + damage = damage / 10; + } + + if (negative) { + digits[numdigits] = 10; + numdigits++; + } + + for (i = 0; i < numdigits; i++) { + VectorMA(origin, (float) (((float) numdigits / 2) - i) * NUMBER_SIZE, vec, re->origin); + re->customShader = cgs.media.numberShaders[digits[numdigits-1-i]]; + trap_R_AddRefEntityToScene( re ); + } +} + @@ -936,6 +1040,10 @@ void CG_AddLocalEntities( void ) { CG_AddScorePlum( le ); break; + case LE_DAMAGEPLUM: + CG_AddDamagePlum( le ); + break; + #ifdef MISSIONPACK case LE_KAMIKAZE: CG_AddKamikaze( le ); diff --git a/code/game/bg_events.h b/code/game/bg_events.h index b9e0b2ce..27d74e09 100644 --- a/code/game/bg_events.h +++ b/code/game/bg_events.h @@ -108,7 +108,9 @@ DECLARE_EVENT( EV_TAUNT_NO ), DECLARE_EVENT( EV_TAUNT_FOLLOWME ), DECLARE_EVENT( EV_TAUNT_GETFLAG ), DECLARE_EVENT( EV_TAUNT_GUARDBASE ), -DECLARE_EVENT( EV_TAUNT_PATROL ) +DECLARE_EVENT( EV_TAUNT_PATROL ), + +DECLARE_EVENT( EV_DAMAGEPLUM ) // damage plum #ifdef EVENT_ENUMS , DECLARE_EVENT( EV_MAX ) diff --git a/code/game/g_active.c b/code/game/g_active.c index ad5d2878..edb92d49 100644 --- a/code/game/g_active.c +++ b/code/game/g_active.c @@ -1217,6 +1217,12 @@ void ClientEndFrame( gentity_t *ent ) { client->damage.team = 0; } + // send accumulated damage plums + for ( i = 0; i < client->damagePlumCount; i++ ) { + DamagePlum( ent, client->damagePlums[i].origin, client->damagePlums[i].damage ); + } + client->damagePlumCount = 0; + // set the bit for the reachability area the client is currently in // i = trap_AAS_PointReachabilityAreaIndex( ent->client->ps.origin ); // ent->client->areabits[i >> 3] |= 1 << (i & 7); diff --git a/code/game/g_combat.c b/code/game/g_combat.c index 5a88e713..1fc77728 100644 --- a/code/game/g_combat.c +++ b/code/game/g_combat.c @@ -22,6 +22,37 @@ void ScorePlum( gentity_t *ent, vec3_t origin, int score ) { plum->s.time = score; } +/* +============ +DamagePlum +============ +*/ +void DamagePlum( gentity_t *attacker, vec3_t origin, int damage ) { + gentity_t *plum; + char userinfo[MAX_INFO_STRING]; + int damagePlumsEnabled; + + if ( !attacker || !attacker->client ) { + return; + } + + // check if the client supports damage plums + trap_GetUserinfo( attacker->s.number, userinfo, sizeof( userinfo ) ); + damagePlumsEnabled = atoi( Info_ValueForKey( userinfo, "cg_damagePlums" ) ); + + if ( !damagePlumsEnabled ) { + return; + } + + plum = G_TempEntity( origin, EV_DAMAGEPLUM ); + // only send this temp entity to the attacker + plum->r.svFlags |= SVF_SINGLECLIENT; + plum->r.singleClient = attacker->s.number; + // + plum->s.otherEntityNum = attacker->s.number; + plum->s.time = damage; +} + /* ============ AddScore @@ -805,6 +836,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, int asave; int knockback; int max; + int i; + qboolean found; #ifdef MISSIONPACK vec3_t bouncedir, impactpoint; #endif @@ -1018,6 +1051,24 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, attacker->client->damage.amount += take + asave; } #endif + if ( !OnSameTeam( targ, attacker ) ) { + // accumulate damage per target for damage plums + found = qfalse; + for ( i = 0; i < attacker->client->damagePlumCount; i++ ) { + if ( attacker->client->damagePlums[i].clientNum == targ->s.number ) { + attacker->client->damagePlums[i].damage += take + asave; + found = qtrue; + break; + } + } + if ( !found && attacker->client->damagePlumCount < MAX_CLIENTS ) { + attacker->client->damagePlums[attacker->client->damagePlumCount].clientNum = targ->s.number; + attacker->client->damagePlums[attacker->client->damagePlumCount].damage = take + asave; + VectorCopy( targ->r.currentOrigin, attacker->client->damagePlums[attacker->client->damagePlumCount].origin ); + attacker->client->damagePlums[attacker->client->damagePlumCount].origin[2] += 48; + attacker->client->damagePlumCount++; + } + } } // add to the damage inflicted on a player this frame diff --git a/code/game/g_local.h b/code/game/g_local.h index 7c8b9a4f..ac20095d 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -334,6 +334,14 @@ struct gclient_s { int enemy; int amount; } damage; + + // damage plums - track damage per target for this frame + struct { + int clientNum; + int damage; + vec3_t origin; + } damagePlums[MAX_CLIENTS]; + int damagePlumCount; }; @@ -528,6 +536,7 @@ const char *BuildShaderStateConfig( void ); qboolean CanDamage (gentity_t *targ, vec3_t origin); void G_Damage (gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_t dir, vec3_t point, int damage, int dflags, int mod); qboolean G_RadiusDamage (vec3_t origin, gentity_t *attacker, float damage, float radius, gentity_t *ignore, int mod); +void DamagePlum( gentity_t *attacker, vec3_t origin, int damage ); int G_InvulnerabilityEffect( gentity_t *targ, vec3_t dir, vec3_t point, vec3_t impactpoint, vec3_t bouncedir ); void body_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath ); void TossClientItems( gentity_t *self ); diff --git a/code/game/g_main.c b/code/game/g_main.c index dba12900..dc0a13c0 100644 --- a/code/game/g_main.c +++ b/code/game/g_main.c @@ -1467,6 +1467,7 @@ static void G_WarmupEnd( void ) client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_NONE; client->ps.persistant[PERS_ATTACKEE_ARMOR] = 0; client->damage.enemy = client->damage.team = 0; + client->damagePlumCount = 0; client->ps.stats[STAT_CLIENTS_READY] = 0; client->ps.stats[STAT_HOLDABLE_ITEM] = 0; From a7a06191f9378a661b836326b9e6d67eac3f6461 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Fri, 21 Nov 2025 13:23:48 -0500 Subject: [PATCH 2/4] Only parse cg_damagePlums userinfo on change --- code/cgame/cg_effects.c | 4 ++-- code/cgame/cg_localents.c | 1 + code/game/g_client.c | 7 +++++++ code/game/g_combat.c | 10 +--------- code/game/g_local.h | 1 + 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/code/cgame/cg_effects.c b/code/cgame/cg_effects.c index 894e5864..8abdfa71 100644 --- a/code/cgame/cg_effects.c +++ b/code/cgame/cg_effects.c @@ -407,10 +407,10 @@ void CG_ScorePlum( int client, const vec3_t origin, int score ) { le->endTime = cg.time + 4000; le->lifeRate = 1.0 / ( le->endTime - le->startTime ); - + le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0; le->radius = score; - + VectorCopy( origin, le->pos.trBase ); if ( origin[2] >= lastPos[2] - 20 && origin[2] <= lastPos[2] + 20 ) { le->pos.trBase[2] -= 20; diff --git a/code/cgame/cg_localents.c b/code/cgame/cg_localents.c index 9160e068..2680657e 100644 --- a/code/cgame/cg_localents.c +++ b/code/cgame/cg_localents.c @@ -944,6 +944,7 @@ void CG_AddDamagePlum( localEntity_t *le ) { VectorNormalize(vec); // if the view would be "inside" the sprite, kill the sprite + // so it doesn't add too much overdraw VectorSubtract( origin, cg.refdef.vieworg, delta ); len = VectorLength( delta ); if ( len < 20 ) { diff --git a/code/game/g_client.c b/code/game/g_client.c index da5cbcb1..32883008 100644 --- a/code/game/g_client.c +++ b/code/game/g_client.c @@ -624,6 +624,13 @@ qboolean ClientUserinfoChanged( int clientNum ) { client->pers.predictItemPickup = qtrue; } + // client wants damage plum data? + if ( atoi( Info_ValueForKey( userinfo, "cg_damagePlums" ) ) ) { + client->pers.damagePlums = qtrue; + } else { + client->pers.damagePlums = qfalse; + } + // set name Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) ); s = Info_ValueForKey( userinfo, "name" ); diff --git a/code/game/g_combat.c b/code/game/g_combat.c index 1fc77728..418c5c8a 100644 --- a/code/game/g_combat.c +++ b/code/game/g_combat.c @@ -32,15 +32,7 @@ void DamagePlum( gentity_t *attacker, vec3_t origin, int damage ) { char userinfo[MAX_INFO_STRING]; int damagePlumsEnabled; - if ( !attacker || !attacker->client ) { - return; - } - - // check if the client supports damage plums - trap_GetUserinfo( attacker->s.number, userinfo, sizeof( userinfo ) ); - damagePlumsEnabled = atoi( Info_ValueForKey( userinfo, "cg_damagePlums" ) ); - - if ( !damagePlumsEnabled ) { + if ( !attacker || !attacker->client || !attacker->client->pers.damagePlums) { return; } diff --git a/code/game/g_local.h b/code/game/g_local.h index ac20095d..f2d50134 100644 --- a/code/game/g_local.h +++ b/code/game/g_local.h @@ -240,6 +240,7 @@ typedef struct { int teamVoted; qboolean inGame; + qboolean damagePlums; // do we want to display damage numbers? } clientPersistant_t; // unlagged From 6c55f47031fd4fed52ac72d3002f20ea2761fc45 Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Sat, 10 Jan 2026 14:42:08 -0500 Subject: [PATCH 3/4] Follow Quake Live thresholds Also, adjust to match colors and set a consistent size. Spawn entity at about half height. Overall, should look closer to Quake Live appearance. --- code/cgame/cg_localents.c | 74 +++++++++++++++++++-------------------- code/game/g_combat.c | 2 +- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/code/cgame/cg_localents.c b/code/cgame/cg_localents.c index 2680657e..d0726275 100644 --- a/code/cgame/cg_localents.c +++ b/code/cgame/cg_localents.c @@ -878,12 +878,9 @@ CG_AddDamagePlum void CG_AddDamagePlum( localEntity_t *le ) { refEntity_t *re; vec3_t origin, delta, dir, vec, up = {0, 0, 1}; - float c, len; + float c, len, distance; int i, damage, digits[10], numdigits, negative; - float progress, fade; - float spread_x, spread_y; - float vertical_offset, peak_height; - float rise_progress, fall_progress; + float progress, fade, spread_x, spread_y, vertical_offset, peak_height; re = &le->refEntity; @@ -891,67 +888,68 @@ void CG_AddDamagePlum( localEntity_t *le ) { damage = le->radius; - // Color based on damage amount - gradient from white to red - if (damage >= 50) { + // Color based on damage amount - gradient from blue to red + if (damage > 75) { + // Red re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0x00; re->shaderRGBA[2] = 0x00; - } else if (damage >= 25) { + } else if (damage > 50) { + // Orange re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0x80; re->shaderRGBA[2] = 0x00; - } else if (damage >= 10) { + } else if (damage > 25) { + // Yellow re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0xff; re->shaderRGBA[2] = 0x00; } else { - re->shaderRGBA[0] = 0xff; - re->shaderRGBA[1] = 0xff; + // Blue + re->shaderRGBA[0] = 0x00; + re->shaderRGBA[1] = 0x80; re->shaderRGBA[2] = 0xff; } - // Fade out after 250ms (after peak at 25% progress) + // Fade out after 75% of arc (750ms) progress = 1.0 - c; // 0.0 at start, 1.0 at end - if (progress < 0.25) { - fade = 1.0; // Full opacity for first 250ms + if (progress < 0.75f) { + fade = 1.0f; // Full opacity for first 750ms } else { - fade = 1.0 - ((progress - 0.25) / 0.75); // Fade out over remaining 750ms + fade = 1.0f - ((progress - 0.75f) / 0.25f); // Fade out over remaining 250ms } re->shaderRGBA[3] = 0xff * fade; - re->radius = NUMBER_SIZE / 2; - VectorCopy(le->pos.trBase, origin); - spread_x = le->pos.trDelta[0] * 70.0 * progress; - spread_y = le->pos.trDelta[1] * 70.0 * progress; + // Calculate distance to base origin for scaling sprite and arc + VectorSubtract( origin, cg.refdef.vieworg, delta ); + len = VectorLengthSquared( delta ); + if ( len < 20*20 ) { + // if the view would be "inside" the sprite, kill the sprite + CG_FreeLocalEntity( le ); + return; + } + + distance = sqrt(len); + re->radius = (NUMBER_SIZE / 1280.0f) * distance * tan(cg.refdef.fov_x * M_PI / 360.0f); + + // Horizontal spread + spread_x = le->pos.trDelta[0] * 20.0 * re->radius * progress; + spread_y = le->pos.trDelta[1] * 20.0 * re->radius * progress; origin[0] += spread_x; origin[1] += spread_y; - peak_height = 30.0 * le->pos.trDelta[2]; - - if (progress < 0.25) { - rise_progress = progress / 0.25; - vertical_offset = peak_height * (1.0 - (1.0 - rise_progress) * (1.0 - rise_progress)); - } else { - fall_progress = (progress - 0.25) / 0.75; - vertical_offset = peak_height - (peak_height + 48.0) * fall_progress * fall_progress; - } + // Vertical arc - symmetric rise and fall over the full duration + // Uses sine wave for smooth, even arc that peaks at 50% progress + peak_height = 15.0 * le->pos.trDelta[2] * re->radius; + vertical_offset = peak_height * sin(progress * M_PI); origin[2] += vertical_offset; VectorSubtract(cg.refdef.vieworg, origin, dir); CrossProduct(dir, up, vec); VectorNormalize(vec); - // if the view would be "inside" the sprite, kill the sprite - // so it doesn't add too much overdraw - VectorSubtract( origin, cg.refdef.vieworg, delta ); - len = VectorLength( delta ); - if ( len < 20 ) { - CG_FreeLocalEntity( le ); - return; - } - negative = qfalse; if (damage < 0) { negative = qtrue; @@ -969,7 +967,7 @@ void CG_AddDamagePlum( localEntity_t *le ) { } for (i = 0; i < numdigits; i++) { - VectorMA(origin, (float) (((float) numdigits / 2) - i) * NUMBER_SIZE, vec, re->origin); + VectorMA(origin, (float) (((float) numdigits / 2) - i) * (re->radius * 2), vec, re->origin); re->customShader = cgs.media.numberShaders[digits[numdigits-1-i]]; trap_R_AddRefEntityToScene( re ); } diff --git a/code/game/g_combat.c b/code/game/g_combat.c index 418c5c8a..189b5761 100644 --- a/code/game/g_combat.c +++ b/code/game/g_combat.c @@ -1057,7 +1057,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, attacker->client->damagePlums[attacker->client->damagePlumCount].clientNum = targ->s.number; attacker->client->damagePlums[attacker->client->damagePlumCount].damage = take + asave; VectorCopy( targ->r.currentOrigin, attacker->client->damagePlums[attacker->client->damagePlumCount].origin ); - attacker->client->damagePlums[attacker->client->damagePlumCount].origin[2] += 48; + attacker->client->damagePlums[attacker->client->damagePlumCount].origin[2] += 24; attacker->client->damagePlumCount++; } } From 196ac1731f782faa9658bb44488eed8d892010ae Mon Sep 17 00:00:00 2001 From: Ernie Miller Date: Mon, 12 Jan 2026 08:12:00 -0500 Subject: [PATCH 4/4] Update code/game/g_combat.c Remove unused variables. Co-authored-by: WofWca --- code/game/g_combat.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/game/g_combat.c b/code/game/g_combat.c index 189b5761..caf47f5c 100644 --- a/code/game/g_combat.c +++ b/code/game/g_combat.c @@ -29,8 +29,6 @@ DamagePlum */ void DamagePlum( gentity_t *attacker, vec3_t origin, int damage ) { gentity_t *plum; - char userinfo[MAX_INFO_STRING]; - int damagePlumsEnabled; if ( !attacker || !attacker->client || !attacker->client->pers.damagePlums) { return;