Example #1
0
//NOTE NOTE NOTE NOTE NOTE NOTE
//I want to keep this function BG too, because it's fairly generic already, and it
//would be nice to have proper prediction of animations. -rww
// This function makes sure that the rider's in this vehicle are properly animated.
void AnimateRiders( Vehicle_t *pVeh )
{
	animNumber_t Anim = BOTH_VS_IDLE;
	float fSpeedPercToMax;
	int iFlags = SETANIM_FLAG_NORMAL, iBlend = 300;
	playerState_t *pilotPS;
	playerState_t *parentPS;
	int curTime;


	// Boarding animation.
	if ( pVeh->m_iBoarding != 0 )
	{
		// We've just started moarding, set the amount of time it will take to finish moarding.
		if ( pVeh->m_iBoarding < 0 )
		{
			int iAnimLen;

			// Boarding from left...
			if ( pVeh->m_iBoarding == -1 )
			{
				Anim = BOTH_VS_MOUNT_L;
			}
			else if ( pVeh->m_iBoarding == -2 )
			{
				Anim = BOTH_VS_MOUNT_R;
			}
			else if ( pVeh->m_iBoarding == -3 )
			{
				Anim = BOTH_VS_MOUNTJUMP_L;
			}
			else if ( pVeh->m_iBoarding == VEH_MOUNT_THROW_LEFT)
			{
				iBlend = 0;
				Anim = BOTH_VS_MOUNTTHROW_R;
			}
			else if ( pVeh->m_iBoarding == VEH_MOUNT_THROW_RIGHT)
			{
				iBlend = 0;
				Anim = BOTH_VS_MOUNTTHROW_L;
			}

			// Set the delay time (which happens to be the time it takes for the animation to complete).
			// NOTE: Here I made it so the delay is actually 40% (0.4f) of the animation time.
#ifdef _JK2MP
			iAnimLen = BG_AnimLength( pVeh->m_pPilot->localAnimIndex, Anim ) * 0.4f;
			pVeh->m_iBoarding = BG_GetTime() + iAnimLen;
#else
 			iAnimLen = PM_AnimLength( pVeh->m_pPilot->client->clientInfo.animFileIndex, Anim );// * 0.4f;
			if (pVeh->m_iBoarding!=VEH_MOUNT_THROW_LEFT && pVeh->m_iBoarding!=VEH_MOUNT_THROW_RIGHT)
			{
				pVeh->m_iBoarding = level.time + (iAnimLen*0.4f);
			}
			else
			{
				pVeh->m_iBoarding = level.time + iAnimLen;
			}
#endif
			// Set the animation, which won't be interrupted until it's completed.
			// TODO: But what if he's killed? Should the animation remain persistant???
			iFlags = SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
			
#ifdef _JK2MP
			BG_SetAnim(pVeh->m_pPilot->playerState, bgAllAnims[pVeh->m_pPilot->localAnimIndex].anims,
				SETANIM_BOTH, Anim, iFlags, iBlend);
#else
			NPC_SetAnim( pVeh->m_pPilot, SETANIM_BOTH, Anim, iFlags, iBlend );
			if (pVeh->m_pOldPilot)
			{
				iAnimLen = PM_AnimLength( pVeh->m_pPilot->client->clientInfo.animFileIndex, BOTH_VS_MOUNTTHROWEE);
				NPC_SetAnim( pVeh->m_pOldPilot, SETANIM_BOTH, BOTH_VS_MOUNTTHROWEE, iFlags, iBlend );
			}
#endif
		}

#ifndef _JK2MP
		if (pVeh->m_pOldPilot && pVeh->m_pOldPilot->client->ps.torsoAnimTimer<=0)
		{
			if (Q_irand(0, player->count)==0)
			{
				player->count++;
 				player->lastEnemy = pVeh->m_pOldPilot;
				G_StartMatrixEffect(player, MEF_LOOK_AT_ENEMY|MEF_NO_RANGEVAR|MEF_NO_VERTBOB|MEF_NO_SPIN, 1000);
			}

 			gentity_t*	oldPilot = pVeh->m_pOldPilot;
			pVeh->m_pVehicleInfo->Eject(pVeh, pVeh->m_pOldPilot, qtrue);		// will set pointer to zero

			// Kill Him
			//----------
			oldPilot->client->noRagTime = -1;	// no ragdoll for you
			G_Damage(oldPilot, pVeh->m_pPilot, pVeh->m_pPilot, pVeh->m_pPilot->currentAngles, pVeh->m_pPilot->currentOrigin, 1000, 0, MOD_CRUSH);

			// Compute THe Throw Direction As Backwards From The Vehicle's Velocity
			//----------------------------------------------------------------------
			vec3_t		throwDir;
			VectorScale(pVeh->m_pParentEntity->client->ps.velocity, -1.0f, throwDir);
			VectorNormalize(throwDir);
			throwDir[2] += 0.3f;	// up a little

			// Now Throw Him Out
			//-------------------
			G_Throw(oldPilot, throwDir, VectorLength(pVeh->m_pParentEntity->client->ps.velocity)/10.0f);
			NPC_SetAnim(oldPilot, SETANIM_BOTH, BOTH_DEATHBACKWARD1, SETANIM_FLAG_OVERRIDE, iBlend );
		}
#endif

		return;
	}

#ifdef _JK2MP //fixme
	if (1) return;
#endif

#ifdef _JK2MP
	pilotPS = pVeh->m_pPilot->playerState;
	parentPS = pVeh->m_pPilot->playerState;
#else
	pilotPS = &pVeh->m_pPilot->client->ps;
	parentPS = &pVeh->m_pParentEntity->client->ps;
#endif

#ifndef _JK2MP//SP
	curTime = level.time;
#elif QAGAME//MP GAME
	curTime = level.time;
#elif CGAME//MP CGAME
	//FIXME: pass in ucmd?  Not sure if this is reliable...
	curTime = pm->cmd.serverTime;
#endif

	// Percentage of maximum speed relative to current speed.
	fSpeedPercToMax = parentPS->speed / pVeh->m_pVehicleInfo->speedMax;

	// Going in reverse...
#ifdef _JK2MP
	if ( pVeh->m_ucmd.forwardmove < 0 && !(pVeh->m_ulFlags & VEH_SLIDEBREAKING))
#else
	if ( fSpeedPercToMax < -0.018f && !(pVeh->m_ulFlags & VEH_SLIDEBREAKING))
#endif
	{
		Anim = BOTH_VS_REV;
		iBlend = 500;
	}
	else 
	{
		bool		HasWeapon	= ((pilotPS->weapon != WP_NONE) && (pilotPS->weapon != WP_MELEE));
		bool		Attacking	= (HasWeapon && !!(pVeh->m_ucmd.buttons&BUTTON_ATTACK));
#ifdef _JK2MP //fixme: flying tends to spaz out a lot
		bool		Flying		= false;
		bool		Crashing	= false;
#else
		bool		Flying		= !!(pVeh->m_ulFlags & VEH_FLYING);
		bool		Crashing	= !!(pVeh->m_ulFlags & VEH_CRASHING);
#endif
		bool		Right		= (pVeh->m_ucmd.rightmove>0);
		bool		Left		= (pVeh->m_ucmd.rightmove<0);
		bool		Turbo		= (curTime<pVeh->m_iTurboTime);
		EWeaponPose	WeaponPose	= WPOSE_NONE;


		// Remove Crashing Flag
		//----------------------
		pVeh->m_ulFlags &= ~VEH_CRASHING;


		// Put Away Saber When It Is Not Active
		//--------------------------------------
#ifndef _JK2MP
		if (HasWeapon && (Turbo || (pilotPS->weapon==WP_SABER && !pilotPS->SaberActive())))
		{
			if (pVeh->m_pPilot->s.number<MAX_CLIENTS)
			{
				CG_ChangeWeapon(WP_NONE);
			}

			pVeh->m_pPilot->client->ps.weapon = WP_NONE;
			G_RemoveWeaponModels(pVeh->m_pPilot);
		}
#endif

		// Don't Interrupt Attack Anims
		//------------------------------
#ifdef _JK2MP
		if (pilotPS->weaponTime>0)
		{
			return;
		}
#else		
		if (pilotPS->torsoAnim>=BOTH_VS_ATL_S && pilotPS->torsoAnim<=BOTH_VS_ATF_G)
		{
			float		bodyCurrent	  = 0.0f;
			int			bodyEnd		  = 0;
			if (!!gi.G2API_GetBoneAnimIndex(&pVeh->m_pPilot->ghoul2[pVeh->m_pPilot->playerModel], pVeh->m_pPilot->rootBone, level.time, &bodyCurrent, NULL, &bodyEnd, NULL, NULL, NULL))
			{
				if (bodyCurrent<=((float)(bodyEnd)-1.5f))
				{
					return;
				}
			}
		}
#endif

		// Compute The Weapon Pose
		//--------------------------
		if (pilotPS->weapon==WP_BLASTER)
		{
			WeaponPose = WPOSE_BLASTER;
		}
		else if (pilotPS->weapon==WP_SABER)
		{
			if ( (pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VS_ATL_TO_R_S)
			{
				pVeh->m_ulFlags	&= ~VEH_SABERINLEFTHAND;
			}
			if (!(pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VS_ATR_TO_L_S)
			{
				pVeh->m_ulFlags	|=  VEH_SABERINLEFTHAND;
			}
			WeaponPose = (pVeh->m_ulFlags&VEH_SABERINLEFTHAND)?(WPOSE_SABERLEFT):(WPOSE_SABERRIGHT);
		}
		

 		if (Attacking && WeaponPose)
		{// Attack!
			iBlend	= 100;
 			iFlags	= SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART;
	
			// Auto Aiming
			//===============================================
			if (!Left && !Right)		// Allow player strafe keys to override
			{
#ifndef _JK2MP
				if (pVeh->m_pPilot->enemy)
				{
					vec3_t	toEnemy;
					float	toEnemyDistance;
					vec3_t	actorRight;
					float	actorRightDot;

					VectorSubtract(pVeh->m_pPilot->currentOrigin, pVeh->m_pPilot->enemy->currentOrigin, toEnemy);
					toEnemyDistance = VectorNormalize(toEnemy);

					AngleVectors(pVeh->m_pParentEntity->currentAngles, 0, actorRight, 0);
					actorRightDot = DotProduct(toEnemy, actorRight);

	 				if (fabsf(actorRightDot)>0.5f || pilotPS->weapon==WP_SABER)
					{
						Left	= (actorRightDot>0.0f);
						Right	= !Left;
					}
					else
					{
						Right = Left = false;
					}
				}
				else 
#endif
				if (pilotPS->weapon==WP_SABER && !Left && !Right)
				{
					Left = (WeaponPose==WPOSE_SABERLEFT);
					Right	= !Left;
				}
			}


			if (Left)
			{// Attack Left
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VS_ATL_G;		break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VS_ATL_S;		break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VS_ATR_TO_L_S;	break;
				default:				assert(0);
				}
			}
			else if (Right)
			{// Attack Right
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VS_ATR_G;		break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VS_ATL_TO_R_S;	break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VS_ATR_S;		break;
				default:				assert(0);
				}
			}
			else
			{// Attack Ahead
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VS_ATF_G;		break;
				default:				assert(0);
				}
			}

		}
		else if (Left && pVeh->m_ucmd.buttons&BUTTON_USE)
		{// Look To The Left Behind
			iBlend	= 400;
			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
			switch(WeaponPose)
			{
			case WPOSE_SABERLEFT:	Anim = BOTH_VS_IDLE_SL;		break;
			case WPOSE_SABERRIGHT:	Anim = BOTH_VS_IDLE_SR;		break;
			default:				Anim = BOTH_VS_LOOKLEFT;
			}
		}
		else if (Right && pVeh->m_ucmd.buttons&BUTTON_USE)
		{// Look To The Right Behind
			iBlend	= 400;
			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;
			switch(WeaponPose)
			{
			case WPOSE_SABERLEFT:	Anim = BOTH_VS_IDLE_SL;		break;
			case WPOSE_SABERRIGHT:	Anim = BOTH_VS_IDLE_SR;		break;
			default:				Anim = BOTH_VS_LOOKRIGHT;
			}
		}
		else if (Turbo)
		{// Kicked In Turbo
			iBlend	= 50;
			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;
			Anim	= BOTH_VS_TURBO;
		}
		else if (Flying)
		{// Off the ground in a jump
			iBlend	= 800;
			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD;

			switch(WeaponPose)
			{
			case WPOSE_NONE:		Anim = BOTH_VS_AIR;			break;
			case WPOSE_BLASTER:		Anim = BOTH_VS_AIR_G;		break;
			case WPOSE_SABERLEFT:	Anim = BOTH_VS_AIR_SL;		break;
			case WPOSE_SABERRIGHT:	Anim = BOTH_VS_AIR_SR;		break;
			default:				assert(0);
			}
		}
		else if (Crashing)
		{// Hit the ground!
			iBlend	= 100;
			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;

			switch(WeaponPose)
			{
			case WPOSE_NONE:		Anim = BOTH_VS_LAND;		break;
			case WPOSE_BLASTER:		Anim = BOTH_VS_LAND_G;		break;
			case WPOSE_SABERLEFT:	Anim = BOTH_VS_LAND_SL;		break;
			case WPOSE_SABERRIGHT:	Anim = BOTH_VS_LAND_SR;		break;
			default:				assert(0);
			}
		}
		else
		{// No Special Moves
			iBlend	= 300;
 			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;

			if (pVeh->m_vOrientation[ROLL] <= -20)
			{// Lean Left
				switch(WeaponPose)
				{
				case WPOSE_NONE:		Anim = BOTH_VS_LEANL;			break;
				case WPOSE_BLASTER:		Anim = BOTH_VS_LEANL_G;			break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VS_LEANL_SL;		break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VS_LEANL_SR;		break;
				default:				assert(0);
				}
			}
			else if (pVeh->m_vOrientation[ROLL] >= 20)
			{// Lean Right
				switch(WeaponPose)
				{
				case WPOSE_NONE:		Anim = BOTH_VS_LEANR;			break;
				case WPOSE_BLASTER:		Anim = BOTH_VS_LEANR_G;			break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VS_LEANR_SL;		break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VS_LEANR_SR;		break;
				default:				assert(0);
				}
			}
			else
			{// No Lean
				switch(WeaponPose)
				{
				case WPOSE_NONE:		Anim = BOTH_VS_IDLE;			break;
				case WPOSE_BLASTER:		Anim = BOTH_VS_IDLE_G;			break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VS_IDLE_SL;			break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VS_IDLE_SR;			break;
				default:				assert(0);
				}
			}
		}// No Special Moves
	}// Going backwards?

