summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_ents.c19
-rw-r--r--src/cgame/cg_event.c16
-rw-r--r--src/cgame/cg_local.h4
-rw-r--r--src/cgame/cg_weapons.c59
-rw-r--r--src/game/bg_misc.c65
-rw-r--r--src/game/bg_pmove.c31
-rw-r--r--src/game/bg_public.h25
-rw-r--r--src/game/g_active.c17
-rw-r--r--src/game/g_local.h1
-rw-r--r--src/game/g_missile.c44
-rw-r--r--src/game/g_weapon.c41
11 files changed, 300 insertions, 22 deletions
diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c
index d6e8595b..615727cc 100644
--- a/src/cgame/cg_ents.c
+++ b/src/cgame/cg_ents.c
@@ -288,6 +288,25 @@ static void CG_Missile( centity_t *cent )
return;
break;
+ case WP_LUCIFER_CANON:
+ ent.skinNum = cg.clientFrame & 1;
+ ent.hModel = weapon->missileModel;
+ ent.renderfx = weapon->missileRenderfx | RF_NOSHADOW;
+
+ // convert direction of travel into axis
+ if ( VectorNormalize2( s1->pos.trDelta, ent.axis[ 0 ] ) == 0 )
+ ent.axis[ 0 ][ 2 ] = 1;
+
+ RotateAroundDirection( ent.axis, cg.time / 4 );
+
+ fraction = (float)s1->generic1 / (float)LC_TOTAL_CHARGE;
+ VectorScale( ent.axis[ 0 ], fraction, ent.axis[ 0 ] );
+ VectorScale( ent.axis[ 1 ], fraction, ent.axis[ 1 ] );
+ VectorScale( ent.axis[ 2 ], fraction, ent.axis[ 2 ] );
+ ent.nonNormalizedAxes = qtrue;
+
+ break;
+
case WP_FLAMER:
//TA: don't actually display the missile (use the particle engine)
return;
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index f0b747b0..72e8ab21 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -924,19 +924,19 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
case EV_MISSILE_HIT:
DEBUGNAME("EV_MISSILE_HIT");
ByteToDir( es->eventParm, dir );
- CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum );
+ CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum, es->generic1 );
break;
case EV_MISSILE_MISS:
DEBUGNAME("EV_MISSILE_MISS");
ByteToDir( es->eventParm, dir );
- CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT );
+ CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT, es->generic1 );
break;
case EV_MISSILE_MISS_METAL:
DEBUGNAME("EV_MISSILE_MISS_METAL");
ByteToDir( es->eventParm, dir );
- CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL );
+ CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL, es->generic1 );
break;
case EV_ITEM_EXPLOSION:
@@ -963,7 +963,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
CG_TeslaTrail( es->origin2, es->pos.trBase );
if ( es->eventParm != 255 ) {
ByteToDir( es->eventParm, dir );
- CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT );
+ CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT, 0 );
}
break;
@@ -997,11 +997,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
else
spark = cgs.media.gibSpark2;
- velocity[ 0 ] = crandom( ) * MASS_EJECTION_VEL;
- velocity[ 1 ] = crandom( ) * MASS_EJECTION_VEL;
- velocity[ 2 ] = MASS_EJECTION_VEL + crandom( ) * MASS_EJECTION_VEL;
+ velocity[ 0 ] = ( 2 * random( ) - 1.0f ) * MASS_EJECTION_VEL;
+ velocity[ 1 ] = ( 2 * random( ) - 1.0f ) * MASS_EJECTION_VEL;
+ velocity[ 2 ] = ( 2 * random( ) - 1.0f ) * MASS_EJECTION_VEL;
- CG_LaunchSprite( origin, velocity, accel, 0.6, 4.0f, 2.0f, 255, 0, rand( ) % 360,
+ CG_LaunchSprite( origin, velocity, accel, 0.999, 4.0f, 2.0f, 255, 0, rand( ) % 360,
cg.time, 5000 + ( crandom( ) * 3000 ),
spark, qfalse, qfalse );
}
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 06fbc132..ff6e4aa2 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1448,9 +1448,9 @@ void CG_InitWeapons( );
void CG_RegisterWeapon( int weaponNum );
void CG_FireWeapon( centity_t *cent );
-void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType );
+void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType, int damage );
void CG_Explosion( int clientNum, vec3_t origin, vec3_t dir );
-void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum );
+void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum, int damage );
void CG_ShotgunFire( entityState_t *es );
void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum );
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index b67267db..4d66f626 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -727,6 +727,15 @@ void CG_RegisterWeapon( int weaponNum )
cgs.media.railRingsShader = trap_R_RegisterShader( "railDisc" );
break;
+ case WP_LUCIFER_CANON:
+ weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/bfg/bfg_hum.wav", qfalse );
+ MAKERGB( weaponInfo->flashDlightColor, 1, 0.7f, 1 );
+ weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/bfg/bfg_fire.wav", qfalse );
+ cgs.media.bfgExplosionShader = trap_R_RegisterShader( "bfgExplosion" );
+ weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/bfg.md3" );
+ weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
+ break;
+
case WP_VENOM:
MAKERGB( weaponInfo->flashDlightColor, 0, 0, 0 );
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse );
@@ -1359,6 +1368,14 @@ void CG_AddViewWeapon( playerState_t *ps ) {
VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );
+ if( ps->weapon == WP_LUCIFER_CANON && ps->stats[ STAT_MISC ] > 0 )
+ {
+ float fraction = (float)ps->stats[ STAT_MISC ] / (float)LC_TOTAL_CHARGE;
+
+ VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[0], hand.origin );
+ VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[1], hand.origin );
+ }
+
AnglesToAxis( angles, hand.axis );
// map torso animations to weapon animations
@@ -1820,7 +1837,7 @@ CG_MissileHitWall
Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing
=================
*/
-void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType ) {
+void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType, int damage ) {
qhandle_t mod;
qhandle_t mark;
qhandle_t shader;
@@ -1829,7 +1846,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im
float light;
vec3_t lightColor;
localEntity_t *le;
- int r;
+ int r, i;
qboolean alphaFade;
qboolean isSprite;
int duration;
@@ -1890,6 +1907,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im
case WP_MASS_DRIVER:
shader = cgs.media.bulletExplosionShader;
mark = cgs.media.bulletMarkShader;
+ radius = 8;
break;
case WP_MACHINEGUN:
case WP_CHAINGUN:
@@ -1908,6 +1926,39 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im
radius = 8;
break;
+
+ #define LCANON_EJECTION_VEL 300
+
+ case WP_LUCIFER_CANON:
+ mod = cgs.media.dishFlashModel;
+ shader = cgs.media.bfgExplosionShader;
+ mark = cgs.media.bulletMarkShader;
+ radius = 8;
+ sfx = cgs.media.sfx_plasmaexp;
+ isSprite = qtrue;
+
+ for( i = 0; i <= damage / 20; i++ )
+ {
+ qhandle_t spark;
+ vec3_t velocity;
+ vec3_t accel = { 0.0f, 0.0f, -DEFAULT_GRAVITY };
+
+ VectorMA( origin, 1.0f, dir, origin );
+
+ if( random( ) > 0.5f )
+ spark = cgs.media.gibSpark1;
+ else
+ spark = cgs.media.scannerBlipShader;
+
+ velocity[ 0 ] = ( 2 * random( ) - 1.0f ) * LCANON_EJECTION_VEL;
+ velocity[ 1 ] = ( 2 * random( ) - 1.0f ) * LCANON_EJECTION_VEL;
+ velocity[ 2 ] = ( 2 * random( ) - 1.0f ) * LCANON_EJECTION_VEL;
+
+ CG_LaunchSprite( origin, velocity, accel, 0.9, 1.0f, 40.0f, 255, 0, rand( ) % 360,
+ cg.time, 2000 + ( crandom( ) * 1000 ),
+ spark, qfalse, qfalse );
+ }
+ break;
}
if ( sfx ) {
@@ -1956,7 +2007,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im
CG_MissileHitPlayer
=================
*/
-void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum ) {
+void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum, int damage ) {
CG_Bleed( origin, entityNum );
// some weapons will make an explosion with the blood, while
@@ -2262,7 +2313,7 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh,
if ( flesh ) {
CG_Bleed( end, fleshEntityNum );
} else {
- CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT );
+ CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT, 0 );
}
}
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index e6243391..9d4e359d 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -2126,6 +2126,69 @@ weaponAttributes_t bg_weapons[ ] =
WUT_HUMANS //WUTeam_t team;
},
{
+ WP_LUCIFER_CANON, //int weaponNum;
+ 100, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "lcanon", //char *weaponName;
+ "Lucifer Canon", //char *weaponHumanName;
+ { "models/weapons2/bfg/bfg.md3", 0, 0, 0 },
+ "icons/iconw_bfg",
+ 30, //int quan;
+ 0, //int clips;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ 500, //int repeatRate;
+ 2000, //int reloadTime;
+ qtrue, //qboolean hasAltMode;
+ qfalse, //qboolean synced;
+ qtrue, //qboolean purchasable;
+ WUT_HUMANS //WUTeam_t team;
+ },
+ {
+ WP_LAS_GUN, //int weaponNum;
+ 100, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "lgun", //char *weaponName;
+ "Las Gun", //char *weaponHumanName;
+ { "models/weapons2/grenadel/grenadel.md3", 0, 0, 0 },
+ "icons/iconw_plasma",
+ 300, //int quan;
+ 0, //int clips;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qtrue, //int usesEnergy;
+ 100, //int repeatRate;
+ 2000, //int reloadTime;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean synced;
+ qtrue, //qboolean purchasable;
+ WUT_HUMANS //WUTeam_t team;
+ },
+ {
+ WP_PAIN_SAW, //int weaponNum;
+ 100, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "psaw", //char *weaponName;
+ "Pain Saw", //char *weaponHumanName;
+ { "models/weapons2/gauntlet/gauntlet.md3", 0, 0, 0 },
+ "icons/iconw_gauntlet",
+ 0, //int quan;
+ 0, //int clips;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 100, //int repeatRate;
+ 0, //int reloadTime;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean synced;
+ qtrue, //qboolean purchasable;
+ WUT_HUMANS //WUTeam_t team;
+ },
+ {
WP_HBUILD, //int weaponNum;
100, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
@@ -3042,6 +3105,8 @@ weapon_t BG_FindWeaponAmmoForUpgrade( int upgrade )
if( bg_upgrades[ i ].upgradeNum == upgrade )
return bg_upgrades[ i ].weaponAmmo;
}
+
+ return WP_NONE;
}
/*
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 017e9155..18fa084c 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -680,7 +680,7 @@ static void PM_JetPackMove( void ) {
if( pm->cmd.upmove > 0.0f )
wishvel[ 2 ] = 48.0f;
if( pm->cmd.upmove < 0.0f )
- wishvel[ 2 ] = -48.0f;
+ wishvel[ 2 ] = -96.0f;
VectorCopy( wishvel, wishdir );
wishspeed = VectorNormalize( wishdir );
@@ -2301,6 +2301,22 @@ static void PM_Weapon( void )
}
break;
+ case WP_LUCIFER_CANON:
+ attack1 = pm->cmd.buttons & BUTTON_ATTACK;
+ attack2 = pm->cmd.buttons & BUTTON_ATTACK2;
+
+ if( ( attack1 || pm->ps->stats[ STAT_MISC ] == 0 ) && !attack2 )
+ {
+ pm->ps->weaponTime = 0;
+ pm->ps->weaponstate = WEAPON_READY;
+ return;
+ }
+
+ //erp this looks confusing
+ if( pm->ps->stats[ STAT_MISC ] > 0 )
+ attack1 = !attack1;
+ break;
+
default:
//by default primary and secondary attacks are allowed
attack1 = pm->cmd.buttons & BUTTON_ATTACK;
@@ -2360,7 +2376,18 @@ static void PM_Weapon( void )
// take an ammo away if not infinite
if( !BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) )
{
- ammo--;
+ //special case for lCanon
+ if( pm->ps->weapon == WP_LUCIFER_CANON && attack1 )
+ {
+ ammo -= (int)( ceil( ( (float)pm->ps->stats[ STAT_MISC ] / (float)LC_TOTAL_CHARGE ) * 10.0f ) );
+
+ //stay on the safe side
+ if( ammo < 0 )
+ ammo = 0;
+ }
+ else
+ ammo--;
+
BG_packAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips, maxclips );
}
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index add68d21..77ad6f2b 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -46,6 +46,9 @@
#define MAX_POUNCE_SPEED 750
#define POUNCE_TIME 1000.0f
+#define LC_TOTAL_CHARGE 255
+#define LC_CHARGE_TIME 2000.0f
+
//
// config strings are a general means of communicating variable length strings
// from the server to all connected clients.
@@ -341,6 +344,9 @@ typedef enum
WP_DIRECT_ZAP,
WP_MASS_DRIVER,
WP_PULSE_RIFLE,
+ WP_LUCIFER_CANON,
+ WP_LAS_GUN,
+ WP_PAIN_SAW,
//build weapons must remain in a block
WP_ABUILD,
@@ -982,7 +988,20 @@ typedef struct
WUTeam_t team;
} upgradeAttributes_t;
+
//TA:
+void BG_unpackAmmoArray( int weapon, int ammo[ ], int ammo2[ ], int *quan, int *clips, int *maxclips );
+void BG_packAmmoArray( int weapon, int ammo[ ], int ammo2[ ], int quan, int clips, int maxclips );
+void BG_packWeapon( int weapon, int stats[ ] );
+void BG_removeWeapon( int weapon, int stats[ ] );
+qboolean BG_gotWeapon( int weapon, int stats[ ] );
+void BG_packItem( int item, int stats[ ] );
+void BG_removeItem( int item, int stats[ ] );
+qboolean BG_gotItem( int item, int stats[ ] );
+void BG_activateItem( int item, int stats[ ] );
+void BG_deactivateItem( int item, int stats[ ] );
+qboolean BG_activated( int item, int stats[ ] );
+
int BG_FindBuildNumForName( char *name );
int BG_FindBuildNumForEntityName( char *name );
char *BG_FindNameForBuildable( int bclass );
@@ -1123,12 +1142,6 @@ void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *
qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime );
-//TA: extra bits: (which I apparently dont need)
-void BG_unpackAmmoArray( int weapon, int ammo[ ], int ammo2[ ], int *quan, int *clips, int *maxclips );
-void BG_packAmmoArray( int weapon, int ammo[ ], int ammo2[ ], int quan, int clips, int maxclips );
-void BG_packWeapon( int weapon, int stats[ ] );
-qboolean BG_gotWeapon( int weapon, int stats[ ] );
-
#define CREEP_BASESIZE 120
#define REACTOR_BASESIZE 1000
#define REPEATER_BASESIZE 500
diff --git a/src/game/g_active.c b/src/game/g_active.c
index ff229da7..89c45cf7 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -492,6 +492,23 @@ void ClientTimerActions( gentity_t *ent, int msec )
client->ps.stats[ STAT_MISC ] = MAX_POUNCE_SPEED;
}
+ //client is charging up an lcanon
+ if( client->ps.weapon == WP_LUCIFER_CANON )
+ {
+ int ammo;
+
+ BG_unpackAmmoArray( WP_LUCIFER_CANON, client->ps.ammo, client->ps.powerups, &ammo, NULL, NULL );
+
+ if( client->ps.stats[ STAT_MISC ] < LC_TOTAL_CHARGE && ucmd->buttons & BUTTON_ATTACK )
+ client->ps.stats[ STAT_MISC ] += ( 100.0f / LC_CHARGE_TIME ) * LC_TOTAL_CHARGE;
+
+ if( client->ps.stats[ STAT_MISC ] > LC_TOTAL_CHARGE )
+ client->ps.stats[ STAT_MISC ] = LC_TOTAL_CHARGE;
+
+ if( client->ps.stats[ STAT_MISC ] > ( ammo * LC_TOTAL_CHARGE ) / 10 )
+ client->ps.stats[ STAT_MISC ] = ammo * LC_TOTAL_CHARGE / 10;
+ }
+
#define LAUNCH_TIME 2000
switch( client->ps.weapon )
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 1628f5bd..2125291c 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -625,6 +625,7 @@ gentity_t *fire_blaster( gentity_t *self, vec3_t start, vec3_t aimdir );
gentity_t *fire_flamer( gentity_t *self, vec3_t start, vec3_t aimdir );
gentity_t *fire_plasma( gentity_t *self, vec3_t start, vec3_t aimdir );
gentity_t *fire_pulseRifle( gentity_t *self, vec3_t start, vec3_t dir );
+gentity_t *fire_luciferCanon( gentity_t *self, vec3_t start, vec3_t dir, int damage );
gentity_t *fire_grenade( gentity_t *self, vec3_t start, vec3_t aimdir );
gentity_t *fire_rocket( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_lockblob( gentity_t *self, vec3_t start, vec3_t dir );
diff --git a/src/game/g_missile.c b/src/game/g_missile.c
index 942697eb..bbbf07cd 100644
--- a/src/game/g_missile.c
+++ b/src/game/g_missile.c
@@ -362,6 +362,50 @@ gentity_t *fire_pulseRifle( gentity_t *self, vec3_t start, vec3_t dir )
/*
=================
+fire_luciferCanon
+
+=================
+*/
+gentity_t *fire_luciferCanon( gentity_t *self, vec3_t start, vec3_t dir, int damage )
+{
+ gentity_t *bolt;
+ int localDamage = (int)( ceil( ( (float)damage /
+ (float)LC_TOTAL_CHARGE ) * 100.0f ) );
+
+ VectorNormalize( dir );
+
+ bolt = G_Spawn( );
+ bolt->classname = "lcanon";
+ bolt->nextthink = level.time + 10000;
+ bolt->think = G_ExplodeMissile;
+ bolt->s.eType = ET_MISSILE;
+ bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
+ bolt->s.weapon = WP_LUCIFER_CANON;
+ bolt->r.ownerNum = self->s.number;
+ bolt->parent = self;
+ bolt->damage = localDamage;
+ bolt->splashDamage = localDamage / 2;
+ bolt->splashRadius = localDamage;
+ bolt->s.generic1 = damage;
+ //bolt->methodOfDeath = MOD_FLAMER;
+ //bolt->splashMethodOfDeath = MOD_FLAMER_SPLASH;
+ bolt->clipmask = MASK_SHOT;
+ bolt->target_ent = NULL;
+
+ bolt->s.pos.trType = TR_LINEAR;
+ bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
+ VectorCopy( start, bolt->s.pos.trBase );
+ VectorScale( dir, 250, bolt->s.pos.trDelta );
+ SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
+
+ VectorCopy (start, bolt->r.currentOrigin);
+
+ return bolt;
+}
+
+//=============================================================================
+/*
+=================
fire_lockblob
=================
*/
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index cf1a0beb..4965fdb0 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -230,6 +230,31 @@ void flamerFire( gentity_t *ent )
/*
======================================================================
+LUCIFER CANON
+
+======================================================================
+*/
+
+/*
+===============
+LCChargeFire
+===============
+*/
+void LCChargeFire( gentity_t *ent, qboolean secondary )
+{
+ gentity_t *m;
+
+ if( secondary )
+ ent->client->ps.stats[ STAT_MISC ] = LC_TOTAL_CHARGE / 10;
+
+ m = fire_luciferCanon( ent, muzzle, forward, ent->client->ps.stats[ STAT_MISC ] );
+
+ ent->client->ps.stats[ STAT_MISC ] = 0;
+}
+
+/*
+======================================================================
+
TESLA GENERATOR
======================================================================
@@ -775,6 +800,13 @@ void FireWeapon2( gentity_t *ent )
case WP_VENOM:
case WP_POUNCE:
break;
+ case WP_LUCIFER_CANON:
+ LCChargeFire( ent, qtrue );
+ break;
+ case WP_LAS_GUN:
+ break;
+ case WP_PAIN_SAW:
+ break;
case WP_ABUILD:
case WP_ABUILD2:
case WP_HBUILD:
@@ -847,6 +879,15 @@ void FireWeapon( gentity_t *ent )
case WP_DIRECT_ZAP:
directZapFire( ent );
break;
+ case WP_LUCIFER_CANON:
+ LCChargeFire( ent, qfalse );
+ break;
+ case WP_LAS_GUN:
+ massDriverFire( ent );
+ break;
+ case WP_PAIN_SAW:
+ gClawFire( ent );
+ break;
case WP_ABUILD:
buildFire( ent, MN_A_BUILD );
break;