All new shell ejection code

This commit is contained in:
Bryce Hutchings 2002-03-16 21:50:09 +00:00
parent 879bb46829
commit 30d61a8c7c
4 changed files with 193 additions and 105 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -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" );

View file

@ -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