//--------------------------------------------------------- void FireWeapon( gentity_t *ent, qboolean alt_fire ) //--------------------------------------------------------- { float alert = 256; // track shots taken for accuracy tracking. ent->client->ps.persistant[PERS_ACCURACY_SHOTS]++; // set aiming directions if ( ent->s.weapon == WP_DISRUPTOR && alt_fire ) { if ( ent->NPC ) { //snipers must use the angles they actually did their shot trace with AngleVectors( ent->lastAngles, wpFwd, wpVright, wpUp ); } } else if ( ent->s.weapon == WP_ATST_SIDE || ent->s.weapon == WP_ATST_MAIN ) { vec3_t delta1, enemy_org1, muzzle1; vec3_t angleToEnemy1; VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle1 ); if ( !ent->s.number ) {//player driving an AT-ST //SIGH... because we can't anticipate alt-fire, must calc muzzle here and now mdxaBone_t boltMatrix; int bolt; if ( ent->client->ps.weapon == WP_ATST_MAIN ) {//FIXME: alt_fire should fire both barrels, but slower? if ( ent->alt_fire ) { bolt = ent->handRBolt; } else { bolt = ent->handLBolt; } } else {// ATST SIDE weapons if ( ent->alt_fire ) { if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_light_blaster_cann" ) ) {//don't have it! return; } bolt = ent->genericBolt2; } else { if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_concussion_charger" ) ) {//don't have it! return; } bolt = ent->genericBolt1; } } vec3_t yawOnlyAngles = {0, ent->currentAngles[YAW], 0}; if ( ent->currentAngles[YAW] != ent->client->ps.legsYaw ) { yawOnlyAngles[YAW] = ent->client->ps.legsYaw; } gi.G2API_GetBoltMatrix( ent->ghoul2, ent->playerModel, bolt, &boltMatrix, yawOnlyAngles, ent->currentOrigin, (cg.time?cg.time:level.time), NULL, ent->s.modelScale ); // work the matrix axis stuff into the original axis and origins used. gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, ent->client->renderInfo.muzzlePoint ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, ent->client->renderInfo.muzzleDir ); ent->client->renderInfo.mPCalcTime = level.time; AngleVectors( ent->client->ps.viewangles, wpFwd, wpVright, wpUp ); //CalcMuzzlePoint( ent, wpFwd, vright, wpUp, wpMuzzle, 0 ); } else if ( !ent->enemy ) {//an NPC with no enemy to auto-aim at VectorCopy( ent->client->renderInfo.muzzleDir, wpFwd ); } else {//NPC, auto-aim at enemy CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, wpFwd, wpVright, wpUp); } } else if ( ent->s.weapon == WP_BOT_LASER && ent->enemy ) { vec3_t delta1, enemy_org1, muzzle1; vec3_t angleToEnemy1; CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 ); CalcEntitySpot( ent, SPOT_WEAPON, muzzle1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, wpFwd, wpVright, wpUp); } else { AngleVectors( ent->client->ps.viewangles, wpFwd, wpVright, wpUp ); } ent->alt_fire = alt_fire; CalcMuzzlePoint ( ent, wpFwd, wpVright, wpUp, wpMuzzle , 0); // fire the specific weapon switch( ent->s.weapon ) { // Player weapons //----------------- case WP_SABER: return; break; case WP_BRYAR_PISTOL: WP_FireBryarPistol( ent, alt_fire ); break; case WP_BLASTER: WP_FireBlaster( ent, alt_fire ); break; case WP_DISRUPTOR: alert = 50; // if you want it to alert enemies, remove this WP_FireDisruptor( ent, alt_fire ); break; case WP_BOWCASTER: WP_FireBowcaster( ent, alt_fire ); break; case WP_REPEATER: WP_FireRepeater( ent, alt_fire ); break; case WP_DEMP2: WP_FireDEMP2( ent, alt_fire ); break; case WP_FLECHETTE: WP_FireFlechette( ent, alt_fire ); break; case WP_ROCKET_LAUNCHER: WP_FireRocket( ent, alt_fire ); break; case WP_THERMAL: WP_FireThermalDetonator( ent, alt_fire ); break; case WP_TRIP_MINE: alert = 0; // if you want it to alert enemies, remove this WP_PlaceLaserTrap( ent, alt_fire ); break; case WP_DET_PACK: alert = 0; // if you want it to alert enemies, remove this WP_FireDetPack( ent, alt_fire ); break; case WP_BOT_LASER: WP_BotLaser( ent ); break; case WP_EMPLACED_GUN: // doesn't care about whether it's alt-fire or not. We can do an alt-fire if needed WP_EmplacedFire( ent ); break; case WP_MELEE: alert = 0; // if you want it to alert enemies, remove this WP_Melee( ent ); break; case WP_ATST_MAIN: WP_ATSTMainFire( ent ); break; case WP_ATST_SIDE: // TEMP if ( alt_fire ) { // WP_FireRocket( ent, qfalse ); WP_ATSTSideAltFire(ent); } else { if ( ent->s.number == 0 && ent->client->ps.vehicleModel ) { WP_ATSTMainFire( ent ); } else { WP_ATSTSideFire(ent); } } break; case WP_TIE_FIGHTER: // TEMP WP_EmplacedFire( ent ); break; case WP_RAPID_FIRE_CONC: // TEMP if ( alt_fire ) { WP_FireRepeater( ent, alt_fire ); } else { WP_EmplacedFire( ent ); } break; case WP_STUN_BATON: WP_FireStunBaton( ent, alt_fire ); break; case WP_BLASTER_PISTOL: // enemy version WP_FireBryarPistol( ent, qfalse ); // never an alt-fire? break; // case WP_TRICORDER: // WP_TricorderScan( ent, alt_fire ); // break; default: return; break; } if ( !ent->s.number ) { if ( ent->s.weapon == WP_FLECHETTE || (ent->s.weapon == WP_BOWCASTER && !alt_fire) ) {//these can fire multiple shots, count them individually within the firing functions } else if ( W_AccuracyLoggableWeapon( ent->s.weapon, alt_fire, MOD_UNKNOWN ) ) { ent->client->sess.missionStats.shotsFired++; } } // We should probably just use this as a default behavior, in special cases, just set alert to false. if ( ent->s.number == 0 && alert > 0 ) { AddSoundEvent( ent, wpMuzzle, alert, AEL_DISCOVERED ); AddSightEvent( ent, wpMuzzle, alert*2, AEL_DISCOVERED, 20 ); } }
//------------------------------------------------------ void G_MissileImpact( gentity_t *ent, trace_t *trace, int hitLoc=HL_NONE ) { gentity_t *other; vec3_t diff; other = &g_entities[trace->entityNum]; if ( other == ent ) { assert(0&&"missile hit itself!!!"); return; } if ( trace->plane.normal[0] == 0.0f && trace->plane.normal[1] == 0.0f && trace->plane.normal[2] == 0.0f ) {//model moved into missile in flight probably... trace->plane.normal[0] = -ent->s.pos.trDelta[0]; trace->plane.normal[1] = -ent->s.pos.trDelta[1]; trace->plane.normal[2] = -ent->s.pos.trDelta[2]; VectorNormalize(trace->plane.normal); } if ( ent->owner && (other->takedamage||other->client) ) { if ( !ent->lastEnemy || ent->lastEnemy == ent->owner ) {//a missile that was not reflected or, if so, still is owned by original owner if( LogAccuracyHit( other, ent->owner ) ) { ent->owner->client->ps.persistant[PERS_ACCURACY_HITS]++; } if ( ent->owner->client && !ent->owner->s.number ) { if ( W_AccuracyLoggableWeapon( ent->s.weapon, qfalse, ent->methodOfDeath ) ) { ent->owner->client->sess.missionStats.hits++; } } } } // check for bounce //OR: if the surfaceParm is has a reflect property (magnetic shielding) and the missile isn't an exploding missile qboolean bounce = !!( (!other->takedamage && (ent->s.eFlags&(EF_BOUNCE|EF_BOUNCE_HALF))) || (((trace->surfaceFlags&SURF_FORCEFIELD)||(other->flags&FL_SHIELDED))&&!ent->splashDamage&&!ent->splashRadius&&ent->s.weapon != WP_NOGHRI_STICK) ); if ( ent->dflags & DAMAGE_HEAVY_WEAP_CLASS ) { // heavy class missiles generally never bounce. bounce = qfalse; } if ( other->flags & (FL_DMG_BY_HEAVY_WEAP_ONLY | FL_SHIELDED )) { // Dumb assumption, but I guess we must be a shielded ion_cannon?? We should probably verify // if it's an ion_cannon that's Heavy Weapon only, we don't want to make it shielded do we...? if ( (!strcmp( "misc_ion_cannon", other->classname )) && (other->flags & FL_SHIELDED) ) { // Anything will bounce off of us. bounce = qtrue; // Not exactly the debounce time, but rather the impact time for the shield effect...play effect for 1 second other->painDebounceTime = level.time + 1000; } } if ( ent->s.weapon == WP_DEMP2 ) { // demp2 shots can never bounce bounce = qfalse; // in fact, alt-charge shots will not call the regular impact functions if ( ent->alt_fire ) { // detonate at the trace end VectorCopy( trace->endpos, ent->currentOrigin ); VectorCopy( trace->plane.normal, ent->pos1 ); DEMP2_AltDetonate( ent ); return; } } if ( bounce ) { // Check to see if there is a bounce count if ( ent->bounceCount ) { // decrement number of bounces and then see if it should be done bouncing if ( !(--ent->bounceCount) ) { // He (or she) will bounce no more (after this current bounce, that is). ent->s.eFlags &= ~( EF_BOUNCE | EF_BOUNCE_HALF ); } } if ( other->NPC ) { G_Damage( other, ent, ent->owner, ent->currentOrigin, ent->s.pos.trDelta, 0, DAMAGE_NO_DAMAGE, MOD_UNKNOWN ); } G_BounceMissile( ent, trace ); if ( ent->owner )//&& ent->owner->s.number == 0 ) { G_MissileAddAlerts( ent ); } G_MissileBounceEffect( ent, trace->endpos, trace->plane.normal, trace->entityNum==ENTITYNUM_WORLD ); return; } // I would glom onto the EF_BOUNCE code section above, but don't feel like risking breaking something else if ( (!other->takedamage && ( ent->s.eFlags&(EF_BOUNCE_SHRAPNEL) ) ) || ((trace->surfaceFlags&SURF_FORCEFIELD)&&!ent->splashDamage&&!ent->splashRadius) ) { if ( !(other->contents&CONTENTS_LIGHTSABER) || g_spskill->integer <= 0//on easy, it reflects all shots || (g_spskill->integer == 1 && ent->s.weapon != WP_FLECHETTE && ent->s.weapon != WP_DEMP2 )//on medium it won't reflect flechette or demp shots || (g_spskill->integer >= 2 && ent->s.weapon != WP_FLECHETTE && ent->s.weapon != WP_DEMP2 && ent->s.weapon != WP_BOWCASTER && ent->s.weapon != WP_REPEATER )//on hard it won't reflect flechette, demp, repeater or bowcaster shots ) { G_BounceMissile( ent, trace ); if ( --ent->bounceCount < 0 ) { ent->s.eFlags &= ~EF_BOUNCE_SHRAPNEL; } G_MissileBounceEffect( ent, trace->endpos, trace->plane.normal, trace->entityNum==ENTITYNUM_WORLD ); return; } } if ( (!other->takedamage || (other->client && other->health <= 0)) && ent->s.weapon == WP_THERMAL && !ent->alt_fire ) {//rolling thermal det - FIXME: make this an eFlag like bounce & stick!!! //G_BounceRollMissile( ent, trace ); if ( ent->owner )//&& ent->owner->s.number == 0 ) { G_MissileAddAlerts( ent ); } //gi.linkentity( ent ); return; } // check for sticking if ( ent->s.eFlags & EF_MISSILE_STICK ) { if ( ent->owner )//&& ent->owner->s.number == 0 ) { //Add the event if ( ent->s.weapon == WP_TRIP_MINE ) { AddSoundEvent( ent->owner, ent->currentOrigin, ent->splashRadius/2, AEL_DISCOVERED/*AEL_DANGER*/, qfalse, qtrue ); AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius*2, AEL_DISCOVERED/*AEL_DANGER*/, 60 ); /* AddSoundEvent( ent->owner, ent->currentOrigin, ent->splashRadius*2, AEL_DANGER, qfalse, qtrue ); AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius*2, AEL_DANGER, 60 ); */ } else { AddSoundEvent( ent->owner, ent->currentOrigin, 128, AEL_DISCOVERED, qfalse, qtrue ); AddSightEvent( ent->owner, ent->currentOrigin, 256, AEL_DISCOVERED, 10 ); } } G_MissileStick( ent, other, trace ); return; } extern bool WP_DoingMoronicForcedAnimationForForcePowers(gentity_t *ent); // check for hitting a lightsaber if ( other->contents & CONTENTS_LIGHTSABER ) { if ( other->owner && !other->owner->s.number && other->owner->client ) { other->owner->client->sess.missionStats.saberBlocksCnt++; } if ( ( g_spskill->integer <= 0//on easy, it reflects all shots || (g_spskill->integer == 1 && ent->s.weapon != WP_FLECHETTE && ent->s.weapon != WP_DEMP2 )//on medium it won't reflect flechette or demp shots || (g_spskill->integer >= 2 && ent->s.weapon != WP_FLECHETTE && ent->s.weapon != WP_DEMP2 && ent->s.weapon != WP_BOWCASTER && ent->s.weapon != WP_REPEATER )//on hard it won't reflect flechette, demp, repeater or bowcaster shots ) && (!ent->splashDamage || !ent->splashRadius) //this would be cool, though, to "bat" the thermal det away... && ent->s.weapon != WP_NOGHRI_STICK )//gas bomb, don't reflect { //FIXME: take other's owner's FP_SABER_DEFENSE into account here somehow? if ( !other->owner || !other->owner->client || other->owner->client->ps.saberInFlight || (InFront( ent->currentOrigin, other->owner->currentOrigin, other->owner->client->ps.viewangles, SABER_REFLECT_MISSILE_CONE ) && !WP_DoingMoronicForcedAnimationForForcePowers(other)) )//other->owner->s.number != 0 || {//Jedi cannot block shots from behind! int blockChance = 0; switch ( other->owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE] ) {//level 1 reflects 50% of the time, level 2 reflects 75% of the time case FORCE_LEVEL_3: blockChance = 10; break; case FORCE_LEVEL_2: blockChance = 3; break; case FORCE_LEVEL_1: blockChance = 1; break; } if ( blockChance && (other->owner->client->ps.forcePowersActive&(1<<FP_SPEED)) ) {//in in force speed, better chance of deflecting the shot blockChance += other->owner->client->ps.forcePowerLevel[FP_SPEED]*2; } if ( Q_irand( 0, blockChance ) ) { VectorSubtract(ent->currentOrigin, other->currentOrigin, diff); VectorNormalize(diff); G_ReflectMissile( other, ent, diff); if ( other->owner && other->owner->client ) { other->owner->client->ps.saberEventFlags |= SEF_DEFLECTED; } //do the effect VectorCopy( ent->s.pos.trDelta, diff ); VectorNormalize( diff ); G_MissileReflectEffect( ent, trace->endpos, trace->plane.normal ); return; } } } else {//still do the bounce effect G_MissileReflectEffect( ent, trace->endpos, trace->plane.normal ); } } G_MissileImpacted( ent, other, trace->endpos, trace->plane.normal, hitLoc ); }
//--------------------------------------------------------- void FireWeapon( gentity_t *ent, qboolean alt_fire ) //--------------------------------------------------------- { float alert = 256; Vehicle_t *pVeh = NULL; // track shots taken for accuracy tracking. ent->client->ps.persistant[PERS_ACCURACY_SHOTS]++; // If this is a vehicle, fire it's weapon and we're done. if ( ent && ent->client && ent->client->NPC_class == CLASS_VEHICLE ) { FireVehicleWeapon( ent, alt_fire ); return; } // set aiming directions if ( ent->s.weapon == WP_DISRUPTOR && alt_fire ) { if ( ent->NPC ) { //snipers must use the angles they actually did their shot trace with AngleVectors( ent->lastAngles, forwardVec, vrightVec, up ); } } else if ( ent->s.weapon == WP_ATST_SIDE || ent->s.weapon == WP_ATST_MAIN ) { vec3_t delta1, enemy_org1, muzzle1; vec3_t angleToEnemy1; VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle1 ); if ( !ent->s.number ) {//player driving an AT-ST //SIGH... because we can't anticipate alt-fire, must calc muzzle here and now mdxaBone_t boltMatrix; int bolt; if ( ent->client->ps.weapon == WP_ATST_MAIN ) {//FIXME: alt_fire should fire both barrels, but slower? if ( ent->alt_fire ) { bolt = ent->handRBolt; } else { bolt = ent->handLBolt; } } else {// ATST SIDE weapons if ( ent->alt_fire ) { if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_light_blaster_cann" ) ) {//don't have it! return; } bolt = ent->genericBolt2; } else { if ( gi.G2API_GetSurfaceRenderStatus( &ent->ghoul2[ent->playerModel], "head_concussion_charger" ) ) {//don't have it! return; } bolt = ent->genericBolt1; } } vec3_t yawOnlyAngles = {0, ent->currentAngles[YAW], 0}; if ( ent->currentAngles[YAW] != ent->client->ps.legsYaw ) { yawOnlyAngles[YAW] = ent->client->ps.legsYaw; } gi.G2API_GetBoltMatrix( ent->ghoul2, ent->playerModel, bolt, &boltMatrix, yawOnlyAngles, ent->currentOrigin, (cg.time?cg.time:level.time), NULL, ent->s.modelScale ); // work the matrix axis stuff into the original axis and origins used. gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, ent->client->renderInfo.muzzlePoint ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, ent->client->renderInfo.muzzleDir ); ent->client->renderInfo.mPCalcTime = level.time; AngleVectors( ent->client->ps.viewangles, forwardVec, vrightVec, up ); //CalcMuzzlePoint( ent, forwardVec, vrightVec, up, muzzle, 0 ); } else if ( !ent->enemy ) {//an NPC with no enemy to auto-aim at VectorCopy( ent->client->renderInfo.muzzleDir, forwardVec ); } else {//NPC, auto-aim at enemy CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forwardVec, vrightVec, up); } } else if ( ent->s.weapon == WP_BOT_LASER && ent->enemy ) { vec3_t delta1, enemy_org1, muzzle1; vec3_t angleToEnemy1; CalcEntitySpot( ent->enemy, SPOT_HEAD, enemy_org1 ); CalcEntitySpot( ent, SPOT_WEAPON, muzzle1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forwardVec, vrightVec, up); } else { if ( (pVeh = G_IsRidingVehicle( ent )) != NULL) //riding a vehicle {//use our muzzleDir, can't use viewangles or vehicle m_vOrientation because we may be animated to shoot left or right... if ((ent->s.eFlags&EF_NODRAW))//we're inside it { vec3_t aimAngles; VectorCopy( ent->client->renderInfo.muzzleDir, forwardVec ); vectoangles( forwardVec, aimAngles ); //we're only keeping the yaw aimAngles[PITCH] = ent->client->ps.viewangles[PITCH]; aimAngles[ROLL] = 0; AngleVectors( aimAngles, forwardVec, vrightVec, up ); } else { vec3_t actorRight; vec3_t actorFwd; VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle ); AngleVectors(ent->currentAngles, actorFwd, actorRight, 0); // Aiming Left //------------- if (ent->client->ps.torsoAnim==BOTH_VT_ATL_G || ent->client->ps.torsoAnim==BOTH_VS_ATL_G) { VectorScale(actorRight, -1.0f, forwardVec); } // Aiming Right //-------------- else if (ent->client->ps.torsoAnim==BOTH_VT_ATR_G || ent->client->ps.torsoAnim==BOTH_VS_ATR_G) { VectorCopy(actorRight, forwardVec); } // Aiming Forward //---------------- else { VectorCopy(actorFwd, forwardVec); } // If We Have An Enemy, Fudge The Aim To Hit The Enemy if (ent->enemy) { vec3_t toEnemy; VectorSubtract(ent->enemy->currentOrigin, ent->currentOrigin, toEnemy); VectorNormalize(toEnemy); if (DotProduct(toEnemy, forwardVec)>0.75f && ((ent->s.number==0 && !Q_irand(0,2)) || // the player has a 1 in 3 chance (ent->s.number!=0 && !Q_irand(0,5)))) // other guys have a 1 in 6 chance { VectorCopy(toEnemy, forwardVec); } else { forwardVec[0] += Q_flrand(-0.1f, 0.1f); forwardVec[1] += Q_flrand(-0.1f, 0.1f); forwardVec[2] += Q_flrand(-0.1f, 0.1f); } } } } else { AngleVectors( ent->client->ps.viewangles, forwardVec, vrightVec, up ); } } ent->alt_fire = alt_fire; if (!pVeh) { if (ent->NPC && (ent->NPC->scriptFlags&SCF_FIRE_WEAPON_NO_ANIM)) { VectorCopy( ent->client->renderInfo.muzzlePoint, muzzle ); VectorCopy( ent->client->renderInfo.muzzleDir, forwardVec ); MakeNormalVectors(forwardVec, vrightVec, up); } else { CalcMuzzlePoint ( ent, forwardVec, vrightVec, up, muzzle , 0); } } // fire the specific weapon switch( ent->s.weapon ) { // Player weapons //----------------- case WP_SABER: return; break; case WP_BRYAR_PISTOL: case WP_BLASTER_PISTOL: WP_FireBryarPistol( ent, alt_fire ); break; case WP_BLASTER: WP_FireBlaster( ent, alt_fire ); break; case WP_TUSKEN_RIFLE: if ( alt_fire ) { WP_FireTuskenRifle( ent ); } else { WP_Melee( ent ); } break; case WP_DISRUPTOR: alert = 50; // if you want it to alert enemies, remove this WP_FireDisruptor( ent, alt_fire ); break; case WP_BOWCASTER: WP_FireBowcaster( ent, alt_fire ); break; case WP_REPEATER: WP_FireRepeater( ent, alt_fire ); break; case WP_DEMP2: WP_FireDEMP2( ent, alt_fire ); break; case WP_FLECHETTE: WP_FireFlechette( ent, alt_fire ); break; case WP_ROCKET_LAUNCHER: WP_FireRocket( ent, alt_fire ); break; case WP_CONCUSSION: WP_Concussion( ent, alt_fire ); break; case WP_THERMAL: WP_FireThermalDetonator( ent, alt_fire ); break; case WP_TRIP_MINE: alert = 0; // if you want it to alert enemies, remove this WP_PlaceLaserTrap( ent, alt_fire ); break; case WP_DET_PACK: alert = 0; // if you want it to alert enemies, remove this WP_FireDetPack( ent, alt_fire ); break; case WP_BOT_LASER: WP_BotLaser( ent ); break; case WP_EMPLACED_GUN: // doesn't care about whether it's alt-fire or not. We can do an alt-fire if needed WP_EmplacedFire( ent ); break; case WP_MELEE: alert = 0; // if you want it to alert enemies, remove this if ( !alt_fire || !g_debugMelee->integer ) { WP_Melee( ent ); } break; case WP_ATST_MAIN: WP_ATSTMainFire( ent ); break; case WP_ATST_SIDE: // TEMP if ( alt_fire ) { // WP_FireRocket( ent, qfalse ); WP_ATSTSideAltFire(ent); } else { // FIXME! /* if ( ent->s.number == 0 && ent->client->NPC_class == CLASS_VEHICLE && vehicleData[((CVehicleNPC *)ent->NPC)->m_iVehicleTypeID].type == VH_FIGHTER ) { WP_ATSTMainFire( ent ); } else*/ { WP_ATSTSideFire(ent); } } break; case WP_TIE_FIGHTER: // TEMP WP_EmplacedFire( ent ); break; case WP_RAPID_FIRE_CONC: // TEMP if ( alt_fire ) { WP_FireRepeater( ent, alt_fire ); } else { WP_EmplacedFire( ent ); } break; case WP_STUN_BATON: WP_FireStunBaton( ent, alt_fire ); break; // case WP_BLASTER_PISTOL: case WP_JAWA: WP_FireBryarPistol( ent, qfalse ); // never an alt-fire? break; case WP_SCEPTER: WP_FireScepter( ent, alt_fire ); break; case WP_NOGHRI_STICK: if ( !alt_fire ) { WP_FireNoghriStick( ent ); } //else does melee attack/damage/func break; case WP_TUSKEN_STAFF: default: return; break; } if ( !ent->s.number ) { if ( ent->s.weapon == WP_FLECHETTE || (ent->s.weapon == WP_BOWCASTER && !alt_fire) ) {//these can fire multiple shots, count them individually within the firing functions } else if ( W_AccuracyLoggableWeapon( ent->s.weapon, alt_fire, MOD_UNKNOWN ) ) { ent->client->sess.missionStats.shotsFired++; } } // We should probably just use this as a default behavior, in special cases, just set alert to false. if ( ent->s.number == 0 && alert > 0 ) { if ( ent->client->ps.groundEntityNum == ENTITYNUM_WORLD//FIXME: check for sand contents type? && ent->s.weapon != WP_STUN_BATON && ent->s.weapon != WP_MELEE && ent->s.weapon != WP_TUSKEN_STAFF && ent->s.weapon != WP_THERMAL && ent->s.weapon != WP_TRIP_MINE && ent->s.weapon != WP_DET_PACK ) {//the vibration of the shot carries through your feet into the ground AddSoundEvent( ent, muzzle, alert, AEL_DISCOVERED, qfalse, qtrue ); } else {//an in-air alert AddSoundEvent( ent, muzzle, alert, AEL_DISCOVERED ); } AddSightEvent( ent, muzzle, alert*2, AEL_DISCOVERED, 20 ); } }