Exemple #1
0
//-----------------------------------------------------------------------------
gentity_t *CreateMissile( vec3_t org, vec3_t dir, float vel, int life, gentity_t *owner, qboolean altFire )
//-----------------------------------------------------------------------------
{
	gentity_t	*missile;

	missile = G_Spawn();
	
	missile->nextthink = level.time + life;
	missile->e_ThinkFunc = thinkF_G_FreeEntity;
	missile->s.eType = ET_MISSILE;
	missile->owner = owner;

	Vehicle_t*	pVeh = G_IsRidingVehicle(owner);

	missile->alt_fire = altFire;

	missile->s.pos.trType = TR_LINEAR;
	missile->s.pos.trTime = level.time;// - 10;	// move a bit on the very first frame
	VectorCopy( org, missile->s.pos.trBase );
	VectorScale( dir, vel, missile->s.pos.trDelta );
 	if (pVeh)
	{
 		missile->s.eFlags |= EF_USE_ANGLEDELTA;
	 	vectoangles(missile->s.pos.trDelta, missile->s.angles);
	  	VectorMA(missile->s.pos.trDelta, 2.0f, pVeh->m_pParentEntity->client->ps.velocity, missile->s.pos.trDelta);
	}

	VectorCopy( org, missile->currentOrigin);
	gi.linkentity( missile );

	return missile;
}
Exemple #2
0
void	Pilot_Update(void)
{
	mActivePilotCount = 0;
	mRegistered.clear();
	for (int i=0; i<ENTITYNUM_WORLD; i++)
	{
		if (g_entities[i].inuse && 
			g_entities[i].client &&
			g_entities[i].NPC && 
			g_entities[i].NPC->greetEnt &&
			g_entities[i].NPC->greetEnt->owner==(&g_entities[i])
			)
		{
			mActivePilotCount++;
		}
		if ( g_entities[i].inuse && 
			 g_entities[i].client &&
			 g_entities[i].m_pVehicle &&
			!g_entities[i].owner &&
			 g_entities[i].health>0 &&
			 g_entities[i].m_pVehicle->m_pVehicleInfo->type==VH_SPEEDER && 
			!mRegistered.full())
		{
			mRegistered.push_back(&g_entities[i]);
		}

	}


	if (player && 
		player->inuse && 
		TIMER_Done(player, "FlybySoundArchitectureDebounce"))
	{
    	TIMER_Set(player, "FlybySoundArchitectureDebounce", 300);

		Vehicle_t*	pVeh = G_IsRidingVehicle(player);

		if (pVeh && 
			(pVeh->m_pVehicleInfo->soundFlyBy || pVeh->m_pVehicleInfo->soundFlyBy2) &&
			//fabsf(pVeh->m_pParentEntity->currentAngles[2])<15.0f &&
			VectorLength(pVeh->m_pParentEntity->client->ps.velocity)>500.0f)
		{
			vec3_t	projectedPosition;
			vec3_t	projectedDirection;
			vec3_t	projectedRight;
			vec3_t	anglesNoRoll;

			VectorCopy(pVeh->m_pParentEntity->currentAngles, anglesNoRoll);
			anglesNoRoll[2] = 0;
			AngleVectors(anglesNoRoll, projectedDirection, projectedRight, 0);

			VectorMA(player->currentOrigin, 1.2f, pVeh->m_pParentEntity->client->ps.velocity, projectedPosition);
			VectorMA(projectedPosition, Q_flrand(-200.0f, 200.0f), projectedRight, projectedPosition); 

			gi.trace(&mPilotViewTrace, 
				player->currentOrigin, 
				0, 
				0, 
				projectedPosition, 
				player->s.number, 
 				MASK_SHOT, G2_NOCOLLIDE, 0);

			if ((mPilotViewTrace.allsolid==qfalse) && 
				(mPilotViewTrace.startsolid==qfalse) && 
				(mPilotViewTrace.fraction<0.99f) && 
				(mPilotViewTrace.plane.normal[2]<0.5f) &&
				(DotProduct(projectedDirection, mPilotViewTrace.plane.normal)<-0.5f)
				)
			{
 			//	CG_DrawEdge(player->currentOrigin, mPilotViewTrace.endpos, EDGE_IMPACT_POSSIBLE);
 		  		TIMER_Set(player, "FlybySoundArchitectureDebounce", Q_irand(1000, 2000));

				int soundFlyBy = pVeh->m_pVehicleInfo->soundFlyBy;
				if (pVeh->m_pVehicleInfo->soundFlyBy2 && (!soundFlyBy || !Q_irand(0,1)))
				{
					soundFlyBy = pVeh->m_pVehicleInfo->soundFlyBy2;
				}
				G_SoundAtSpot(mPilotViewTrace.endpos, soundFlyBy, qtrue);
			}
			else
			{
 			//	CG_DrawEdge(player->currentOrigin, mPilotViewTrace.endpos, EDGE_IMPACT_SAFE);
			}
		}
	}
}
Exemple #3
0
//----------------------------------------------------------
void emplaced_gun_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	vec3_t fwd1, fwd2;

	if ( self->health <= 0 )
	{
		// can't use a dead gun.
		return;
	}

	if ( self->svFlags & SVF_INACTIVE )
	{
		return; // can't use inactive gun
	}

	if ( !activator->client )
	{
		return; // only a client can use it.
	}

	if ( self->activator )
	{
		// someone is already in the gun.
		return;
	}

	if ( other && other->client && G_IsRidingVehicle( other ) )
	{//can't use eweb when on a vehicle
		return;
	}

	if ( activator && activator->client && G_IsRidingVehicle( activator ) )
	{//can't use eweb when on a vehicle
		return;
	}

	// We'll just let the designers duke this one out....I mean, as to whether they even want to limit such a thing.
	if ( self->spawnflags & EMPLACED_FACING )
	{
		// Let's get some direction vectors for the users
		AngleVectors( activator->client->ps.viewangles, fwd1, NULL, NULL );

		// Get the guns direction vector
		AngleVectors( self->pos1, fwd2, NULL, NULL );

		float dot = DotProduct( fwd1, fwd2 );

		// Must be reasonably facing the way the gun points ( 90 degrees or so ), otherwise we don't allow to use it.
		if ( dot < 0.0f )
		{
			return;
		}
	}

	// don't allow using it again for half a second
	if ( self->delay + 500 < level.time )
	{
		int	oldWeapon = activator->s.weapon;

		if ( oldWeapon == WP_SABER )
		{
			self->alt_fire = activator->client->ps.SaberActive();
		}

		// swap the users weapon with the emplaced gun and add the ammo the gun has to the player
		activator->client->ps.weapon = self->s.weapon;
		Add_Ammo( activator, WP_EMPLACED_GUN, self->count );
		activator->client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_EMPLACED_GUN );

		// Allow us to point from one to the other
		activator->owner = self; // kind of dumb, but when we are locked to the weapon, we are owned by it.
		self->activator = activator;

		G_RemoveWeaponModels( activator );

