コード例 #1
0
ファイル: SpeederNPC.c プロジェクト: dmead/jkaq3
//MP RULE - ALL PROCESSMOVECOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!!
//If you really need to violate this rule for SP, then use ifdefs.
//By BG-compatible, I mean no use of game-specific data - ONLY use
//stuff available in the MP bgEntity (in SP, the bgEntity is #defined
//as a gentity, but the MP-compatible access restrictions are based
//on the bgEntity structure in the MP codebase) -rww
// ProcessMoveCommands the Vehicle.
static void ProcessMoveCommands( Vehicle_t *pVeh )
{
	/************************************************************************************/
	/*	BEGIN	Here is where we move the vehicle (forward or back or whatever). BEGIN	*/
	/************************************************************************************/
	//Client sets ucmds and such for speed alterations
	float speedInc, speedIdleDec, speedIdle, speedIdleAccel, speedMin, speedMax;
	playerState_t *parentPS;
	playerState_t *pilotPS = NULL;
	int	curTime;

#ifdef _JK2MP
	parentPS = pVeh->m_pParentEntity->playerState;
	if (pVeh->m_pPilot)
	{
		pilotPS = pVeh->m_pPilot->playerState;
	}
#else
	parentPS = &pVeh->m_pParentEntity->client->ps;
	if (pVeh->m_pPilot)
	{
		pilotPS = &pVeh->m_pPilot->client->ps;
	}
#endif


	// If we're flying, make us accelerate at 40% (about half) acceleration rate, and restore the pitch
	// to origin (straight) position (at 5% increments). 
	if ( pVeh->m_ulFlags & VEH_FLYING ) 
	{
		speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier * 0.4f;
	}
#ifdef _JK2MP
	else if ( !parentPS->m_iVehicleNum )
#else
	else if ( !pVeh->m_pVehicleInfo->Inhabited( pVeh ) )
#endif
	{//drifts to a stop
		speedInc = 0;
		//pVeh->m_ucmd.forwardmove = 127;
	}
	else
	{
		speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier;
	}
	speedIdleDec = pVeh->m_pVehicleInfo->decelIdle * pVeh->m_fTimeModifier;

#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



	if ( (pVeh->m_pPilot /*&& (pilotPS->weapon == WP_NONE || pilotPS->weapon == WP_MELEE )*/ &&
		(pVeh->m_ucmd.buttons & BUTTON_ALT_ATTACK) && pVeh->m_pVehicleInfo->turboSpeed)
		/*||
		(parentPS && parentPS->electrifyTime > curTime && pVeh->m_pVehicleInfo->turboSpeed)*/ //make them go!
		)
	{
		if ( (parentPS && parentPS->electrifyTime > curTime) ||
			 (pVeh->m_pPilot->playerState &&
			  (pVeh->m_pPilot->playerState->weapon == WP_MELEE ||
			  (pVeh->m_pPilot->playerState->weapon == WP_SABER && BG_SabersOff( pVeh->m_pPilot->playerState ) ))) )
		{
			if ((curTime - pVeh->m_iTurboTime)>pVeh->m_pVehicleInfo->turboRecharge)
			{
				pVeh->m_iTurboTime = (curTime + pVeh->m_pVehicleInfo->turboDuration);
				if (pVeh->m_pVehicleInfo->iTurboStartFX)
				{
					int i;
					for (i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++)
					{
#ifdef QAGAME
						if (pVeh->m_pParentEntity &&
							pVeh->m_pParentEntity->ghoul2 &&
							pVeh->m_pParentEntity->playerState)
						{ //fine, I'll use a tempent for this, but only because it's played only once at the start of a turbo.
							vec3_t boltOrg, boltDir;
							mdxaBone_t boltMatrix;

							VectorSet(boltDir, 0.0f, pVeh->m_pParentEntity->playerState->viewangles[YAW], 0.0f);

							trap_G2API_GetBoltMatrix(pVeh->m_pParentEntity->ghoul2, 0, pVeh->m_iExhaustTag[i], &boltMatrix, boltDir, pVeh->m_pParentEntity->playerState->origin, level.time, NULL, pVeh->m_pParentEntity->modelScale);
							BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltOrg);
							BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltDir);
							G_PlayEffectID(pVeh->m_pVehicleInfo->iTurboStartFX, boltOrg, boltDir);
						}
#endif
					}
				}
				parentPS->speed = pVeh->m_pVehicleInfo->turboSpeed;	// Instantly Jump To Turbo Speed
			}
		}
	}

	// Slide Breaking
	if (pVeh->m_ulFlags&VEH_SLIDEBREAKING)
	{
		if (pVeh->m_ucmd.forwardmove>=0 
#ifndef _JK2MP
			|| ((level.time - pVeh->m_pParentEntity->lastMoveTime)>500)
#endif
			)
		{
			pVeh->m_ulFlags &= ~VEH_SLIDEBREAKING;
		}
		parentPS->speed = 0;
	}
	else if (
		(curTime > pVeh->m_iTurboTime) && 
		!(pVeh->m_ulFlags&VEH_FLYING) && 
		pVeh->m_ucmd.forwardmove<0 && 
		fabs(pVeh->m_vOrientation[ROLL])>25.0f)
	{
		pVeh->m_ulFlags |= VEH_SLIDEBREAKING;
	}


	if ( curTime < pVeh->m_iTurboTime )
	{
		speedMax = pVeh->m_pVehicleInfo->turboSpeed;
		if (parentPS)
		{
			parentPS->eFlags |= EF_JETPACK_ACTIVE;
		}
	}
	else
	{
		speedMax = pVeh->m_pVehicleInfo->speedMax;
		if (parentPS)
		{
			parentPS->eFlags &= ~EF_JETPACK_ACTIVE;
		}
	}


	speedIdle = pVeh->m_pVehicleInfo->speedIdle;
	speedIdleAccel = pVeh->m_pVehicleInfo->accelIdle * pVeh->m_fTimeModifier;
	speedMin = pVeh->m_pVehicleInfo->speedMin;

	if ( parentPS->speed || parentPS->groundEntityNum == ENTITYNUM_NONE  ||
		 pVeh->m_ucmd.forwardmove || pVeh->m_ucmd.upmove > 0 )
	{ 
		if ( pVeh->m_ucmd.forwardmove > 0 && speedInc )
		{
			parentPS->speed += speedInc;
		}
		else if ( pVeh->m_ucmd.forwardmove < 0 )
		{
			if ( parentPS->speed > speedIdle )
			{
				parentPS->speed -= speedInc;
			}
			else if ( parentPS->speed > speedMin )
			{
				parentPS->speed -= speedIdleDec;
			}
		}
		// No input, so coast to stop.
		else if ( parentPS->speed > 0.0f )
		{
			parentPS->speed -= speedIdleDec;
			if ( parentPS->speed < 0.0f )
			{
				parentPS->speed = 0.0f;
			}
		}
		else if ( parentPS->speed < 0.0f )
		{
			parentPS->speed += speedIdleDec;
			if ( parentPS->speed > 0.0f )
			{
				parentPS->speed = 0.0f;
			}
		}
	}
	else
	{
		if ( !pVeh->m_pVehicleInfo->strafePerc 
#ifdef _JK2MP
			|| (0 && pVeh->m_pParentEntity->s.number < MAX_CLIENTS) )
#else
			|| (!g_speederControlScheme->value && !pVeh->m_pParentEntity->s.number) )
