diff --git a/reaction/cgame/cg_local.h b/reaction/cgame/cg_local.h index 0cd955c5..1af944a7 100644 --- a/reaction/cgame/cg_local.h +++ b/reaction/cgame/cg_local.h @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.53 2002/03/16 21:50:09 niceass +// All new shell ejection code +// // Revision 1.52 2002/03/14 16:04:26 slicer // Optimization on radio parsing // @@ -263,7 +266,7 @@ typedef struct centity_s { qboolean currentValid; // true if cg.frame holds this entity int muzzleFlashTime; // move to playerEntity? - int ejectBrass; // NiceAss: set if the weapon should eject a shell + int ejectBrassTime; // NiceAss: set if the weapon should eject a shell int previousEvent; int teleportFlag; @@ -910,6 +913,7 @@ typedef struct { qhandle_t smoke2; qhandle_t machinegunBrassModel; + qhandle_t largeBrassModel; qhandle_t shotgunBrassModel; qhandle_t railRingsShader; @@ -1766,6 +1770,8 @@ void CG_InitLocalEntities( void ); localEntity_t *CG_AllocLocalEntity( void ); void CG_AddLocalEntities( void ); void CG_FreeLocalEntity( localEntity_t *le ); +void CG_LE_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ); +void CG_LE_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ); // // cg_effects.c diff --git a/reaction/cgame/cg_localents.c b/reaction/cgame/cg_localents.c index edc0a4ac..c4ec656b 100644 --- a/reaction/cgame/cg_localents.c +++ b/reaction/cgame/cg_localents.c @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.8 2002/03/16 21:49:45 niceass +// All new shell ejection code +// // Revision 1.7 2002/01/14 01:19:23 niceass // No more default 800 gravity on items - NiceAss // @@ -210,29 +213,38 @@ CG_ReflectVelocity ================ */ void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) { - vec3_t velocity; + vec3_t velocity, normal; float dot; int hitTime; + // NiceAss: Make the reflection less perfect + VectorCopy( trace->plane.normal, normal ); + if (le->leFlags == LEF_TUMBLE) { + normal[0] += crandom() * 0.1; + normal[1] += crandom() * 0.1; + normal[2] += crandom() * 0.1; + VectorNormalize(normal); + } + // reflect the velocity on the trace plane hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction; - CG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity ); - dot = DotProduct( velocity, trace->plane.normal ); - VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta ); + CG_LE_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity ); + dot = DotProduct( velocity, normal ); + VectorMA( velocity, -2*dot, normal, le->pos.trDelta ); VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta ); VectorCopy( trace->endpos, le->pos.trBase ); le->pos.trTime = cg.time; - // check for stop, making sure that even on low FPS systems it doesn't bobble if ( trace->allsolid || - ( trace->plane.normal[2] > 0 && + VectorLength(le->pos.trDelta) < 30.0 ) { + // NiceAss: I don't know what this crap is, but it didn't work too well no sloped surfaces + /*( trace->plane.normal[2] > 0 && ( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) { + */ le->pos.trType = TR_STATIONARY; - } else { - } } @@ -269,7 +281,8 @@ void CG_AddFragment( localEntity_t *le ) { } // calculate new position - CG_EvaluateTrajectory( &le->pos, cg.time, newOrigin ); + CG_LE_EvaluateTrajectory( &le->pos, cg.time, newOrigin ); + // trace a line from previous position to new position CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID ); @@ -280,7 +293,7 @@ void CG_AddFragment( localEntity_t *le ) { if ( le->leFlags & LEF_TUMBLE ) { vec3_t angles; - CG_EvaluateTrajectory( &le->angles, cg.time, angles ); + CG_LE_EvaluateTrajectory( &le->angles, cg.time, angles ); AnglesToAxis( angles, le->refEntity.axis ); } @@ -880,6 +893,84 @@ void CG_AddLocalEntities( void ) { } } +/* + The only difference is that this will account for water friction +*/ +void CG_LE_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) { + float deltaTime; + float phase; + float friction = 1.0f; + switch( tr->trType ) { + case TR_STATIONARY: + case TR_INTERPOLATE: + VectorCopy( tr->trBase, result ); + break; + case TR_LINEAR: + deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds + VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); + break; + case TR_SINE: + deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration; + phase = sin( deltaTime * M_PI * 2 ); + VectorMA( tr->trBase, phase, tr->trDelta, result ); + break; + case TR_LINEAR_STOP: + if ( atTime > tr->trTime + tr->trDuration ) { + atTime = tr->trTime + tr->trDuration; + } + deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds + if ( deltaTime < 0 ) { + deltaTime = 0; + } + VectorMA( tr->trBase, deltaTime, tr->trDelta, result ); + break; + case TR_GRAVITY: + if (trap_CM_PointContents(tr->trBase, 0) & CONTENTS_WATER) friction = 0.3f; + deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds + VectorMA( tr->trBase, deltaTime * friction, tr->trDelta, result ); + result[2] -= 0.5 * cg_gravity.value * friction * deltaTime * deltaTime; + break; + default: + Com_Error( ERR_DROP, "CG_LE_EvaluateTrajectory: unknown trType: %i", tr->trTime ); + break; + } +} +void CG_LE_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ) { + float deltaTime; + float phase; + float friction = 1.0f; + switch( tr->trType ) { + case TR_STATIONARY: + case TR_INTERPOLATE: + VectorClear( result ); + break; + case TR_LINEAR: + VectorCopy( tr->trDelta, result ); + break; + case TR_SINE: + deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration; + phase = cos( deltaTime * M_PI * 2 ); // derivative of sin = cos + phase *= 0.5; + VectorScale( tr->trDelta, phase, result ); + break; + case TR_LINEAR_STOP: + if ( atTime > tr->trTime + tr->trDuration ) { + VectorClear( result ); + return; + } + VectorCopy( tr->trDelta, result ); + break; + case TR_GRAVITY: + if (trap_CM_PointContents(tr->trBase, 0) & CONTENTS_WATER) friction = 0.3f; + deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds + VectorScale( tr->trDelta, friction, result ); + result[2] -= cg_gravity.value*friction*deltaTime; + break; + default: + Com_Error( ERR_DROP, "CG_LE_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime ); + break; + } +} diff --git a/reaction/cgame/cg_main.c b/reaction/cgame/cg_main.c index f123c897..b68249d6 100644 --- a/reaction/cgame/cg_main.c +++ b/reaction/cgame/cg_main.c @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.45 2002/03/16 21:49:08 niceass +// All new shell ejection code +// // Revision 1.44 2002/03/14 16:04:26 slicer // Optimization on radio parsing // @@ -296,7 +299,7 @@ static cvarTable_t cvarTable[] = { // bk001129 { &cg_crosshairHealth, "cg_crosshairHealth", "1", CVAR_ARCHIVE }, { &cg_crosshairX, "cg_crosshairX", "0", CVAR_ARCHIVE }, { &cg_crosshairY, "cg_crosshairY", "0", CVAR_ARCHIVE }, - { &cg_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE }, + { &cg_brassTime, "cg_brassTime", "10000", CVAR_ARCHIVE }, { &cg_simpleItems, "cg_simpleItems", "0", CVAR_ARCHIVE }, { &cg_addMarks, "cg_marks", "1", CVAR_ARCHIVE }, { &cg_lagometer, "cg_lagometer", "1", CVAR_ARCHIVE }, @@ -1185,7 +1188,7 @@ static void CG_RegisterGraphics( void ) { cgs.media.armorIcon = trap_R_RegisterShaderNoMip( "icons/iconr_yellow" ); cgs.media.machinegunBrassModel = trap_R_RegisterModel( "models/weapons2/shells/m_shell.md3" ); - //Elder: changed from m_shel to s_shell + cgs.media.largeBrassModel = trap_R_RegisterModel( "models/weapons2/shells/l_shell.md3" ); cgs.media.shotgunBrassModel = trap_R_RegisterModel( "models/weapons2/shells/s_shell.md3" ); cgs.media.gibAbdomen = trap_R_RegisterModel( "models/gibs/abdomen.md3" ); diff --git a/reaction/cgame/cg_weapons.c b/reaction/cgame/cg_weapons.c index b98d1757..e30c7b03 100644 --- a/reaction/cgame/cg_weapons.c +++ b/reaction/cgame/cg_weapons.c @@ -5,6 +5,9 @@ //----------------------------------------------------------------------------- // // $Log$ +// Revision 1.54 2002/03/16 21:48:39 niceass +// All new shell ejection code +// // Revision 1.53 2002/03/13 18:41:18 slicer // Adjusted some of elder's unzoom code for the new sniper system ( server side ) // @@ -196,10 +199,6 @@ localEntity_t *CG_MachineGunEjectBrass( centity_t *cent ) { le = CG_AllocLocalEntity(); re = &le->refEntity; - velocity[0] = 0; - velocity[1] = -100 + 50 * crandom(); - velocity[2] = 100 + 50 * crandom(); - le->leType = LE_FRAGMENT; le->startTime = cg.time; le->endTime = le->startTime + cg_brassTime.integer + ( cg_brassTime.integer / 4 ) * random(); @@ -207,52 +206,18 @@ localEntity_t *CG_MachineGunEjectBrass( centity_t *cent ) { le->pos.trType = TR_GRAVITY; le->pos.trTime = cg.time - (rand()&15); - AnglesToAxis( cent->lerpAngles, v ); - - offset[0] = 8; - offset[1] = -4; - offset[2] = 24; - - // NiceAss: Added for better starting location of brass - if (cg.predictedPlayerState.pm_flags & PMF_DUCKED) { - offset[2] -= 14; - } - - xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0]; - xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1]; - xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2]; - VectorAdd( cent->lerpOrigin, xoffset, re->origin ); - - VectorCopy( re->origin, le->pos.trBase ); - - if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) { - waterScale = 0.10f; - } - - xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0]; - xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1]; - xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2]; - - VectorScale( xvelocity, waterScale, le->pos.trDelta ); - AxisCopy( axisDefault, re->axis ); re->hModel = cgs.media.machinegunBrassModel; - le->bounceFactor = 0.4 * waterScale; + le->bounceFactor = 0.5; le->angles.trType = TR_LINEAR; le->angles.trTime = cg.time; - le->angles.trBase[0] = rand()&31; - le->angles.trBase[1] = rand()&31; - le->angles.trBase[2] = rand()&31; - le->angles.trBase[0] = 5+rand()&10; - le->angles.trBase[1] = 2+rand()&5; - le->angles.trBase[2] = 0; -// le->angles.trDelta[0] = 2; -// le->angles.trDelta[1] = 1; -// le->angles.trDelta[2] = 0; + le->angles.trDelta[0] = rand()%200-100; + le->angles.trDelta[1] = rand()%200-100; + le->angles.trDelta[2] = rand()%200-100; le->leFlags = LEF_TUMBLE; le->leBounceSoundType = LEBS_BRASS; @@ -265,7 +230,6 @@ localEntity_t *CG_MachineGunEjectBrass( centity_t *cent ) { CG_ShotgunEjectBrass ========================== */ -//static void CG_ShotgunEjectBrass( centity_t *cent, vec3_t origin, vec3_t axis[3] ) { localEntity_t *CG_ShotgunEjectBrass( centity_t *cent ) { localEntity_t *le; refEntity_t *re; @@ -289,14 +253,6 @@ localEntity_t *CG_ShotgunEjectBrass( centity_t *cent ) { le = CG_AllocLocalEntity(); re = &le->refEntity; - velocity[0] = 60 + 60 * crandom(); - if ( i == 0 ) { - velocity[1] = 40 + 10 * crandom(); - } else { - velocity[1] = -40 + 10 * crandom(); - } - velocity[2] = 100 + 50 * crandom(); - le->leType = LE_FRAGMENT; le->startTime = cg.time; le->endTime = le->startTime + cg_brassTime.integer*3 + cg_brassTime.integer * random(); @@ -304,34 +260,6 @@ localEntity_t *CG_ShotgunEjectBrass( centity_t *cent ) { le->pos.trType = TR_GRAVITY; le->pos.trTime = cg.time; - AnglesToAxis( cent->lerpAngles, v ); - - offset[0] = 8; - offset[1] = 0; - offset[2] = 24; - - // NiceAss: Added for better starting location of brass - if (cg.predictedPlayerState.pm_flags & PMF_DUCKED) { - offset[2] -= 14; - } - - xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0]; - xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1]; - xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2]; - VectorAdd( cent->lerpOrigin, xoffset, re->origin ); - - VectorCopy( re->origin, le->pos.trBase ); - - if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) { - waterScale = 0.10f; - } - - xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0]; - xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1]; - xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2]; - - VectorScale( xvelocity, waterScale, le->pos.trDelta ); - AxisCopy( axisDefault, re->axis ); re->hModel = cgs.media.shotgunBrassModel; @@ -339,12 +267,10 @@ localEntity_t *CG_ShotgunEjectBrass( centity_t *cent ) { le->angles.trType = TR_LINEAR; le->angles.trTime = cg.time; - le->angles.trBase[0] = rand()&31; - le->angles.trBase[1] = rand()&31; - le->angles.trBase[2] = rand()&31; - le->angles.trDelta[0] = 1; - le->angles.trDelta[1] = 0.5; - le->angles.trDelta[2] = 0; + + le->angles.trDelta[0] = rand()%200-100; + le->angles.trDelta[1] = rand()%200-100; + le->angles.trDelta[2] = rand()%200-100; le->leFlags = LEF_TUMBLE; le->leBounceSoundType = LEBS_BRASS; @@ -1417,11 +1343,12 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent // Blaze: Can remove this because no more spinning barrel // refEntity_t barrel; refEntity_t flash; + refEntity_t silencer; vec3_t angles; weapon_t weaponNum; weaponInfo_t *weapon; centity_t *nonPredictedCent; - localEntity_t *shell; + localEntity_t *shell = NULL; weaponNum = cent->currentState.weapon; @@ -1614,17 +1541,72 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent */ //CG_LightningBolt( nonPredictedCent, parent->lightingOrigin ); + if ( ps ) { + float scale; + vec3_t angles; + + if (weaponNum == WP_PISTOL) scale = 0.6; + if (weaponNum == WP_SSG3000) scale = 0.9; + if (weaponNum == WP_MP5) scale = 1.0; + + memset( &silencer, 0, sizeof( silencer ) ); + silencer.hModel = cgs.media.rq3_silencerModel; + silencer.shadowPlane = parent->shadowPlane; + silencer.renderfx = parent->renderfx; + + angles[YAW] = 90; + angles[PITCH] = 0; + angles[ROLL] = 0; + AnglesToAxis( angles, silencer.axis ); + + CG_PositionRotatedEntityOnTag( &silencer, &gun, weapon->firstModel, "tag_silencer"); + + VectorScale( silencer.axis[0], scale, silencer.axis[0] ); + VectorScale( silencer.axis[1], scale, silencer.axis[1] ); + VectorScale( silencer.axis[2], scale, silencer.axis[2] ); + + flash.nonNormalizedAxes = qtrue; + //CG_AddWeaponWithPowerups( &silencer, cent->currentState.powerups ); + } // NiceAss: Tag locations used for shell ejection - if ( cent->ejectBrass && weapon->ejectBrassFunc && + if ( cg.time > cent->ejectBrassTime && cent->ejectBrassTime && weapon->ejectBrassFunc && ( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) ) { + shell = weapon->ejectBrassFunc( cent ); - if ( shell && ( weaponNum == WP_PISTOL || weaponNum == WP_MP5 ) ) { - CG_PositionRotatedEntityOnTag( &shell->refEntity, &gun, gun.hModel, "tag_shell"); + + if ( weaponNum == WP_M4 || weaponNum == WP_SSG3000) { + shell->refEntity.hModel = cgs.media.largeBrassModel; + shell->bounceFactor *= 0.75; + } + + if ( shell != NULL && weaponNum != WP_HANDCANNON ) { + float speed = 1.0f; + + if (ps) { + if ( weapon->item->giTag == WP_AKIMBO && !ps->stats[STAT_BURST] ) + CG_PositionRotatedEntityOnTag( &shell->refEntity, &gun, gun.hModel, "tag_shell2"); + else + CG_PositionRotatedEntityOnTag( &shell->refEntity, &gun, gun.hModel, "tag_shell"); + } + else { + if ( weapon->item->giTag == WP_AKIMBO && cg.akimboFlash ) + CG_PositionRotatedEntityOnTag( &shell->refEntity, &gun, gun.hModel, "tag_shell2"); + else + CG_PositionRotatedEntityOnTag( &shell->refEntity, &gun, gun.hModel, "tag_shell"); + + } + VectorCopy( shell->refEntity.origin, shell->pos.trBase ); + + if (trap_CM_PointContents(shell->pos.trBase, 0) == CONTENTS_WATER) speed = 0.5f; + vectoangles( shell->refEntity.axis[0], shell->angles.trBase); - } - cent->ejectBrass = qfalse; + VectorScale( shell->refEntity.axis[0], 140 * speed, shell->pos.trDelta ); + VectorAdd( shell->pos.trDelta, cent->currentState.pos.trDelta, shell->pos.trDelta); + } + + cent->ejectBrassTime = 0; } //Elder: re-added to fix loss of muzzle flashes! @@ -2556,7 +2538,13 @@ void CG_FireWeapon( centity_t *cent, int weapModification ) { }*/ // NiceAss: - cent->ejectBrass = qtrue; + if (ent->weapon == WP_M3) + cent->ejectBrassTime = cg.time+500; + else if (ent->weapon == WP_SSG3000) + cent->ejectBrassTime = cg.time+650; + else if (ent->weapon != WP_KNIFE && ent->weapon != WP_GRENADE) + cent->ejectBrassTime = cg.time; + // mark the entity as muzzle flashing, so when it is added it will // append the flash to the weapon model