Files
GTASource/game/vehicleAi/task/TaskVehicleGoTo.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

381 lines
11 KiB
C++

#include "TaskVehicleGoTo.h"
// Game headers
#include "VehicleAi\task\TaskVehicleCruise.h"
#include "VehicleAi\task\TaskVehicleGoToAutomobile.h"
#include "VehicleAi\task\TaskVehicleGoToHelicopter.h"
#include "VehicleAi\task\TaskVehicleGoToPlane.h"
#include "VehicleAi\task\TaskVehicleGoToSubmarine.h"
#include "VehicleAi\task\TaskVehiclePark.h"
#include "VehicleAi\VehicleIntelligence.h"
AI_OPTIMISATIONS()
AI_VEHICLE_OPTIMISATIONS()
////////////////////////////////////////////////////////////////////
CTaskVehicleGoTo::CTaskVehicleGoTo(const sVehicleMissionParams& params) :
CTaskVehicleMissionBase(params)
{
SetInternalTaskType(CTaskTypes::TASK_VEHICLE_GOTO);
}
////////////////////////////////////////////////////////////////////
CTaskVehicleGoTo::~CTaskVehicleGoTo()
{
}
////////////////////////////////////////////////////////////////////
CTaskVehicleFollow::CTaskVehicleFollow(const sVehicleMissionParams& params, const int FollowDistance)
: CTaskVehicleMissionBase(params)
, m_fHeliRequestedOrientation(-1.0f)
, m_iFlightHeight(7)
, m_iMinHeightAboveTerrain(20)
, m_iHeliFlags(0)
{
m_iFollowCarDistance = FollowDistance;
SetInternalTaskType(CTaskTypes::TASK_VEHICLE_FOLLOW);
}
CTaskVehicleFollow::CTaskVehicleFollow(const CTaskVehicleFollow& in_rhs)
: CTaskVehicleMissionBase(in_rhs.m_Params)
, m_iFollowCarDistance(in_rhs.m_iFollowCarDistance)
, m_fHeliRequestedOrientation(in_rhs.m_fHeliRequestedOrientation)
, m_iFlightHeight(in_rhs.m_iFlightHeight)
, m_iMinHeightAboveTerrain(in_rhs.m_iMinHeightAboveTerrain)
, m_iHeliFlags(in_rhs.m_iHeliFlags)
{
SetInternalTaskType(CTaskTypes::TASK_VEHICLE_FOLLOW);
}
void CTaskVehicleFollow::SetHelicopterSpecificParams( float fHeliRequestedOrientation, int iFlightHeight, int iMinHeightAboveTerrain, s32 iHeliFlags )
{
m_fHeliRequestedOrientation = fHeliRequestedOrientation;
m_iFlightHeight = iFlightHeight;
m_iMinHeightAboveTerrain = iMinHeightAboveTerrain;
m_iHeliFlags = iHeliFlags;
}
void CTaskVehicleFollow::CleanUp()
{
//Clear the avoidance cache.
if (GetVehicle())
{
GetVehicle()->GetIntelligence()->ClearAvoidanceCache();
}
}
void CTaskVehicleFollow::UpdateAvoidanceCache()
{
Vector3 vTargetCoors;
const CVehicle* pVehicle = GetVehicle();
if (GetTargetEntity()->GetIsTypeVehicle())
{
const CVehicle* pTargetVehicle = static_cast<const CVehicle*>(GetTargetEntity());
FindTargetCoors(pVehicle, vTargetCoors);
Vector3 vTargetCoorsLocalSpace = VEC3V_TO_VECTOR3(pTargetVehicle->GetTransform().UnTransform(VECTOR3_TO_VEC3V(vTargetCoors)));
CVehicleIntelligence::AvoidanceCache& rCache = pVehicle->GetIntelligence()->GetAvoidanceCache();
rCache.m_pTarget = pTargetVehicle;
rCache.m_fDesiredOffset = -vTargetCoorsLocalSpace.y;
}
}
/////////////////////////////////////////////////////////////////
CTask::FSM_Return CTaskVehicleFollow::UpdateFSM( const s32 iState, const FSM_Event iEvent )
{
CVehicle *pVehicle = GetVehicle(); //Get the vehicle ptr.
FSM_Begin
//
FSM_State(State_Follow)
FSM_OnUpdate
return Follow_OnUpdate(pVehicle);
//
FSM_State(State_FollowAutomobile)
FSM_OnEnter
FollowAutomobile_OnEnter(pVehicle);
FSM_OnUpdate
return FollowAutomobile_OnUpdate(pVehicle);
//
FSM_State(State_FollowHelicopter)
FSM_OnEnter
FollowHelicopter_OnEnter(pVehicle);
FSM_OnUpdate
return FollowHelicopter_OnUpdate(pVehicle);
//
FSM_State(State_FollowSubmarine)
FSM_OnEnter
FollowSubmarine_OnEnter(pVehicle);
FSM_OnUpdate
return FollowSubmarine_OnUpdate(pVehicle);
//
FSM_State(State_Stop)
FSM_OnEnter
Stop_OnEnter(pVehicle);
FSM_OnUpdate
return Stop_OnUpdate(pVehicle);
FSM_End
}
/////////////////////////////////////////////////////////////////////////////////
// FUNCTION : State_Follow
// PURPOSE :
/////////////////////////////////////////////////////////////////////////////////
aiTask::FSM_Return CTaskVehicleFollow::Follow_OnUpdate (CVehicle* pVehicle)
{
//make sure there is still a target to block
if (!GetTargetEntity())
{
SetState(State_Stop);
return FSM_Continue;
}
UpdateAvoidanceCache();
switch(pVehicle->GetVehicleType())
{
case VEHICLE_TYPE_PLANE:
Assert(0);
SetState(State_Stop);
break;
case VEHICLE_TYPE_HELI:
case VEHICLE_TYPE_BLIMP:
SetState(State_FollowHelicopter);
break;
case VEHICLE_TYPE_SUBMARINE:
SetState(State_FollowSubmarine);
break;
default:
SetState(State_FollowAutomobile);
}
return FSM_Continue;
}
/////////////////////////////////////////////////////////////////////////////////
// State_FollowAutomobile
/////////////////////////////////////////////////////////////////////////////////
void CTaskVehicleFollow::FollowAutomobile_OnEnter (CVehicle* UNUSED_PARAM(pVehicle))
{
sVehicleMissionParams params = m_Params;
params.m_fTargetArriveDist = 0.0f;
SetNewTask(CVehicleIntelligence::CreateAutomobileGotoTask(params, m_iFollowCarDistance + 1.0f));
}
/////////////////////////////////////////////////////////////////////////////////
aiTask::FSM_Return CTaskVehicleFollow::FollowAutomobile_OnUpdate (CVehicle* pVehicle)
{
//make sure there is still a target to block
if (!GetTargetEntity())
{
SetState(State_Stop);
return FSM_Continue;
}
// If we're close to the target we take the gas down.
float desiredSpeed = pVehicle->GetVelocity().XYMag();
const Vector3 vTargetEntityPosition = VEC3V_TO_VECTOR3(GetTargetEntity()->GetTransform().GetPosition());
float DistToTarget =(VEC3V_TO_VECTOR3(pVehicle->GetTransform().GetPosition()) - vTargetEntityPosition).Mag();
if(DistToTarget < m_iFollowCarDistance + 10.0f)
{
float HisSpeed =((CPhysical *)GetTargetEntity())->GetVelocity().XYMag();
float DistDiff = DistToTarget - m_iFollowCarDistance;
if(DistDiff < 0.0f)
{ // We're too close. Slow down.
desiredSpeed = rage::Max(HisSpeed + DistDiff * 5.0f, 0.0f);
}
else
{
desiredSpeed = HisSpeed + DistDiff * 2.0f;
}
}
else
{
desiredSpeed = GetCruiseSpeed();
}
TUNE_GROUP_FLOAT( CAR_FOLLOW_AI, CHEAT_SPEED_INCREASE_MAX_DISTANCE, 40.0f, 0.0f, 100.0f, 0.1f );
TUNE_GROUP_FLOAT( CAR_FOLLOW_AI, CHEAT_SPEED_INCREASE_MIN_DISTANCE, 20.0f, 0.0f, 100.0f, 0.1f );
TUNE_GROUP_FLOAT( CAR_FOLLOW_AI, CHEAT_SPEED_INCREASE_MAX_PERC, 5.0f, 0.0f, 100.0f, 0.1f );
TUNE_GROUP_FLOAT( CAR_FOLLOW_AI, CHEAT_SPEED_INCREASE_MIN_PERC, 1.0f, 0.0f, 100.0f, 0.1f );
// Cheat increase in speed to help AI cars catch up with the player.
float fCheatSpeedIncrease = Clamp((DistToTarget - CHEAT_SPEED_INCREASE_MIN_DISTANCE)/(CHEAT_SPEED_INCREASE_MAX_DISTANCE-CHEAT_SPEED_INCREASE_MIN_DISTANCE), 0.0f, 1.0f);
fCheatSpeedIncrease = Lerp(fCheatSpeedIncrease, CHEAT_SPEED_INCREASE_MIN_PERC, CHEAT_SPEED_INCREASE_MAX_PERC);
pVehicle->SetCheatPowerIncrease(fCheatSpeedIncrease);
if (GetSubTask() && GetSubTask()->GetTaskType() == CTaskTypes::TASK_VEHICLE_GOTO_AUTOMOBILE_NEW)
{
CTaskVehicleGoToAutomobileNew * pGoToTask = (CTaskVehicleGoToAutomobileNew*)GetSubTask();
SetTargetPosition(&vTargetEntityPosition);
UpdateAvoidanceCache();
pGoToTask->SetTargetPosition(&m_Params.GetTargetPosition());
pGoToTask->SetCruiseSpeed(desiredSpeed);
}
Assert(pVehicle->GetSteerAngle() > -1.0f && pVehicle->GetSteerAngle() < 1.0f);
return FSM_Continue;
}
/////////////////////////////////////////////////////////////////////////////////
// State_FollowHelicopter
/////////////////////////////////////////////////////////////////////////////////
void CTaskVehicleFollow::FollowHelicopter_OnEnter (CVehicle* UNUSED_PARAM(pVehicle))
{
Vector3 v = VEC3V_TO_VECTOR3(GetTargetEntity()->GetTransform().GetPosition());
sVehicleMissionParams params;
params.m_fCruiseSpeed = GetCruiseSpeed();
params.SetTargetPosition(v);
params.m_fTargetArriveDist = 0.0f;
SetNewTask(rage_new CTaskVehicleGoToHelicopter(params, m_iHeliFlags, m_fHeliRequestedOrientation, m_iMinHeightAboveTerrain));
}
/////////////////////////////////////////////////////////////////////////////////
void CTaskVehicleFollow::ModifyTargetForArrivalTolerance(Vector3 &io_targetPos, const CVehicle& in_Vehicle ) const
{
Vector3 vPosition = VEC3V_TO_VECTOR3(in_Vehicle.GetTransform().GetPosition());
Vector3 vTargetToVehicle = vPosition - io_targetPos;
float fDistanceXY = vTargetToVehicle.XYMag();
if ( fDistanceXY > FLT_MIN )
{
vTargetToVehicle.z = 0.0f;
Vector3 vTargetToVehicleDirectionXY;
vTargetToVehicleDirectionXY.Normalize(vTargetToVehicle);
static dev_float s_Tune = 0.75f;
fDistanceXY = Min( fDistanceXY, m_Params.m_fTargetArriveDist * s_Tune);
io_targetPos = io_targetPos + vTargetToVehicleDirectionXY * fDistanceXY;
}
}
aiTask::FSM_Return CTaskVehicleFollow::FollowHelicopter_OnUpdate(CVehicle* pVehicle)
{
//make sure there is still a target to block
if (!GetTargetEntity())
{
SetState(State_Stop);
return FSM_Continue;
}
//set the target position to follow
if(GetSubTask())
{
CTaskVehicleMissionBase *pCarTask = static_cast<CTaskVehicleMissionBase*>(GetSubTask());
Vector3 targetPos = VEC3V_TO_VECTOR3(GetTargetEntity()->GetTransform().GetPosition());
ModifyTargetForArrivalTolerance(targetPos, *pVehicle);
SetTargetPosition(&targetPos);
UpdateAvoidanceCache();
pCarTask->SetTargetPosition(&m_Params.GetTargetPosition());
}
return FSM_Continue;
}
/////////////////////////////////////////////////////////////////////////////////
// State_FollowSubmarine
/////////////////////////////////////////////////////////////////////////////////
void CTaskVehicleFollow::FollowSubmarine_OnEnter (CVehicle* UNUSED_PARAM(pVehicle))
{
Vector3 v = VEC3V_TO_VECTOR3(GetTargetEntity()->GetTransform().GetPosition());
sVehicleMissionParams params = m_Params;
params.SetTargetPosition(v);
params.ClearTargetEntity();
SetNewTask(rage_new CTaskVehicleGoToSubmarine(params));
}
/////////////////////////////////////////////////////////////////////////////////
aiTask::FSM_Return CTaskVehicleFollow::FollowSubmarine_OnUpdate (CVehicle* UNUSED_PARAM(pVehicle))
{
//make sure there is still a target to block
if (!GetTargetEntity())
{
SetState(State_Stop);
return FSM_Continue;
}
//set the target position to follow
if(GetSubTask())
{
CTaskVehicleMissionBase *pCarTask = static_cast<CTaskVehicleMissionBase*>(GetSubTask());
Vector3 targetPos = VEC3V_TO_VECTOR3(GetTargetEntity()->GetTransform().GetPosition());
SetTargetPosition(&targetPos);
UpdateAvoidanceCache();
pCarTask->SetTargetPosition(&m_Params.GetTargetPosition());
}
return FSM_Continue;
}
/////////////////////////////////////////////////////////////////////////////////
void CTaskVehicleFollow::Stop_OnEnter (CVehicle* UNUSED_PARAM(pVehicle))
{
SetNewTask(rage_new CTaskVehicleStop());
}
/////////////////////////////////////////////////////////////////////////////////
aiTask::FSM_Return CTaskVehicleFollow::Stop_OnUpdate (CVehicle* UNUSED_PARAM(pVehicle))
{
if (GetIsSubtaskFinished(CTaskTypes::TASK_VEHICLE_STOP))
{
return FSM_Quit;
}
return FSM_Continue;
}
////////////////////////////////////////////////////////////////////////
#if !__FINAL
const char * CTaskVehicleFollow::GetStaticStateName( s32 iState )
{
Assert(iState>=State_Follow&&iState<=State_Stop);
static const char* aStateNames[] =
{
"State_Follow",
"State_FollowAutomobile",
"State_FollowHelicopter",
"State_FollowSubmarine",
"State_Stop",
};
return aStateNames[iState];
}
#endif