#ifdef _JK2MP
	iFlags &= ~SETANIM_FLAG_OVERRIDE;
	if (pVeh->m_pPilot->playerState->torsoAnim == Anim)
	{
		pVeh->m_pPilot->playerState->torsoTimer = BG_AnimLength(pVeh->m_pPilot->localAnimIndex, Anim);
	}
	if (pVeh->m_pPilot->playerState->legsAnim == Anim)
	{
		pVeh->m_pPilot->playerState->legsTimer = BG_AnimLength(pVeh->m_pPilot->localAnimIndex, Anim);
	}
	BG_SetAnim(pVeh->m_pPilot->playerState, bgAllAnims[pVeh->m_pPilot->localAnimIndex].anims,
		SETANIM_BOTH, Anim, iFlags|SETANIM_FLAG_HOLD, iBlend);
#else
	NPC_SetAnim( pVeh->m_pPilot, SETANIM_BOTH, Anim, iFlags, iBlend );
#endif
}
Example #2
0
void ExitEmplacedWeapon( gentity_t *ent )
{
	// requesting to unlock from the weapon
	// We'll leave the gun pointed in the direction it was last facing, though we'll cut out the pitch
	if ( ent->client )
	{
		// if we are the player we will have put down a brush that blocks NPCs so that we have a clear spot to get back out.
		//gentity_t *place = G_Find( NULL, FOFS(classname), "emp_placeholder" );

		if ( ent->health > 0 )
		{//he's still alive, and we have a placeholder, so put him back
			if ( ent->owner->nextTrain )
			{
				// reset the players position
				VectorCopy( ent->owner->nextTrain->currentOrigin, ent->client->ps.origin );
				//reset ent's size to normal
				VectorCopy( ent->owner->nextTrain->mins, ent->mins );
				VectorCopy( ent->owner->nextTrain->maxs, ent->maxs );
				//free the placeholder
				G_FreeEntity( ent->owner->nextTrain );
				//re-link the ent
				gi.linkentity( ent );
			}
			else if ( ent->owner->e_UseFunc == useF_eweb_use )//yeah, crappy way to check this, but...
			{
				// so give 'em a push away from us
				vec3_t backDir, start, end;
				trace_t trace;
				gentity_t *eweb = ent->owner;
				float curRadius = 0.0f;
				float minRadius, maxRadius;
				qboolean safeExit = qfalse;

				VectorSubtract( ent->currentOrigin, eweb->currentOrigin, backDir );
				backDir[2] = 0;
				minRadius = VectorNormalize( backDir )-8.0f;

				maxRadius = (ent->maxs[0]+ent->maxs[1])*0.5f;
				maxRadius += (eweb->maxs[0]+eweb->maxs[1])*0.5f;
				maxRadius *= 1.5f;

				if ( minRadius >= maxRadius - 1.0f )
				{
					maxRadius = minRadius + 8.0f;
				}

				ent->owner = NULL;//so his trace hits me

				for ( curRadius = minRadius; curRadius <= maxRadius; curRadius += 4.0f )
				{
					VectorMA( ent->currentOrigin, curRadius, backDir, start );
					//make sure they're not in the ground
					VectorCopy( start, end );
					start[2] += 18;
					end[2] -= 18;
					gi.trace(&trace, start, ent->mins, ent->maxs, end, ent->s.number, ent->clipmask, (EG2_Collision)0, 0);
					if ( !trace.allsolid && !trace.startsolid )
					{
						G_SetOrigin( ent, trace.endpos );
						gi.linkentity( ent );
						safeExit = qtrue;
						break;
					}
				}
				//Hmm... otherwise, don't allow them to get off?
				ent->owner = eweb;
				if ( !safeExit )
				{//don't try again for a second
					ent->owner->delay = level.time + 500;
					return;
				}
			}
		}
		else if ( ent->health <= 0 )
		{
			// dead, so give 'em a push out of the chair
			vec3_t dir;
			AngleVectors( ent->owner->s.angles, NULL, dir, NULL );

			if ( rand() & 1 )
			{
				VectorScale( dir, -1, dir );
			}

			VectorMA( ent->client->ps.velocity, 75, dir, ent->client->ps.velocity );
		}
		//don't let them move towards me for a couple frames so they don't step back into me while I'm becoming solid to them
		if ( ent->s.number < MAX_CLIENTS )
		{
			if ( ent->client->ps.pm_time < 100 )
			{
				ent->client->ps.pm_time = 100;
			}
			ent->client->ps.pm_flags |= (PMF_TIME_NOFRICTION|PMF_TIME_KNOCKBACK);
		}

		if ( !ent->owner->bounceCount )
		{//not an EWeb - the overridden bone angles will remember the angle we left it at
			VectorCopy( ent->client->ps.viewangles, ent->owner->s.angles );
			ent->owner->s.angles[PITCH] = 0;
			G_SetAngles( ent->owner, ent->owner->s.angles );
			VectorCopy( ent->owner->s.angles, ent->owner->pos1 );
		}
	}

	// Remove the emplaced gun from our inventory
	ent->client->ps.stats[STAT_WEAPONS] &= ~( 1 << WP_EMPLACED_GUN );

extern void ChangeWeapon( gentity_t *ent, int newWeapon );
extern void CG_ChangeWeapon( int num );
	if ( ent->health <= 0 ) 
	{//when die, don't set weapon back on when ejected from emplaced/eweb
		//empty hands
		ent->client->ps.weapon = WP_NONE;
		if ( ent->NPC )
		{
			ChangeWeapon( ent, ent->client->ps.weapon );	// should be OK actually.
		}
		else
		{
			CG_ChangeWeapon( ent->client->ps.weapon );
		}
		if ( ent->s.number < MAX_CLIENTS )
		{
			gi.cvar_set( "cg_thirdperson", "1" );
		}
	}
	else
	{
		// when we lock or unlock from the the gun, we get our old weapon back
		ent->client->ps.weapon = ent->owner->s.weapon;

		if ( ent->NPC )
		{//BTW, if a saber-using NPC ever gets off of an emplaced gun/eweb, this will not work, look at NPC_ChangeWeapon for the proper way
			ChangeWeapon( ent, ent->client->ps.weapon );
		}
		else
		{
			G_RemoveWeaponModels( ent );
			CG_ChangeWeapon( ent->client->ps.weapon );
			if ( ent->client->ps.weapon == WP_SABER )
			{
				WP_SaberAddG2SaberModels( ent );
			}
			else
			{
				G_CreateG2AttachedWeaponModel( ent, weaponData[ent->client->ps.weapon].weaponMdl, ent->handRBolt, 0 );
			}

			if ( ent->s.number < MAX_CLIENTS )
			{
				if ( ent->client->ps.weapon == WP_SABER )
				{
					gi.cvar_set( "cg_thirdperson", "1" );
				}
				else if ( ent->client->ps.weapon != WP_SABER && cg_gunAutoFirst.integer )
				{
					gi.cvar_set( "cg_thirdperson", "0" );
				}
			}
		}

		if ( ent->client->ps.weapon == WP_SABER )
		{
			if ( ent->owner->alt_fire )
			{
				ent->client->ps.SaberActivate();
			}
			else
			{
				ent->client->ps.SaberDeactivate();
			}
		}
	}
	//set the emplaced gun/eweb's weapon back to the emplaced gun
	ent->owner->s.weapon = WP_EMPLACED_GUN;
//	gi.G2API_DetachG2Model( &ent->ghoul2[ent->playerModel] );

	ent->s.eFlags &= ~EF_LOCKED_TO_WEAPON;
	ent->client->ps.eFlags &= ~EF_LOCKED_TO_WEAPON;

	ent->owner->noDamageTeam = TEAM_FREE;
	ent->owner->svFlags &= ~SVF_NONNPC_ENEMY;
	ent->owner->delay = level.time;
	ent->owner->activator = NULL;

	if ( !ent->NPC )
	{
		// by keeping the owner, a dead npc can be pushed out of the chair without colliding with it
		ent->owner = NULL;
	}
}
Example #3
0
void eweb_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	if ( !eweb_can_be_used( self, other, activator ) )
	{
		return;
	}

	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 );
	}

	VectorCopy( activator->currentOrigin, self->pos4 );//keep this around so we know when to make them play the strafe anim

	// 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: 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/eweb/eweb_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 );
	}
}
Example #4
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 );
		}
	}
}
Example #5
0
//rwwFIXMEFIXME: This is all going to have to be predicted I think, or it will feel awful
//and lagged
// This function makes sure that the rider's in this vehicle are properly animated.
static void AnimateRiders( Vehicle_t *pVeh )
{
	animNumber_t Anim = BOTH_VT_IDLE;
	int iFlags = SETANIM_FLAG_NORMAL, iBlend = 500;
	gentity_t *pilot = (gentity_t *)pVeh->m_pPilot;
	gentity_t *parent = (gentity_t *)pVeh->m_pParentEntity;
	playerState_t *pilotPS;
	playerState_t *parentPS;
	float fSpeedPercToMax;

#ifdef _JK2MP
	pilotPS = pVeh->m_pPilot->playerState;
	parentPS = pVeh->m_pPilot->playerState;
#else
	pilotPS = &pVeh->m_pPilot->client->ps;
	parentPS = &pVeh->m_pParentEntity->client->ps;
#endif

	// Boarding animation.
	if ( pVeh->m_iBoarding != 0 )
	{
		return;
	}

	// Percentage of maximum speed relative to current speed.
	fSpeedPercToMax = parent->client->ps.speed / pVeh->m_pVehicleInfo->speedMax;

	// Going in reverse...
#ifdef _JK2MP //handled in pmove in mp
	if (0)
#else
	if ( fSpeedPercToMax < -0.01f )
#endif
	{
		Anim = BOTH_VT_WALK_REV;
		iBlend = 600;
	}
	else
	{
		bool		HasWeapon	= (qboolean)((pilotPS->weapon != WP_NONE) && (pilotPS->weapon != WP_MELEE));
		bool		Attacking	= (qboolean)(HasWeapon && !!(pVeh->m_ucmd.buttons&BUTTON_ATTACK));
		bool		Right		= (qboolean)(pVeh->m_ucmd.rightmove>0);
		bool		Left		= (qboolean)(pVeh->m_ucmd.rightmove<0);
		bool		Turbo		= (qboolean)(fSpeedPercToMax>0.0f && level.time<pVeh->m_iTurboTime);
		bool		Walking		= (qboolean)(fSpeedPercToMax>0.0f && ((pVeh->m_ucmd.buttons&BUTTON_WALKING) || fSpeedPercToMax<=0.275f));
		bool		Running		= (qboolean)(fSpeedPercToMax>0.275f);
		EWeaponPose	WeaponPose	= WPOSE_NONE;


		// Remove Crashing Flag
		//----------------------
		pVeh->m_ulFlags &= ~VEH_CRASHING;


		// Put Away Saber When It Is Not Active
		//--------------------------------------
#ifndef _JK2MP
		if (HasWeapon && (Turbo || (pilotPS->weapon==WP_SABER && !pilotPS->SaberActive())))
		{
			if (pVeh->m_pPilot->s.number<MAX_CLIENTS)
			{
				CG_ChangeWeapon(WP_NONE);
			}

			pVeh->m_pPilot->client->ps.weapon = WP_NONE;
			G_RemoveWeaponModels(pVeh->m_pPilot);
		}
#endif

		// Don't Interrupt Attack Anims
		//------------------------------
#ifdef _JK2MP
		if (pilotPS->weaponTime>0)
		{
			return;
		}
#else		
		if (pilotPS->torsoAnim>=BOTH_VT_ATL_S && pilotPS->torsoAnim<=BOTH_VT_ATF_G)
		{
			float		bodyCurrent	  = 0.0f;
			int			bodyEnd		  = 0;
			if (!!gi.G2API_GetBoneAnimIndex(&pVeh->m_pPilot->ghoul2[pVeh->m_pPilot->playerModel], pVeh->m_pPilot->rootBone, level.time, &bodyCurrent, NULL, &bodyEnd, NULL, NULL, NULL))
			{
				if (bodyCurrent<=((float)(bodyEnd)-1.5f))
				{
					return;
				}
			}
		}
#endif

		// Compute The Weapon Pose
		//--------------------------
		if (pilotPS->weapon==WP_BLASTER)
		{
			WeaponPose = WPOSE_BLASTER;
		}
		else if (pilotPS->weapon==WP_SABER)
		{
			if ( (pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VT_ATL_TO_R_S)
			{
				pVeh->m_ulFlags	&= ~VEH_SABERINLEFTHAND;
			}
			if (!(pVeh->m_ulFlags&VEH_SABERINLEFTHAND) && pilotPS->torsoAnim==BOTH_VT_ATR_TO_L_S)
			{
				pVeh->m_ulFlags	|=  VEH_SABERINLEFTHAND;
			}
			WeaponPose = (pVeh->m_ulFlags&VEH_SABERINLEFTHAND)?(WPOSE_SABERLEFT):(WPOSE_SABERRIGHT);
		}
		

 		if (Attacking && WeaponPose)
		{// Attack!
			iBlend	= 100;
 			iFlags	= SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART;

			if (Turbo)
			{
				Right = true;
				Left = false;
			}

			// Auto Aiming
			//===============================================
			if (!Left && !Right)		// Allow player strafe keys to override
			{
#ifndef _JK2MP
				if (pVeh->m_pPilot->enemy)
				{
					vec3_t	toEnemy;
					float	toEnemyDistance;
					vec3_t	actorRight;
					float	actorRightDot;

					VectorSubtract(pVeh->m_pPilot->currentOrigin, pVeh->m_pPilot->enemy->currentOrigin, toEnemy);
					toEnemyDistance = VectorNormalize(toEnemy);

					AngleVectors(pVeh->m_pParentEntity->currentAngles, 0, actorRight, 0);
					actorRightDot = DotProduct(toEnemy, actorRight);

	 				if (fabsf(actorRightDot)>0.5f || pilotPS->weapon==WP_SABER)
					{
						Left	= (actorRightDot>0.0f);
						Right	= !Left;
					}
					else
					{
						Right = Left = false;
					}
				}
				else
#endif
				if (pilotPS->weapon==WP_SABER && !Left && !Right)
				{
					Left = (qboolean)(WeaponPose==WPOSE_SABERLEFT);
					Right	= (qboolean)(!Left);
				}
			}


			if (Left)
			{// Attack Left
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VT_ATL_G;		break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VT_ATL_S;		break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VT_ATR_TO_L_S;	break;
				default:				assert(0);
				}
			}
			else if (Right)
			{// Attack Right
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VT_ATR_G;		break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VT_ATL_TO_R_S;	break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VT_ATR_S;		break;
				default:				assert(0);
				}
			}
			else
			{// Attack Ahead
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VT_ATF_G;		break;
				default:				assert(0);
				}
			}
		}
		else if (Turbo)
		{// Kicked In Turbo
			iBlend	= 50;
			iFlags	= SETANIM_FLAG_OVERRIDE;
			Anim	= BOTH_VT_TURBO;
		}
		else
		{// No Special Moves
			iBlend	= 300;
 			iFlags	= SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLDLESS;

			if (WeaponPose==WPOSE_NONE)
			{
				if (Walking)
				{
					Anim = BOTH_VT_WALK_FWD;
				}
				else if (Running)
				{
					Anim = BOTH_VT_RUN_FWD;
				}
				else
				{
					Anim = BOTH_VT_IDLE1;//(Q_irand(0,1)==0)?(BOTH_VT_IDLE):(BOTH_VT_IDLE1);
				}
			}
			else
			{
				switch(WeaponPose)
				{
				case WPOSE_BLASTER:		Anim = BOTH_VT_IDLE_G;			break;
				case WPOSE_SABERLEFT:	Anim = BOTH_VT_IDLE_SL;			break;
				case WPOSE_SABERRIGHT:	Anim = BOTH_VT_IDLE_SR;			break;
				default:				assert(0);
				}
			}
		}// No Special Moves
	}

	Vehicle_SetAnim( pilot, SETANIM_BOTH, Anim, iFlags, iBlend );
}