extern void ChangeWeapon( gentity_t *ent, int newWeapon );
		if ( activator->NPC )
		{
			ChangeWeapon( activator, WP_EMPLACED_GUN );
		}
		else if ( activator->s.number == 0 )
		{
			// we don't want for it to draw the weapon select stuff
			cg.weaponSelect = WP_EMPLACED_GUN;
			CG_CenterPrint( "@SP_INGAME_EXIT_VIEW", SCREEN_HEIGHT * 0.95 );
		}
		// Since we move the activator inside of the gun, we reserve a solid spot where they were standing in order to be able to get back out without being in solid
		if ( self->nextTrain )
		{//you never know
			G_FreeEntity( self->nextTrain );
		}
		self->nextTrain = G_Spawn();
		//self->nextTrain->classname = "emp_placeholder";
		self->nextTrain->contents = CONTENTS_MONSTERCLIP|CONTENTS_PLAYERCLIP;//hmm... playerclip too now that we're doing it for NPCs?
		G_SetOrigin( self->nextTrain, activator->client->ps.origin );
		VectorCopy( activator->mins, self->nextTrain->mins );
		VectorCopy( activator->maxs, self->nextTrain->maxs );
		gi.linkentity( self->nextTrain );

		//need to inflate the activator's mins/maxs since the gunsit anim puts them outside of their bbox
		VectorSet( activator->mins, -24, -24, -24 );
		VectorSet( activator->maxs, 24, 24, 40 );

		// Move the activator into the center of the gun.  For NPC's the only way the can get out of the gun is to die.
		VectorCopy( self->s.origin, activator->client->ps.origin );
		activator->client->ps.origin[2] += 30; // move them up so they aren't standing in the floor
		gi.linkentity( activator );

		// the gun will track which weapon we used to have
		self->s.weapon = oldWeapon;

		// Lock the player
		activator->client->ps.eFlags |= EF_LOCKED_TO_WEAPON;
		activator->owner = self; // kind of dumb, but when we are locked to the weapon, we are owned by it.
		self->activator = activator;
		self->delay = level.time; // can't disconnect from the thing for half a second

		// Let the gun be considered an enemy
		//Ugh, so much AI code seems to assume enemies are clients, maybe this shouldn't be on, but it's too late in the game to change it now without knowing what side-effects this will have
		self->svFlags |= SVF_NONNPC_ENEMY;
		self->noDamageTeam = activator->client->playerTeam;

		// FIXME: don't do this, we'll try and actually put the player in this beast
		// move the player to the center of the gun
