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

265 lines
6.7 KiB
C++

// File header
#include "Task/Weapons/TaskDetonator.h"
// Game headers
#include "Animation/MovePed.h"
#include "Debug/DebugScene.h"
#include "Peds/Ped.h"
#include "Task/Combat/Cover/TaskCover.h"
#include "Task/Response/TaskDuckAndCover.h"
#include "Task/Weapons/TaskSwapWeapon.h"
#include "Weapons/Projectiles/ProjectileManager.h"
#include "Weapons/Weapon.h"
AI_OPTIMISATIONS()
//////////////////////////////////////////////////////////////////////////
// CTaskDetonator
//////////////////////////////////////////////////////////////////////////
fwMvNetworkId CTaskDetonator::ms_DetonateNetworkId("DetonateNetwork",0x7A92FE6E);
fwMvClipId CTaskDetonator::ms_CrouchFireId("fire_crouch", 0x07bc56892);
fwMvClipId CTaskDetonator::ms_FireId("fire", 0x0d30a036b);
CTaskDetonator::CTaskDetonator(const CWeaponController::WeaponControllerType weaponControllerType, float fDuration)
: m_weaponControllerType(weaponControllerType)
, m_fDuration(fDuration)
, m_bHasFired(false)
, m_fDetonateTime(-1.0f)
{
m_GenericClipHelper.SetInsertCallback(MakeFunctorRet(*this, &CTaskDetonator::InsertDetonatorNetworkCB));
SetInternalTaskType(CTaskTypes::TASK_DETONATOR);
}
CTaskDetonator::~CTaskDetonator()
{
m_GenericClipHelper.BlendOutClip();
}
CTaskDetonator::FSM_Return CTaskDetonator::ProcessPreFSM()
{
CPed *pPed = GetPed(); //Get the ped ptr.
pPed->SetPedResetFlag( CPED_RESET_FLAG_TemporarilyBlockWeaponSwitching, true );
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::UpdateFSM(const s32 iState, const FSM_Event iEvent)
{
CPed *pPed = GetPed(); //Get the ped ptr.
weaponAssert(pPed->GetWeaponManager());
FSM_Begin
FSM_State(State_Init)
FSM_OnUpdate
return StateInit_OnUpdate(pPed);
FSM_State(State_Detonate)
FSM_OnEnter
return StateDetonate_OnEnter(pPed);
FSM_OnUpdate
return StateDetonate_OnUpdate(pPed);
FSM_State(State_DuckAndDetonate)
FSM_OnEnter
return StateDuckAndDetonate_OnEnter(pPed);
FSM_OnUpdate
return StateDuckAndDetonate_OnUpdate(pPed);
FSM_State(State_Swap)
FSM_OnEnter
return StateSwap_OnEnter(pPed);
FSM_OnUpdate
return StateSwap_OnUpdate(pPed);
FSM_State(State_Quit)
FSM_OnUpdate
return FSM_Quit;
FSM_End
}
#if !__FINAL
const char * CTaskDetonator::GetStaticStateName( s32 iState )
{
static const char* aStateNames[] =
{
"Init",
"Detonate",
"Duck And Detonate",
"Swap",
"Quit",
};
return aStateNames[iState];
}
#endif // !__FINAL
CTaskDetonator::FSM_Return CTaskDetonator::StateInit_OnUpdate(CPed* pPed)
{
TUNE_GROUP_FLOAT(DETONATIONS,MAX_DISTANCE_FOR_DUCK_IN_DETONATION, 10.0f, 0.0f, 40.0f, 0.1f);
if(pPed->GetWeaponManager()->GetRequiresWeaponSwitch())
{
// Swap weapon, as we have the incorrect (or holstered) weapon equipped
SetState(State_Swap);
}
else
{
// We'll need to do something custom in cover, disabling for now as it leaves the ped unable to move properly, also it don't look too great
if( !pPed->GetIsInCover() && CProjectileManager::GetProjectileWithinDistance(pPed, AMMOTYPE_STICKYBOMB, MAX_DISTANCE_FOR_DUCK_IN_DETONATION)!= NULL )
{
// If there's something we're going to blow up within a specified range (7m), then duck and cover before detonation
SetState(State_DuckAndDetonate);
}
else
{
// Otherwise just flick the switch
SetState(State_Detonate);
}
}
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::StateDetonate_OnEnter(CPed* pPed)
{
const CWeapon* pWeapon = pPed->GetWeaponManager()->GetEquippedWeapon();
if(!pWeapon)
{
return FSM_Quit;
}
const CWeaponInfo* pWeaponInfo = pWeapon->GetWeaponInfo();
if(!pWeaponInfo)
{
return FSM_Quit;
}
fwMvClipSetId clipSetId = pWeaponInfo->GetAppropriateWeaponClipSetId(pPed);
fwMvClipId clipId = pPed->GetIsCrouching() ? ms_CrouchFireId : ms_FireId;
m_GenericClipHelper.BlendInClipBySetAndClip(pPed, clipSetId, clipId, NORMAL_BLEND_IN_DELTA, NORMAL_BLEND_OUT_DELTA, false, true);
m_GenericClipHelper.SetFilter((u32)BONEMASK_ARMONLY_R);
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::StateDetonate_OnUpdate(CPed* pPed)
{
if (m_GenericClipHelper.IsHeldAtEnd())
{
return FSM_Quit;
}
if (m_fDetonateTime < 0.0f)
{
CClipEventTags::FindEventPhase(m_GenericClipHelper.GetClip(), CClipEventTags::Detonation, m_fDetonateTime);
}
if (!m_bHasFired && m_GenericClipHelper.GetPhase() >= m_fDetonateTime)
{
m_bHasFired = true;
if(pPed->GetWeaponManager()->GetIsDetonatorActive())
{
const CWeaponInfo* pWeaponInfo = pPed->GetWeaponManager()->GetEquippedWeaponInfo();
if(pWeaponInfo && pWeaponInfo->GetIsDetonator())
{
CProjectileManager::ExplodeProjectiles(pPed, AMMOTYPE_STICKYBOMB);
}
}
}
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::StateDuckAndDetonate_OnEnter(CPed* pPed)
{
const CWeapon* pWeapon = pPed->GetWeaponManager()->GetEquippedWeapon();
if(!pWeapon)
{
return FSM_Quit;
}
const CWeaponInfo* pWeaponInfo = pWeapon->GetWeaponInfo();
if(!pWeaponInfo)
{
return FSM_Quit;
}
// Start the DuckAndCover
SetNewTask(rage_new CTaskDuckAndCover());
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::StateDuckAndDetonate_OnUpdate(CPed* pPed )
{
const aiTask *pDuckTask = GetSubTask();
// Check for the subtask being in state "State_Ducking"
if(pDuckTask && pDuckTask->GetState() == CTaskDuckAndCover::State_Ducking)
{
if (!m_bHasFired )
{
m_bHasFired = true;
if(pPed->GetWeaponManager()->GetIsDetonatorActive())
{
const CWeaponInfo* pWeaponInfo = pPed->GetWeaponManager()->GetEquippedWeaponInfo();
if(pWeaponInfo && pWeaponInfo->GetIsDetonator())
{
CProjectileManager::ExplodeProjectiles(pPed, AMMOTYPE_STICKYBOMB);
}
}
}
}
if (GetIsFlagSet(aiTaskFlags::SubTaskFinished))
{
return FSM_Quit;
}
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::StateSwap_OnEnter(CPed* UNUSED_PARAM(pPed))
{
s32 iFlags = SWAP_HOLSTER | SWAP_DRAW | SWAP_TO_AIM;
SetNewTask(rage_new CTaskSwapWeapon(iFlags));
return FSM_Continue;
}
CTaskDetonator::FSM_Return CTaskDetonator::StateSwap_OnUpdate(CPed* UNUSED_PARAM(pPed))
{
if(GetIsFlagSet(aiTaskFlags::SubTaskFinished))
{
// Set state to detonate
SetState(State_Detonate);
}
return FSM_Continue;
}
bool CTaskDetonator::InsertDetonatorNetworkCB(fwMoveNetworkPlayer* pPlayer, float fBlendDuration, u32)
{
CPed* pPed = GetPed();
if (GetParent() && GetParent()->GetTaskType() == CTaskTypes::TASK_IN_COVER)
{
CTaskInCover* pCoverTask = static_cast<CTaskInCover*>(GetParent());
if (pCoverTask->GetMovementNetworkHelper() && pCoverTask->GetMovementNetworkHelper()->IsNetworkAttached())
{
pCoverTask->GetMoveNetworkHelper()->SetSubNetwork(pPlayer, ms_DetonateNetworkId);
}
}
else
{
pPed->GetMovePed().SetTaskNetwork(pPlayer, fBlendDuration);
}
return true;
}