Ejemplo n.º 1
0
/*
-------------------------
NAVNEW_Bypass
-------------------------
*/
qboolean NAVNEW_Bypass( gentity_t *self, gentity_t *blocker, vec3_t blocked_dir, float blocked_dist, vec3_t movedir, qboolean setBlockedInfo )
{
	//Draw debug info if requested
	if ( NAVDEBUG_showCollision )
	{
		CG_DrawEdge( self->currentOrigin, blocker->currentOrigin, EDGE_NORMAL );
	}

	vec3_t	moveangles, right;

	vectoangles( movedir, moveangles );
	moveangles[2] = 0;
	AngleVectors( moveangles, NULL, right, NULL );

	//Check to see what dir the other guy is moving in (if any) and pick the opposite dir
	if ( NAVNEW_DanceWithBlocker( self, blocker, movedir, right ) )
	{
		return qtrue;
	}

	//Okay, so he's not moving to my side, see which side of him is most clear
	if ( NAVNEW_SidestepBlocker( self, blocker, blocked_dir, blocked_dist, movedir, right ) )
	{
		return qtrue;
	}

	//Neither side is clear, tell him to step aside
	NAVNEW_PushBlocker( self, blocker, right, setBlockedInfo );

	return qfalse;
}
Ejemplo n.º 2
0
////////////////////////////////////////////////////////////////////////////////////////
// This func actually does the damage inflicting traces
////////////////////////////////////////////////////////////////////////////////////////
void Boba_FireFlameThrower( gentity_t *self )
{
	trace_t		tr;
	vec3_t		start, end, dir;
	CVec3		traceMins(self->mins);
	CVec3		traceMaxs(self->maxs);
	gentity_t*	traceEnt	= NULL;  
	int			damage		= Q_irand( BOBA_FLAMETHROWDAMAGEMIN, BOBA_FLAMETHROWDAMAGEMAX );

  	AngleVectors(self->currentAngles, dir, 0, 0); 
	dir[2] = 0.0f; 
	VectorCopy(self->currentOrigin, start); 
	traceMins *= 0.5f;
	traceMaxs *= 0.5f; 
	start[2] += 40.0f;

	VectorMA( start, 150.0f, dir, end ); 

	if (g_bobaDebug->integer)
	{
		CG_DrawEdge(start, end, EDGE_IMPACT_POSSIBLE);
	}
	gi.trace( &tr, start, self->mins, self->maxs, end, self->s.number, MASK_SHOT, (EG2_Collision)0, 0);

	traceEnt = &g_entities[tr.entityNum];
	if ( tr.entityNum < ENTITYNUM_WORLD && traceEnt->takedamage )
	{
		G_Damage( traceEnt, self, self, dir, tr.endpos, damage, DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK|DAMAGE_NO_HIT_LOC|DAMAGE_IGNORE_TEAM, MOD_LAVA, HL_NONE );
		if (traceEnt->health>0)
		{
//			G_Knockdown( traceEnt, self, dir, Q_irand(200, 330), qfalse);
			G_Throw(traceEnt, dir, 30);
		}
	}
}
Ejemplo n.º 3
0
void	Pilot_Steer_Vehicle()
{
	if (!NPC->enemy || !NPC->enemy->client)
	{
		return;
	}






// SETUP
//=======
	// Setup Actor Data
	//------------------
	CVec3		ActorPos(NPC->currentOrigin);
	CVec3		ActorAngles(NPC->currentAngles);
				ActorAngles[2]	= 0;
	Vehicle_t*	ActorVeh		= NPCInfo->greetEnt->m_pVehicle;
	bool		ActorInTurbo	= (ActorVeh->m_iTurboTime>level.time);
	float		ActorSpeed		= (ActorVeh)?(VectorLength(ActorVeh->m_pParentEntity->client->ps.velocity)):(NPC->client->ps.speed);


	// If my vehicle is spinning out of control, just hold on, we're going to die!!!!!
	//---------------------------------------------------------------------------------
	if (ActorVeh && (ActorVeh->m_ulFlags & VEH_OUTOFCONTROL))
	{
		if (NPC->client->ps.weapon!=WP_NONE)
		{
			NPC_ChangeWeapon(WP_NONE);
		}
		ucmd.buttons	&=~BUTTON_ATTACK;
		ucmd.buttons	&=~BUTTON_ALT_ATTACK;
		return;
	}

	CVec3		ActorDirection;
				AngleVectors(ActorAngles.v, ActorDirection.v, 0, 0);

	CVec3		ActorFuturePos(ActorPos);
				ActorFuturePos.ScaleAdd(ActorDirection, FUTURE_PRED_DIST);

	bool		ActorDoTurbo	= false;
	bool		ActorAccelerate	= false;
	bool		ActorAimAtTarget= true;
	float		ActorYawOffset	= 0.0f;


	// Setup Enemy Data
	//------------------
	CVec3		EnemyPos(NPC->enemy->currentOrigin);
	CVec3		EnemyAngles(NPC->enemy->currentAngles);
				EnemyAngles[2]	= 0;
	Vehicle_t*	EnemyVeh		= (NPC->enemy->s.m_iVehicleNum)?(g_entities[NPC->enemy->s.m_iVehicleNum].m_pVehicle):(0);
	bool		EnemyInTurbo	= (EnemyVeh && EnemyVeh->m_iTurboTime>level.time);
	float		EnemySpeed		= (EnemyVeh)?(EnemyVeh->m_pParentEntity->client->ps.speed):(NPC->enemy->resultspeed);
	bool		EnemySlideBreak	= (EnemyVeh && (EnemyVeh->m_ulFlags&VEH_SLIDEBREAKING || EnemyVeh->m_ulFlags&VEH_STRAFERAM));
	bool		EnemyDead		= (NPC->enemy->health<=0);

	bool		ActorFlank		= (NPCInfo->lastAvoidSteerSideDebouncer>level.time && EnemyVeh && EnemySpeed>10.0f);

	CVec3		EnemyDirection;
	CVec3		EnemyRight;
				AngleVectors(EnemyAngles.v, EnemyDirection.v, EnemyRight.v, 0);

	CVec3		EnemyFuturePos(EnemyPos);
				EnemyFuturePos.ScaleAdd(EnemyDirection, FUTURE_PRED_DIST);

	ESide		EnemySide		= ActorPos.LRTest(EnemyPos, EnemyFuturePos);
	CVec3		EnemyFlankPos(EnemyFuturePos);
				EnemyFlankPos.ScaleAdd(EnemyRight, (EnemySide==Side_Right)?(FUTURE_SIDE_DIST):(-FUTURE_SIDE_DIST));

	// Debug Draw Enemy Data
	//-----------------------
	if (false)
	{
		CG_DrawEdge(EnemyPos.v,			EnemyFuturePos.v, EDGE_IMPACT_SAFE);
		CG_DrawEdge(EnemyFuturePos.v,	EnemyFlankPos.v, EDGE_IMPACT_SAFE);
	}


	// Setup Move And Aim Directions
	//-------------------------------
	CVec3		MoveDirection((ActorFlank)?(EnemyFlankPos):(EnemyFuturePos));
				MoveDirection	-= ActorPos;
	float		MoveDistance	= MoveDirection.SafeNorm();
	float		MoveAccuracy	= MoveDirection.Dot(ActorDirection);

	CVec3		AimDirection(EnemyPos);
				AimDirection	-= ActorPos;
	float		AimDistance		= AimDirection.SafeNorm();
	float		AimAccuracy		= AimDirection.Dot(ActorDirection);



	if (!ActorFlank && TIMER_Done(NPC, "FlankAttackCheck"))
	{
		TIMER_Set(NPC, "FlankAttackCheck", Q_irand(1000, 3000));
		if (MoveDistance<4000 && Q_irand(0, 1)==0)
		{
			NPCInfo->lastAvoidSteerSideDebouncer	= level.time + Q_irand(8000, 14000);
		}
	}



	// Fly By Sounds
	//---------------
	if ((ActorVeh->m_pVehicleInfo->soundFlyBy || ActorVeh->m_pVehicleInfo->soundFlyBy2) &&
		EnemyVeh &&
		MoveDistance<800 &&
		ActorSpeed>500.0f &&
		TIMER_Done(NPC, "FlybySoundDebouncer")
		)
	{
		if (EnemySpeed<100.0f || (ActorDirection.Dot(EnemyDirection)*(MoveDistance/800.0f))<-0.5f)
		{
			TIMER_Set(NPC, "FlybySoundDebouncer", 2000);
			int soundFlyBy = ActorVeh->m_pVehicleInfo->soundFlyBy;
			if (ActorVeh->m_pVehicleInfo->soundFlyBy2 && (!soundFlyBy || !Q_irand(0,1)))
			{
				soundFlyBy = ActorVeh->m_pVehicleInfo->soundFlyBy2;
			}
			G_Sound(ActorVeh->m_pParentEntity, soundFlyBy);		
		}
	}



// FLY PAST BEHAVIOR
//===================
 	if (EnemySlideBreak || !TIMER_Done(NPC, "MinHoldDirectionTime"))
	{
		if (TIMER_Done(NPC, "MinHoldDirectionTime"))
		{ 
			TIMER_Set(NPC, "MinHoldDirectionTime", 500);	// Hold For At Least 500 ms
		}
		ActorAccelerate		= true;							// Go
		ActorAimAtTarget	= false;						// Don't Alter Our Aim Direction
		ucmd.buttons		&=~BUTTON_VEH_SPEED;			// Let Normal Vehicle Controls Go
	}


// FLANKING BEHAVIOR
//===================
	else if (ActorFlank)
	{
  		ActorAccelerate	= true;
		ActorDoTurbo	= (MoveDistance>2500 || EnemyInTurbo);
		ucmd.buttons	|= BUTTON_VEH_SPEED;			// Tells PMove to use the ps.speed we calculate here, not the one from g_vehicles.c


		// For Flanking, We Calculate The Speed By Hand, Rather Than Using Pure Accelerate / No Accelerate Functionality
		//---------------------------------------------------------------------------------------------------------------
		NPC->client->ps.speed = ActorVeh->m_pVehicleInfo->speedMax * ((ActorInTurbo)?(1.35f):(1.15f));


		// If In Slowing Distance, Scale Down The Speed As We Approach Our Move Target
		//-----------------------------------------------------------------------------
		if (MoveDistance<ATTACK_FLANK_SLOWING)
		{
			NPC->client->ps.speed *= (MoveDistance/ATTACK_FLANK_SLOWING);
			NPC->client->ps.speed += EnemySpeed;

			// Match Enemy Speed
			//-------------------
			if (NPC->client->ps.speed<5.0f && EnemySpeed<5.0f)
			{
				NPC->client->ps.speed = EnemySpeed;
			}

			// Extra Slow Down When Out In Front
			//-----------------------------------
 			if  (MoveAccuracy<0.0f)
			{
				NPC->client->ps.speed *= (MoveAccuracy + 1.0f);
			}

	
			MoveDirection	*=        (MoveDistance/ATTACK_FLANK_SLOWING);
			EnemyDirection	*= 1.0f - (MoveDistance/ATTACK_FLANK_SLOWING);
			MoveDirection	+= EnemyDirection;

			if (TIMER_Done(NPC, "RamCheck"))
			{
				TIMER_Set(NPC, "RamCheck", Q_irand(1000, 3000));
				if (MoveDistance<RAM_DIST && Q_irand(0, 2)==0)
				{
					VEH_StartStrafeRam(ActorVeh, (EnemySide==Side_Left));
				}
			}
		}
	}


// NORMAL CHASE BEHAVIOR
//=======================
	else
	{
		if (!EnemyVeh && AimAccuracy>0.99f && MoveDistance<500 && !EnemyDead)
		{
			ActorAccelerate = true;
			ActorDoTurbo	= false;
		}
		else
		{
			ActorAccelerate = ((MoveDistance>500 && EnemySpeed>20.0f) || MoveDistance>1000);
			ActorDoTurbo	= (MoveDistance>3000 && EnemySpeed>20.0f);
		}
		ucmd.buttons	&=~BUTTON_VEH_SPEED;
	}




// APPLY RESULTS
//=======================
	// Decide Turbo
	//--------------
	if (ActorDoTurbo || ActorInTurbo)
	{
		ucmd.buttons |= BUTTON_ALT_ATTACK;
	}
	else
	{
		ucmd.buttons &=~BUTTON_ALT_ATTACK;
	}

	// Decide Acceleration
	//---------------------
	ucmd.forwardmove = (ActorAccelerate)?(127):(0);



	// Decide To Shoot
	//-----------------
	ucmd.buttons	&=~BUTTON_ATTACK;
	ucmd.rightmove	= 0;
 	if (AimDistance<2000 && !EnemyDead)
	{
		// If Doing A Ram Attack
		//-----------------------
		if (ActorYawOffset!=0)
		{
			if (NPC->client->ps.weapon!=WP_NONE)
			{
				NPC_ChangeWeapon(WP_NONE);
			}
			ucmd.buttons	&=~BUTTON_ATTACK;
		}
 		else if (AimAccuracy>ATTACK_FWD)
		{
			if (NPC->client->ps.weapon!=WP_NONE)
			{
				NPC_ChangeWeapon(WP_NONE);
			}
			ucmd.buttons	|= BUTTON_ATTACK;
		}
		else if (AimAccuracy<AIM_SIDE && AimAccuracy>-AIM_SIDE)
		{
			if (NPC->client->ps.weapon!=WP_BLASTER)
			{
				NPC_ChangeWeapon(WP_BLASTER);
			}

			if (AimAccuracy<ATTACK_SIDE && AimAccuracy>-ATTACK_SIDE)
			{
				//if (!TIMER_Done(NPC, "RiderAltAttack"))
				//{
				//	ucmd.buttons |= BUTTON_ALT_ATTACK;
				//}
				//else
				//{
                    ucmd.buttons |= BUTTON_ATTACK;

			/*		if (TIMER_Done(NPC, "RiderAltAttackCheck"))
					{
						TIMER_Set(NPC, "RiderAltAttackCheck", Q_irand(1000, 3000));
						if (Q_irand(0, 2)==0)
						{
							TIMER_Set(NPC, "RiderAltAttack", 300);
						}
					}*/
				//}
				WeaponThink(true);
			}
			ucmd.rightmove = (EnemySide==Side_Left)?( 127):(-127);
		}
		else
		{
			if (NPC->client->ps.weapon!=WP_NONE)
			{
				NPC_ChangeWeapon(WP_NONE);
			}
		}
	}
	else
	{
		if (NPC->client->ps.weapon!=WP_NONE)
		{
			NPC_ChangeWeapon(WP_NONE);
		}
	}


	// Aim At Target
	//---------------
	if (ActorAimAtTarget)
	{
		MoveDirection.VecToAng();
		NPCInfo->desiredPitch	= AngleNormalize360(MoveDirection[PITCH]);
		NPCInfo->desiredYaw		= AngleNormalize360(MoveDirection[YAW] + ActorYawOffset);
	}
	NPC_UpdateAngles(qtrue, qtrue);
}
Ejemplo n.º 4
0
bool	Boba_Flee()
{
	bool	EnemyRecentlySeen	= ((level.time - NPCInfo->enemyLastSeenTime)<10000);
	bool	ReachedEscapePoint	= (Distance(level.combatPoints[NPCInfo->combatPoint].origin, NPC->currentOrigin)<50.0f);
	bool	HasBeenGoneEnough	= (level.time>NPCInfo->surrenderTime || (level.time - NPCInfo->enemyLastSeenTime)>400000);


	// Is It Time To Come Back For Some More?
	//----------------------------------------
 	if (!EnemyRecentlySeen || ReachedEscapePoint)
	{
		NPC->svFlags |= SVF_NOCLIENT;
		if (HasBeenGoneEnough)
		{
			if ((level.time - NPCInfo->enemyLastSeenTime)>400000)
			{
				Boba_Printf("  Gone Too Long, Attempting Respawn");
			}

			if (Boba_Respawn())
			{
				return true;
			}
		}
	  	else if (ReachedEscapePoint && (NPCInfo->surrenderTime - level.time)>3000)
		{
 			if (TIMER_Done(NPC, "SpookPlayerTimer"))
			{
				vec3_t		testDirection;
				TIMER_Set(NPC, "SpookPlayerTimer", Q_irand(2000, 10000));
				switch(Q_irand(0, 1))
				{
				case 0:
					Boba_Printf("SPOOK: Dust");
					Boba_DustFallNear(NPC->enemy->currentOrigin, Q_irand(1,2));
					break;

				case 1:
					Boba_Printf("SPOOK: Footsteps");
  					testDirection[0] =  (random() * 0.5f) - 1.0f;
	 		 		testDirection[0] += (testDirection[0]>0.0f)?(0.5f):(-0.5f);
					testDirection[1] = (random() * 0.5f) - 1.0f;
					testDirection[1] += (testDirection[1]>0.0f)?(0.5f):(-0.5f);
					testDirection[2] = 1.0f;
		 	 		VectorMA(NPC->enemy->currentOrigin, 400.0f, testDirection, BobaFootStepLoc);

					BobaFootStepCount = Q_irand(3,8);
					break;
				}
			}

			if (BobaFootStepCount && TIMER_Done(NPC, "BobaFootStepFakeTimer"))
			{
				TIMER_Set(NPC, "BobaFootStepFakeTimer", Q_irand(300, 800));
				BobaFootStepCount --;
				G_SoundAtSpot(BobaFootStepLoc, G_SoundIndex(va("sound/player/footsteps/boot%d", Q_irand(1,4))), qtrue);
			}

		 	if (TIMER_Done(NPC, "ResampleEnemyDirection") && NPC->enemy->resultspeed>10.0f)
			{
				TIMER_Set(NPC, "ResampleEnemyDirection", Q_irand(500, 1000));
				AverageEnemyDirectionSamples ++;

				vec3_t	moveDir;
				VectorCopy(NPC->enemy->client->ps.velocity, moveDir);
				VectorNormalize(moveDir);

				VectorAdd(AverageEnemyDirection, moveDir, AverageEnemyDirection);
			}

	 		if (g_bobaDebug->integer && AverageEnemyDirectionSamples)
			{
				vec3_t	endPos;
				VectorMA(NPC->enemy->currentOrigin, 500.0f / (float)AverageEnemyDirectionSamples, AverageEnemyDirection, endPos);
				CG_DrawEdge(NPC->enemy->currentOrigin, endPos, EDGE_IMPACT_POSSIBLE);
			}
		}
	}
	else
	{
		NPCInfo->surrenderTime += 100;
	}

	// Finish The Flame Thrower First...
	//-----------------------------------
	if (NPCInfo->aiFlags&NPCAI_FLAMETHROW)
	{
		Boba_DoFlameThrower( NPC );
		NPC_FacePosition( NPC->enemy->currentOrigin, qtrue);
		NPC_UpdateAngles(qtrue, qtrue);
		return true;
	}

	bool	IsOnAPath = !!NPC_MoveToGoal(qtrue);
	if (!ReachedEscapePoint &&
		NPCInfo->aiFlags&NPCAI_BLOCKED && 
		NPC->client->moveType!=MT_FLYSWIM && 
		((level.time - NPCInfo->blockedDebounceTime)>1000)
		)
	{
		if (!Boba_CanSeeEnemy(NPC) && Distance(NPC->currentOrigin, level.combatPoints[NPCInfo->combatPoint].origin)<200)
		{
			Boba_Printf("BLOCKED: Just Teleporting There");
			G_SetOrigin(NPC, level.combatPoints[NPCInfo->combatPoint].origin);
		}
		else
		{
			Boba_Printf("BLOCKED: Attempting Jump");

			if (IsOnAPath)
			{
				if (NPC_TryJump(NPCInfo->blockedTargetPosition))
				{
				}
				else
				{
					Boba_Printf("  Failed");
				}
			}
			else if (EnemyRecentlySeen)
			{
				if (NPC_TryJump(NPCInfo->enemyLastSeenLocation))
				{
	 			}
				else
				{
					Boba_Printf("  Failed");
				}
			}
		}
	}


	NPC_UpdateAngles( qtrue, qtrue );
	return true;
}
Ejemplo n.º 5
0
void	Boba_Update()
{
	// Never Forget The Player... Never.
	//-----------------------------------
	if (player && player->inuse && !NPC->enemy)
	{
		G_SetEnemy(NPC, player);
		NPC->svFlags				|= SVF_LOCKEDENEMY;	// Don't forget about the enemy once you've found him
	}

	// Hey, This Is Boba, He Tests The Trace All The Time
	//----------------------------------------------------
	if (NPC->enemy)
	{
		if (!(NPC->svFlags&SVF_NOCLIENT))
		{
			trace_t		testTrace;
			vec3_t		eyes;
			CalcEntitySpot( NPC, SPOT_HEAD_LEAN, eyes );
			gi.trace (&testTrace, eyes, NULL, NULL, NPC->enemy->currentOrigin, NPC->s.number, MASK_SHOT, (EG2_Collision)0, 0);

			bool	wasSeen = Boba_CanSeeEnemy(NPC);

			if (!testTrace.startsolid && 
				!testTrace.allsolid && 
				testTrace.entityNum == NPC->enemy->s.number)
			{
				NPCInfo->enemyLastSeenTime	= level.time;
				NPCInfo->enemyLastHeardTime	= level.time;
				VectorCopy(NPC->enemy->currentOrigin, NPCInfo->enemyLastSeenLocation);
				VectorCopy(NPC->enemy->currentOrigin, NPCInfo->enemyLastHeardLocation);
			}
			else if (gi.inPVS( NPC->enemy->currentOrigin, NPC->currentOrigin))
			{
				NPCInfo->enemyLastHeardTime	= level.time;
				VectorCopy(NPC->enemy->currentOrigin, NPCInfo->enemyLastHeardLocation);
			}

			if (g_bobaDebug->integer)
			{
				bool	nowSeen = Boba_CanSeeEnemy(NPC);
				if (!wasSeen && nowSeen)
				{
					Boba_Printf("Enemy Seen");
				}
				if (wasSeen && !nowSeen)
				{
					Boba_Printf("Enemy Lost");
				}
				CG_DrawEdge(NPC->currentOrigin, NPC->enemy->currentOrigin, (nowSeen)?(EDGE_IMPACT_SAFE):(EDGE_IMPACT_POSSIBLE));
			}
		}

		if (!NPCInfo->surrenderTime)
		{
			if ((level.time - NPCInfo->enemyLastSeenTime)>20000 && TIMER_Done(NPC, "TooLongGoneRespawn"))
			{
				TIMER_Set(NPC, "TooLongGoneRespawn", 30000);	// Give him some time to get to you before trying again
				Boba_Printf("Gone Too Long, Attempting Respawn Even Though Not Hiding");
				Boba_Respawn();
			}
		}
	}


	// Make Sure He Always Appears In The Last Area With Full Health When His Death Script Is Turned On
	//--------------------------------------------------------------------------------------------------
	if (!BobaHadDeathScript && NPC->behaviorSet[BSET_DEATH]!=0)
	{
		if (!gi.inPVS(NPC->enemy->currentOrigin, NPC->currentOrigin))
		{
			Boba_Printf("Attempting Final Battle Spawn...");
			if (Boba_Respawn())
			{
				BobaHadDeathScript = true;
			}
			else
			{
				Boba_Printf("Failed");
			}
		}
	}



	// Don't Forget To Turn Off That Flame Thrower, Mr. Fett - You're Waisting Precious Natural Gases
	//------------------------------------------------------------------------------------------------
	if ((NPCInfo->aiFlags&NPCAI_FLAMETHROW) && (TIMER_Done(NPC, "flameTime")))
	{
		Boba_StopFlameThrower(NPC);
	}


	// Occasionally A Jump Turns Into A Rocket Fly
	//---------------------------------------------
	if ( NPC->client->ps.groundEntityNum == ENTITYNUM_NONE 
		&& NPC->client->ps.forceJumpZStart
		&& !Q_irand( 0, 10 ) )
	{//take off
		Boba_FlyStart( NPC );
	}


	// If Hurting, Try To Run Away
	//-----------------------------
	if (!NPCInfo->surrenderTime && (NPC->health<NPC->max_health/10))
	{
		Boba_Printf("Time To Surrender, Searching For Flee Point");


		// Find The Closest Flee Point That I Can Get To
		//-----------------------------------------------
		int cp = NPC_FindCombatPoint(NPC->currentOrigin, 0, NPC->currentOrigin, CP_FLEE|CP_HAS_ROUTE|CP_TRYFAR|CP_HORZ_DIST_COLL, 0, -1);
		if (cp!=-1)
		{
			NPC_SetCombatPoint( cp );
			NPC_SetMoveGoal( NPC, level.combatPoints[cp].origin, 8, qtrue, cp );
			if (NPC->count<6)
			{
 	 		 	NPCInfo->surrenderTime = level.time + Q_irand(5000, 10000) + 1000*(6-NPC->count);
			}
			else
			{
 	 			NPCInfo->surrenderTime = level.time + Q_irand(5000, 10000);
			}
		}
		else
		{
			Boba_Printf("  Failure");
		}
	}
}
Ejemplo n.º 6
0
/*
-------------------------
NAVNEW_MoveToGoal
-------------------------
*/
int	NAVNEW_MoveToGoal( gentity_t *self, navInfo_t &info )
{
	int			bestNode = WAYPOINT_NONE;
	qboolean	foundClearPath = qfalse;
	vec3_t		origin;
	navInfo_t	tempInfo;
	qboolean	setBlockedInfo = qtrue;
	qboolean	inGoalWP;
	int			numTries = 0;

	memcpy( &tempInfo, &info, sizeof( tempInfo ) );

	//Must have a goal entity to move there
	if( self->NPC->goalEntity == NULL )
		return WAYPOINT_NONE;

	if ( self->waypoint == WAYPOINT_NONE && self->noWaypointTime > level.time )
	{//didn't have a valid one in about the past second, don't look again just yet
		return WAYPOINT_NONE;
	}
	if ( self->NPC->goalEntity->waypoint == WAYPOINT_NONE && self->NPC->goalEntity->noWaypointTime > level.time )
	{//didn't have a valid one in about the past second, don't look again just yet
		return WAYPOINT_NONE;
	}
	if ( self->noWaypointTime > level.time &&
		self->NPC->goalEntity->noWaypointTime > level.time )
	{//just use current waypoints
		bestNode = navigator.GetBestNodeAltRoute( self->waypoint, self->NPC->goalEntity->waypoint, bestNode );
	}
	//FIXME!!!!: this is making them wiggle back and forth between waypoints
	else if ( (bestNode = navigator.GetBestPathBetweenEnts( self, self->NPC->goalEntity, NF_CLEAR_PATH )) == NODE_NONE )//!NAVNEW_GetWaypoints( self, qtrue ) )
	{//one of us didn't have a valid waypoint!
		if ( self->waypoint == NODE_NONE )
		{//don't even try to find one again for a bit
			self->noWaypointTime = level.time + Q_irand( 500, 1500 );
		}
		if ( self->NPC->goalEntity->waypoint == NODE_NONE )
		{//don't even try to find one again for a bit
			self->NPC->goalEntity->noWaypointTime = level.time + Q_irand( 500, 1500 );
		}
		return WAYPOINT_NONE;
	}
	else
	{
		if ( self->NPC->goalEntity->noWaypointTime < level.time )
		{
			self->NPC->goalEntity->noWaypointTime = level.time + Q_irand( 500, 1500 );
		}
	}

	while( !foundClearPath )
	{
		/*inBestWP = */inGoalWP = qfalse;
		/*
		bestNode = navigator.GetBestNodeAltRoute( self->waypoint, self->NPC->goalEntity->waypoint, bestNode );
		*/

		if ( bestNode == WAYPOINT_NONE )
		{
			goto failed;
		}

		//see if we can get directly to the next node off bestNode en route to goal's node...
		//NOTE: shouldn't be necc. now
		/*
		int oldBestNode = bestNode;
		bestNode = NAV_TestBestNode( self, self->waypoint, bestNode, qtrue );//, self->NPC->goalEntity->waypoint );//
		//NOTE: Guaranteed to return something
		if ( bestNode != oldBestNode )
		{//we were blocked somehow
			if ( setBlockedInfo )
			{
				self->NPC->aiFlags |= NPCAI_BLOCKED;
				navigator.GetNodePosition( oldBestNode, NPCInfo->blockedDest );
			}
		}
		*/
		navigator.GetNodePosition( bestNode, origin );
		/*
		if ( !goalWPFailed )
		{//we haven't already tried to go straight to goal or goal's wp
			if ( bestNode == self->NPC->goalEntity->waypoint )
			{//our bestNode is the goal's wp
				if ( NAV_HitNavGoal( self->currentOrigin, self->mins, self->maxs, origin, navigator.GetNodeRadius( bestNode ), FlyingCreature( self ) ) )
				{//we're in the goal's wp
					inGoalWP = qtrue;
					//we're in the goalEntity's waypoint already
					//so head for the goalEntity since we know it's clear of architecture
					//FIXME: this is pretty stupid because the NPCs try to go straight
					//		towards their goal before then even try macro_nav...
					VectorCopy( self->NPC->goalEntity->currentOrigin, origin );
				}
			}
		}
		*/
		if ( !inGoalWP )
		{//not heading straight for goal
			if ( bestNode == self->waypoint )
			{//we know it's clear or architecture
				//navigator.GetNodePosition( self->waypoint, origin );
				/*
				if ( NAV_HitNavGoal( self->currentOrigin, self->mins, self->maxs, origin, navigator.GetNodeRadius( bestNode ), FlyingCreature( self ) ) )
				{//we're in the wp we're heading for already
					inBestWP = qtrue;
				}
				*/
			}
			else
			{//heading to an edge off our confirmed clear waypoint... make sure it's clear
				//it it's not, bestNode will fall back to our waypoint
				int oldBestNode = bestNode;
				bestNode = NAV_TestBestNode( self, self->waypoint, bestNode, qtrue );
				if ( bestNode == self->waypoint )
				{//we fell back to our waypoint, reset the origin
					self->NPC->aiFlags |= NPCAI_BLOCKED;
					navigator.GetNodePosition( oldBestNode, NPCInfo->blockedDest );
					navigator.GetNodePosition( bestNode, origin );
				}
			}
		}
		//Com_Printf( "goalwp = %d, mywp = %d, node = %d, origin = %s\n", self->NPC->goalEntity->waypoint, self->waypoint, bestNode, vtos(origin) );

		memcpy( &tempInfo, &info, sizeof( tempInfo ) );
		VectorSubtract( origin, self->currentOrigin, tempInfo.direction );
		VectorNormalize( tempInfo.direction );

		//NOTE: One very important thing NAVNEW_AvoidCollision does is
		//		it actually CHANGES the value of "direction" - it changes it to
		//		whatever dir you need to go in to avoid the obstacle...
		foundClearPath = NAVNEW_AvoidCollision( self, self->NPC->goalEntity, tempInfo, setBlockedInfo, 5 );

		if ( !foundClearPath )
		{//blocked by an ent
			if ( inGoalWP )
			{//we were heading straight for the goal, head for the goal's wp instead
				navigator.GetNodePosition( bestNode, origin );
				foundClearPath = NAVNEW_AvoidCollision( self, self->NPC->goalEntity, tempInfo, setBlockedInfo, 5 );
			}
		}

		if ( foundClearPath )
		{//clear!
			//If we got set to blocked, clear it
			NPC_ClearBlocked( self );
			//Take the dir
			memcpy( &info, &tempInfo, sizeof( info ) );
			if ( self->s.weapon == WP_SABER )
			{//jedi
				if ( info.direction[2] * info.distance > 64 )
				{
					self->NPC->aiFlags |= NPCAI_BLOCKED;
					VectorCopy( origin, NPCInfo->blockedDest );
					goto failed;
				}
			}
		}
		else
		{//blocked by ent!
			if ( setBlockedInfo )
			{
				self->NPC->aiFlags |= NPCAI_BLOCKED;
				navigator.GetNodePosition( bestNode, NPCInfo->blockedDest );
			}
			//Only set blocked info first time
			setBlockedInfo = qfalse;

			if ( inGoalWP )
			{//we headed for our goal and failed and our goal's WP and failed
				if ( self->waypoint == self->NPC->goalEntity->waypoint )
				{//our waypoint is our goal's waypoint, nothing we can do
					//remember that this node is blocked
					navigator.AddFailedNode( self, self->waypoint );
					goto failed;
				}
				else
				{//try going for our waypoint this time
					//goalWPFailed = qtrue;
					inGoalWP = qfalse;
				}
			}
			else if ( bestNode != self->waypoint )
			{//we headed toward our next waypoint (instead of our waypoint) and failed
				if ( d_altRoutes->integer )
				{//mark this edge failed and try our waypoint
					//NOTE: don't assume there is something blocking the direct path
					//			between my waypoint and the bestNode... I could be off
					//			that path because of collision avoidance...
					if ( d_patched->integer &&//use patch-style navigation
 						( !navigator.NodesAreNeighbors( self->waypoint, bestNode )
						|| NAVNEW_TestNodeConnectionBlocked( self->waypoint, bestNode, self, self->NPC->goalEntity->s.number, qfalse, qtrue ) ) )
					{//the direct path between these 2 nodes is blocked by an ent
						navigator.AddFailedEdge( self->s.number, self->waypoint, bestNode );
					}
					bestNode = self->waypoint;
				}
				else
				{
					//we should stop
					goto failed;
				}
			}
			else
			{//we headed for *our* waypoint and couldn't get to it
				if ( d_altRoutes->integer )
				{
					//remember that this node is blocked
					navigator.AddFailedNode( self, self->waypoint );
					//Now we should get our waypoints again
					//FIXME: cache the trace-data for subsequent calls as only the route info would have changed
					//if ( (bestNode = navigator.GetBestPathBetweenEnts( self, self->NPC->goalEntity, NF_CLEAR_PATH )) == NODE_NONE )//!NAVNEW_GetWaypoints( self, qfalse ) )
					{//one of our waypoints is WAYPOINT_NONE now
						goto failed;
					}
				}
				else
				{
					//we should stop
					goto failed;
				}
			}

			if ( ++numTries >= 10 )
			{
				goto failed;
			}
		}
	}

//finish:
	//Draw any debug info, if requested
	if ( NAVDEBUG_showEnemyPath )
	{
		vec3_t	dest, start;

		//Get the positions
		navigator.GetNodePosition( self->NPC->goalEntity->waypoint, dest );
		navigator.GetNodePosition( bestNode, start );

		//Draw the route
		CG_DrawNode( start, NODE_START );
		if ( bestNode != self->waypoint )
		{
			vec3_t	wpPos;
			navigator.GetNodePosition( self->waypoint, wpPos );
			CG_DrawNode( wpPos, NODE_NAVGOAL );
		}
		CG_DrawNode( dest, NODE_GOAL );
		CG_DrawEdge( dest, self->NPC->goalEntity->currentOrigin, EDGE_PATH );
		CG_DrawNode( self->NPC->goalEntity->currentOrigin, NODE_GOAL );
		navigator.ShowPath( bestNode, self->NPC->goalEntity->waypoint );
	}

	self->NPC->shoveCount = 0;

	//let me keep this waypoint for a while
	if ( self->noWaypointTime < level.time )
	{
		self->noWaypointTime = level.time + Q_irand( 500, 1500 );
	}
	return bestNode;

failed:
	//FIXME: What we should really do here is have a list of the goal's and our
	//		closest clearpath waypoints, ranked.  If the first set fails, try the rest
	//		until there are no alternatives.

	navigator.GetNodePosition( self->waypoint, origin );

	//do this to avoid ping-ponging?
	return WAYPOINT_NONE;
	/*
	//this was causing ping-ponging
	if ( DistanceSquared( origin, self->currentOrigin ) < 16 )//woo, magic number
	{//We're right up on our waypoint, so that won't help, return none
		//Or maybe find the nextbest here?
		return WAYPOINT_NONE;
	}
	else
	{//Try going to our waypoint
		bestNode = self->waypoint;

		VectorSubtract( origin, self->currentOrigin, info.direction );
		VectorNormalize( info.direction );
	}

	goto finish;
	*/
}
Ejemplo n.º 7
0
/*
-------------------------
NAVNEW_AvoidCollision
-------------------------
*/
qboolean NAVNEW_AvoidCollision( gentity_t *self, gentity_t *goal, navInfo_t &info, qboolean setBlockedInfo, int blockedMovesLimit )
{
	vec3_t	movedir;
	vec3_t	movepos;

	//Cap our distance
	if ( info.distance > MAX_COLL_AVOID_DIST )
	{
		info.distance = MAX_COLL_AVOID_DIST;
	}

	//Get an end position
	VectorMA( self->currentOrigin, info.distance, info.direction, movepos );
	VectorCopy( info.direction, movedir );

	//Now test against entities
	if ( NAV_CheckAhead( self, movepos, info.trace, CONTENTS_BODY ) == qfalse )
	{
		//Get the blocker
		info.blocker = &g_entities[ info.trace.entityNum ];
		info.flags |= NIF_COLLISION;

		//Ok to hit our goal entity
		if ( goal == info.blocker )
			return qtrue;

		if ( setBlockedInfo )
		{
			if ( self->NPC->consecutiveBlockedMoves > blockedMovesLimit  )
			{
				if ( d_patched->integer )
				{//use patch-style navigation
					self->NPC->consecutiveBlockedMoves++;
				}
				NPC_SetBlocked( self, info.blocker );
				return qfalse;
			}
			self->NPC->consecutiveBlockedMoves++;
		}
		//See if we're moving along with them
		//if ( NAVNEW_TrueCollision( self, info.blocker, movedir, info.direction ) == qfalse )
		//	return qtrue;

		//Test for blocking by standing on goal
		if ( NAV_TestForBlocked( self, goal, info.blocker, info.distance, info.flags ) == qtrue )
			return qfalse;

		//If the above function said we're blocked, don't do the extra checks
		/*
		if ( info.flags & NIF_BLOCKED )
			return qtrue;
		*/

		//See if we can get that entity to move out of our way
		if ( NAVNEW_ResolveEntityCollision( self, info.blocker, movedir, info.pathDirection, setBlockedInfo ) == qfalse )
			return qfalse;

		VectorCopy( movedir, info.direction );

		return qtrue;
	}
	else
	{
		if ( setBlockedInfo )
		{
			self->NPC->consecutiveBlockedMoves = 0;
		}
	}

	//Our path is clear, just move there
	if ( NAVDEBUG_showCollision )
	{
		CG_DrawEdge( self->currentOrigin, movepos, EDGE_MOVEDIR );
	}

	return qtrue;
}
Ejemplo n.º 8
0
void	Rail_Update()
{
	if (mRailSystemActive)// && false)
	{
		for (int track=0; track<mRailTracks.size(); track++)
		{
			if (level.time>mRailTracks[track].mNextUpdateTime && !mRailTracks[track].mMovers.empty())
			{
				mRailTracks[track].Update();
			}
		}

		// Is The Player Outside?
		//------------------------
 		if (player && gi.WE_IsOutside(player->currentOrigin))
		{
			int		wooshSound;
			vec3_t	wooshSoundPos;
			vec3_t	moverOrigin;
			vec3_t	playerToMover;
			float	playerToMoverDistance;
			float	playerToMoverDistanceFraction;

			// Iterate Over All The Movers
			//-----------------------------
 			for (int moverIndex=0; moverIndex<mRailMovers.size(); moverIndex++)
			{
 				CRailMover&	mover = mRailMovers[moverIndex];

				// Is It Active, And Has The Sound Already Played On It?
				//--------------------------------------------------------
   			 	if (mover.Active() && !mover.mSoundPlayed)
				{ 
 					VectorAdd(mover.mEnt->currentOrigin, mover.mOriginOffset.v, moverOrigin);
 					VectorSubtract(moverOrigin, player->currentOrigin, playerToMover);
					playerToMover[2]		= 0.0f;
 					playerToMoverDistance	= VectorNormalize(playerToMover);


					// Is It Close Enough?
					//---------------------
					if ((( mover.mLane || !mover.mCenter) &&								// Not Center Track
						 (playerToMoverDistance<WOOSH_ALL_RANGE) && 						//  And Close Enough
						 (DotProduct(playerToMover, mover.mTrack->mDirection.v)>-0.45f))	//  And On The Side
						||																	//OR
						((!mover.mLane &&  mover.mCenter) &&								// Is Center Track
						  (playerToMoverDistance<WOOSH_SUPPORT_RANGE ||						//  And Close Enough for Support
						  (playerToMoverDistance<WOOSH_TUNNEL_RANGE && mover.mRows>10))		//   Or Close Enough For Tunnel
						 ))
					{
						mover.mSoundPlayed = true;
						wooshSound = 0;

						// The Centered Entities Play Right On The Player's Head For Full Volume
						//-----------------------------------------------------------------------
						if (mover.mCenter && !mover.mLane)
						{
 							VectorCopy(player->currentOrigin, wooshSoundPos);
 							wooshSoundPos[2] += 50;

							// If It Is Very Long, Play The Tunnel Sound
							//-------------------------------------------
							if (mover.mRows>10)
							{
								wooshSound = mWooshTun[Q_irand(0, mWooshTun.size()-1)];
							}

							// Otherwise It Is A Support
							//---------------------------
							else 
							{ 
								wooshSound = mWooshSup[Q_irand(0, mWooshSup.size()-1)];
							}
						}

						// All Other Entities Play At A Fraction Of Their Normal Range
						//-------------------------------------------------------------
 						else 
						{
							// Scale The Play Pos By The Square Of The Distance
							//--------------------------------------------------
							playerToMoverDistanceFraction = playerToMoverDistance/WOOSH_ALL_RANGE;
 							playerToMoverDistanceFraction *= playerToMoverDistanceFraction;
							playerToMoverDistanceFraction *= 0.6f;
							playerToMoverDistance *= playerToMoverDistanceFraction;
 							VectorMA(player->currentOrigin, playerToMoverDistance, playerToMover, wooshSoundPos);

							// Large Building
							//----------------
							if (mover.mRows>4)
							{
								wooshSound = mWooshLar[Q_irand(0, mWooshLar.size()-1)];
							}

							// Medium Building
							//-----------------
							else if (mover.mRows>2)
							{
								wooshSound = mWooshMed[Q_irand(0, mWooshMed.size()-1)];
							}

							// Small Building
							//----------------
							else 
							{ 
								wooshSound = mWooshSml[Q_irand(0, mWooshSml.size()-1)];
							}
						}

						// If A Woosh Sound Was Selected, Play It Now
						//--------------------------------------------
						if (wooshSound)
						{
							G_SoundAtSpot(wooshSoundPos, wooshSound, qfalse);
							if (WOOSH_DEBUG)
							{
								CG_DrawEdge(player->currentOrigin, wooshSoundPos, EDGE_WHITE_TWOSECOND);
							}
						}
					}
				}
			}
		}
	}
}