summaryrefslogtreecommitdiff
path: root/src/cgame/cg_weapons.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame/cg_weapons.c')
-rw-r--r--src/cgame/cg_weapons.c176
1 files changed, 173 insertions, 3 deletions
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index 2b41d13..8e3b438 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -65,8 +65,6 @@ void CG_RegisterUpgrade( int upgradeNum )
upgradeInfo->upgradeIcon = cg_weapons[ WP_GRENADE ].weaponIcon;
else if( upgradeNum == UP_MINE )
upgradeInfo->upgradeIcon = cg_weapons[ WP_MINE ].weaponIcon;
- else if( upgradeNum == UP_SMOKE )
- upgradeInfo->upgradeIcon = cg_weapons[ WP_SMOKE ].weaponIcon;
else if( ( icon = BG_Upgrade( upgradeNum )->icon ) )
upgradeInfo->upgradeIcon = trap_R_RegisterShader( icon );
}
@@ -418,6 +416,26 @@ static qboolean CG_ParseWeaponModeSection( weaponInfoMode_t *wim, char **text_p
continue;
}
+ else if( !Q_stricmp( token, "impactQuake" ) )
+ {
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->impactQuake = atof( token );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "flashQuake" ) )
+ {
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->flashQuake = atof( token );
+
+ continue;
+ }
else if( !Q_stricmp( token, "}" ) )
return qtrue; //reached the end of this weapon section
else
@@ -868,6 +886,60 @@ static float CG_MachinegunSpinAngle( centity_t *cent, qboolean firing )
return angle;
}
+/*
+=============
+CG_RenderGenericBeam
+=============
+*/
+
+void CG_RenderGenericBeam( const vec3_t start, const vec3_t end, qhandle_t shader, float radius )
+{
+ vec3_t delta, viewdelta, side;
+ float length;
+ polyVert_t quad[ 4 ];
+
+ VectorSubtract( end, start, delta );
+ length = VectorLength( delta );
+ VectorSubtract( start, cg.refdef.vieworg, viewdelta );
+ CrossProduct( delta, viewdelta, side );
+ VectorNormalize( side );
+
+ VectorMA( start, radius, side, quad[ 3 ].xyz );
+ VectorMA( start, -radius, side, quad[ 2 ].xyz );
+ VectorMA( end, -radius, side, quad[ 1 ].xyz );
+ VectorMA( end, radius, side, quad[ 0 ].xyz );
+
+ quad[ 0 ].st[ 0 ] = length / radius * 0.1;
+ quad[ 0 ].st[ 1 ] = 0;
+ quad[ 0 ].modulate[ 0 ] = 255;
+ quad[ 0 ].modulate[ 1 ] = 255;
+ quad[ 0 ].modulate[ 2 ] = 255;
+ quad[ 0 ].modulate[ 3 ] = 255;
+
+ quad[ 1 ].st[ 0 ] = length / radius * 0.1;
+ quad[ 1 ].st[ 1 ] = 1;
+ quad[ 1 ].modulate[ 0 ] = 255;
+ quad[ 1 ].modulate[ 1 ] = 255;
+ quad[ 1 ].modulate[ 2 ] = 255;
+ quad[ 1 ].modulate[ 3 ] = 255;
+
+ quad[ 2 ].st[ 0 ] = 0;
+ quad[ 2 ].st[ 1 ] = 1;
+ quad[ 2 ].modulate[ 0 ] = 255;
+ quad[ 2 ].modulate[ 1 ] = 255;
+ quad[ 2 ].modulate[ 2 ] = 255;
+ quad[ 2 ].modulate[ 3 ] = 255;
+
+ quad[ 3 ].st[ 0 ] = 0;
+ quad[ 3 ].st[ 1 ] = 0;
+ quad[ 3 ].modulate[ 0 ] = 255;
+ quad[ 3 ].modulate[ 1 ] = 255;
+ quad[ 3 ].modulate[ 2 ] = 255;
+ quad[ 3 ].modulate[ 3 ] = 255;
+
+ trap_R_AddPolyToScene( shader, 4, quad );
+}
+
/*
=============
@@ -878,6 +950,7 @@ The main player will have this called for BOTH cases, so effects like light and
sound should only be done on the world model case.
=============
*/
+
void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent )
{
refEntity_t gun;
@@ -1116,6 +1189,66 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
cent->muzzlePsTrigger = qfalse;
}
+ // Lightning Gun's beam
+ if( weaponNum == WP_LIGHTNING_GUN )
+ {
+ attachment_t attachment;
+ vec3_t muzzle, forward, end, beam_start;
+ trace_t tr;
+
+ if( ps )
+ {
+ BG_GetClientViewOrigin( ps, muzzle );
+ AngleVectors( ps->viewangles, forward, NULL, NULL );
+ }
+ else
+ {
+ // NOTE: this code assumes that the player's normal is (0,0,1)
+ // it will break when humans start walking on walls
+ class_t class = ( cent->currentState.misc >> 8 ) & 0xFF;
+
+ VectorCopy( cent->lerpOrigin, muzzle );
+
+ // the only way to tell if a human is crouching is to check its bbox
+ // which is transmitted in a weird, encoded form (hence the magic number)
+ if( class == PCL_HUMAN && cent->currentState.solid == 3151887 )
+ muzzle[ 2 ] += BG_ClassConfig( class )->crouchViewheight;
+ else
+ muzzle[ 2 ] += BG_ClassConfig( class )->viewheight;
+
+ AngleVectors( cent->lerpAngles, forward, NULL, NULL );
+ }
+
+ VectorMA( muzzle, LIGHTNING_RANGE, forward, end );
+
+ CG_Trace( &tr, muzzle, NULL, NULL, end, cg.predictedPlayerState.clientNum, MASK_SHOT );
+
+ memset( &attachment, 0, sizeof( attachment ) );
+
+ if( noGunModel )
+ CG_SetAttachmentTag( &attachment, *parent, parent->hModel, "tag_weapon" );
+ else
+ CG_SetAttachmentTag( &attachment, gun, gun.hModel, "tag_flash" );
+
+ CG_AttachToTag( &attachment );
+
+ if( CG_AttachmentPoint( &attachment, beam_start ) )
+ CG_RenderGenericBeam( beam_start, tr.endpos, cgs.media.lightningBeam, 3 );
+
+ if( tr.entityNum != ENTITYNUM_NONE &&
+ !( tr.surfaceFlags & SURF_NOIMPACT ) )
+ {
+ particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.lightningImpactPS );
+
+ if( CG_IsParticleSystemValid( &ps ) )
+ {
+ CG_SetAttachmentPoint( &ps->attachment, tr.endpos );
+ CG_SetParticleSystemNormal( ps, tr.plane.normal );
+ CG_AttachToPoint( &ps->attachment );
+ }
+ }
+ }
+
// make a dlight for the flash
if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] ||
weapon->wim[ weaponMode ].flashDlightColor[ 1 ] ||
@@ -1254,6 +1387,15 @@ void CG_AddViewWeapon( playerState_t *ps )
}
+ // Lightning Gun vibration effect
+ if( ( weapon == WP_LIGHTNING_GUN ) && ps->eFlags & EF_FIRING )
+ {
+ VectorMA( hand.origin, random( ) * 0.1, cg.refdef.viewaxis[ 0 ],
+ hand.origin );
+ VectorMA( hand.origin, random( ) * 0.1, cg.refdef.viewaxis[ 1 ],
+ hand.origin );
+ }
+
AnglesToAxis( angles, hand.axis );
// map torso animations to weapon animations
@@ -1654,6 +1796,7 @@ void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode )
int c;
weaponInfo_t *wi;
weapon_t weaponNum;
+ qboolean skipSound = qfalse;
es = &cent->currentState;
@@ -1673,6 +1816,10 @@ void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode )
wi = &cg_weapons[ weaponNum ];
+ if( wi->wim[ weaponMode ].continuousFlash &&
+ cent->muzzleFlashTime >= cg.time - 100 )
+ skipSound = qtrue;
+
// mark the entity as muzzle flashing, so when it is added it will
// append the flash to the weapon model
cent->muzzleFlashTime = cg.time;
@@ -1684,6 +1831,9 @@ void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode )
cent->muzzlePsTrigger = qtrue;
}
+ if( skipSound )
+ return;
+
// play a sound
for( c = 0; c < 4; c++ )
{
@@ -1697,6 +1847,14 @@ void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode )
if( wi->wim[ weaponMode ].flashSound[ c ] )
trap_S_StartSound( NULL, es->number, CHAN_WEAPON, wi->wim[ weaponMode ].flashSound[ c ] );
}
+
+ if( cent == &cg.predictedPlayerEntity )
+ {
+ float quake;
+
+ quake = wi->wim[ weaponMode ].flashQuake;
+ CG_InduceViewQuake( NULL, quake );
+ }
}
@@ -1713,7 +1871,7 @@ void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientN
qhandle_t mark = 0;
qhandle_t ps = 0;
int c;
- float radius = 1.0f;
+ float radius = 1.0f, quake;
weaponInfo_t *weapon = &cg_weapons[ weaponNum ];
if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES )
@@ -1722,6 +1880,7 @@ void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientN
mark = weapon->wim[ weaponMode ].impactMark;
radius = weapon->wim[ weaponMode ].impactMarkSize;
ps = weapon->wim[ weaponMode ].impactParticleSystem;
+ quake = weapon->wim[ weaponMode ].impactQuake;
if( soundType == IMPACTSOUND_FLESH )
{
@@ -1775,6 +1934,11 @@ void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientN
//
if( radius > 0.0f )
CG_ImpactMark( mark, origin, dir, random( ) * 360, 1, 1, 1, 1, qfalse, radius, qfalse );
+
+ if( weaponNum == WP_LUCIFER_CANNON )
+ quake *= charge;
+
+ CG_InduceViewQuake( origin, quake );
}
@@ -1788,6 +1952,7 @@ void CG_MissileHitEntity( weapon_t weaponNum, weaponMode_t weaponMode,
{
vec3_t normal;
weaponInfo_t *weapon = &cg_weapons[ weaponNum ];
+ float quake = weapon->wim[ weaponMode ].impactQuake;
VectorCopy( dir, normal );
VectorInverse( normal );
@@ -1817,6 +1982,11 @@ void CG_MissileHitEntity( weapon_t weaponNum, weaponMode_t weaponMode,
CG_MissileHitWall( weaponNum, weaponMode, 0, origin, dir, sound, charge );
}
+
+ if( weaponNum == WP_LUCIFER_CANNON )
+ quake *= charge;
+
+ CG_InduceViewQuake( origin, quake );
}