summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_buildable.c16
-rw-r--r--src/cgame/cg_ents.c78
-rw-r--r--src/cgame/cg_event.c19
-rw-r--r--src/cgame/cg_local.h84
-rw-r--r--src/cgame/cg_main.c6
-rw-r--r--src/cgame/cg_particles.c11
-rw-r--r--src/cgame/cg_view.c28
-rw-r--r--src/cgame/cg_weapons.c738
8 files changed, 409 insertions, 571 deletions
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c
index f185b026..d0c286f4 100644
--- a/src/cgame/cg_buildable.c
+++ b/src/cgame/cg_buildable.c
@@ -935,21 +935,25 @@ void CG_Buildable( centity_t *cent )
//weapon effects for turrets
if( es->eFlags & EF_FIRING )
{
- weaponInfo_t *weapon = &cg_weapons[ es->weapon ];
+ weaponInfo_t *weapon = &cg_weapons[ es->weapon ];
if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ||
BG_FindProjTypeForBuildable( es->modelindex ) == WP_TESLAGEN )
{
- if( weapon->flashDlightColor[ 0 ] || weapon->flashDlightColor[ 1 ] || weapon->flashDlightColor[ 2 ] )
+ if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] ||
+ weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] ||
+ weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] )
{
- trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ), weapon->flashDlightColor[ 0 ],
- weapon->flashDlightColor[ 1 ], weapon->flashDlightColor[ 2 ] );
+ trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ),
+ weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ],
+ weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ],
+ weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] );
}
}
- if( weapon->firingSound )
+ if( weapon->wim[ WPM_PRIMARY ].firingSound )
{
- trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->firingSound );
+ trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->wim[ WPM_PRIMARY ].firingSound );
}
else if( weapon->readySound )
trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound );
diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c
index 43897f4e..c35b9281 100644
--- a/src/cgame/cg_ents.c
+++ b/src/cgame/cg_ents.c
@@ -318,18 +318,23 @@ CG_LaunchMissile
static void CG_LaunchMissile( centity_t *cent )
{
entityState_t *es;
- const weaponInfo_t *weapon;
+ const weaponInfo_t *wi;
particleSystem_t *ps;
+ weapon_t weapon;
+ weaponMode_t weaponMode;
es = &cent->currentState;
- if( es->weapon > WP_NUM_WEAPONS )
- es->weapon = 0;
+
+ weapon = es->weapon;
+ if( weapon > WP_NUM_WEAPONS )
+ weapon = WP_NONE;
- weapon = &cg_weapons[ es->weapon ];
+ wi = &cg_weapons[ weapon ];
+ weaponMode = es->generic1;
- if( weapon->missileParticleSystem )
+ if( wi->wim[ weaponMode ].missileParticleSystem )
{
- ps = CG_SpawnNewParticleSystem( weapon->missileParticleSystem );
+ ps = CG_SpawnNewParticleSystem( wi->wim[ weaponMode ].missileParticleSystem );
CG_SetParticleSystemCent( ps, cent );
CG_AttachParticleSystemToCent( ps );
}
@@ -343,41 +348,43 @@ CG_Missile
static void CG_Missile( centity_t *cent )
{
refEntity_t ent;
- entityState_t *s1;
- const weaponInfo_t *weapon;
+ entityState_t *es;
+ const weaponInfo_t *wi;
vec3_t up;
float fraction;
int index;
- qboolean switchBugWorkaround = qfalse;
+ weapon_t weapon;
+ weaponMode_t weaponMode;
- s1 = &cent->currentState;
- if( s1->weapon > WP_NUM_WEAPONS )
- s1->weapon = 0;
-
- weapon = &cg_weapons[ s1->weapon ];
+ es = &cent->currentState;
+ weapon = es->weapon;
+ if( weapon > WP_NUM_WEAPONS )
+ weapon = WP_NONE;
+
+ wi = &cg_weapons[ weapon ];
+ weaponMode = es->generic1;
+
// calculate the axis
- VectorCopy( s1->angles, cent->lerpAngles );
-
- // add trails
- if( weapon->missileTrailFunc )
- weapon->missileTrailFunc( cent, weapon );
+ VectorCopy( es->angles, cent->lerpAngles );
// add dynamic light
- if( weapon->missileDlight )
+ if( wi->wim[ weaponMode ].missileDlight )
{
- trap_R_AddLightToScene( cent->lerpOrigin, weapon->missileDlight,
- weapon->missileDlightColor[ 0 ], weapon->missileDlightColor[ 1 ], weapon->missileDlightColor[ 2 ] );
+ trap_R_AddLightToScene( cent->lerpOrigin, wi->wim[ weaponMode ].missileDlight,
+ wi->wim[ weaponMode ].missileDlightColor[ 0 ],
+ wi->wim[ weaponMode ].missileDlightColor[ 1 ],
+ wi->wim[ weaponMode ].missileDlightColor[ 2 ] );
}
// add missile sound
- if( weapon->missileSound )
+ if( wi->wim[ weaponMode ].missileSound )
{
vec3_t velocity;
BG_EvaluateTrajectoryDelta( &cent->currentState.pos, cg.time, velocity );
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, velocity, weapon->missileSound );
+ trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, velocity, wi->wim[ weaponMode ].missileSound );
}
// create the render entity
@@ -385,34 +392,34 @@ static void CG_Missile( centity_t *cent )
VectorCopy( cent->lerpOrigin, ent.origin );
VectorCopy( cent->lerpOrigin, ent.oldorigin );
- if( weapon->usesSpriteMissle )
+ if( wi->wim[ weaponMode ].usesSpriteMissle )
{
ent.reType = RT_SPRITE;
- ent.radius = weapon->missileSpriteSize;
+ ent.radius = wi->wim[ weaponMode ].missileSpriteSize;
ent.rotation = 0;
- ent.customShader = weapon->missileSprite;
+ ent.customShader = wi->wim[ weaponMode ].missileSprite;
}
else
{
- ent.hModel = weapon->missileModel;
- ent.renderfx = weapon->missileRenderfx | RF_NOSHADOW;
+ ent.hModel = wi->wim[ weaponMode ].missileModel;
+ ent.renderfx = wi->wim[ weaponMode ].missileRenderfx | RF_NOSHADOW;
// convert direction of travel into axis
- if( VectorNormalize2( s1->pos.trDelta, ent.axis[ 0 ] ) == 0 )
+ if( VectorNormalize2( es->pos.trDelta, ent.axis[ 0 ] ) == 0 )
ent.axis[ 0 ][ 2 ] = 1;
- if( weapon->missileRotates )
+ if( wi->wim[ weaponMode ].missileRotates )
{
// spin as it moves
- if( s1->pos.trType != TR_STATIONARY )
+ if( es->pos.trType != TR_STATIONARY )
RotateAroundDirection( ent.axis, cg.time / 4 );
else
- RotateAroundDirection( ent.axis, s1->time );
+ RotateAroundDirection( ent.axis, es->time );
}
}
//only refresh if there is something to display
- if( weapon->missileSprite || weapon->missileModel )
+ if( wi->wim[ weaponMode ].missileSprite || wi->wim[ weaponMode ].missileModel )
trap_R_AddRefEntityToScene( &ent );
}
@@ -855,8 +862,6 @@ CG_CEntityPVSEnter
*/
static void CG_CEntityPVSEnter( centity_t *cent )
{
- int i;
-
if( cg_debugPVS.integer )
CG_Printf( "Entity %d entered PVS\n", cent->currentState.number );
@@ -1014,6 +1019,7 @@ void CG_AddPacketEntities( void )
// generate and add the entity from the playerstate
ps = &cg.predictedPlayerState;
BG_PlayerStateToEntityState( ps, &cg.predictedPlayerEntity.currentState, qfalse );
+ cg.predictedPlayerEntity.valid = qtrue;
CG_AddCEntity( &cg.predictedPlayerEntity );
// lerp the non-predicted value for lightning gun origins
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index 9aa0028b..5a0c29a1 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -587,17 +587,17 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
case EV_FIRE_WEAPON:
DEBUGNAME( "EV_FIRE_WEAPON" );
- CG_FireWeapon( cent, 0 );
+ CG_FireWeapon( cent, WPM_PRIMARY );
break;
case EV_FIRE_WEAPON2:
DEBUGNAME( "EV_FIRE_WEAPON2" );
- CG_FireWeapon( cent, 1 ); //FIXME:??
+ CG_FireWeapon( cent, WPM_SECONDARY );
break;
case EV_FIRE_WEAPON3:
DEBUGNAME( "EV_FIRE_WEAPON3" );
- CG_FireWeapon( cent, 2 ); //FIXME:??
+ CG_FireWeapon( cent, WPM_TERTIARY );
break;
//=================================================================
@@ -646,19 +646,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, es->generic1 );
+ CG_MissileHitPlayer( es->weapon, es->generic1, position, dir, es->otherEntityNum );
break;
case EV_MISSILE_MISS:
DEBUGNAME( "EV_MISSILE_MISS" );
ByteToDir( es->eventParm, dir );
- CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT, es->generic1 );
+ CG_MissileHitWall( es->weapon, es->generic1, 0, position, dir, IMPACTSOUND_DEFAULT );
break;
case EV_MISSILE_MISS_METAL:
DEBUGNAME( "EV_MISSILE_MISS_METAL" );
ByteToDir( es->eventParm, dir );
- CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL, es->generic1 );
+ CG_MissileHitWall( es->weapon, es->generic1, 0, position, dir, IMPACTSOUND_METAL );
break;
case EV_BUILDABLE_EXPLOSION:
@@ -804,7 +804,12 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
case EV_POISONCLOUD:
DEBUGNAME( "EV_POISONCLOUD" );
- cg.firstPoisonedTime = cg.time;
+ cg.poisonedTime = cg.time;
+ {
+ particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.poisonCloudPS );
+ CG_SetParticleSystemCent( ps, &cg.predictedPlayerEntity );
+ CG_AttachParticleSystemToCent( ps );
+ }
break;
case EV_PLAYER_RESPAWN:
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 0e94e52c..08df7337 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -374,11 +374,6 @@ typedef struct
lerpFrame_t legs, torso, flag, nonseg;
int painTime;
int painDirection; // flip from 0 to 1
- int lightningFiring;
-
- // railgun trail spawning
- vec3_t railgunImpact;
- qboolean railgunFlash;
// machinegun spinning
float barrelAngle;
@@ -429,9 +424,6 @@ typedef struct centity_s
lerpFrame_t lerpFrame;
//TA:
- int flamerTime; //limit flameball count
- int poisonTime; //limit poison count
- int firstPoisonTime; //when poison cloud starts
int jetTime; //limit jet count
buildableAnimNumber_t buildableAnim; //persistant anim number
@@ -642,35 +634,15 @@ typedef struct
} clientInfo_t;
-// each WP_* weapon enum has an associated weaponInfo_t
-// that contains media references necessary to present the
-// weapon and its effects
-typedef struct weaponInfo_s
+typedef struct weaponInfoMode_s
{
- qboolean registered;
- char *humanName;
-
- qhandle_t handsModel; // the hands don't actually draw, they just position the weapon
- qhandle_t weaponModel;
- qhandle_t barrelModel;
- qhandle_t flashModel;
-
- vec3_t weaponMidpoint; // so it will rotate centered instead of by tag
-
float flashDlight;
vec3_t flashDlightColor;
sfxHandle_t flashSound[ 4 ]; // fast firing weapons randomly choose
qboolean continuousFlash;
- qhandle_t weaponIcon;
- qhandle_t ammoIcon;
-
- qhandle_t crossHair;
- int crossHairSize;
-
qhandle_t missileModel;
sfxHandle_t missileSound;
- void (*missileTrailFunc)( centity_t *, const struct weaponInfo_s *wi );
float missileDlight;
vec3_t missileDlightColor;
int missileRenderfx;
@@ -680,26 +652,48 @@ typedef struct weaponInfo_s
qhandle_t missileParticleSystem;
qboolean missileRotates;
- void (*ejectBrassFunc)( centity_t * );
-
- float trailRadius;
- float wiTrailTime;
-
- sfxHandle_t readySound;
sfxHandle_t firingSound;
qboolean loopFireSound;
qhandle_t muzzleParticleSystem;
qboolean alwaysImpact;
- qhandle_t impactDish;
- qhandle_t impactDishShader;
+ qhandle_t impactModel;
+ qhandle_t impactModelShader;
qhandle_t impactParticleSystem;
qhandle_t impactMark;
qhandle_t impactMarkSize;
sfxHandle_t impactSound[ 4 ]; //random impact sound
float impactDlight;
vec3_t impactDlightColor;
+} weaponInfoMode_t;
+
+// each WP_* weapon enum has an associated weaponInfo_t
+// that contains media references necessary to present the
+// weapon and its effects
+typedef struct weaponInfo_s
+{
+ qboolean registered;
+ char *humanName;
+
+ qhandle_t handsModel; // the hands don't actually draw, they just position the weapon
+ qhandle_t weaponModel;
+ qhandle_t barrelModel;
+ qhandle_t flashModel;
+
+ vec3_t weaponMidpoint; // so it will rotate centered instead of by tag
+
+ qhandle_t weaponIcon;
+ qhandle_t ammoIcon;
+
+ qhandle_t crossHair;
+ int crossHairSize;
+
+ void (*ejectBrassFunc)( centity_t * );
+
+ sfxHandle_t readySound;
+
+ weaponInfoMode_t wim[ WPM_NUM_WEAPONMODES ];
} weaponInfo_t;
typedef struct upgradeInfo_s
@@ -972,6 +966,8 @@ typedef struct
qboolean weapon2Firing;
qboolean weapon3Firing;
+ int poisonedTime;
+
vec3_t lastNormal; //TA: view smoothage
vec3_t lastVangles; //TA: view smoothage
smooth_t sList[ MAXSMOOTHS ]; //TA: WW smoothing
@@ -980,9 +976,6 @@ typedef struct
int rightMoveTime;
int upMoveTime;
- int poisonedTime; //TA: poison cloud
- int firstPoisonedTime; //TA: poison cloud
-
float charModelFraction; //TA: loading percentages
float mediaFraction;
float buildablesFraction;
@@ -1067,9 +1060,7 @@ typedef struct
qhandle_t greenBloodMarkShader;
qhandle_t greenBloodExplosionShader;
qhandle_t explosionTrailShader;
- qhandle_t poisonCloudShader;
- qhandle_t flameShader[ 32 ];
qhandle_t flameExplShader;
qhandle_t creepShader;
@@ -1188,7 +1179,7 @@ typedef struct
sfxHandle_t buildableRepairSound;
sfxHandle_t buildableRepairedSound;
- qhandle_t testParticleSystem;
+ qhandle_t poisonCloudPS;
} cgMedia_t;
@@ -1579,10 +1570,11 @@ void CG_RegisterUpgrade( int upgradeNum );
void CG_InitWeapons( );
void CG_RegisterWeapon( int weaponNum );
-void CG_FireWeapon( centity_t *cent, int mode );
-void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType, int damage );
+void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode );
+void CG_MissileHitWall( weapon_t weapon, weaponMode_t weaponMode, int clientNum,
+ vec3_t origin, vec3_t dir, impactSound_t soundType );
void CG_Explosion( int clientNum, vec3_t origin, vec3_t dir );
-void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum, int damage );
+void CG_MissileHitPlayer( weapon_t weapon, weaponMode_t weaponMode, vec3_t origin, vec3_t dir, int entityNum );
void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum );
void CG_TeslaTrail( vec3_t start, vec3_t end, int srcENum, int destENum );
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index e42f1f50..cee6422d 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -715,10 +715,6 @@ static void CG_RegisterGraphics( void )
cgs.media.greenBloodExplosionShader = trap_R_RegisterShader( "greenBloodExplosion" );
cgs.media.greenBloodMarkShader = trap_R_RegisterShader( "greenBloodMark" );
cgs.media.explosionTrailShader = trap_R_RegisterShader( "explosionTrail" );
- cgs.media.poisonCloudShader = trap_R_RegisterShader( "poisonCloud" );
-
- for( i = 0; i < 32; i++ )
- cgs.media.flameShader[ i ] = trap_R_RegisterShader( va( "fireball%d", i + 1 ) );
cgs.media.scannerBlipShader = trap_R_RegisterShader( "gfx/2d/blip" );
cgs.media.scannerLineShader = trap_R_RegisterShader( "white" );
@@ -792,7 +788,7 @@ static void CG_RegisterGraphics( void )
cgs.media.wakeMarkShader = trap_R_RegisterShader( "wake" );
cgs.media.bloodMarkShader = trap_R_RegisterShader( "bloodMark" );
- cgs.media.testParticleSystem = CG_RegisterParticleSystem( "blah" );
+ cgs.media.poisonCloudPS = CG_RegisterParticleSystem( "poisonCloud" );
// register the inline models
cgs.numInlineModels = trap_CM_NumInlineModels( );
diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c
index 75f3c4ab..57395c49 100644
--- a/src/cgame/cg_particles.c
+++ b/src/cgame/cg_particles.c
@@ -1465,8 +1465,9 @@ static void CG_GarbageCollectParticleSystems( void )
if( !count )
ps->valid = qfalse;
- //check systems where the parent cent has left te PVS
- if( ps->attachType == PSA_CENT_ORIGIN )
+ //check systems where the parent cent has left the PVS
+ //( centNum 0 - player entity, is always valid )
+ if( ps->attachType == PSA_CENT_ORIGIN && ps->attachment.centNum != 0 )
{
if( !cg_entities[ ps->attachment.centNum ].valid )
ps->valid = qfalse;
@@ -1696,7 +1697,11 @@ static void CG_RenderParticle( particle_t *p )
if( bp->framerate == 0.0f )
{
//sync animation time to lifeTime of particle
- index = (int)( timeFrac * bp->numFrames );
+ index = (int)( timeFrac * ( bp->numFrames + 1 ) );
+
+ if( index >= bp->numFrames )
+ index = bp->numFrames - 1;
+
re.customShader = bp->shaders[ index ];
}
else
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index 81ce0e58..9baf32d1 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -360,7 +360,6 @@ static void CG_StepOffset( void )
#define PCLOUD_ROLL_FREQUENCY 0.4f
#define PCLOUD_ZOOM_AMPLITUDE 15
#define PCLOUD_ZOOM_FREQUENCY 0.7f
-#define PCLOUD_SPRITE_GAP 25
/*
@@ -578,33 +577,12 @@ static void CG_OffsetFirstPersonView( void )
float fraction = sin( ( (float)cg.time / 1000.0f ) * M_PI * 2 * PCLOUD_ROLL_FREQUENCY );
float pitchFraction = sin( ( (float)cg.time / 1000.0f ) * M_PI * 5 * PCLOUD_ROLL_FREQUENCY );
- fraction *= 1.0f - ( ( cg.time - cg.firstPoisonedTime ) / (float)HYDRA_PCLOUD_TIME );
- pitchFraction *= 1.0f - ( ( cg.time - cg.firstPoisonedTime ) / (float)HYDRA_PCLOUD_TIME );
+ fraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)HYDRA_PCLOUD_TIME );
+ pitchFraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)HYDRA_PCLOUD_TIME );
angles[ ROLL ] += fraction * PCLOUD_ROLL_AMPLITUDE;
angles[ YAW ] += fraction * PCLOUD_ROLL_AMPLITUDE;
angles[ PITCH ] += pitchFraction * PCLOUD_ROLL_AMPLITUDE / 2.0f;
-
- if( cg.time > cg.poisonedTime )
- {
- vec3_t accel = { 0.0f, 0.0f, 300.0f };
- vec3_t forward, right, up;
- vec3_t spriteOrigin;
-
- AngleVectors( angles, forward, right, NULL );
- forward[ 2 ] = 0.0f;
- VectorCopy( cg.predictedPlayerState.velocity, up );
- up[ 2 ] += 32.0f;
- VectorMA( origin, 32.0f, forward, spriteOrigin );
- VectorMA( spriteOrigin, ( rand( ) % 128 ) - 64, right, spriteOrigin );
-
- CG_LaunchSprite( spriteOrigin, up, accel, 0.0f,
- 0.5f, 10.0f, 40.0f, 127.0f, 0.0f,
- rand( ) % 360, cg.time, rand( ) % 10000, 500,
- cgs.media.poisonCloudShader, qfalse, qfalse );
-
- cg.poisonedTime = cg.time + PCLOUD_SPRITE_GAP;
- }
}
//TA: this *feels* more realisitic for humans
@@ -811,7 +789,7 @@ static int CG_CalcFov( void )
{
phase = cg.time / 1000.0 * PCLOUD_ZOOM_FREQUENCY * M_PI * 2;
v = PCLOUD_ZOOM_AMPLITUDE * sin( phase );
- v *= 1.0f - ( ( cg.time - cg.firstPoisonedTime ) / (float)HYDRA_PCLOUD_TIME );
+ v *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)HYDRA_PCLOUD_TIME );
fov_x += v;
fov_y += v;
}
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index 5398ac34..5a6fc802 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -199,44 +199,24 @@ void CG_InitUpgrades( void )
CG_RegisterUpgrade( i );
}
+
/*
-======================
-CG_ParseWeaponFile
+===============
+CG_ParseWeaponModeSection
-Parses a configuration file describing a weapon
-======================
+Parse a weapon mode section
+===============
*/
-static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
+static qboolean CG_ParseWeaponModeSection( weaponInfoMode_t *wim, char **text_p )
{
- char *text_p;
- int i;
- int len;
- char *token;
- char text[ 20000 ];
- fileHandle_t f;
-
- // load the file
- len = trap_FS_FOpenFile( filename, &f, FS_READ );
- if( len <= 0 )
- return qfalse;
-
- if( len >= sizeof( text ) - 1 )
- {
- CG_Printf( "File %s too long\n", filename );
- return qfalse;
- }
-
- trap_FS_Read( text, len, f );
- text[ len ] = 0;
- trap_FS_FCloseFile( f );
-
- // parse the text
- text_p = text;
+ char *token;
+ float number, randFrac;
+ int i;
// read optional parameters
while( 1 )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -244,49 +224,16 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
if( !Q_stricmp( token, "" ) )
return qfalse;
- if( !Q_stricmp( token, "weaponModel" ) )
- {
- char path[ MAX_QPATH ];
-
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- wi->weaponModel = trap_R_RegisterModel( token );
-
- if( !wi->weaponModel )
- CG_Printf( "Weapon model not found %s: %s\n", filename, token );
-
- strcpy( path, token );
- COM_StripExtension( path, path );
- strcat( path, "_flash.md3" );
- wi->flashModel = trap_R_RegisterModel( path );
-
- strcpy( path, token );
- COM_StripExtension( path, path );
- strcat( path, "_barrel.md3" );
- wi->barrelModel = trap_R_RegisterModel( path );
-
- strcpy( path, token );
- COM_StripExtension( path, path );
- strcat( path, "_hand.md3" );
- wi->handsModel = trap_R_RegisterModel( path );
-
- if( !wi->handsModel )
- wi->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" );
-
- continue;
- }
- else if( !Q_stricmp( token, "missileModel" ) )
+ if( !Q_stricmp( token, "missileModel" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->missileModel = trap_R_RegisterModel( token );
+ wim->missileModel = trap_R_RegisterModel( token );
- if( !wi->missileModel )
- CG_Printf( "Missile model not found %s: %s\n", filename, token );
+ if( !wim->missileModel )
+ CG_Printf( S_COLOR_RED "ERROR: missile model not found %s\n", token );
continue;
}
@@ -294,7 +241,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
int size = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -303,83 +250,83 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
if( size < 0 )
size = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->missileSprite = trap_R_RegisterShader( token );
- wi->missileSpriteSize = size;
- wi->usesSpriteMissle = qtrue;
+ wim->missileSprite = trap_R_RegisterShader( token );
+ wim->missileSpriteSize = size;
+ wim->usesSpriteMissle = qtrue;
- if( !wi->missileSprite )
- CG_Printf( "Missile sprite not found %s: %s\n", filename, token );
+ if( !wim->missileSprite )
+ CG_Printf( S_COLOR_RED "ERROR: missile sprite not found %s\n", token );
continue;
}
else if( !Q_stricmp( token, "missileRotates" ) )
{
- wi->missileRotates = qtrue;
+ wim->missileRotates = qtrue;
continue;
}
else if( !Q_stricmp( token, "missileParticleSystem" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->missileParticleSystem = CG_RegisterParticleSystem( token );
+ wim->missileParticleSystem = CG_RegisterParticleSystem( token );
- if( !wi->missileParticleSystem )
- CG_Printf( "Missile particle system not found %s: %s\n", filename, token );
+ if( !wim->missileParticleSystem )
+ CG_Printf( S_COLOR_RED "ERROR: missile particle system not found %s\n", token );
continue;
}
else if( !Q_stricmp( token, "muzzleParticleSystem" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->muzzleParticleSystem = CG_RegisterParticleSystem( token );
+ wim->muzzleParticleSystem = CG_RegisterParticleSystem( token );
- if( !wi->muzzleParticleSystem )
- CG_Printf( "Muzzle particle system not found %s: %s\n", filename, token );
+ if( !wim->muzzleParticleSystem )
+ CG_Printf( S_COLOR_RED "ERROR: muzzle particle system not found %s\n", token );
continue;
}
else if( !Q_stricmp( token, "impactParticleSystem" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->impactParticleSystem = CG_RegisterParticleSystem( token );
+ wim->impactParticleSystem = CG_RegisterParticleSystem( token );
- if( !wi->impactParticleSystem )
- CG_Printf( "Impact particle system not found %s: %s\n", filename, token );
+ if( !wim->impactParticleSystem )
+ CG_Printf( S_COLOR_RED "ERROR: impact particle system not found %s\n", token );
continue;
}
- else if( !Q_stricmp( token, "impactDish" ) )
+ else if( !Q_stricmp( token, "impactModel" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->impactDish = trap_R_RegisterModel( token );
+ wim->impactModel = trap_R_RegisterModel( token );
- if( !wi->impactDish )
- CG_Printf( "Impact dish model not found %s: %s\n", filename, token );
+ if( !wim->impactModel )
+ CG_Printf( S_COLOR_RED "ERROR: impact model not found %s\n", token );
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->impactDishShader = trap_R_RegisterShader( token );
+ wim->impactModelShader = trap_R_RegisterShader( token );
- if( !wi->impactDishShader )
- CG_Printf( "Impact dish shader not found %s: %s\n", filename, token );
+ if( !wim->impactModelShader )
+ CG_Printf( S_COLOR_RED "ERROR: impact model shader not found %s\n", token );
continue;
}
@@ -387,7 +334,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
int size = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -396,15 +343,15 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
if( size < 0 )
size = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->impactMark = trap_R_RegisterShader( token );
- wi->impactMarkSize = size;
+ wim->impactMark = trap_R_RegisterShader( token );
+ wim->impactMarkSize = size;
- if( !wi->impactMark )
- CG_Printf( "Impact mark shader not found %s: %s\n", filename, token );
+ if( !wim->impactMark )
+ CG_Printf( S_COLOR_RED "ERROR: impact mark shader not found %s\n", token );
continue;
}
@@ -412,7 +359,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
int index = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -423,14 +370,14 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
else if( index > 3 )
index = 3;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->impactSound[ index ] = trap_S_RegisterSound( token, qfalse );
+ wim->impactSound[ index ] = trap_S_RegisterSound( token, qfalse );
- if( !wi->impactSound[ index ] )
- CG_Printf( "Weapon impact sound %d not found %s: %s\n", index, filename, token );
+ if( !wim->impactSound[ index ] )
+ CG_Printf( S_COLOR_RED "ERROR: impact sound %d not found %s\n", index, token );
continue;
}
@@ -438,11 +385,11 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
for( i = 0 ; i < 3 ; i++ )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->impactDlightColor[ i ] = atof( token );
+ wim->impactDlightColor[ i ] = atof( token );
}
continue;
@@ -451,7 +398,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
int size = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -460,13 +407,13 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
if( size < 0 )
size = 0;
- wi->impactDlight = size;
+ wim->impactDlight = size;
continue;
}
else if( !Q_stricmp( token, "alwaysImpact" ) )
{
- wi->alwaysImpact = qtrue;
+ wim->alwaysImpact = qtrue;
continue;
}
@@ -474,18 +421,18 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
for( i = 0 ; i < 3 ; i++ )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->flashDlightColor[ i ] = atof( token );
+ wim->flashDlightColor[ i ] = atof( token );
}
continue;
}
else if( !Q_stricmp( token, "continuousFlash" ) )
{
- wi->continuousFlash = qtrue;
+ wim->continuousFlash = qtrue;
continue;
}
@@ -493,11 +440,11 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
for( i = 0 ; i < 3 ; i++ )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->missileDlightColor[ i ] = atof( token );
+ wim->missileDlightColor[ i ] = atof( token );
}
continue;
@@ -506,7 +453,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
int size = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -515,46 +462,33 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
if( size < 0 )
size = 0;
- wi->missileDlight = size;
-
- continue;
- }
- else if( !Q_stricmp( token, "idleSound" ) )
- {
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- wi->readySound = trap_S_RegisterSound( token, qfalse );
-
- if( !wi->readySound )
- CG_Printf( "Weapon idle sound not found %s: %s\n", filename, token );
+ wim->missileDlight = size;
continue;
}
else if( !Q_stricmp( token, "firingSound" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->firingSound = trap_S_RegisterSound( token, qfalse );
+ wim->firingSound = trap_S_RegisterSound( token, qfalse );
- if( !wi->firingSound )
- CG_Printf( "Weapon firing sound not found %s: %s\n", filename, token );
+ if( !wim->firingSound )
+ CG_Printf( S_COLOR_RED "ERROR: firing sound not found %s\n", token );
continue;
}
else if( !Q_stricmp( token, "missileSound" ) )
{
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
- wi->missileSound = trap_S_RegisterSound( token, qfalse );
+ wim->missileSound = trap_S_RegisterSound( token, qfalse );
- if( !wi->missileSound )
- CG_Printf( "Weapon missile sound not found %s: %s\n", filename, token );
+ if( !wim->missileSound )
+ CG_Printf( S_COLOR_RED "ERROR: missile sound not found %s\n", token );
continue;
}
@@ -562,7 +496,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
{
int index = 0;
- token = COM_Parse( &text_p );
+ token = COM_Parse( text_p );
if( !token )
break;
@@ -573,14 +507,150 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
else if( index > 3 )
index = 3;
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->flashSound[ index ] = trap_S_RegisterSound( token, qfalse );
+
+ if( !wim->flashSound[ index ] )
+ CG_Printf( S_COLOR_RED "ERROR: flash sound %d not found %s\n", index, token );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "}" ) )
+ return qtrue; //reached the end of this weapon section
+ else
+ {
+ CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in weapon section\n", token );
+ return qfalse;
+ }
+ }
+
+ return qfalse;
+}
+/*
+======================
+CG_ParseWeaponFile
+
+Parses a configuration file describing a weapon
+======================
+*/
+static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
+{
+ char *text_p;
+ int i;
+ int len;
+ char *token;
+ char text[ 20000 ];
+ fileHandle_t f;
+ weaponMode_t weaponMode = WPM_NONE;
+
+ // load the file
+ len = trap_FS_FOpenFile( filename, &f, FS_READ );
+ if( len <= 0 )
+ return qfalse;
+
+ if( len >= sizeof( text ) - 1 )
+ {
+ CG_Printf( "File %s too long\n", filename );
+ return qfalse;
+ }
+
+ trap_FS_Read( text, len, f );
+ text[ len ] = 0;
+ trap_FS_FCloseFile( f );
+
+ // parse the text
+ text_p = text;
+
+ // read optional parameters
+ while( 1 )
+ {
+ token = COM_Parse( &text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "" ) )
+ break;
+
+ if( !Q_stricmp( token, "{" ) )
+ {
+ if( weaponMode == WPM_NONE )
+ {
+ CG_Printf( S_COLOR_RED "ERROR: weapon mode section started without a declaration\n" );
+ return qfalse;
+ }
+ else if( !CG_ParseWeaponModeSection( &wi->wim[ weaponMode ], &text_p ) )
+ {
+ CG_Printf( S_COLOR_RED "ERROR: failed to parse weapon mode section\n" );
+ return qfalse;
+ }
+
+ //start parsing ejectors again
+ weaponMode = WPM_NONE;
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "primary" ) )
+ {
+ weaponMode = WPM_PRIMARY;
+ continue;
+ }
+ else if( !Q_stricmp( token, "secondary" ) )
+ {
+ weaponMode = WPM_SECONDARY;
+ continue;
+ }
+ else if( !Q_stricmp( token, "tertiary" ) )
+ {
+ weaponMode = WPM_TERTIARY;
+ continue;
+ }
+ else if( !Q_stricmp( token, "weaponModel" ) )
+ {
+ char path[ MAX_QPATH ];
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ wi->weaponModel = trap_R_RegisterModel( token );
+
+ if( !wi->weaponModel )
+ CG_Printf( S_COLOR_RED "ERROR: weapon model not found %s\n", token );
+
+ strcpy( path, token );
+ COM_StripExtension( path, path );
+ strcat( path, "_flash.md3" );
+ wi->flashModel = trap_R_RegisterModel( path );
+
+ strcpy( path, token );
+ COM_StripExtension( path, path );
+ strcat( path, "_barrel.md3" );
+ wi->barrelModel = trap_R_RegisterModel( path );
+
+ strcpy( path, token );
+ COM_StripExtension( path, path );
+ strcat( path, "_hand.md3" );
+ wi->handsModel = trap_R_RegisterModel( path );
+
+ if( !wi->handsModel )
+ wi->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "idleSound" ) )
+ {
token = COM_Parse( &text_p );
if( !token )
break;
- wi->flashSound[ index ] = trap_S_RegisterSound( token, qfalse );
+ wi->readySound = trap_S_RegisterSound( token, qfalse );
- if( !wi->flashSound[ index ] )
- CG_Printf( "Weapon flash sound %d not found %s: %s\n", index, filename, token );
+ if( !wi->readySound )
+ CG_Printf( S_COLOR_RED "ERROR: weapon idle sound not found %s\n", token );
continue;
}
@@ -593,7 +663,7 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
wi->weaponIcon = wi->ammoIcon = trap_R_RegisterShader( token );
if( !wi->weaponIcon )
- CG_Printf( "Weapon icon shader not found %s: %s\n", filename, token );
+ CG_Printf( S_COLOR_RED "ERROR: weapon icon not found %s\n", token );
continue;
}
@@ -618,12 +688,13 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
wi->crossHairSize = size;
if( !wi->crossHair )
- CG_Printf( "Weapon crosshair not found %s: %s\n", filename, token );
+ CG_Printf( S_COLOR_RED "ERROR: weapon crosshair not found %s\n", token );
continue;
}
- Com_Printf( "unknown token '%s' in %s\n", token, filename );
+ Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
+ return qfalse;
}
return qtrue;
@@ -660,14 +731,17 @@ void CG_RegisterWeapon( int weaponNum )
weaponInfo->humanName = BG_FindHumanNameForWeapon( weaponNum );
- CG_ParseWeaponFile( path, weaponInfo );
+ if( !CG_ParseWeaponFile( path, weaponInfo ) )
+ Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path );
// calc midpoint for rotation
trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs );
for( i = 0 ; i < 3 ; i++ )
weaponInfo->weaponMidpoint[ i ] = mins[ i ] + 0.5 * ( maxs[ i ] - mins[ i ] );
- weaponInfo->loopFireSound = qfalse;
+ //FIXME:
+ for( i = WPM_NONE + 1; i < WPM_NUM_WEAPONMODES; i++ )
+ weaponInfo->wim[ i ].loopFireSound = qfalse;
switch( weaponNum )
{
@@ -789,227 +863,6 @@ static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles )
/*
-===============
-CG_LightningBolt
-
-Origin will be the exact tag point, which is slightly
-different than the muzzle point used for determining hits.
-The cent should be the non-predicted cent if it is from the player,
-so the endpoint will reflect the simulated strike (lagging the predicted
-angle)
-===============
-*/
-static void CG_LightningBolt( centity_t *cent, vec3_t origin )
-{
- trace_t trace;
- refEntity_t beam;
- vec3_t forward;
- vec3_t muzzlePoint, endPoint;
-
- if( cent->currentState.weapon != WP_TESLAGEN )
- return;
-
- memset( &beam, 0, sizeof( beam ) );
-
- // CPMA "true" lightning
- if( ( cent->currentState.number == cg.predictedPlayerState.clientNum ) &&
- ( cg_trueLightning.value != 0 ) )
- {
- vec3_t angle;
- int i;
-
- for( i = 0; i < 3; i++ )
- {
- float a = cent->lerpAngles[ i ] - cg.refdefViewAngles[ i ];
- if( a > 180 )
- a -= 360;
-
- if( a < -180 )
- a += 360;
-
- angle[ i ] = cg.refdefViewAngles[ i ] + a * ( 1.0 - cg_trueLightning.value );
-
- if( angle[ i ] < 0 )
- angle[ i ] += 360;
-
- if( angle[ i ] > 360 )
- angle[ i ] -= 360;
- }
-
- AngleVectors( angle, forward, NULL, NULL );
- VectorCopy( cent->lerpOrigin, muzzlePoint );
-// VectorCopy(cg.refdef.vieworg, muzzlePoint );
- }
- else
- {
- // !CPMA
- AngleVectors( cent->lerpAngles, forward, NULL, NULL );
- VectorCopy( cent->lerpOrigin, muzzlePoint );
- }
-
- // FIXME: crouch
- muzzlePoint[ 2 ] += DEFAULT_VIEWHEIGHT;
-
- VectorMA( muzzlePoint, 14, forward, muzzlePoint );
-
- // project forward by the lightning range
- VectorMA( muzzlePoint, TESLAGEN_RANGE, forward, endPoint );
-
- // see if it hit a wall
- CG_Trace( &trace, muzzlePoint, vec3_origin, vec3_origin, endPoint,
- cent->currentState.number, MASK_SHOT );
-
- // this is the endpoint
- VectorCopy( trace.endpos, beam.oldorigin );
-
- // use the provided origin, even though it may be slightly
- // different than the muzzle origin
- VectorCopy( origin, beam.origin );
-
- beam.reType = RT_LIGHTNING;
- beam.customShader = cgs.media.lightningShader;
- trap_R_AddRefEntityToScene( &beam );
-
- // add the impact flare if it hit something
- if( trace.fraction < 1.0 )
- {
- vec3_t angles;
- vec3_t dir;
-
- VectorSubtract( beam.oldorigin, beam.origin, dir );
- VectorNormalize( dir );
-
- memset( &beam, 0, sizeof( beam ) );
- beam.hModel = cgs.media.lightningExplosionModel;
-
- VectorMA( trace.endpos, -16, dir, beam.origin );
-
- // make a random orientation
- angles[ 0 ] = rand( ) % 360;
- angles[ 1 ] = rand( ) % 360;
- angles[ 2 ] = rand( ) % 360;
- AnglesToAxis( angles, beam.axis );
- trap_R_AddRefEntityToScene( &beam );
- }
-}
-
-
-#define POISONCLOUD_LIFETIME 800
-#define POISONCLOUD_SPEED 80.0f
-#define POISONCLOUD_GAP 40
-#define POISONCLOUD_LAG 0.75f
-#define POISONCLOUD_SPREAD 160.0f
-
-/*
-===============
-CG_PoisonCloud
-===============
-*/
-static void CG_PoisonCloud( centity_t *cent, int firstPoisonTime )
-{
- vec3_t forward, right, up;
- vec3_t muzzlePoint;
- vec3_t velocity;
- vec3_t pVelocity;
- vec3_t accel = { 0.0f, 0.0f, 2.0f };
- vec3_t surfNormal;
- entityState_t *es = &cent->currentState;
-
- if( cent->currentState.weapon != WP_GRAB_CLAW_UPG )
- return;
-
- //finite lifetime
- if( firstPoisonTime + POISONCLOUD_LIFETIME < cg.time )
- return;
-
- //not time for the next ball yet
- if( cg.time < cent->poisonTime )
- return;
-
- if( cent->currentState.clientNum == cg.predictedPlayerState.clientNum && !cg.renderingThirdPerson )
- {
- AngleVectors( cg.refdefViewAngles, forward, right, up );
- VectorCopy( cg.refdef.vieworg, muzzlePoint );
- VectorScale( cg.predictedPlayerState.velocity, POISONCLOUD_LAG, pVelocity );
- }
- else
- {
- AngleVectors( cent->lerpAngles, forward, right, up );
- VectorCopy( cent->lerpOrigin, muzzlePoint );
-
- //FIXME: this is gonna look weird when crouching
- muzzlePoint[ 2 ] += DEFAULT_VIEWHEIGHT;
- VectorScale( cent->currentState.pos.trDelta, POISONCLOUD_LAG, pVelocity );
- }
-
- VectorMA( pVelocity, POISONCLOUD_SPEED, forward, velocity );
-
- VectorMA( muzzlePoint, 24.0f, forward, muzzlePoint );
- VectorMA( muzzlePoint, -6.0f, up, muzzlePoint );
-
- if( es->eFlags & EF_WALLCLIMBCEILING )
- VectorSet( surfNormal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( es->angles2, surfNormal );
-
- VectorMA( velocity, -33.0f, surfNormal, velocity );
-
- CG_LaunchSprite( muzzlePoint, velocity, accel, POISONCLOUD_SPREAD,
- 0.5f, 10.0f, 40.0f, 127.0f, 0.0f,
- rand( ) % 360, cg.time, cg.time, POISONCLOUD_LIFETIME,
- cgs.media.poisonCloudShader, qfalse, qfalse );
-
- //set next ball time
- cent->poisonTime = cg.time + POISONCLOUD_GAP;
-}
-
-#define FIREBALL_GAP 15 //basically as fast as possible yet regular
-
-/*
-===============
-CG_FlameTrail
-===============
-*/
-static void CG_FlameTrail( centity_t *cent, vec3_t origin )
-{
- vec3_t forward, right, up;
- vec3_t muzzlePoint;
- vec3_t velocity;
- vec3_t pVelocity;
-
- if( cent->currentState.weapon != WP_FLAMER )
- return;
-
- //not time for the next ball yet
- if( cg.time < cent->flamerTime )
- return;
-
- VectorCopy( origin, muzzlePoint );
-
- if( cent->currentState.clientNum == cg.predictedPlayerState.clientNum && !cg.renderingThirdPerson )
- {
- AngleVectors( cg.refdefViewAngles, forward, right, up );
- VectorScale( cg.predictedPlayerState.velocity, FLAMER_LAG, pVelocity );
- }
- else
- {
- AngleVectors( cent->lerpAngles, forward, right, up );
- VectorScale( cent->currentState.pos.trDelta, FLAMER_LAG, pVelocity );
- }
-
- VectorMA( pVelocity, FLAMER_SPEED, forward, velocity );
-
- CG_LaunchSprite( muzzlePoint, velocity, vec3_origin, 0.0f,
- 0.1f, 4.0f, 40.0f, 255.0f, 255.0f,
- rand( ) % 360, cg.time, cg.time, FLAMER_LIFETIME,
- cgs.media.flameShader[ 0 ], qfalse, qfalse );
-
- //set next ball time
- cent->flamerTime = cg.time + FIREBALL_GAP;
-}
-
-
-/*
======================
CG_MachinegunSpinAngle
======================
@@ -1073,11 +926,13 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
refEntity_t flash;
vec3_t angles;
weapon_t weaponNum;
+ weaponMode_t weaponMode;
weaponInfo_t *weapon;
centity_t *nonPredictedCent;
weaponNum = cent->currentState.weapon;
-
+ weaponMode = cent->currentState.generic1;
+
CG_RegisterWeapon( weaponNum );
weapon = &cg_weapons[ weaponNum ];
@@ -1122,12 +977,11 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
if( !ps )
{
// add weapon ready sound
- cent->pe.lightningFiring = qfalse;
- if( ( cent->currentState.eFlags & EF_FIRING ) && weapon->firingSound )
+ if( ( cent->currentState.eFlags & EF_FIRING ) && weapon->wim[ weaponMode ].firingSound )
{
// lightning gun and guantlet make a different sound when fire is held down
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->firingSound );
- cent->pe.lightningFiring = qtrue;
+ trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin,
+ weapon->wim[ weaponMode ].firingSound );
}
else if( weapon->readySound )
trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound );
@@ -1165,16 +1019,20 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
if( ( nonPredictedCent - cg_entities ) != cent->currentState.clientNum )
nonPredictedCent = cent;
- CG_PoisonCloud( nonPredictedCent, cent->firstPoisonTime );
-
if( cent->muzzlePS )
{
if( ps || cg.renderingThirdPerson ||
cent->currentState.number != cg.predictedPlayerState.clientNum )
CG_SetParticleSystemTag( cent->muzzlePS, gun, weapon->weaponModel, "tag_flash" );
+ //FIXME: this leaves open the possibility for keep a persistent muzzle system going
+ // by hopping between firing buttons -- currently nothing with a persistent
+ // muzzle system has multiple fire modes however
//if the PS is infinite disable it when not firing
- if( !( cent->currentState.eFlags & EF_FIRING ) && CG_IsParticleSystemInfinite( cent->muzzlePS ) )
+ if( !( cent->currentState.eFlags & EF_FIRING ) &&
+ !( cent->currentState.eFlags & EF_FIRING2 ) &&
+ !( cent->currentState.eFlags & EF_FIRING3 ) &&
+ CG_IsParticleSystemInfinite( cent->muzzlePS ) )
{
CG_DestroyParticleSystem( cent->muzzlePS );
cent->muzzlePS = NULL;
@@ -1182,11 +1040,11 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
}
// add the flash
- if( !( weapon->continuousFlash &&
+ if( !( weapon->wim[ weaponMode ].continuousFlash &&
( nonPredictedCent->currentState.eFlags & EF_FIRING ) ) )
{
// impulse flash
- if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME && !cent->pe.railgunFlash )
+ if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME )
return;
}
@@ -1210,25 +1068,24 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
if( ps || cg.renderingThirdPerson ||
cent->currentState.number != cg.predictedPlayerState.clientNum )
{
- if( weapon->muzzleParticleSystem && cent->muzzlePsTrigger )
+ if( weapon->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger )
{
- cent->muzzlePS = CG_SpawnNewParticleSystem( weapon->muzzleParticleSystem );
+ cent->muzzlePS = CG_SpawnNewParticleSystem( weapon->wim[ weaponMode ].muzzleParticleSystem );
CG_SetParticleSystemTag( cent->muzzlePS, gun, weapon->weaponModel, "tag_flash" );
CG_SetParticleSystemCent( cent->muzzlePS, cent );
CG_AttachParticleSystemToTag( cent->muzzlePS );
cent->muzzlePsTrigger = qfalse;
}
- // add lightning bolt
- CG_LightningBolt( nonPredictedCent, flash.origin );
-
- /*CG_FlameTrail( nonPredictedCent, flash.origin );*/
-
// make a dlight for the flash
- if( weapon->flashDlightColor[ 0 ] || weapon->flashDlightColor[ 1 ] || weapon->flashDlightColor[ 2 ] )
+ if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] ||
+ weapon->wim[ weaponMode ].flashDlightColor[ 1 ] ||
+ weapon->wim[ weaponMode ].flashDlightColor[ 2 ] )
{
- trap_R_AddLightToScene( flash.origin, 300 + ( rand( ) & 31 ), weapon->flashDlightColor[ 0 ],
- weapon->flashDlightColor[ 1 ], weapon->flashDlightColor[ 2 ] );
+ trap_R_AddLightToScene( flash.origin, 300 + ( rand( ) & 31 ),
+ weapon->wim[ weaponMode ].flashDlightColor[ 0 ],
+ weapon->wim[ weaponMode ].flashDlightColor[ 1 ],
+ weapon->wim[ weaponMode ].flashDlightColor[ 2 ] );
}
}
}
@@ -1247,7 +1104,8 @@ void CG_AddViewWeapon( playerState_t *ps )
clientInfo_t *ci;
float fovOffset;
vec3_t angles;
- weaponInfo_t *weapon;
+ weaponInfo_t *wi;
+ weapon_t weapon = ps->weapon;
if( ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) ||
( ps->stats[ STAT_STATE ] & SS_INFESTING ) ||
@@ -1255,7 +1113,7 @@ void CG_AddViewWeapon( playerState_t *ps )
return;
//TA: no weapon carried - can't draw it
- if( ps->weapon == WP_NONE )
+ if( weapon == WP_NONE )
return;
if( ps->pm_type == PM_INTERMISSION )
@@ -1274,14 +1132,13 @@ void CG_AddViewWeapon( playerState_t *ps )
{
vec3_t origin;
+ //FIXME: deal with new particle system
if( cg.predictedPlayerState.eFlags & EF_FIRING )
{
// special hack for lightning gun...
// TA: and flamer
VectorCopy( cg.refdef.vieworg, origin );
VectorMA( origin, -8, cg.refdef.viewaxis[ 2 ], origin );
- CG_LightningBolt( &cg_entities[ ps->clientNum ], origin );
- CG_FlameTrail( &cg_entities[ ps->clientNum ], cg.refdef.vieworg );
}
return;
@@ -1300,8 +1157,8 @@ void CG_AddViewWeapon( playerState_t *ps )
fovOffset = 0;
cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
- CG_RegisterWeapon( ps->weapon );
- weapon = &cg_weapons[ ps->weapon ];
+ CG_RegisterWeapon( weapon );
+ wi = &cg_weapons[ weapon ];
memset( &hand, 0, sizeof( hand ) );
@@ -1312,7 +1169,7 @@ 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_CANNON && ps->stats[ STAT_MISC ] > 0 )
+ if( weapon == WP_LUCIFER_CANNON && ps->stats[ STAT_MISC ] > 0 )
{
float fraction = (float)ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE;
@@ -1338,7 +1195,7 @@ void CG_AddViewWeapon( playerState_t *ps )
hand.backlerp = cent->pe.torso.backlerp;
}
- hand.hModel = weapon->handsModel;
+ hand.hModel = wi->handsModel;
hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
// add everything onto the hand
@@ -1670,73 +1527,67 @@ CG_FireWeapon
Caused by an EV_FIRE_WEAPON event
================
*/
-void CG_FireWeapon( centity_t *cent, int mode )
+void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode )
{
- entityState_t *ent;
+ entityState_t *es;
int c;
- weaponInfo_t *weap;
+ weaponInfo_t *wi;
+ weapon_t weaponNum;
- ent = &cent->currentState;
- if( ent->weapon == WP_NONE )
+ es = &cent->currentState;
+
+ weaponNum = es->weapon;
+
+ if( weaponNum == WP_NONE )
return;
- if( ent->weapon >= WP_NUM_WEAPONS )
+ if( weaponNum >= WP_NUM_WEAPONS )
{
CG_Error( "CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS" );
return;
}
- weap = &cg_weapons[ ent->weapon ];
+ wi = &cg_weapons[ weaponNum ];
// mark the entity as muzzle flashing, so when it is added it will
// append the flash to the weapon model
cent->muzzleFlashTime = cg.time;
- if( ent->weapon == WP_GRAB_CLAW_UPG && mode == 1 )
- cent->firstPoisonTime = cg.time;
-
- if( weap->muzzleParticleSystem )
+ if( wi->wim[ weaponMode ].muzzleParticleSystem )
{
if( !( cent->muzzlePS && CG_IsParticleSystemInfinite( cent->muzzlePS ) ) )
cent->muzzlePsTrigger = qtrue;
}
- // lightning gun only does this this on initial press
- if( ent->weapon == WP_TESLAGEN )
- {
- if( cent->pe.lightningFiring )
- return;
- }
-
// play a sound
for( c = 0; c < 4; c++ )
{
- if( !weap->flashSound[ c ] )
+ if( !wi->wim[ weaponMode ].flashSound[ c ] )
break;
}
if( c > 0 )
{
c = rand( ) % c;
- if( weap->flashSound[ c ] )
- trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->flashSound[ c ] );
+ if( wi->wim[ weaponMode ].flashSound[ c ] )
+ trap_S_StartSound( NULL, es->number, CHAN_WEAPON, wi->wim[ weaponMode ].flashSound[ c ] );
}
// do brass ejection
- if( weap->ejectBrassFunc && cg_brassTime.integer > 0 )
+ if( wi->ejectBrassFunc && cg_brassTime.integer > 0 )
{
- if( ent->eType == ET_BUILDABLE )
+ if( es->eType == ET_BUILDABLE )
{
//yucko hack to get turret brass ejecting with the barrel instead of the base
vec3_t temp;
VectorCopy( cent->lerpAngles, temp );
- VectorCopy( ent->angles2, cent->lerpAngles );
- weap->ejectBrassFunc( cent );
+ VectorCopy( es->angles2, cent->lerpAngles );
+ wi->ejectBrassFunc( cent );
VectorCopy( temp, cent->lerpAngles );
}
else
- weap->ejectBrassFunc( cent );
+ wi->ejectBrassFunc( cent );
}
}
@@ -1748,7 +1599,8 @@ CG_MissileHitWall
Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing
=================
*/
-void CG_MissileHitWall( int weaponNum, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType, int damage )
+void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientNum,
+ vec3_t origin, vec3_t dir, impactSound_t soundType )
{
qhandle_t mod = 0;
qhandle_t mark = 0;
@@ -1759,30 +1611,29 @@ void CG_MissileHitWall( int weaponNum, int clientNum, vec3_t origin, vec3_t dir,
float light = 0.0f;
vec3_t lightColor = { 0.0f, 0.0f, 0.0f };
localEntity_t *le;
- weaponInfo_t *weapon;
+ weaponMode_t mode;
+ weaponInfo_t *weapon = &cg_weapons[ weaponNum ];
- weapon = &cg_weapons[ weaponNum ];
-
- mark = weapon->impactMark;
- radius = weapon->impactMarkSize;
- mod = weapon->impactDish;
- shader = weapon->impactDishShader;
- light = weapon->impactDlight;
- VectorCopy( weapon->impactDlightColor, lightColor );
- ps = weapon->impactParticleSystem;
+ mark = weapon->wim[ weaponMode ].impactMark;
+ radius = weapon->wim[ weaponMode ].impactMarkSize;
+ mod = weapon->wim[ weaponMode ].impactModel;
+ shader = weapon->wim[ weaponMode ].impactModelShader;
+ light = weapon->wim[ weaponMode ].impactDlight;
+ VectorCopy( weapon->wim[ weaponMode ].impactDlightColor, lightColor );
+ ps = weapon->wim[ weaponMode ].impactParticleSystem;
// play a sound
for( c = 0; c < 4; c++ )
{
- if( !weapon->impactSound[ c ] )
+ if( !weapon->wim[ weaponMode ].impactSound[ c ] )
break;
}
if( c > 0 )
{
c = rand( ) % c;
- if( weapon->impactSound[ c ] )
- trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weapon->impactSound[ c ] );
+ if( weapon->wim[ weaponMode ].impactSound[ c ] )
+ trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weapon->wim[ weaponMode ].impactSound[ c ] );
}
//create impact particle system
@@ -1824,14 +1675,15 @@ void CG_MissileHitWall( int weaponNum, int clientNum, vec3_t origin, vec3_t dir,
CG_MissileHitPlayer
=================
*/
-void CG_MissileHitPlayer( int weaponNum, vec3_t origin, vec3_t dir, int entityNum, int damage )
+void CG_MissileHitPlayer( weapon_t weaponNum, weaponMode_t weaponMode, vec3_t origin, vec3_t dir, int entityNum )
{
+ weaponMode_t mode;
weaponInfo_t *weapon = &cg_weapons[ weaponNum ];
CG_Bleed( origin, entityNum );
- if( weapon->alwaysImpact )
- CG_MissileHitWall( weaponNum, 0, origin, dir, IMPACTSOUND_FLESH, damage );
+ if( weapon->wim[ weaponMode ].alwaysImpact )
+ CG_MissileHitWall( weaponNum, weaponMode, 0, origin, dir, IMPACTSOUND_FLESH );
}
@@ -2015,5 +1867,5 @@ 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, 0 );
+ CG_MissileHitWall( WP_MACHINEGUN, WPM_PRIMARY, 0, end, normal, IMPACTSOUND_DEFAULT );
}