diff options
-rw-r--r-- | src/cgame/cg_buildable.c | 16 | ||||
-rw-r--r-- | src/cgame/cg_ents.c | 78 | ||||
-rw-r--r-- | src/cgame/cg_event.c | 19 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 84 | ||||
-rw-r--r-- | src/cgame/cg_main.c | 6 | ||||
-rw-r--r-- | src/cgame/cg_particles.c | 11 | ||||
-rw-r--r-- | src/cgame/cg_view.c | 28 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 738 | ||||
-rw-r--r-- | src/game/bg_misc.c | 4 | ||||
-rw-r--r-- | src/game/bg_pmove.c | 28 | ||||
-rw-r--r-- | src/game/bg_public.h | 11 | ||||
-rw-r--r-- | src/game/g_buildable.c | 16 | ||||
-rw-r--r-- | src/game/g_cmds.c | 12 | ||||
-rw-r--r-- | src/game/g_missile.c | 12 | ||||
-rw-r--r-- | src/game/g_weapon.c | 16 |
15 files changed, 480 insertions, 599 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 = ¢->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 = ¢->currentState; - if( s1->weapon > WP_NUM_WEAPONS ) - s1->weapon = 0; - - weapon = &cg_weapons[ s1->weapon ]; + es = ¢->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( ¢->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 = ¢->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 = ¢->currentState; - if( ent->weapon == WP_NONE ) + es = ¢->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 ); } diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index eca4e53d..70136c4d 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -2615,8 +2615,8 @@ weaponAttributes_t bg_weapons[ ] = 0, //int price; ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages SLOT_WEAPON, //int slots; - "groundpound", //char *weaponName; - "Ground Pound", //char *weaponHumanName; + "charge", //char *weaponName; + "Charge", //char *weaponHumanName; 0, //int quan; 0, //int clips; 0, //int maxClips; diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c index 31f76844..39ac8c12 100644 --- a/src/game/bg_pmove.c +++ b/src/game/bg_pmove.c @@ -484,7 +484,8 @@ static qboolean PM_CheckPounce( void ) { vec3_t forward; - if( pm->ps->weapon != WP_POUNCE && pm->ps->weapon != WP_POUNCE_UPG ) + if( pm->ps->weapon != WP_POUNCE && + pm->ps->weapon != WP_POUNCE_UPG ) return qfalse; if( pm->cmd.buttons & BUTTON_ATTACK2 ) @@ -545,11 +546,14 @@ static qboolean PM_CheckJump( void ) return qfalse; //can't jump and pounce charge at the same time - if( ( pm->ps->weapon == WP_POUNCE || pm->ps->weapon == WP_POUNCE_UPG ) && pm->ps->stats[ STAT_MISC ] > 0 ) + if( ( pm->ps->weapon == WP_POUNCE || + pm->ps->weapon == WP_POUNCE_UPG ) && + pm->ps->stats[ STAT_MISC ] > 0 ) return qfalse; //can't jump and charge at the same time - if( ( pm->ps->weapon == WP_CHARGE ) && pm->ps->stats[ STAT_MISC ] > 0 ) + if( ( pm->ps->weapon == WP_CHARGE ) && + pm->ps->stats[ STAT_MISC ] > 0 ) return qfalse; if( ( pm->ps->stats[ STAT_PTEAM ] == PTE_HUMANS ) && @@ -2483,11 +2487,11 @@ Generates weapon events and modifes the weapon counter */ static void PM_Weapon( void ) { - int addTime = 200; //default addTime - should never be used - int ammo, clips, maxclips; - qboolean attack1 = qfalse; - qboolean attack2 = qfalse; - qboolean attack3 = qfalse; + int addTime = 200; //default addTime - should never be used + int ammo, clips, maxclips; + qboolean attack1 = qfalse; + qboolean attack2 = qfalse; + qboolean attack3 = qfalse; // don't allow attack until all buttons are up if( pm->ps->pm_flags & PMF_RESPAWNED ) @@ -2695,6 +2699,7 @@ static void PM_Weapon( void ) return; } + pm->ps->generic1 = WPM_TERTIARY; PM_AddEvent( EV_FIRE_WEAPON3 ); addTime = BG_FindRepeatRate3ForWeapon( pm->ps->weapon ); } @@ -2709,6 +2714,7 @@ static void PM_Weapon( void ) { if( BG_WeaponHasAltMode( pm->ps->weapon ) ) { + pm->ps->generic1 = WPM_SECONDARY; PM_AddEvent( EV_FIRE_WEAPON2 ); addTime = BG_FindRepeatRate2ForWeapon( pm->ps->weapon ); } @@ -2721,6 +2727,7 @@ static void PM_Weapon( void ) } else if( attack1 ) { + pm->ps->generic1 = WPM_PRIMARY; PM_AddEvent( EV_FIRE_WEAPON ); addTime = BG_FindRepeatRate1ForWeapon( pm->ps->weapon ); } @@ -2731,12 +2738,14 @@ static void PM_Weapon( void ) switch( pm->ps->weapon ) { case WP_VENOM: + pm->ps->generic1 = WPM_PRIMARY; PM_AddEvent( EV_FIRE_WEAPON ); addTime = BG_FindRepeatRate1ForWeapon( pm->ps->weapon ); break; case WP_POUNCE: case WP_POUNCE_UPG: + pm->ps->generic1 = WPM_SECONDARY; PM_AddEvent( EV_FIRE_WEAPON2 ); addTime = BG_FindRepeatRate2ForWeapon( pm->ps->weapon ); break; @@ -2971,7 +2980,8 @@ void trap_SnapVector( float *v ); void PmoveSingle (pmove_t *pmove) { - int ammo, clips, maxclips; + int ammo, clips, maxclips; + pm = pmove; BG_unpackAmmoArray( 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 ad7404df..def97d26 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -313,6 +313,17 @@ typedef enum typedef enum { + WPM_NONE, + + WPM_PRIMARY, + WPM_SECONDARY, + WPM_TERTIARY, + + WPM_NUM_WEAPONMODES +} weaponMode_t; + +typedef enum +{ WP_NONE, WP_VENOM, diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 50b64f1c..2d4a19c7 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -1280,10 +1280,12 @@ Use for human power repeater */ void HRpt_Use( gentity_t *self, gentity_t *other, gentity_t *activator ) { - int maxAmmo, maxClips; - int ammo, clips; - + int maxAmmo, maxClips; + int ammo, clips; + weapon_t weapon; playerState_t *ps = &activator->client->ps; + + weapon = ps->weapon; if( !self->spawned ) return; @@ -1291,15 +1293,15 @@ void HRpt_Use( gentity_t *self, gentity_t *other, gentity_t *activator ) if( activator->client->lastRefilTime + ENERGY_REFIL_TIME > level.time ) return; - if( !BG_FindUsesEnergyForWeapon( ps->weapon ) ) + if( !BG_FindUsesEnergyForWeapon( weapon ) ) return; - BG_FindAmmoForWeapon( ps->weapon, &maxAmmo, NULL, &maxClips ); + BG_FindAmmoForWeapon( weapon, &maxAmmo, NULL, &maxClips ); if( BG_gotItem( UP_BATTPACK, ps->stats ) ) maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); - BG_unpackAmmoArray( ps->weapon, ps->ammo, ps->powerups, &ammo, &clips, NULL ); + BG_unpackAmmoArray( weapon, ps->ammo, ps->powerups, &ammo, &clips, NULL ); if( ammo == maxAmmo && clips < maxClips ) { @@ -1313,7 +1315,7 @@ void HRpt_Use( gentity_t *self, gentity_t *other, gentity_t *activator ) if( ammo > maxAmmo ) ammo = maxAmmo; - BG_packAmmoArray( ps->weapon, ps->ammo, ps->powerups, ammo, clips, maxClips ); + BG_packAmmoArray( weapon, ps->ammo, ps->powerups, ammo, clips, maxClips ); G_AddEvent( activator, EV_RPTUSE_SOUND, 0 ); activator->client->lastRefilTime = level.time; diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 9c2c7143..12cc7dff 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1170,7 +1170,8 @@ void Cmd_Destroy_f( gentity_t *ent, qboolean deconstruct ) else G_FreeEntity( traceEnt ); - ent->client->ps.stats[ STAT_MISC ] += BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 1; + ent->client->ps.stats[ STAT_MISC ] += + BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 1; } } } @@ -1728,11 +1729,10 @@ void Cmd_Test_f( gentity_t *ent ) if( !CheatsOk( ent ) ) return; - G_Printf( "%d %d %d\n", - ent->client->sess.sessionTeam, - ent->client->ps.stats[ STAT_PTEAM ], - ent->client->ps.persistant[ PERS_TEAM ] - ); + ent->client->ps.stats[ STAT_STATE ] |= SS_POISONCLOUDED; + ent->client->lastPoisonCloudedTime = level.time; + ent->client->lastPoisonCloudedClient = ent; + G_AddPredictableEvent( ent, EV_POISONCLOUD, 0 ); } /* diff --git a/src/game/g_missile.c b/src/game/g_missile.c index 8eb4169f..ac2a46e8 100644 --- a/src/game/g_missile.c +++ b/src/game/g_missile.c @@ -76,7 +76,8 @@ void G_ExplodeMissile( gentity_t *ent ) ent->s.eType = ET_GENERAL; //TA: tired... can't be fucked... hack - if( ent->s.weapon != WP_LOCKBLOB_LAUNCHER && ent->s.weapon != WP_FLAMER ) + if( ent->s.weapon != WP_LOCKBLOB_LAUNCHER && + ent->s.weapon != WP_FLAMER ) G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( dir ) ); ent->freeAfterEvent = qtrue; @@ -292,6 +293,7 @@ gentity_t *fire_flamer( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_FLAMER; + bolt->s.generic1 = self->s.generic1; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = FLAMER_DMG; @@ -335,6 +337,7 @@ gentity_t *fire_blaster( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_BLASTER; + bolt->s.generic1 = self->s.generic1; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = BLASTER_DMG; @@ -377,6 +380,7 @@ gentity_t *fire_pulseRifle( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_PULSE_RIFLE; + bolt->s.generic1 = self->s.generic1; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = PRIFLE_DMG; @@ -421,12 +425,12 @@ gentity_t *fire_luciferCannon( gentity_t *self, vec3_t start, vec3_t dir, int da bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_LUCIFER_CANNON; + bolt->s.generic1 = self->s.generic1; //weaponMode 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_LCANNON; bolt->splashMethodOfDeath = MOD_LCANNON_SPLASH; bolt->clipmask = MASK_SHOT; @@ -554,6 +558,7 @@ gentity_t *fire_hive( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eFlags |= EF_BOUNCE|EF_NO_BOUNCE_SOUND; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_HIVE; + bolt->s.generic1 = WPM_PRIMARY; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = HIVE_DMG; @@ -593,6 +598,7 @@ gentity_t *fire_lockblob( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_LOCKBLOB_LAUNCHER; + bolt->s.generic1 = self->s.generic1; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = 0; @@ -630,6 +636,7 @@ gentity_t *fire_slowBlob( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_POUNCE_UPG; + bolt->s.generic1 = self->s.generic1; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = DRAGOON_SLOWBLOB_DMG; @@ -668,6 +675,7 @@ gentity_t *fire_paraLockBlob( gentity_t *self, vec3_t start, vec3_t dir ) bolt->s.eType = ET_MISSILE; bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN; bolt->s.weapon = WP_LOCKBLOB_LAUNCHER; + bolt->s.generic1 = self->s.generic1; //weaponMode bolt->r.ownerNum = self->s.number; bolt->parent = self; bolt->damage = 0; diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c index 1b1de4ab..6adf48a1 100644 --- a/src/game/g_weapon.c +++ b/src/game/g_weapon.c @@ -96,6 +96,7 @@ void meleeAttack( gentity_t *ent, float range, int damage, meansOfDeath_t mod ) tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } if ( traceEnt->takedamage ) @@ -188,11 +189,14 @@ void massDriverFire( gentity_t *ent ) tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } else { 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; //weaponMode } if( traceEnt->takedamage ) @@ -316,18 +320,21 @@ void lasGunFire( gentity_t *ent ) // snap the endpos to integers, but nudged towards the line SnapVectorTowards( tr.endpos, muzzle ); - // send bullet impact + // send impact if( traceEnt->takedamage && traceEnt->client ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } else { 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; //weaponMode } tent->s.otherEntityNum = ent->s.number; @@ -370,6 +377,7 @@ void painSawFire( gentity_t *ent ) tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } if ( traceEnt->takedamage ) @@ -545,7 +553,8 @@ void buildFire( gentity_t *ent, dynMenu_t menu ) if( G_ValidateBuild( ent, ent->client->ps.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) ) { ent->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE; - ent->client->ps.stats[ STAT_MISC ] += BG_FindBuildDelayForWeapon( ent->s.weapon ); + ent->client->ps.stats[ STAT_MISC ] += + BG_FindBuildDelayForWeapon( ent->s.weapon ); } return; } @@ -605,6 +614,7 @@ qboolean CheckVenomAttack( gentity_t *ent ) tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } G_Damage( traceEnt, ent, ent, forward, tr.endpos, SOLDIER_BITE_DMG, DAMAGE_NO_KNOCKBACK, MOD_SOLDIER_BITE ); @@ -748,6 +758,7 @@ qboolean CheckPounceAttack( gentity_t *ent ) tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } if( !traceEnt->takedamage ) @@ -949,6 +960,7 @@ void ChargeAttack( gentity_t *ent, gentity_t *victim ) tent->s.otherEntityNum = victim->s.number; tent->s.eventParm = DirToByte( normal ); tent->s.weapon = ent->s.weapon; + tent->s.generic1 = ent->s.generic1; //weaponMode } if( !victim->takedamage ) |