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

273 lines
6.0 KiB
C++

#include "task/Response/TaskGangs.h"
#include "Peds/Ped.h"
#include "Vehicles/vehicle.h"
#include "task/Combat/TaskNewCombat.h"
#include "task/Combat/TaskThreatResponse.h"
#include "task/Vehicle/TaskEnterVehicle.h"
CTaskGangPatrol::CTaskGangPatrol(CPed* pPrimaryTarget)
: m_pPrimaryTarget(pPrimaryTarget)
{
SetInternalTaskType(CTaskTypes::TASK_GANG_PATROL);
}
CTaskGangPatrol::~CTaskGangPatrol()
{
}
bool CTaskGangPatrol::ProcessMoveSignals()
{
CPed* pPed = GetPed();
if (pPed)
{
CVehicle* pVehicle = pPed->GetMyVehicle();
if (pVehicle)
{
pVehicle->m_nVehicleFlags.bDisablePretendOccupants = true;
pVehicle->m_nVehicleFlags.bPreventBeingDummyUnlessCollisionLoadedThisFrame = true;
}
}
return true;
}
CTask::FSM_Return CTaskGangPatrol::UpdateFSM( const s32 iState, const FSM_Event iEvent )
{
FSM_Begin
FSM_State(State_Start)
FSM_OnUpdate
return Start_OnUpdate();
FSM_State(State_AttackTarget)
FSM_OnEnter
AttackTarget_OnEnter();
FSM_OnUpdate
return AttackTarget_OnUpdate();
FSM_State(State_EnterVehicle)
FSM_OnEnter
EnterVehicle_OnEnter();
FSM_OnUpdate
return EnterVehicle_OnUpdate();
FSM_State(State_WaitingForVehicleOccupants)
FSM_OnEnter
WaitingForVehicleOccupants_OnEnter();
FSM_OnUpdate
return WaitingForVehicleOccupants_OnUpdate();
FSM_State(State_Finish)
FSM_OnUpdate
return FSM_Quit;
FSM_End
}
#if !__FINAL
const char * CTaskGangPatrol::GetStaticStateName( s32 iState )
{
taskAssert(iState >= State_Start && iState <= State_Finish);
switch (iState)
{
case State_Start: return "State_Start";
case State_AttackTarget: return "State_AttackTarget";
case State_EnterVehicle: return "State_EnterVehicle";
case State_WaitingForVehicleOccupants: return "State_WaitingForVehicleOccupants";
case State_Finish: return "State_Finish";
default: taskAssert(0);
}
return "State_Invalid";
}
#endif // !__FINAL
CTask::FSM_Return CTaskGangPatrol::Start_OnUpdate()
{
RequestProcessMoveSignalCalls();
//Attack the target.
SetState(State_AttackTarget);
return FSM_Continue;
}
void CTaskGangPatrol::AttackTarget_OnEnter()
{
//Create the task.
CTaskThreatResponse* pTask = rage_new CTaskThreatResponse(m_pPrimaryTarget);
pTask->SetThreatResponseOverride(CTaskThreatResponse::TR_Fight);
pTask->GetConfigFlagsForCombat().SetFlag(CTaskCombat::ComF_RequiresOrder);
//Start the task.
SetNewTask(pTask);
}
CTask::FSM_Return CTaskGangPatrol::AttackTarget_OnUpdate()
{
//Check if the task has finished.
if(GetIsFlagSet(aiTaskFlags::SubTaskFinished))
{
//Check if the last used vehicle is close, and the driver is not dead.
if(IsLastUsedVehicleClose() && !IsDriverDead())
{
SetState(State_EnterVehicle);
}
else
{
SetState(State_Finish);
}
}
return FSM_Continue;
}
void CTaskGangPatrol::EnterVehicle_OnEnter()
{
//Assert that the vehicle is valid.
CVehicle* pVehicle = GetPed()->GetMyVehicle();
taskAssert(pVehicle);
//Create the task.
s32 iSeatIndex = pVehicle->GetSeatManager()->GetLastPedsSeatIndex(GetPed());
SeatRequestType srType = (iSeatIndex >= 0) ? SR_Specific : SR_Any;
CTaskEnterVehicle* pTask = rage_new CTaskEnterVehicle(pVehicle, srType, iSeatIndex);
//Start the task.
SetNewTask(pTask);
}
aiTask::FSM_Return CTaskGangPatrol::EnterVehicle_OnUpdate()
{
//Check if the sub-task has finished.
if(GetIsFlagSet(aiTaskFlags::SubTaskFinished))
{
//Check if we are driving the vehicle.
if(GetPed()->GetIsDrivingVehicle())
{
SetState(State_WaitingForVehicleOccupants);
}
else
{
SetState(State_Finish);
}
}
return FSM_Continue;
}
void CTaskGangPatrol::WaitingForVehicleOccupants_OnEnter()
{
//Assert that we are driving the vehicle.
taskAssert(GetPed()->GetIsDrivingVehicle());
}
aiTask::FSM_Return CTaskGangPatrol::WaitingForVehicleOccupants_OnUpdate()
{
//Check if we should not wait for vehicle occupants.
if(!ShouldWaitForVehicleOccupants())
{
SetState(State_Finish);
}
return FSM_Continue;
}
bool CTaskGangPatrol::IsDriverDead() const
{
//Ensure the vehicle is valid.
const CVehicle* pVehicle = GetPed()->GetMyVehicle();
if(!pVehicle)
{
return false;
}
//Ensure the driver is valid.
const CPed* pDriver = (pVehicle->GetDriver()) ? pVehicle->GetDriver() :
pVehicle->GetSeatManager()->GetLastPedInSeat(Seat_driver);
if(!pDriver)
{
return false;
}
//Ensure the driver is dead.
if(!pDriver->IsInjured())
{
return false;
}
return true;
}
bool CTaskGangPatrol::IsLastUsedVehicleClose() const
{
//Ensure the vehicle is valid.
const CVehicle* pVehicle = GetPed()->GetMyVehicle();
if(!pVehicle)
{
return false;
}
//Ensure the distance is within the threshold.
ScalarV scDistSq = DistSquared(GetPed()->GetTransform().GetPosition(), pVehicle->GetTransform().GetPosition());
static dev_float s_fMaxDistance = 30.0f;
ScalarV scMaxDistSq = ScalarVFromF32(square(s_fMaxDistance));
if(IsGreaterThanAll(scDistSq, scMaxDistSq))
{
return false;
}
return true;
}
bool CTaskGangPatrol::ShouldWaitForVehicleOccupant(const CPed& rPed) const
{
//Ensure the ped is not dead.
if(rPed.IsInjured())
{
return false;
}
//Ensure the ped is not in a vehicle.
if(rPed.GetIsInVehicle())
{
return false;
}
//Check if the ped is getting in our vehicle.
if(rPed.GetVehiclePedEntering() == GetPed()->GetVehiclePedInside())
{
return true;
}
//Check if we have been in the state for a small amount of time.
static dev_float s_fMaxTime = 3.0f;
if(GetTimeInState() <= s_fMaxTime)
{
return true;
}
return false;
}
bool CTaskGangPatrol::ShouldWaitForVehicleOccupants() const
{
//Ensure the vehicle is valid.
const CVehicle* pVehicle = GetPed()->GetMyVehicle();
if(!pVehicle)
{
return false;
}
//Iterate over the seats.
for(s32 i = 1; i < pVehicle->GetSeatManager()->GetMaxSeats(); ++i)
{
//Check if we should wait for the last ped in the seat.
const CPed* pLastPedInSeat = pVehicle->GetSeatManager()->GetLastPedInSeat(i);
if(pLastPedInSeat && ShouldWaitForVehicleOccupant(*pLastPedInSeat))
{
return true;
}
}
return false;
}