//		activator->contents = 0;
//		VectorCopy( self->currentOrigin, activator->client->ps.origin );

		SetClientViewAngle( activator, self->pos1 );

		//FIXME: should really wait a bit after spawn and get this just once?
		self->waypoint = NAV::GetNearestNode(self);
#ifdef _DEBUG
		if ( self->waypoint == -1 )
		{
			gi.Printf( S_COLOR_RED"ERROR: no waypoint for emplaced_gun %s at %s\n", self->targetname, vtos(self->currentOrigin) );
		}
#endif

		G_Sound( self, G_SoundIndex( "sound/weapons/emplaced/emplaced_mount.mp3" ));

		if ( !(self->spawnflags&EMPLACED_PLAYERUSE) || activator->s.number == 0 )
		{//player-only usescript or any usescript
			// Run use script
			G_ActivateBehavior( self, BSET_USE );
		}
	}
}
Exemple #4
0
qboolean eweb_can_be_used( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	if ( self->health <= 0 )
	{
		// can't use a dead gun.
		return qfalse;
	}

	if ( self->svFlags & SVF_INACTIVE )
	{
		return qfalse; // can't use inactive gun
	}

	if ( !activator->client )
	{
		return qfalse; // only a client can use it.
	}

	if ( self->activator )
	{
		// someone is already in the gun.
		return qfalse;
	}

	if ( other && other->client && G_IsRidingVehicle( other ) )
	{//can't use eweb when on a vehicle
		return qfalse;
	}

	if ( activator && activator->client && G_IsRidingVehicle( activator ) )
	{//can't use eweb when on a vehicle
		return qfalse;
	}

	if ( activator && activator->client && (activator->client->ps.pm_flags&PMF_DUCKED) )
	{//stand up, ya cowardly varmint!
		return qfalse;
	}

	if ( activator && activator->health <= 0 )
	{//dead men ain't got no more use fer guns...
		return qfalse;
	}

	vec3_t fwd1, fwd2;
	vec3_t	facingAngles;

	VectorAdd( self->s.angles, self->pos1, facingAngles );
	if ( activator->s.number < MAX_CLIENTS )
	{//player must be facing general direction of the turret head
		// Let's get some direction vectors for the users
		AngleVectors( activator->client->ps.viewangles, fwd1, NULL, NULL );
		fwd1[2] = 0;

		// Get the gun's direction vector
		AngleVectors( facingAngles, fwd2, NULL, NULL );
		fwd2[2] = 0;

		float dot = DotProduct( fwd1, fwd2 );

		// Must be reasonably facing the way the gun points ( 90 degrees or so ), otherwise we don't allow to use it.
		if ( dot < 0.75f )
		{
			return qfalse;
		}
	}

	if ( self->delay + 500 < level.time )
	{
		return qtrue;
	}
	return qfalse;
}
Exemple #5
0
qboolean NPC_UpdateAngles ( qboolean doPitch, qboolean doYaw ) 
{
#if 1

	float		error;
	float		decay;
	float		targetPitch = 0;
	float		targetYaw = 0;
	float		yawSpeed;
	qboolean	exact = qtrue;

	// if angle changes are locked; just keep the current angles
	// aimTime isn't even set anymore... so this code was never reached, but I need a way to lock NPC's yaw, so instead of making a new SCF_ flag, just use the existing render flag... - dmv
	if ( !NPC->enemy && ( (level.time < NPCInfo->aimTime) || NPC->client->renderInfo.renderFlags & RF_LOCKEDANGLE) ) 
	{
		if(doPitch)
			targetPitch = NPCInfo->lockedDesiredPitch;

		if(doYaw)
			targetYaw = NPCInfo->lockedDesiredYaw;
	}
	else 
	{
		// we're changing the lockedDesired Pitch/Yaw below so it's lost it's original meaning, get rid of the lock flag
		NPC->client->renderInfo.renderFlags &= ~RF_LOCKEDANGLE;

		if(doPitch)
		{
			targetPitch = NPCInfo->desiredPitch;
			NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
		}

		if(doYaw)
		{
			targetYaw = NPCInfo->desiredYaw;
			NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
		}			
	}

	if ( NPC->s.weapon == WP_EMPLACED_GUN )
	{
		// FIXME: this seems to do nothing, actually...
		yawSpeed = 20;
	}
	else
	{
		if ( NPC->client->NPC_class == CLASS_ROCKETTROOPER 
			&& !NPC->enemy )
		{//just slowly lookin' around
			yawSpeed = 1;
		}
		else
		{
			yawSpeed = NPCInfo->stats.yawSpeed;
		}
	}

	if ( NPC->s.weapon == WP_SABER && NPC->client->ps.forcePowersActive&(1<<FP_SPEED) )
	{
		yawSpeed *= 1.0f/g_timescale->value;
	}

	if (!NPC_IsTrooper(NPC) 
		&& NPC->enemy
		&& !G_IsRidingVehicle( NPC ) 
		&& NPC->client->NPC_class != CLASS_VEHICLE )
	{
		if (NPC->s.weapon==WP_BLASTER_PISTOL || 
			NPC->s.weapon==WP_BLASTER || 
			NPC->s.weapon==WP_BOWCASTER ||
			NPC->s.weapon==WP_REPEATER ||
			NPC->s.weapon==WP_FLECHETTE ||
			NPC->s.weapon==WP_BRYAR_PISTOL ||
			NPC->s.weapon==WP_NOGHRI_STICK)
		{
			yawSpeed *= 10.0f;
		}
	}
	
	if( doYaw )
	{
		// decay yaw error
		error = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
		if( fabs(error) > MIN_ANGLE_ERROR )
		{
			if ( error ) 
			{
				exact = qfalse;

				decay = 60.0 + yawSpeed * 3;
				decay *= 50.0f / 1000.0f;//msec

				if ( error < 0.0 ) 
				{
					error += decay;
					if ( error > 0.0 ) 
					{
						error = 0.0;
					}
				}
				else 
				{
					error -= decay;
					if ( error < 0.0 ) 
					{
						error = 0.0;
					}
				}
			}
		}
		
		ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + error ) - client->ps.delta_angles[YAW];
	}

	//FIXME: have a pitchSpeed?
	if( doPitch )
	{
		// decay pitch error
		error = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
		if ( fabs(error) > MIN_ANGLE_ERROR )
		{
			if ( error ) 
			{
				exact = qfalse;

				decay = 60.0 + yawSpeed * 3;
				decay *= 50.0f / 1000.0f;//msec

				if ( error < 0.0 ) 
				{
					error += decay;
					if ( error > 0.0 ) 
					{
						error = 0.0;
					}
				}
				else 
				{
					error -= decay;
					if ( error < 0.0 ) 
					{
						error = 0.0;
					}
				}
			}
		}

		ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + error ) - client->ps.delta_angles[PITCH];
	}

	ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];

	if ( exact && Q3_TaskIDPending( NPC, TID_ANGLE_FACE ) )
	{
		Q3_TaskIDComplete( NPC, TID_ANGLE_FACE );
	}
	return exact;