#endif
		{//if in a strafe-capable vehicle, clear strafing unless using alternate control scheme
			//pVeh->m_ucmd.rightmove = 0;
		}
	}

	if ( parentPS->speed > speedMax )
	{
		parentPS->speed = speedMax;
	}
	else if ( parentPS->speed < speedMin )
	{
		parentPS->speed = speedMin;
	}

	if (parentPS && parentPS->electrifyTime > curTime)
	{
		parentPS->speed *= (pVeh->m_fTimeModifier/60.0f);
	}


	/********************************************************************************/
	/*	END Here is where we move the vehicle (forward or back or whatever). END	*/
	/********************************************************************************/
}
コード例 #2
0
ファイル: NPC_AI_Grenadier.cpp プロジェクト: Camron/OpenJK
void NPC_BSGrenadier_Attack( void )
{
	//Don't do anything if we're hurt
	if ( NPC->painDebounceTime > level.time )
	{
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

	//NPC_CheckEnemy( qtrue, qfalse );
	//If we don't have an enemy, just idle
	if ( NPC_CheckEnemyExt(qfalse) == qfalse )//!NPC->enemy )//
	{
		NPC->enemy = NULL;
		NPC_BSGrenadier_Patrol();//FIXME: or patrol?
		return;
	}

	if ( TIMER_Done( NPC, "flee" ) && NPC_CheckForDanger( NPC_CheckAlertEvents( qtrue, qtrue, -1, qfalse, AEL_DANGER ) ) )
	{//going to run
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

	if ( !NPC->enemy )
	{//WTF?  somehow we lost our enemy?
		NPC_BSGrenadier_Patrol();//FIXME: or patrol?
		return;
	}

	enemyLOS3 = enemyCS3 = qfalse;
	move3 = qtrue;
	faceEnemy3 = qfalse;
	shoot3 = qfalse;
	enemyDist3 = DistanceSquared( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin );

	//See if we should switch to melee attack
	if ( enemyDist3 < 16384 //128
		&& (!NPC->enemy->client
			|| NPC->enemy->client->ps.weapon != WP_SABER
			|| BG_SabersOff( &NPC->enemy->client->ps ) 
			) 
		)
	{//enemy is close and not using saber
		if ( NPC->client->ps.weapon == WP_THERMAL )
		{//grenadier
			trace_t	trace;
			trap_Trace ( &trace, NPC->r.currentOrigin, NPC->enemy->r.mins, NPC->enemy->r.maxs, NPC->enemy->r.currentOrigin, NPC->s.number, NPC->enemy->clipmask );
			if ( !trace.allsolid && !trace.startsolid && (trace.fraction == 1.0 || trace.entityNum == NPC->enemy->s.number ) )
			{//I can get right to him
				//reset fire-timing variables
				NPC_ChangeWeapon( WP_STUN_BATON );
				if ( !(NPCInfo->scriptFlags&SCF_CHASE_ENEMIES) )//NPCInfo->behaviorState == BS_STAND_AND_SHOOT )
				{//FIXME: should we be overriding scriptFlags?
					NPCInfo->scriptFlags |= SCF_CHASE_ENEMIES;//NPCInfo->behaviorState = BS_HUNT_AND_KILL;
				}
			}
		}
	}
	else if ( enemyDist3 > 65536 || (NPC->enemy->client && NPC->enemy->client->ps.weapon == WP_SABER && !NPC->enemy->client->ps.saberHolstered) )//256
	{//enemy is far or using saber
		if ( NPC->client->ps.weapon == WP_STUN_BATON && (NPC->client->ps.stats[STAT_WEAPONS]&(1<<WP_THERMAL)) )
		{//fisticuffs, make switch to thermal if have it
			//reset fire-timing variables
			NPC_ChangeWeapon( WP_THERMAL );
		}
	}

	//can we see our target?
	if ( NPC_ClearLOS4( NPC->enemy ) )
	{
		NPCInfo->enemyLastSeenTime = level.time;
		enemyLOS3 = qtrue;

		if ( NPC->client->ps.weapon == WP_STUN_BATON )
		{
			if ( enemyDist3 <= 4096 && InFOV3( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, 90, 45 ) )//within 64 & infront
			{
				VectorCopy( NPC->enemy->r.currentOrigin, NPCInfo->enemyLastSeenLocation );
				enemyCS3 = qtrue;
			}
		}
		else if ( InFOV3( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, 45, 90 ) )
		{//in front of me 
			//can we shoot our target?
			//FIXME: how accurate/necessary is this check?
			int hit = NPC_ShotEntity( NPC->enemy, NULL );
			gentity_t *hitEnt = &g_entities[hit];
			if ( hit == NPC->enemy->s.number 
				|| ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPC->client->enemyTeam ) )
			{
				float enemyHorzDist;

				VectorCopy( NPC->enemy->r.currentOrigin, NPCInfo->enemyLastSeenLocation );
				enemyHorzDist = DistanceHorizontalSquared( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin );
				if ( enemyHorzDist < 1048576 )
				{//within 1024
					enemyCS3 = qtrue;
					NPC_AimAdjust( 2 );//adjust aim better longer we have clear shot at enemy
				}
				else
				{
					NPC_AimAdjust( 1 );//adjust aim better longer we can see enemy
				}
			}
		}
	}
	else
	{
		NPC_AimAdjust( -1 );//adjust aim worse longer we cannot see enemy
	}
	/*
	else if ( trap_InPVS( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) )
	{
		NPCInfo->enemyLastSeenTime = level.time;
		faceEnemy3 = qtrue;
	}
	*/

	if ( enemyLOS3 )
	{//FIXME: no need to face enemy if we're moving to some other goal and he's too far away to shoot?
		faceEnemy3 = qtrue;
	}

	if ( enemyCS3 )
	{
		shoot3 = qtrue;
		if ( NPC->client->ps.weapon == WP_THERMAL )
		{//don't chase and throw
			move3 = qfalse;
		}
		else if ( NPC->client->ps.weapon == WP_STUN_BATON && enemyDist3 < (NPC->r.maxs[0]+NPC->enemy->r.maxs[0]+16)*(NPC->r.maxs[0]+NPC->enemy->r.maxs[0]+16) )
		{//close enough
			move3 = qfalse;
		}
	}//this should make him chase enemy when out of range...?

	//Check for movement to take care of
	Grenadier_CheckMoveState();

	//See if we should override shooting decision with any special considerations
	Grenadier_CheckFireState();

	if ( move3 )
	{//move toward goal
		if ( NPCInfo->goalEntity )//&& ( NPCInfo->goalEntity != NPC->enemy || enemyDist3 > 10000 ) )//100 squared
		{
			move3 = Grenadier_Move();
		}
		else
		{
			move3 = qfalse;
		}
	}

	if ( !move3 )
	{
		if ( !TIMER_Done( NPC, "duck" ) )
		{
			ucmd.upmove = -127;
		}
		//FIXME: what about leaning?
	}
	else
	{//stop ducking!
		TIMER_Set( NPC, "duck", -1 );
	}

	if ( !faceEnemy3 )
	{//we want to face in the dir we're running
		if ( move3 )
		{//don't run away and shoot
			NPCInfo->desiredYaw = NPCInfo->lastPathAngles[YAW];
			NPCInfo->desiredPitch = 0;
			shoot3 = qfalse;
		}
		NPC_UpdateAngles( qtrue, qtrue );
	}
	else// if ( faceEnemy3 )
	{//face the enemy
		NPC_FaceEnemy(qtrue);
	}

	if ( NPCInfo->scriptFlags&SCF_DONT_FIRE )
	{
		shoot3 = qfalse;
	}

	//FIXME: don't shoot right away!
	if ( shoot3 )
	{//try to shoot if it's time
		if ( TIMER_Done( NPC, "attackDelay" ) )
		{	
			if( !(NPCInfo->scriptFlags & SCF_FIRE_WEAPON) ) // we've already fired, no need to do it again here
			{
				WeaponThink( qtrue );
				TIMER_Set( NPC, "attackDelay", NPCInfo->shotTime-level.time );
			}
			
		}
	}
}