Example #1
0
/*
===============
UI_PlayerAngles
===============
*/
static void UI_PlayerAngles( playerInfo_t *pi, vec3_t legs[3], vec3_t torso[3], vec3_t head[3] ) {
	vec3_t		legsAngles, torsoAngles, headAngles;
	float		dest;
	float		adjust;

	VectorCopy( pi->viewAngles, headAngles );
	headAngles[YAW] = AngleMod( headAngles[YAW] );
	VectorClear( legsAngles );
	VectorClear( torsoAngles );

	// --------- yaw -------------

	// allow yaw to drift a bit
	if ( ( pi->legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE 
		|| ( pi->torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND  ) {
		// if not standing still, always point all in the same direction
		pi->torso.yawing = qtrue;	// always center
		pi->torso.pitching = qtrue;	// always center
		pi->legs.yawing = qtrue;	// always center
	}

	// adjust legs for movement dir
	adjust = UI_MovedirAdjustment( pi );
	legsAngles[YAW] = headAngles[YAW] + adjust;
	torsoAngles[YAW] = headAngles[YAW] + 0.25 * adjust;


	// torso
	UI_SwingAngles( torsoAngles[YAW], 25, 90, SWINGSPEED, &pi->torso.yawAngle, &pi->torso.yawing );
	UI_SwingAngles( legsAngles[YAW], 40, 90, SWINGSPEED, &pi->legs.yawAngle, &pi->legs.yawing );

	torsoAngles[YAW] = pi->torso.yawAngle;
	legsAngles[YAW] = pi->legs.yawAngle;

	// --------- pitch -------------

	// only show a fraction of the pitch angle in the torso
	if ( headAngles[PITCH] > 180 ) {
		dest = (-360 + headAngles[PITCH]) * 0.75;
	} else {
		dest = headAngles[PITCH] * 0.75;
	}
	UI_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching );
	torsoAngles[PITCH] = pi->torso.pitchAngle;

	// pull the angles back out of the hierarchial chain
	AnglesSubtract( headAngles, torsoAngles, headAngles );
	AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
	AnglesToAxis( legsAngles, legs );
	AnglesToAxis( torsoAngles, torso );
	AnglesToAxis( headAngles, head );
}
Example #2
0
//-----------------------------------------------------
qboolean VEH_TurretAim( Vehicle_t *pVeh, 
						 gentity_t *parent, 
						 gentity_t *turretEnemy,
						 turretStats_t *turretStats, 
						 vehWeaponInfo_t *vehWeapon, 
						 int turretNum, int curMuzzle, vec3_t desiredAngles )
//-----------------------------------------------------
{
	vec3_t	curAngles, addAngles, newAngles, yawAngles, pitchAngles;
	float	aimCorrect = qfalse;

	WP_CalcVehMuzzle( parent, curMuzzle );
	//get the current absolute angles of the turret right now
	vectoangles( pVeh->m_vMuzzleDir[curMuzzle], curAngles );
	//subtract out the vehicle's angles to get the relative alignment
	AnglesSubtract( curAngles, pVeh->m_vOrientation, curAngles );

	if ( turretEnemy )
	{
		aimCorrect = qtrue;
		// ...then we'll calculate what new aim adjustments we should attempt to make this frame
		// Aim at enemy
		VEH_TurretAnglesToEnemy( pVeh, curMuzzle, vehWeapon->fSpeed, turretEnemy, turretStats->bAILead, desiredAngles ); 
	}
	//subtract out the vehicle's angles to get the relative desired alignment
	AnglesSubtract( desiredAngles, pVeh->m_vOrientation, desiredAngles );
	//Now clamp the desired relative angles
	//clamp yaw
	desiredAngles[YAW] = AngleNormalize180( desiredAngles[YAW] );
	if ( pVeh->m_pVehicleInfo->turret[turretNum].yawClampLeft
		&& desiredAngles[YAW] > pVeh->m_pVehicleInfo->turret[turretNum].yawClampLeft )
	{
		aimCorrect = qfalse;
		desiredAngles[YAW] = pVeh->m_pVehicleInfo->turret[turretNum].yawClampLeft;
	}
	if ( pVeh->m_pVehicleInfo->turret[turretNum].yawClampRight
		&& desiredAngles[YAW] < pVeh->m_pVehicleInfo->turret[turretNum].yawClampRight )
	{
		aimCorrect = qfalse;
		desiredAngles[YAW] = pVeh->m_pVehicleInfo->turret[turretNum].yawClampRight;
	}
	//clamp pitch
	desiredAngles[PITCH] = AngleNormalize180( desiredAngles[PITCH] );
	if ( pVeh->m_pVehicleInfo->turret[turretNum].pitchClampDown
		&& desiredAngles[PITCH] > pVeh->m_pVehicleInfo->turret[turretNum].pitchClampDown )
	{
		aimCorrect = qfalse;
		desiredAngles[PITCH] = pVeh->m_pVehicleInfo->turret[turretNum].pitchClampDown;
	}
	if ( pVeh->m_pVehicleInfo->turret[turretNum].pitchClampUp
		&& desiredAngles[PITCH] < pVeh->m_pVehicleInfo->turret[turretNum].pitchClampUp )
	{
		aimCorrect = qfalse;
		desiredAngles[PITCH] = pVeh->m_pVehicleInfo->turret[turretNum].pitchClampUp;
	}
	//Now get the offset we want from our current relative angles
	AnglesSubtract( desiredAngles, curAngles, addAngles );
	//Now cap the addAngles for our fTurnSpeed
	if ( addAngles[PITCH] > turretStats->fTurnSpeed )
	{
		//aimCorrect = qfalse;//???
		addAngles[PITCH] = turretStats->fTurnSpeed;
	}
	else if ( addAngles[PITCH] < -turretStats->fTurnSpeed )
	{
		//aimCorrect = qfalse;//???
		addAngles[PITCH] = -turretStats->fTurnSpeed;
	}
	if ( addAngles[YAW] > turretStats->fTurnSpeed )
	{
		//aimCorrect = qfalse;//???
		addAngles[YAW] = turretStats->fTurnSpeed;
	}
	else if ( addAngles[YAW] < -turretStats->fTurnSpeed )
	{
		//aimCorrect = qfalse;//???
		addAngles[YAW] = -turretStats->fTurnSpeed;
	}
	//Now add the additional angles back in to our current relative angles
	//FIXME: add some AI aim error randomness...?
	newAngles[PITCH] = AngleNormalize180( curAngles[PITCH]+addAngles[PITCH] );
	newAngles[YAW] = AngleNormalize180( curAngles[YAW]+addAngles[YAW] );
	//Now set the bone angles to the new angles
	//set yaw
	if ( turretStats->yawBone )
	{
		VectorClear( yawAngles );
		yawAngles[turretStats->yawAxis] = newAngles[YAW];
		NPC_SetBoneAngles( parent, turretStats->yawBone, yawAngles );
	}
	//set pitch
	if ( turretStats->pitchBone )
	{
		VectorClear( pitchAngles );
		pitchAngles[turretStats->pitchAxis] = newAngles[PITCH];
		NPC_SetBoneAngles( parent, turretStats->pitchBone, pitchAngles );
	}
	//force muzzle to recalc next check
	pVeh->m_iMuzzleTime[curMuzzle] = 0;

	return aimCorrect;
}
Example #3
0
void PM_VehicleImpact(bgEntity_t *pEnt, trace_t *trace)
{
	// See if the vehicle has crashed into the ground.
	Vehicle_t *pSelfVeh = pEnt->m_pVehicle;
	float magnitude = VectorLength( pm->ps->velocity ) * pSelfVeh->m_pVehicleInfo->mass / 50.0f;
	qboolean forceSurfDestruction = qfalse;
#ifdef QAGAME
	gentity_t *hitEnt = trace!=NULL?&g_entities[trace->entityNum]:NULL;

	if (!hitEnt || //nothing to hit
		(pSelfVeh && pSelfVeh->m_pPilot &&//I'm a piloted vehicle
		hitEnt && hitEnt->s.eType == ET_MISSILE && hitEnt->inuse &&//that hit a missile
		hitEnt->r.ownerNum == pSelfVeh->m_pPilot->s.number)//and the missile is owned by my pilot
		)
	{//don't hit it
		return;
	}

	if ( pSelfVeh//I have a vehicle struct
		&& pSelfVeh->m_iRemovedSurfaces )//vehicle has bits removed
	{//spiralling to our deaths, explode on any solid impact
		if ( hitEnt->s.NPC_class == CLASS_VEHICLE )
		{//hit another vehicle, explode!
			//Give credit to whoever got me into this death spiral state
			G_DamageFromKiller( (gentity_t *)pEnt, (gentity_t *)pSelfVeh->m_pParentEntity, (gentity_t *)hitEnt, pm->ps->origin, 999999, DAMAGE_NO_ARMOR, MOD_COLLISION );
			return;
		}
		else if ( !VectorCompare( trace->plane.normal, vec3_origin )
			&& (trace->entityNum == ENTITYNUM_WORLD || hitEnt->r.bmodel ) )
		{//have a valid hit plane and we hit a solid brush
			vec3_t	moveDir;
			float	impactDot;
			VectorCopy( pm->ps->velocity, moveDir );
			VectorNormalize( moveDir );
			impactDot = DotProduct( moveDir, trace->plane.normal );
			if ( impactDot <= -0.7f )//hit rather head-on and hard
			{// Just DIE now
				//Give credit to whoever got me into this death spiral state
				G_DamageFromKiller( (gentity_t *)pEnt, (gentity_t *)pSelfVeh->m_pParentEntity, (gentity_t *)hitEnt, pm->ps->origin, 999999, DAMAGE_NO_ARMOR, MOD_FALLING );
				return;
			}
		}
	}
	
	if ( trace->entityNum < ENTITYNUM_WORLD
		&& hitEnt->s.eType == ET_MOVER
		&& hitEnt->s.apos.trType != TR_STATIONARY//rotating
		&& (hitEnt->spawnflags&16) //IMPACT
		&& Q_stricmp( "func_rotating", hitEnt->classname ) == 0 )
	{//hit a func_rotating that is supposed to destroy anything it touches!
		//guarantee the hit will happen, thereby taking off a piece of the ship
		forceSurfDestruction = qtrue;
	}
	else if ( (fabs(pm->ps->velocity[0])+fabs(pm->ps->velocity[1])) < 100.0f
		&& pm->ps->velocity[2] > -100.0f )
#else
	if ( (fabs(pm->ps->velocity[0])+fabs(pm->ps->velocity[1])) < 100.0f
		&& pm->ps->velocity[2] > -100.0f )
#endif
		/*
	if ( (pSelfVeh->m_ulFlags&VEH_GEARSOPEN) 
		&& trace->plane.normal[2] > 0.7f
		&& fabs(pSelfVeh->m_vOrientation[PITCH]) < 0.2f
		&& fabs(pSelfVeh->m_vOrientation[ROLL]) < 0.2f )*/
	{//we're landing, we're cool
		//FIXME: some sort of landing "thump", not the impactFX
		/*
		if ( pSelfVeh->m_pVehicleInfo->iImpactFX )
		{
			vec3_t up = {0,0,1};
#ifdef QAGAME
			G_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, up );
#else
			trap_FX_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, up, -1, -1 );
#endif
		}
		*/
		//this was annoying me -rww
		//FIXME: this shouldn't even be getting called when the vehicle is at rest!
#ifdef QAGAME
		if (hitEnt && (hitEnt->s.eType == ET_PLAYER || hitEnt->s.eType == ET_NPC) && pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
		{ //always smack players
		}
		else
#endif
		{
			return;
		}
	}
	if ( pSelfVeh &&
		(pSelfVeh->m_pVehicleInfo->type == VH_SPEEDER || pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) && //this is kind of weird on tauntauns and atst's..
		(magnitude >= 100||forceSurfDestruction) )
	{
		if ( pEnt->m_pVehicle->m_iHitDebounce < pm->cmd.serverTime 
			|| forceSurfDestruction )
		{//a bit of a hack, may conflict with getting shot, but...
			//FIXME: impact sound and effect should be gotten from g_vehicleInfo...?
			//FIXME: should pass in trace.endpos and trace.plane.normal
			vec3_t	vehUp;
#ifdef QAGAME
			qboolean noDamage = qfalse;
#else
			bgEntity_t *hitEnt;
#endif

			if ( trace && !pSelfVeh->m_iRemovedSurfaces && !forceSurfDestruction )
			{
				qboolean turnFromImpact = qfalse, turnHitEnt = qfalse;
				float l = pm->ps->speed*0.5f;
				vec3_t	bounceDir;
#ifndef QAGAME
				bgEntity_t *hitEnt = PM_BGEntForNum(trace->entityNum);
#endif
				if ( (trace->entityNum == ENTITYNUM_WORLD || hitEnt->s.solid == SOLID_BMODEL)//bounce off any brush
					 && !VectorCompare(trace->plane.normal, vec3_origin) )//have a valid plane to bounce off of
				{ //bounce off in the opposite direction of the impact
					if (pSelfVeh->m_pVehicleInfo->type == VH_SPEEDER)
					{
						pm->ps->speed *= pml.frametime;
						VectorCopy(trace->plane.normal, bounceDir);
					}
					else if ( trace->plane.normal[2] >= MIN_LANDING_SLOPE//flat enough to land on
						&& pSelfVeh->m_LandTrace.fraction < 1.0f //ground present
						&& pm->ps->speed <= MIN_LANDING_SPEED )
					{//could land here, don't bounce off, in fact, return altogether!
						return;
					}
					else
					{
						if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
						{
							turnFromImpact = qtrue;
						}
						VectorCopy(trace->plane.normal, bounceDir);
					}
				}
				else if ( pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER )
				{//check for impact with another fighter
#ifndef QAGAME
					bgEntity_t *hitEnt = PM_BGEntForNum(trace->entityNum);
#endif
					if ( hitEnt->s.NPC_class == CLASS_VEHICLE
						&& hitEnt->m_pVehicle 
						&& hitEnt->m_pVehicle->m_pVehicleInfo
						&& hitEnt->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
					{//two vehicles hit each other, turn away from the impact
						turnFromImpact = qtrue;
						turnHitEnt = qtrue;
#ifndef QAGAME
						VectorSubtract( pm->ps->origin, hitEnt->s.origin, bounceDir );
#else
						VectorSubtract( pm->ps->origin, hitEnt->r.currentOrigin, bounceDir );
#endif
						VectorNormalize( bounceDir );
					}
				}
				if ( turnFromImpact )
				{//bounce off impact surf and turn away
					vec3_t	pushDir={0}, turnAwayAngles, turnDelta;
					float	turnStrength, pitchTurnStrength, yawTurnStrength;
					vec3_t	moveDir;
					float bounceDot, turnDivider;
					//bounce
					if ( !turnHitEnt )
					{//hit wall
						VectorScale(bounceDir, (pm->ps->speed*0.25f/pSelfVeh->m_pVehicleInfo->mass), pushDir);
					}
					else
					{//hit another fighter
#ifndef QAGAME
						VectorScale( bounceDir, (pm->ps->speed+hitEnt->s.speed)*0.5f, bounceDir );
#else
						if ( hitEnt->client )
						{
							VectorScale( bounceDir, (pm->ps->speed+hitEnt->client->ps.speed)*0.5f, pushDir );
						}
						else
						{
							VectorScale( bounceDir, (pm->ps->speed+hitEnt->s.speed)*0.5f, pushDir );
						}
#endif
						VectorScale(pushDir, (l/pSelfVeh->m_pVehicleInfo->mass), pushDir);
						VectorScale(pushDir, 0.1f, pushDir);
					}
					VectorNormalize2( pm->ps->velocity, moveDir );
					bounceDot = DotProduct( moveDir, bounceDir )*-1;
					if ( bounceDot < 0.1f )
					{
						bounceDot = 0.1f;
					}
					VectorScale( pushDir, bounceDot, pushDir );
					VectorAdd(pm->ps->velocity, pushDir, pm->ps->velocity);
					//turn
					turnDivider = (pSelfVeh->m_pVehicleInfo->mass/400.0f);
					if ( turnHitEnt )
					{//don't turn as much when hit another ship
						turnDivider *= 4.0f;
					}
					if ( turnDivider < 0.5f )
					{
						turnDivider = 0.5f;
					}
					turnStrength = (magnitude/2000.0f);
					if ( turnStrength < 0.1f )
					{
						turnStrength = 0.1f;
					}
					else if ( turnStrength > 2.0f )
					{
						turnStrength = 2.0f;
					}
					//get the angles we are going to turn towards
					vectoangles( bounceDir, turnAwayAngles );
					//get the delta from our current angles to those new angles
					AnglesSubtract( turnAwayAngles, pSelfVeh->m_vOrientation, turnDelta );
					//now do pitch
					if ( !bounceDir[2] )
					{//shouldn't be any pitch
					}
					else
					{
						pitchTurnStrength = turnStrength*turnDelta[PITCH];
						if ( pitchTurnStrength > MAX_IMPACT_TURN_ANGLE )
						{
							pitchTurnStrength = MAX_IMPACT_TURN_ANGLE;
						}
						else if ( pitchTurnStrength < -MAX_IMPACT_TURN_ANGLE )
						{
							pitchTurnStrength = -MAX_IMPACT_TURN_ANGLE;
						}
						//pSelfVeh->m_vOrientation[PITCH] = AngleNormalize180(pSelfVeh->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
						pSelfVeh->m_vFullAngleVelocity[PITCH] = AngleNormalize180(pSelfVeh->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
					}
					//now do yaw
					if ( !bounceDir[0] 
						&& !bounceDir[1] )
					{//shouldn't be any yaw
					}
					else
					{
						yawTurnStrength = turnStrength*turnDelta[YAW];
						if ( yawTurnStrength > MAX_IMPACT_TURN_ANGLE )
						{
							yawTurnStrength = MAX_IMPACT_TURN_ANGLE;
						}
						else if ( yawTurnStrength < -MAX_IMPACT_TURN_ANGLE )
						{
							yawTurnStrength = -MAX_IMPACT_TURN_ANGLE;
						}
						//pSelfVeh->m_vOrientation[ROLL] = AngleNormalize180(pSelfVeh->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
						pSelfVeh->m_vFullAngleVelocity[ROLL] = AngleNormalize180(pSelfVeh->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
					}
					/*
					PM_SetPMViewAngle(pm->ps, pSelfVeh->m_vOrientation, &pSelfVeh->m_ucmd);
					if ( pm_entVeh )
					{//I'm a vehicle, so pm_entVeh is actually my pilot
						bgEntity_t *pilot = pm_entVeh;
						if ( !BG_UnrestrainedPitchRoll( pilot->playerState, pSelfVeh ) )
						{
							//set the rider's viewangles to the vehicle's viewangles
							PM_SetPMViewAngle(pilot->playerState, pSelfVeh->m_vOrientation, &pSelfVeh->m_ucmd);
						}
					}
					*/
#ifdef QAGAME//server-side, turn the guy we hit away from us, too
					if ( turnHitEnt//make the other guy turn and get pushed
						&& hitEnt->client //must be a valid client
						&& !FighterIsLanded( hitEnt->m_pVehicle, &hitEnt->client->ps )//but not if landed
						&& !(hitEnt->spawnflags&2) )//and not if suspended
					{
						l = hitEnt->client->ps.speed;
						//now bounce *them* away and turn them
						//flip the bounceDir
						VectorScale( bounceDir, -1, bounceDir );
						//do bounce
						VectorScale( bounceDir, (pm->ps->speed+l)*0.5f, pushDir );
						VectorScale(pushDir, (l*0.5f/hitEnt->m_pVehicle->m_pVehicleInfo->mass), pushDir);
						VectorNormalize2( hitEnt->client->ps.velocity, moveDir );
						bounceDot = DotProduct( moveDir, bounceDir )*-1;
						if ( bounceDot < 0.1f )
						{
							bounceDot = 0.1f;
						}
						VectorScale( pushDir, bounceDot, pushDir );
						VectorAdd(hitEnt->client->ps.velocity, pushDir, hitEnt->client->ps.velocity);
						//turn
						turnDivider = (hitEnt->m_pVehicle->m_pVehicleInfo->mass/400.0f);
						if ( turnHitEnt )
						{//don't turn as much when hit another ship
							turnDivider *= 4.0f;
						}
						if ( turnDivider < 0.5f )
						{
							turnDivider = 0.5f;
						}
						//get the angles we are going to turn towards
						vectoangles( bounceDir, turnAwayAngles );
						//get the delta from our current angles to those new angles
						AnglesSubtract( turnAwayAngles, hitEnt->m_pVehicle->m_vOrientation, turnDelta );
						//now do pitch
						if ( !bounceDir[2] )
						{//shouldn't be any pitch
						}
						else
						{
							pitchTurnStrength = turnStrength*turnDelta[PITCH];
							if ( pitchTurnStrength > MAX_IMPACT_TURN_ANGLE )
							{
								pitchTurnStrength = MAX_IMPACT_TURN_ANGLE;
							}
							else if ( pitchTurnStrength < -MAX_IMPACT_TURN_ANGLE )
							{
								pitchTurnStrength = -MAX_IMPACT_TURN_ANGLE;
							}
							//hitEnt->m_pVehicle->m_vOrientation[PITCH] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
							hitEnt->m_pVehicle->m_vFullAngleVelocity[PITCH] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
						}
						//now do yaw
						if ( !bounceDir[0] 
							&& !bounceDir[1] )
						{//shouldn't be any yaw
						}
						else
						{
							yawTurnStrength = turnStrength*turnDelta[YAW];
							if ( yawTurnStrength > MAX_IMPACT_TURN_ANGLE )
							{
								yawTurnStrength = MAX_IMPACT_TURN_ANGLE;
							}
							else if ( yawTurnStrength < -MAX_IMPACT_TURN_ANGLE )
							{
								yawTurnStrength = -MAX_IMPACT_TURN_ANGLE;
							}
							//hitEnt->m_pVehicle->m_vOrientation[ROLL] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
							hitEnt->m_pVehicle->m_vFullAngleVelocity[ROLL] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier);
						}
						//NOTE: will these angle changes stick or will they be stomped 
						//		when the vehicle goes through its own update and re-grabs 
						//		its angles from its pilot...?  Should we do a 
						//		SetClientViewAngles on the pilot?
						/*
						SetClientViewAngle( hitEnt, hitEnt->m_pVehicle->m_vOrientation );
						if ( hitEnt->m_pVehicle->m_pPilot 
							&& ((gentity_t *)hitEnt->m_pVehicle->m_pPilot)->client )
						{
							SetClientViewAngle( (gentity_t *)hitEnt->m_pVehicle->m_pPilot, hitEnt->m_pVehicle->m_vOrientation );
						}
						*/
					}
#endif
				}
			}

#ifdef QAGAME
			if (!hitEnt)
			{
				return;
			}

			AngleVectors( pSelfVeh->m_vOrientation, NULL, NULL, vehUp );
			if ( pSelfVeh->m_pVehicleInfo->iImpactFX )
			{
				//G_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, vehUp );
				//tempent use bad!
				G_AddEvent((gentity_t *)pEnt, EV_PLAY_EFFECT_ID, pSelfVeh->m_pVehicleInfo->iImpactFX);
			}
			pEnt->m_pVehicle->m_iHitDebounce = pm->cmd.serverTime + 200;
			magnitude /= pSelfVeh->m_pVehicleInfo->toughness * 50.0f; 

			if (hitEnt 
				&& (hitEnt->s.eType != ET_TERRAIN || !(hitEnt->spawnflags & 1) || pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER))
			{ //don't damage the vehicle from terrain that doesn't want to damage vehicles
				gentity_t *killer = NULL;
				if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
				{ //increase the damage...
					float mult = (pSelfVeh->m_vOrientation[PITCH]*0.1f);
					if (mult < 1.0f)
					{
						mult = 1.0f;
					}
					if (hitEnt->inuse && hitEnt->takedamage)
					{ //if the other guy takes damage, don't hurt us a lot for ramming him
						//unless it's a vehicle, then we get 1.5 times damage
						if (hitEnt->s.eType == ET_NPC &&
							hitEnt->s.NPC_class == CLASS_VEHICLE &&
							hitEnt->m_pVehicle)
						{
							mult = 1.5f;
						}
						else
						{
							mult = 0.5f;
						}
					}

					magnitude *= mult;
				}
				pSelfVeh->m_iLastImpactDmg = magnitude;
				//FIXME: what about proper death credit to the guy who shot you down?
				//FIXME: actually damage part of the ship that impacted?
				if ( hitEnt->s.eType == ET_MISSILE )//missile
				{
					//FIX: NEVER do or take impact damage from a missile...
					noDamage = qtrue;
					if ( (hitEnt->s.eFlags&EF_JETPACK_ACTIVE)//vehicle missile
						&& ((gentity_t *)hitEnt)->r.ownerNum < MAX_CLIENTS )//valid client owner
					{//I ran into a missile and died because of the impact, give credit to the missile's owner (PROBLEM: might this ever accidently give improper credit to client 0?)
						/*
						if ( ((gentity_t *)hitEnt)->r.ownerNum == pEnt->s.number )
						{//hit our own missile?  Don't damage ourselves or it... (so we don't kill ourselves!) if it hits *us*, then fine, but not here
							noDamage = qtrue;
						}
						*/
						killer = &g_entities[((gentity_t *)hitEnt)->r.ownerNum];
					}
				}
				if ( !noDamage )
				{
					G_Damage( (gentity_t *)pEnt, ((gentity_t*)hitEnt), killer!=NULL?killer:((gentity_t *)hitEnt), NULL, pm->ps->origin, magnitude*5, DAMAGE_NO_ARMOR, (hitEnt->s.NPC_class==CLASS_VEHICLE?MOD_COLLISION:MOD_FALLING) );//FIXME: MOD_IMPACT
				}

				if (pSelfVeh->m_pVehicleInfo->surfDestruction)
				{
					G_FlyVehicleSurfaceDestruction((gentity_t *)pEnt, trace, magnitude, forceSurfDestruction );
				}

				pSelfVeh->m_ulFlags |= VEH_CRASHING;
			}

			if (hitEnt &&
				hitEnt->inuse &&
				hitEnt->takedamage)
			{ //damage this guy because we hit him
				float pmult = 1.0f;
				int finalD;
				gentity_t *attackEnt;

				if ( (hitEnt->s.eType == ET_PLAYER && hitEnt->s.number < MAX_CLIENTS) ||
					 (hitEnt->s.eType == ET_NPC && hitEnt->s.NPC_class != CLASS_VEHICLE) )
				{ //probably a humanoid, or something
					if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)
					{ //player die good.. if me fighter
						pmult = 2000.0f;
					}
					else
					{
						pmult = 40.0f;
					}

					if (hitEnt->client &&
						BG_KnockDownable(&hitEnt->client->ps) &&
						G_CanBeEnemy((gentity_t *)pEnt, hitEnt))
					{ //smash!
						if (hitEnt->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN)
						{
							hitEnt->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
							hitEnt->client->ps.forceHandExtendTime = pm->cmd.serverTime + 1100;
							hitEnt->client->ps.forceDodgeAnim = 0; //this toggles between 1 and 0, when it's 1 we should play the get up anim
						}

						hitEnt->client->ps.otherKiller = pEnt->s.number;
						hitEnt->client->ps.otherKillerTime = pm->cmd.serverTime + 5000;
						hitEnt->client->ps.otherKillerDebounceTime = pm->cmd.serverTime + 100;
						hitEnt->client->otherKillerMOD = MOD_COLLISION;
						hitEnt->client->otherKillerVehWeapon = 0;
						hitEnt->client->otherKillerWeaponType = WP_NONE;

						//add my velocity into his to force him along in the correct direction from impact
						VectorAdd(hitEnt->client->ps.velocity, pm->ps->velocity, hitEnt->client->ps.velocity);
						//upward thrust
						hitEnt->client->ps.velocity[2] += 200.0f;
					}
				}

				if (pSelfVeh->m_pPilot)
				{
					attackEnt = (gentity_t *)pSelfVeh->m_pPilot;
				}
				else
				{
					attackEnt = (gentity_t *)pEnt;
				}

				finalD = magnitude*pmult;
				if (finalD < 1)
				{
					finalD = 1;
				}
				if ( !noDamage )
				{
					G_Damage( hitEnt, attackEnt, attackEnt, NULL, pm->ps->origin, finalD, 0, (hitEnt->s.NPC_class==CLASS_VEHICLE?MOD_COLLISION:MOD_FALLING/*MOD_MELEE*/) );//FIXME: MOD_IMPACT
				}
			}
#else	//this is gonna result in "double effects" for the client doing the prediction.
		//it doesn't look bad though. could just use predicted events, but I'm too lazy.
			hitEnt = PM_BGEntForNum(trace->entityNum);

			if (!hitEnt || hitEnt->s.owner != pEnt->s.number)
			{ //don't hit your own missiles!
				AngleVectors( pSelfVeh->m_vOrientation, NULL, NULL, vehUp );
				pEnt->m_pVehicle->m_iHitDebounce = pm->cmd.serverTime + 200;
				trap_FX_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, vehUp, -1, -1 );

				pSelfVeh->m_ulFlags |= VEH_CRASHING;
			}
#endif
		}
	}
}
Example #4
0
static void CG_CalculateWeaponPosition( vector3 *origin, vector3 *angles ) {
	float	scale, fracsin;
	int		delta;
	refdef_t *refdef = CG_GetRefdef();

	VectorCopy( &refdef->vieworg, origin );
	VectorCopy( &refdef->viewangles, angles );

	// on odd legs, invert some angles
	if ( cg.bobcycle & 1 )
		scale = -cg.xyspeed;
	else
		scale = cg.xyspeed;

	// gun angles from bobbing
	if ( cg_gunBobEnable.integer ) {
		angles->pitch += cg.xyspeed	* cg.bobfracsin * cg.gunBob.pitch;
		angles->yaw += scale		* cg.bobfracsin * cg.gunBob.yaw;
		angles->roll += scale		* cg.bobfracsin * cg.gunBob.roll;

		// drop the weapon when landing
		delta = cg.time - cg.landTime;
		if ( delta < LAND_DEFLECT_TIME )
			origin->z += cg.landChange*0.25f * delta / LAND_DEFLECT_TIME;
		else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME )
			origin->z += cg.landChange*0.25f * (LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta) / LAND_RETURN_TIME;

#if 0
		// drop the weapon when stair climbing
		delta = cg.time - cg.stepTime;
		if ( delta < STEP_TIME/2 )
			origin->z -= cg.stepChange*0.25f * delta / (STEP_TIME/2);
		else if ( delta < STEP_TIME )
			origin->z -= cg.stepChange*0.25f * (STEP_TIME - delta) / (STEP_TIME/2);
#endif
	}

	// idle drift
	if ( cg_gunIdleDriftEnable.integer ) {
		scale = cg.xyspeed + 40;
		fracsin = sinf( cg.time * cg.gunIdleDrift.speed );
		angles->pitch += scale * fracsin * cg.gunIdleDrift.amount.pitch;
		angles->yaw += scale * fracsin * cg.gunIdleDrift.amount.yaw;
		angles->roll += scale * fracsin * cg.gunIdleDrift.amount.roll;
	}

	if ( cg_gunMomentumEnable.integer ) {
		// sway viewmodel when changing viewangles
		static vector3 previousAngles{};

		vector3 deltaAngles;
		AnglesSubtract( angles, &previousAngles, &deltaAngles );
		VectorScale( &deltaAngles, 1.0f, &deltaAngles );

		const double f = std::abs( 1.0 / (double)cg_gunMomentumDamp.value );
		const double y = (double)cg_gunMomentumInterval.value;
		const double dampRatio = 1.0 / std::pow( f, y );
		VectorMA( &previousAngles, dampRatio, &deltaAngles, angles );
		VectorCopy( angles, &previousAngles );

		// move viewmodel downwards when jumping etc
		static float previousOriginZ = 0.0f;
		const float deltaZ = origin->z - previousOriginZ;
		if ( deltaZ > 0.0f ) {
			origin->z = origin->z - deltaZ * cg_gunMomentumFall.value;
		}
		previousOriginZ = origin->z;
	}

}
bool TurretComponent::MoveHeadToTarget(int timeDelta) {
	// Note that a timeDelta of zero may happen on a first thinker execution.
	// We do not return in that case since we don't know the return value yet.
	ASSERT_GE(timeDelta, 0);

	float timeMod = (float)timeDelta / 1000.0f;

	// Compute maximum angle changes for this execution.
	Vec3 maxAngleChange;
	maxAngleChange[PITCH] = timeMod * PITCH_SPEED;
	maxAngleChange[YAW]   = timeMod * YAW_SPEED;
	maxAngleChange[ROLL]  = 0.0f;

	// Compute angles to target, relative to the turret's base.
	Vec3 relativeAnglesToTarget = DirectionToRelativeAngles(directionToTarget);

	// Compute difference between angles to target and current angles.
	Vec3 deltaAngles;
	AnglesSubtract(relativeAnglesToTarget.Data(), relativeAimAngles.Data(), deltaAngles.Data());

	// Stop if there is nothing to do.
	if (Math::Length(deltaAngles) < 0.1f) {
		return true;
	}

	bool targetReached = true;
	Vec3 oldRelativeAimAngles = relativeAimAngles;

	// Adjust aim angles towards target angles.
	for (int angle = 0; angle < 3; angle++) {
		if (angle == ROLL) continue;

		if (fabs(deltaAngles[angle]) > maxAngleChange[angle]) {
			relativeAimAngles[angle] += (deltaAngles[angle] < 0.0f)
				? -maxAngleChange[angle]
				:  maxAngleChange[angle];
			targetReached = false;
		} else {
			relativeAimAngles[angle] = relativeAnglesToTarget[angle];
		}
	}

	// Respect pitch limits.
	if (relativeAimAngles[PITCH] > PITCH_CAP) {
		relativeAimAngles[PITCH] = PITCH_CAP;
		targetReached = false;
	}

	if (Math::DistanceSq(oldRelativeAimAngles, relativeAimAngles) > 0.0f) {
		turretLogger.Debug(
			"Aiming. Elapsed: %d ms. Delta: %.2f. Max: %.2f. Old: %s. New: %s. Reached: %s.",
			timeDelta, deltaAngles, maxAngleChange, oldRelativeAimAngles, relativeAimAngles, targetReached
		);
	}

	// TODO: Move gentity_t.buildableAim to BuildableComponent.
	Vec3 absoluteAimAngles = RelativeAnglesToAbsoluteAngles(relativeAimAngles);
	absoluteAimAngles.Store(entity.oldEnt->buildableAim);

	return targetReached;
}
/*
===============
UI_PlayerAngles
===============
*/
static void UI_PlayerAngles( uiPlayerInfo_t *pi, vec3_t legs[3], vec3_t torso[3], vec3_t head[3] ) {
	vec3_t		legsAngles, torsoAngles, headAngles;
	float		dest;
	float		adjust;

	VectorCopy( pi->viewAngles, headAngles );
	headAngles[YAW] = AngleMod( headAngles[YAW] );
	VectorClear( legsAngles );
	VectorClear( torsoAngles );

	// --------- yaw -------------

	// allow yaw to drift a bit
#ifdef TA_WEAPSYS
	if (!BG_PlayerStandAnim(&pi->playercfg, AP_LEGS, pi->legsAnim)
		|| !BG_PlayerStandAnim(&pi->playercfg, AP_TORSO, pi->torsoAnim))
#else
	if ( ( pi->legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE 
		|| ( pi->torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND )
#endif
	{
		// if not standing still, always point all in the same direction
		pi->torso.yawing = qtrue;	// always center
		pi->torso.pitching = qtrue;	// always center
		pi->legs.yawing = qtrue;	// always center
	}

	// adjust legs for movement dir
	adjust = UI_MovedirAdjustment( pi );
	legsAngles[YAW] = headAngles[YAW] + adjust;
	torsoAngles[YAW] = headAngles[YAW] + 0.25 * adjust;


	// torso
#ifdef IOQ3ZTM // BG_SWING_ANGLES
	BG_SwingAngles( torsoAngles[YAW], 25, 90, BG_SWINGSPEED, &pi->torso.yawAngle, &pi->torso.yawing, uis.frametime );
	BG_SwingAngles( legsAngles[YAW], 40, 90, BG_SWINGSPEED, &pi->legs.yawAngle, &pi->legs.yawing, uis.frametime );
#else
	UI_SwingAngles( torsoAngles[YAW], 25, 90, SWINGSPEED, &pi->torso.yawAngle, &pi->torso.yawing );
	UI_SwingAngles( legsAngles[YAW], 40, 90, SWINGSPEED, &pi->legs.yawAngle, &pi->legs.yawing );
#endif

	torsoAngles[YAW] = pi->torso.yawAngle;
	legsAngles[YAW] = pi->legs.yawAngle;

	// --------- pitch -------------

	// only show a fraction of the pitch angle in the torso
	if ( headAngles[PITCH] > 180 ) {
		dest = (-360 + headAngles[PITCH]) * 0.75;
	} else {
		dest = headAngles[PITCH] * 0.75;
	}
#ifdef IOQ3ZTM // BG_SWING_ANGLES
	BG_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching, uis.frametime );
#else
	UI_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching );
#endif
	torsoAngles[PITCH] = pi->torso.pitchAngle;

#ifdef TA_PLAYERSYS
	if ( pi->playercfg.fixedtorso ) {
#else
	if ( pi->fixedtorso ) {
#endif
		torsoAngles[PITCH] = 0.0f;
	}

#ifdef TA_PLAYERSYS
	if ( pi->playercfg.fixedlegs ) {
#else
	if ( pi->fixedlegs ) {
#endif
		legsAngles[YAW] = torsoAngles[YAW];
		legsAngles[PITCH] = 0.0f;
		legsAngles[ROLL] = 0.0f;
	}

	// pull the angles back out of the hierarchial chain
	AnglesSubtract( headAngles, torsoAngles, headAngles );
	AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
	AnglesToAxis( legsAngles, legs );
	AnglesToAxis( torsoAngles, torso );
	AnglesToAxis( headAngles, head );
}


/*
===============
UI_PlayerFloatSprite
===============
*/
static void UI_PlayerFloatSprite( uiPlayerInfo_t *pi, vec3_t origin, qhandle_t shader ) {
	refEntity_t		ent;

	memset( &ent, 0, sizeof( ent ) );
	VectorCopy( origin, ent.origin );
	ent.origin[2] += 42;
	ent.reType = RT_SPRITE;
	ent.customShader = shader;
	ent.radius = 10;
	ent.renderfx = 0;
	trap_R_AddRefEntityToScene( &ent );
}


/*
======================
UI_MachinegunSpinAngle
======================
*/
float	UI_MachinegunSpinAngle( uiPlayerInfo_t *pi ) {
	int		delta;
	float	angle;
	float	speed;
	int		torsoAnim;

	delta = dp_realtime - pi->barrelTime;
	if ( pi->barrelSpinning ) {
		angle = pi->barrelAngle + delta * SPIN_SPEED;
	} else {
		if ( delta > COAST_TIME ) {
			delta = COAST_TIME;
		}

		speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME );
		angle = pi->barrelAngle + delta * speed;
	}

	torsoAnim = pi->torsoAnim  & ~ANIM_TOGGLEBIT;
#ifdef TA_WEAPSYS
	if (BG_PlayerAttackAnim(torsoAnim))
#else
	if( torsoAnim == TORSO_ATTACK2 )
#endif
	{
		torsoAnim = TORSO_ATTACK;
	}
	if ( pi->barrelSpinning == !(torsoAnim == TORSO_ATTACK) ) {
		pi->barrelTime = dp_realtime;
		pi->barrelAngle = AngleMod( angle );
		pi->barrelSpinning = !!(torsoAnim == TORSO_ATTACK);
	}

	return angle;
}