#else

	float		error;
	float		decay;
	float		targetPitch = 0;
	float		targetYaw = 0;
	float		yawSpeed;
	//float		runningMod = NPCInfo->currentSpeed/100.0f;
	qboolean	exact = qtrue;
	qboolean	doSound = qfalse;

	// if angle changes are locked; just keep the current angles
	if ( level.time < NPCInfo->aimTime ) 
	{
		if(doPitch)
			targetPitch = NPCInfo->lockedDesiredPitch;
		if(doYaw)
			targetYaw = NPCInfo->lockedDesiredYaw;
	}
	else 
	{
		if(doPitch)
			targetPitch = NPCInfo->desiredPitch;
		if(doYaw)
			targetYaw = NPCInfo->desiredYaw;

//		NPCInfo->aimTime = level.time + 250;
		if(doPitch)
			NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
		if(doYaw)
			NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
	}

	yawSpeed = NPCInfo->stats.yawSpeed;

	if(doYaw)
	{
		// decay yaw error
		error = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
		if( fabs(error) > MIN_ANGLE_ERROR )
		{
			/*
			if(NPC->client->playerTeam == TEAM_BORG&&
				NPCInfo->behaviorState != BS_FACE&&NPCInfo->tempBehavior!= BS_FACE)
			{//HACK - borg turn more jittery
				if ( error ) 
				{
					exact = qfalse;

					decay = 60.0 + yawSpeed * 3;
					decay *= 50.0 / 1000.0;//msec
					//Snap to
					if(fabs(error) > 10)
					{
						if(random() > 0.6)
						{
							doSound = qtrue;
						}
					}

					if ( error < 0.0)//-10.0 ) 
					{
						error += decay;
						if ( error > 0.0 ) 
						{
							error = 0.0;
						}
					}
					else if ( error > 0.0)//10.0 ) 
					{
						error -= decay;
						if ( error < 0.0 ) 
						{
							error = 0.0;
						}
					}
				}
			}
			else*/
			
			if ( error ) 
			{
				exact = qfalse;

				decay = 60.0 + yawSpeed * 3;
				decay *= 50.0 / 1000.0;//msec

				if ( error < 0.0 ) 
				{
					error += decay;
					if ( error > 0.0 ) 
					{
						error = 0.0;
					}
				}
				else 
				{
					error -= decay;
					if ( error < 0.0 ) 
					{
						error = 0.0;
					}
				}
			}
		}
		ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + error ) - client->ps.delta_angles[YAW];
	}

	//FIXME: have a pitchSpeed?
	if(doPitch)
	{
		// decay pitch error
		error = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
		if ( fabs(error) > MIN_ANGLE_ERROR )
		{
			/*
			if(NPC->client->playerTeam == TEAM_BORG&&
				NPCInfo->behaviorState != BS_FACE&&NPCInfo->tempBehavior!= BS_FACE)
			{//HACK - borg turn more jittery
				if ( error ) 
				{
					exact = qfalse;

					decay = 60.0 + yawSpeed * 3;
					decay *= 50.0 / 1000.0;//msec
					//Snap to
					if(fabs(error) > 10)
					{
						if(random() > 0.6)
						{
							doSound = qtrue;
						}
					}

					if ( error < 0.0)//-10.0 ) 
					{
						error += decay;
						if ( error > 0.0 ) 
						{
							error = 0.0;
						}
					}
					else if ( error > 0.0)//10.0 ) 
					{
						error -= decay;
						if ( error < 0.0 ) 
						{
							error = 0.0;
						}
					}
				}
			}
			else*/
			
			if ( error ) 
			{
				exact = qfalse;

				decay = 60.0 + yawSpeed * 3;
				decay *= 50.0 / 1000.0;//msec

				if ( error < 0.0 ) 
				{
					error += decay;
					if ( error > 0.0 ) 
					{
						error = 0.0;
					}
				}
				else 
				{
					error -= decay;
					if ( error < 0.0 ) 
					{
						error = 0.0;
					}
				}
			}
		}
		ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + error ) - client->ps.delta_angles[PITCH];
	}

	ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];

	/*
	if(doSound)
	{
		G_Sound(NPC, G_SoundIndex(va("sound/enemies/borg/borgservo%d.wav", Q_irand(1, 8))));
	}
	*/

	return exact;

#endif

}
Exemple #6
0
//---------------------------------------------------------
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 );
	}
}