summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
authorenneract <trem.redman@gmail.com>2014-11-24 02:20:51 +0100
committerenneract <trem.redman@gmail.com>2014-11-24 02:20:51 +0100
commitb0a9981e09bbc7c30769f680a4e0ff17c9ea8239 (patch)
treed369ba2f0cebcf878ee32b420ec19a0786e9b4e8 /src/cgame
parentf4413207a03658c719987d02fdbb87443843f43b (diff)
Implement the Lightning Gun.
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_local.h2
-rw-r--r--src/cgame/cg_main.c3
-rw-r--r--src/cgame/cg_weapons.c101
3 files changed, 105 insertions, 1 deletions
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index a477336..72b5a96 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1336,6 +1336,8 @@ typedef struct
qhandle_t headShotPS;
qhandle_t humanWoundsBleedPS;
qhandle_t alienWoundsBleedPS;
+
+ qhandle_t lightningBeam;
} cgMedia_t;
typedef struct
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index b7885ec..9abdc7e 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -821,7 +821,8 @@ static void CG_RegisterGraphics( void )
cgs.media.healthCrossPoisoned = trap_R_RegisterShader( "ui/assets/neutral/cross_poison.tga" );
cgs.media.upgradeClassIconShader = trap_R_RegisterShader( "icons/icona_upgrade.tga" );
-
+
+ cgs.media.lightningBeam = trap_R_RegisterShader( "gfx/lightning/beam" );
cgs.media.disconnectPS = CG_RegisterParticleSystem( "disconnectPS" );
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index 04f6495..86306e1 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -866,6 +866,60 @@ static float CG_MachinegunSpinAngle( centity_t *cent, qboolean firing )
return angle;
}
+/*
+=============
+CG_RenderBeam
+=============
+*/
+
+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 );
+}
+
/*
=============
@@ -876,6 +930,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;
@@ -1114,6 +1169,52 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
cent->muzzlePsTrigger = qfalse;
}
+ 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 );
+ }
+
// make a dlight for the flash
if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] ||
weapon->wim[ weaponMode ].flashDlightColor[ 1 ] ||