diff --git a/README.md b/README.md index 98a2c9c1..1ff0c708 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Unofficial Quake III Arena gamecode patch * fixed UI mouse sensitivity for high-resolution * fixed not being able to gib after match end (right before showing the scores) * fixed shotgun not gibbing unless aiming at the feet + * improved gibs starting positions * fixed server browser + faster scanning * fixed grappling hook muzzle position visuals * new demo UI (subfolders,filtering,sorting) diff --git a/code/cgame/cg_cvar.h b/code/cgame/cg_cvar.h index 46811af9..f6d96d6a 100644 --- a/code/cgame/cg_cvar.h +++ b/code/cgame/cg_cvar.h @@ -18,6 +18,7 @@ CG_CVAR( cg_fov, "cg_fov", "90", CVAR_ARCHIVE ) CG_CVAR( cg_viewsize, "cg_viewsize", "100", CVAR_ARCHIVE ) CG_CVAR( cg_shadows, "cg_shadows", "1", CVAR_ARCHIVE ) CG_CVAR( cg_gibs, "cg_gibs", "1", CVAR_ARCHIVE ) +CG_CVAR( cg_oldGibs, "cg_oldGibs", "0", CVAR_ARCHIVE ) CG_CVAR( cg_draw2D, "cg_draw2D", "1", CVAR_ARCHIVE ) CG_CVAR( cg_drawStatus, "cg_drawStatus", "1", CVAR_ARCHIVE ) CG_CVAR( cg_drawTimer, "cg_drawTimer", "0", CVAR_ARCHIVE ) diff --git a/code/cgame/cg_effects.c b/code/cgame/cg_effects.c index 115c309f..4949eb7b 100644 --- a/code/cgame/cg_effects.c +++ b/code/cgame/cg_effects.c @@ -533,7 +533,8 @@ void CG_Bleed( const vec3_t origin, int entityNum ) { CG_LaunchGib ================== */ -static void CG_LaunchGib( const vec3_t origin, const vec3_t velocity, qhandle_t hModel ) { +static void CG_LaunchGib( const vec3_t origin, const vec3_t angles, + const vec3_t velocity, qhandle_t hModel ) { localEntity_t *le; refEntity_t *re; @@ -545,7 +546,7 @@ static void CG_LaunchGib( const vec3_t origin, const vec3_t velocity, qhandle_t le->endTime = le->startTime + 5000 + random() * 3000; VectorCopy( origin, re->origin ); - AxisCopy( axisDefault, re->axis ); + AnglesToAxis( angles, re->axis ); re->hModel = hModel; le->pos.trType = TR_GRAVITY; @@ -568,21 +569,129 @@ Generated a bunch of gibs launching out from the bodies location */ #define GIB_VELOCITY 250 #define GIB_JUMP 250 -void CG_GibPlayer( const vec3_t playerOrigin ) { +void CG_GibPlayer( const vec3_t playerOrigin, const vec3_t playerAngles ) { vec3_t origin, velocity; + vec3_t forward, right; + // See `playerMins`, `playerMaxs`. + // TODO we could try to check the actual `mins` and `maxs` + // (do we have them available on the client though?), + // to account for crounching or for the "lying on the ground dead" state. + float playerHeight = 32 - MINS_Z; + float bottom = playerOrigin[2] + MINS_Z; + float playerRadius = 15; + + if ( !cg_blood.integer ) { + return; + } + + AngleVectors( playerAngles, forward, right, NULL ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.95 * playerHeight; + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + if ( rand() & 1 ) { + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibSkull ); + } else { + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibBrain ); + } + + // allow gibs to be turned off for speed + if ( !cg_gibs.integer ) { + return; + } + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.65 * playerHeight; + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibAbdomen ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.75 * playerHeight; + VectorMA( origin, 0.5 * playerRadius, right, origin ); + VectorMA( origin, 0.5 * playerRadius, forward, origin ); + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibArm ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.80 * playerHeight; + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibChest ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.66 * playerHeight; + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibFist ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.05 * playerHeight; + VectorMA( origin, -0.5 * playerRadius, right, origin ); + VectorMA( origin, -0.5 * playerRadius, forward, origin ); + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibFoot ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.65 * playerHeight; + VectorMA( origin, -0.6 * playerRadius, right, origin ); + VectorMA( origin, -0.2 * playerRadius, forward, origin ); + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibForearm ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.57 * playerHeight; + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibIntestine ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.42 * playerHeight; + VectorMA( origin, 0.5 * playerRadius, right, origin ); + VectorMA( origin, 0.1 * playerRadius, forward, origin ); + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibLeg ); + + VectorCopy( playerOrigin, origin ); + origin[2] = bottom + 0.44 * playerHeight; + VectorMA( origin, -0.5 * playerRadius, right, origin ); + VectorMA( origin, -0.2 * playerRadius, forward, origin ); + velocity[0] = crandom()*GIB_VELOCITY; + velocity[1] = crandom()*GIB_VELOCITY; + velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; + CG_LaunchGib( origin, playerAngles, velocity, cgs.media.gibLeg ); +} +void CG_GibPlayerOld( const vec3_t playerOrigin ) { + vec3_t origin, angles, velocity; if ( !cg_blood.integer ) { return; } + VectorClear(angles); + VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; if ( rand() & 1 ) { - CG_LaunchGib( origin, velocity, cgs.media.gibSkull ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibSkull ); } else { - CG_LaunchGib( origin, velocity, cgs.media.gibBrain ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibBrain ); } // allow gibs to be turned off for speed @@ -594,55 +703,55 @@ void CG_GibPlayer( const vec3_t playerOrigin ) { velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibAbdomen ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibAbdomen ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibArm ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibArm ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibChest ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibChest ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibFist ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibFist ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibFoot ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibFoot ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibForearm ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibForearm ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibIntestine ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibIntestine ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibLeg ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibLeg ); VectorCopy( playerOrigin, origin ); velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - CG_LaunchGib( origin, velocity, cgs.media.gibLeg ); + CG_LaunchGib( origin, angles, velocity, cgs.media.gibLeg ); } /* diff --git a/code/cgame/cg_event.c b/code/cgame/cg_event.c index 67319e7f..bcfebc1d 100644 --- a/code/cgame/cg_event.c +++ b/code/cgame/cg_event.c @@ -1215,7 +1215,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position, int entityNum ) { #else trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.gibSound ); #endif - CG_GibPlayer( cent->lerpOrigin ); + if (cg_oldGibs.integer) { + CG_GibPlayerOld( cent->lerpOrigin ); + } else { + CG_GibPlayer( cent->lerpOrigin, cent->lerpAngles ); + } break; case EV_STOPLOOPINGSOUND: diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 240f6ed1..6d2ad9e1 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -1406,7 +1406,8 @@ void CG_LightningBoltBeam( vec3_t start, vec3_t end ); #endif void CG_ScorePlum( int client, const vec3_t origin, int score ); -void CG_GibPlayer( const vec3_t playerOrigin ); +void CG_GibPlayer( const vec3_t playerOrigin, const vec3_t playerAngles ); +void CG_GibPlayerOld( const vec3_t playerOrigin ); void CG_BigExplode( vec3_t playerOrigin ); void CG_Bleed( const vec3_t origin, int entityNum ); diff --git a/code/cgame/cg_localents.c b/code/cgame/cg_localents.c index 45535ab7..132ae8c2 100644 --- a/code/cgame/cg_localents.c +++ b/code/cgame/cg_localents.c @@ -760,8 +760,12 @@ void CG_AddInvulnerabilityJuiced( localEntity_t *le ) { le->refEntity.axis[2][2] = (float) 0.7 + 0.3 * (2000 - (t - 3000)) / 2000; } if ( t > 5000 ) { + vec3_t angles; + // Andles don't matter much here. + VectorClear( angles ); + le->endTime = 0; - CG_GibPlayer( le->refEntity.origin ); + CG_GibPlayer( le->refEntity.origin, angles ); } else { trap_R_AddRefEntityToScene( &le->refEntity );