summaryrefslogtreecommitdiff
path: root/src
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
parentf4413207a03658c719987d02fdbb87443843f43b (diff)
Implement the Lightning Gun.
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_local.h2
-rw-r--r--src/cgame/cg_main.c3
-rw-r--r--src/cgame/cg_weapons.c101
-rw-r--r--src/game/bg_misc.c25
-rw-r--r--src/game/bg_mod.h1
-rw-r--r--src/game/bg_public.h1
-rw-r--r--src/game/g_weapon.c49
-rw-r--r--src/game/tremulous.h8
8 files changed, 186 insertions, 4 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 ] ||
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 742363d..efdc300 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -3575,6 +3575,31 @@ static const weaponAttributes_t bg_weapons[ ] =
TEAM_HUMANS //team_t team;
},
{
+ WP_LIGHTNING_GUN, //int weaponNum;
+ LIGHTNING_PRICE, //int price;
+ STAGE_GE_5, //int stages
+ SLOT_WEAPON, //int slots;
+ "lightning", //char *weaponName;
+ "[yefarms]Lightning Gun", //char *humanName;
+ "This is a lightning gun. It guns lightning.",
+ LIGHTNING_AMMO, //int maxAmmo;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ LIGHTNING_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ LIGHTNING_K_SCALE, //float knockbackScale;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ qtrue, //qboolean longRanged;
+ TEAM_HUMANS //team_t team;
+ },
+ {
WP_LUCIFER_CANNON, //int weaponNum;
LCANNON_PRICE, //int price;
STAGE_GE_5, //int stages
diff --git a/src/game/bg_mod.h b/src/game/bg_mod.h
index 4929b32..6f09037 100644
--- a/src/game/bg_mod.h
+++ b/src/game/bg_mod.h
@@ -8,6 +8,7 @@ MOD( MOD_CHAINGUN ),
MOD( MOD_PRIFLE ),
MOD( MOD_MDRIVER ),
MOD( MOD_LASGUN ),
+MOD( MOD_LIGHTNING ),
MOD( MOD_LCANNON ),
MOD( MOD_LCANNON_SPLASH ),
MOD( MOD_FLAMER ),
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index c0b6381..18b0d2e 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -356,6 +356,7 @@ typedef enum
WP_CHAINGUN,
WP_FLAMER,
WP_PULSE_RIFLE,
+ WP_LIGHTNING_GUN,
WP_LUCIFER_CANNON,
WP_ROCKET_LAUNCHER,
WP_GRENADE,
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index d869fb1..1c333ab 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -819,9 +819,7 @@ void LCChargeFire( gentity_t *ent, qboolean secondary )
/*
======================================================================
-
-PULSE RIFLE
-
+ROCKET LAUNCHER
======================================================================
*/
@@ -830,6 +828,48 @@ void rocketLauncherFire( gentity_t *ent )
fire_rocket( ent, muzzle, forward );
}
+
+/*
+======================================================================
+LIGHTNING GUN
+======================================================================
+*/
+
+void lightningGunFire( gentity_t *ent )
+{
+ vec3_t start, end;
+ trace_t tr;
+ gentity_t *target;
+
+ VectorMA( muzzle, LIGHTNING_RANGE, forward, end );
+
+ G_UnlaggedOn( ent, muzzle, LIGHTNING_RANGE );
+ trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
+ G_UnlaggedOff( );
+
+ if( tr.fraction == 1.0f ||
+ tr.entityNum == ENTITYNUM_NONE ||
+ ( tr.surfaceFlags & SURF_NOIMPACT ) )
+ return;
+
+ target = g_entities + tr.entityNum;
+
+ if( target->s.eType == ET_PLAYER || target->s.eType == ET_BUILDABLE )
+ BloodSpurt( ent, target, &tr );
+ else
+ {
+ gentity_t *tent;
+
+ tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS );
+ tent->s.eventParm = DirToByte( tr.plane.normal );
+ tent->s.weapon = ent->s.weapon;
+ tent->s.generic1 = ent->s.generic1;
+ }
+
+ G_Damage( target, ent, ent, forward, tr.endpos, LIGHTNING_DAMAGE, 0, MOD_LIGHTNING );
+}
+
+
/*
======================================================================
TESLA GENERATOR
@@ -1976,6 +2016,9 @@ void FireWeapon( gentity_t *ent )
case WP_ROCKET_LAUNCHER:
rocketLauncherFire( ent );
break;
+ case WP_LIGHTNING_GUN:
+ lightningGunFire( ent );
+ break;
case WP_GRENADE:
throwGrenade( ent );
break;
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index e7512d5..b42a7b4 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -514,6 +514,14 @@ TREMULOUS EDGE MOD SRC FILE
#define PRIFLE_SECONDARY_SPEED 800
#define PRIFLE_SECONDARY_REPEAT 400
+#define LIGHTNING_PRICE 500
+#define LIGHTNING_AMMO 500
+#define LIGHTNING_K_SCALE 500
+#define LIGHTNING_DPS 100 // damage per second
+#define LIGHTNING_REPEAT 50 // keep it as low as possible
+#define LIGHTNING_DAMAGE ( LIGHTNING_DPS * LIGHTNING_REPEAT / 1000 )
+#define LIGHTNING_RANGE 450
+
#define LCANNON_PRICE 600
#define LCANNON_AMMO 80
#define LCANNON_K_SCALE 1.0f