700 lines
20 KiB
C++
700 lines
20 KiB
C++
// Filename : TaskNMShot.h
|
|
// Description: Natural Motion shot class (FSM version)
|
|
|
|
#ifndef INC_TASKNMSHOT_H_
|
|
#define INC_TASKNMSHOT_H_
|
|
|
|
// --- Include Files ------------------------------------------------------------
|
|
|
|
// Game headers
|
|
#include "Task/System/Task.h"
|
|
#include "Task\System\TaskTypes.h"
|
|
#include "Task/Physics/TaskNM.h"
|
|
#include "Task/Physics/TaskNMBrace.h"
|
|
#include "Task/Physics/ThreatenedHelper.h"
|
|
|
|
// ------------------------------------------------------------------------------
|
|
|
|
//
|
|
// Task info for CTaskNMShot
|
|
//
|
|
class CClonedNMShotInfo : public CSerialisedFSMTaskInfo
|
|
{
|
|
public:
|
|
CClonedNMShotInfo( CEntity* pShotBy, u32 nWeaponHash, int nComponent, const Vector3& vecHitPositionWorldSpace, const Vector3& vecHitImpulseWorldSpace,
|
|
const Vector3& vecHitPolyNormalWorldSpace);
|
|
CClonedNMShotInfo();
|
|
~CClonedNMShotInfo() {}
|
|
|
|
virtual s32 GetTaskInfoType( ) const {return INFO_TYPE_NM_SHOT;}
|
|
|
|
// the clone task is created by the CTaskNMControl clone task
|
|
virtual bool AutoCreateCloneTask(CPed* UNUSED_PARAM(pPed)) { return false; }
|
|
|
|
virtual CTaskFSMClone *CreateCloneFSMTask();
|
|
|
|
void Serialise(CSyncDataBase& serialiser)
|
|
{
|
|
CSerialisedFSMTaskInfo::Serialise(serialiser);
|
|
|
|
SERIALISE_BOOL(serialiser, m_bHasShotByEntity, "Has shot by entity");
|
|
|
|
if (m_bHasShotByEntity || serialiser.GetIsMaximumSizeSerialiser())
|
|
{
|
|
SERIALISE_OBJECTID(serialiser, m_shotByEntity, "Shot by entity");
|
|
}
|
|
|
|
SERIALISE_UNSIGNED(serialiser, m_nWeaponHash, SIZEOF_WEAPONHASH, "Weapon hash");
|
|
u32 component = (u32)m_nComponent;
|
|
SERIALISE_UNSIGNED(serialiser, component, SIZEOF_COMPONENT, "Component");
|
|
m_nComponent = (u8)component;
|
|
SERIALISE_VECTOR(serialiser, m_vecOriginalHitImpulseWorldSpace, 600.0f, SIZEOF_HITFORCE, "Hit world impulse");
|
|
SERIALISE_VECTOR(serialiser, m_vecOriginalHitPositionLocalSpace, LOCAL_POS_MAG_LIMIT, SIZEOF_HITPOS, "Hit local pos");
|
|
SERIALISE_VECTOR(serialiser, m_vecOriginalHitPolyNormalWorldSpace, 1.1f, SIZEOF_HITPOLYNORMAL, "Hit world poly normal");
|
|
}
|
|
|
|
u32 GetWeaponHash() const { return m_nWeaponHash; }
|
|
u8 GetComponent() const { return m_nComponent; }
|
|
const Vector3& GetHitImpulse() const { return m_vecOriginalHitImpulseWorldSpace; }
|
|
|
|
private:
|
|
|
|
CClonedNMShotInfo(const CClonedNMShotInfo &);
|
|
CClonedNMShotInfo &operator=(const CClonedNMShotInfo &);
|
|
|
|
static const unsigned int SIZEOF_WEAPONHASH = 32;
|
|
static const unsigned int SIZEOF_COMPONENT = 8;
|
|
static const unsigned int SIZEOF_HITPOS = 16;
|
|
static const unsigned int SIZEOF_HITPOLYNORMAL = 16;
|
|
static const unsigned int SIZEOF_HITFORCE = 20;
|
|
|
|
Vector3 m_vecOriginalHitPositionLocalSpace;
|
|
Vector3 m_vecOriginalHitPolyNormalWorldSpace;
|
|
Vector3 m_vecOriginalHitImpulseWorldSpace;
|
|
ObjectId m_shotByEntity;
|
|
u32 m_nWeaponHash;
|
|
u8 m_nComponent;
|
|
bool m_bHasShotByEntity;
|
|
};
|
|
|
|
//// be hit
|
|
// triggers: getting shot
|
|
// taking a melee hit
|
|
class CTaskNMShot : public CTaskNMBehaviour
|
|
{
|
|
public:
|
|
|
|
////////////////////////////////
|
|
// SHOT
|
|
////////////////////////////////
|
|
enum
|
|
{
|
|
SHOT_DEFAULT,
|
|
SHOT_NORMAL,
|
|
SHOT_SHOTGUN,
|
|
SHOT_UNDERWATER,
|
|
SHOT_DANGLING,
|
|
SHOT_AGAINST_WALL,
|
|
};
|
|
|
|
struct Tunables : CTuning
|
|
{
|
|
Tunables();
|
|
|
|
s32 m_MinimumShotReactionTimePlayerMS;
|
|
s32 m_MinimumShotReactionTimeAIMS;
|
|
bool m_bUseClipPoseHelper;
|
|
bool m_bEnableDebugDraw;
|
|
float m_fImpactConeAngleFront; // ... in degrees!
|
|
float m_fImpactConeAngleBack; // ... in degrees!
|
|
RagdollComponent m_eImpactConeRagdollComponent;
|
|
int m_iShotMinTimeBeforeGunThreaten;
|
|
int m_iShotMaxTimeBeforeGunThreaten;
|
|
int m_iShotMinTimeBetweenFireGun;
|
|
int m_iShotMaxTimeBetweenFireGun;
|
|
|
|
int m_iShotMaxBlindFireTimeL;
|
|
int m_iShotMaxBlindFireTimeH;
|
|
float m_fShotBlindFireProbability;
|
|
float m_fShotHeadAngleToFireGun;
|
|
float m_fShotWeaponAngleToFireGun;
|
|
float m_fFireWeaponStrengthForceMultiplier;
|
|
|
|
float m_fMinFinisherShotgunTotalImpulseNormal;
|
|
float m_fMinFinisherShotgunTotalImpulseBraced;
|
|
float m_fFinisherShotgunBonusArmedSpeedModifier;
|
|
|
|
bool m_ScaleSnapWithSpineOrientation;
|
|
float m_MinSnap; // minimum snap amount
|
|
|
|
int m_BlendOutDelayStanding;
|
|
int m_BlendOutDelayBalanceFailed;
|
|
|
|
struct ShotAgainstWall
|
|
{
|
|
ShotAgainstWall()
|
|
{}
|
|
|
|
float m_HealthRatioLimit; // shot against wall will only be used on peds whose health ratio is below this range
|
|
float m_WallProbeRadius; // Radius of the swept sphere probe
|
|
float m_WallProbeDistance; // Distance of the swept sphere probe
|
|
float m_ProbeHeightAbovePelvis; // height above the pelvis to perform the probe
|
|
float m_ImpulseMult;
|
|
float m_MaxWallAngle; // The maximum allowed angle between shot direction and wall normal
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
ShotAgainstWall m_ShotAgainstWall;
|
|
|
|
float m_BCRExclusionZone;
|
|
|
|
struct Impulses
|
|
{
|
|
// Sniper-specific impulse tuning requested by Jason Bone. Is being used to tune hits from sniper rifles to stop peds from flipping over from hits
|
|
// to the upper body (specifically the clavicles, neck and upper spine). Should really be using the existing weapon force tuning functionality to set
|
|
// lower forces for the bones that are causing issues but this ended up being the preferred solution...
|
|
struct SniperImpulses
|
|
{
|
|
SniperImpulses() {}
|
|
|
|
|
|
float m_MaxHealthImpulseMult;
|
|
float m_MinHealthImpulseMult;
|
|
|
|
float m_MaxDamageTakenImpulseMult;
|
|
float m_MinDamageTakenImpulseMult;
|
|
float m_MaxDamageTakenThreshold;
|
|
float m_MinDamageTakenThreshold;
|
|
|
|
float m_DefaultKillShotImpulseMult;
|
|
float m_DefaultMPKillShotImpulseMult;
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
Impulses()
|
|
{}
|
|
|
|
float m_MaxArmourImpulseMult;
|
|
float m_MinArmourImpulseMult;
|
|
|
|
float m_MaxHealthImpulseMult;
|
|
float m_MinHealthImpulseMult;
|
|
|
|
float m_MaxDamageTakenImpulseMult;
|
|
float m_MinDamageTakenImpulseMult;
|
|
float m_MaxDamageTakenThreshold;
|
|
float m_MinDamageTakenThreshold;
|
|
|
|
float m_DefaultKillShotImpulseMult;
|
|
float m_DefaultRapidFireKillShotImpulseMult;
|
|
float m_DefaultMPKillShotImpulseMult;
|
|
float m_DefaultMPRapidFireKillShotImpulseMult;
|
|
|
|
float m_RapidFireBoostShotImpulseMult;
|
|
int m_RapidFireBoostShotMinRandom;
|
|
int m_RapidFireBoostShotMaxRandom;
|
|
|
|
float m_ShotgunMaxSpeedForLiftImpulse;
|
|
float m_ShotgunMaxLiftImpulse;
|
|
float m_ShotgunLiftNearThreshold;
|
|
float m_ShotgunChanceToMoveSpine3ImpulseToSpine2;
|
|
float m_ShotgunChanceToMoveNeckImpulseToSpine2;
|
|
float m_ShotgunChanceToMoveHeadImpulseToSpine2;
|
|
|
|
float m_EqualizeAmount;
|
|
|
|
float m_COMImpulseScale;
|
|
u32 m_COMImpulseComponent;
|
|
float m_COMImpulseMaxRootVelocityMagnitude;
|
|
bool m_COMImpulseOnlyWhileBalancing;
|
|
|
|
float m_HeadShotImpulseMultiplier;
|
|
float m_HeadShotMPImpulseMultiplier;
|
|
bool m_ScaleHeadShotImpulseWithSpineOrientation;
|
|
float m_MinHeadShotImpulseMultiplier;
|
|
|
|
float m_AutomaticInitialSnapMult;
|
|
float m_BurstFireInitialSnapMult;
|
|
|
|
float m_FinalShotImpulseClampMax;
|
|
|
|
float m_RunningAgainstBulletImpulseMult;
|
|
float m_RunningAgainstBulletImpulseMultMax;
|
|
float m_RunningWithBulletImpulseMult;
|
|
|
|
float m_LegShotFallRootImpulseMinUpright;
|
|
float m_LegShotFallRootImpulseMult;
|
|
|
|
SniperImpulses m_SniperImpulses;
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
Impulses m_Impulses;
|
|
|
|
struct HitPointRandomisation
|
|
{
|
|
bool m_Enable;
|
|
float m_TopSpread;
|
|
float m_BottomSpread;
|
|
float m_Blend;
|
|
RagdollComponent m_TopComponent;
|
|
RagdollComponent m_BottomComponent;
|
|
float m_BiasSide;
|
|
u32 m_BiasSideTime;
|
|
|
|
bool ShouldRandomiseHitPoint(RagdollComponent component) const
|
|
{
|
|
switch(component)
|
|
{
|
|
case RAGDOLL_SPINE0:
|
|
case RAGDOLL_SPINE1:
|
|
case RAGDOLL_SPINE2:
|
|
case RAGDOLL_SPINE3:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool GetRandomHitPoint(Vector3& vRandomHitPoint, const CPed* pPed, RagdollComponent eComponent, bool bBiasSideLeft) const;
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
HitPointRandomisation m_HitRandomisation;
|
|
HitPointRandomisation m_HitRandomisationAutomatic;
|
|
|
|
struct ArmShot
|
|
{
|
|
ArmShot()
|
|
{}
|
|
|
|
int m_MinLookAtArmWoundTime;
|
|
int m_MaxLookAtArmWoundTime;
|
|
|
|
float m_UpperArmImpulseCap;
|
|
float m_LowerArmImpulseCap;
|
|
|
|
float m_UpperArmNoTorsoHitImpulseCap;
|
|
float m_LowerArmNoTorseHitImpulseCap;
|
|
|
|
float m_ClavicleImpulseScale;
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
struct StayUpright
|
|
{
|
|
StayUpright()
|
|
{}
|
|
|
|
float m_HoldingWeaponBonus;
|
|
float m_UnarmedBonus;
|
|
float m_ArmouredBonus;
|
|
float m_MovingMultiplierBonus;
|
|
float m_HealthMultiplierBonus;
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
StayUpright m_StayUpright;
|
|
|
|
ArmShot m_ArmShot;
|
|
|
|
float m_FallingSpeedForHighFall;
|
|
|
|
float m_ChanceOfFallToKneesOnCollapse;
|
|
float m_ChanceOfFallToKneesAfterLastStand;
|
|
|
|
float m_ChanceForGutShotKnockdown;
|
|
|
|
float m_LastStandMaxTotalTime;
|
|
float m_LastStandMaxArmouredTotalTime;
|
|
|
|
s32 m_RapidHitCount;
|
|
s32 m_ArmouredRapidHitCount;
|
|
|
|
bool m_AllowArmouredLegShot;
|
|
bool m_AllowArmouredKnockdown;
|
|
|
|
bool m_ReduceDownedTimeByPerformanceTime;
|
|
s32 m_MinimumDownedTime;
|
|
|
|
bool m_DisableReachForWoundOnHeadShot;
|
|
s32 m_DisableReachForWoundOnHeadShotMinDelay;
|
|
s32 m_DisableReachForWoundOnHeadShotMaxDelay;
|
|
|
|
bool m_DisableReachForWoundOnNeckShot;
|
|
s32 m_DisableReachForWoundOnNeckShotMinDelay;
|
|
s32 m_DisableReachForWoundOnNeckShotMaxDelay;
|
|
|
|
CNmTuningSetGroup m_WeaponSets;
|
|
|
|
struct ParamSets
|
|
{
|
|
// always sent
|
|
CNmTuningSet m_Base;
|
|
|
|
// weapon type
|
|
CNmTuningSet m_Melee;
|
|
CNmTuningSet m_Electrocute;
|
|
|
|
// hit location
|
|
CNmTuningSet m_SprintingLegShot;
|
|
CNmTuningSet m_SprintingDeath;
|
|
CNmTuningSet m_Sprinting;
|
|
CNmTuningSet m_AutomaticHeadShot;
|
|
CNmTuningSet m_HeadShot;
|
|
CNmTuningSet m_AutomaticNeckShot;
|
|
CNmTuningSet m_NeckShot;
|
|
CNmTuningSet m_LegShot;
|
|
CNmTuningSet m_SniperLegShot;
|
|
CNmTuningSet m_ArmShot;
|
|
CNmTuningSet m_BackShot;
|
|
|
|
// target state
|
|
CNmTuningSet m_Underwater;
|
|
CNmTuningSet m_UnderwaterRelax;
|
|
CNmTuningSet m_Armoured;
|
|
CNmTuningSet m_BoundAnkles;
|
|
CNmTuningSet m_FatallyInjured;
|
|
CNmTuningSet m_PlayerDeathSP;
|
|
CNmTuningSet m_PlayerDeathMP;
|
|
CNmTuningSet m_OnStairs;
|
|
|
|
// special
|
|
CNmTuningSet m_ShotAgainstWall;
|
|
CNmTuningSet m_LastStand;
|
|
CNmTuningSet m_LastStandArmoured;
|
|
CNmTuningSet m_HeadLook;
|
|
|
|
CNmTuningSet m_FallToKnees;
|
|
CNmTuningSet m_StaggerFall;
|
|
CNmTuningSet m_CatchFall;
|
|
CNmTuningSet m_SetFallingReactionHealthy;
|
|
CNmTuningSet m_SetFallingReactionInjured;
|
|
CNmTuningSet m_SetFallingReactionFallOverWall;
|
|
CNmTuningSet m_SetFallingReactionFallOverVehicle;
|
|
CNmTuningSet m_RubberBulletKnockdown;
|
|
CNmTuningSet m_Teeter;
|
|
|
|
CNmTuningSet m_HoldingTwoHandedWeapon;
|
|
CNmTuningSet m_HoldingSingleHandedWeapon;
|
|
|
|
CNmTuningSet m_CrouchedOrLowCover;
|
|
|
|
CNmTuningSet m_Female;
|
|
|
|
PAR_SIMPLE_PARSABLE;
|
|
};
|
|
|
|
ParamSets m_ParamSets;
|
|
|
|
CTaskNMBehaviour::Tunables::StandardBlendOutThresholds m_BlendOutThreshold;
|
|
CTaskNMBehaviour::Tunables::BlendOutThreshold m_SubmergedBlendOutThreshold;
|
|
|
|
PAR_PARSABLE;
|
|
};
|
|
|
|
CTaskNMShot(CPed* pPed, u32 nMinTime, u32 nMaxTime, CEntity* pShotBy, u32 nWeaponHash, int nComponent, const Vector3& vecHitPosWorldSpace,
|
|
const Vector3& vecHitImpulseWorldSpace, const Vector3& vecHitPolyNormalWorldSpace, s32 m_hitCountThisPerformance = 0, bool bShotgunMessageSent = false,
|
|
bool bHeldWeapon = false, bool hitPosInLocalSpace = false, u32 lastStandStartTimeMS = 0, u32 lastConfigureBulletsCall = 0,
|
|
bool lastStandActive = false, bool knockDownStarted = false);
|
|
~CTaskNMShot();
|
|
|
|
protected:
|
|
CTaskNMShot(const CTaskNMShot& otherTask);
|
|
|
|
public:
|
|
bool HasBalanceFailed() const { return m_bBalanceFailed; }
|
|
|
|
////////////////////////
|
|
// CTaskSimple functions
|
|
#if !__FINAL
|
|
virtual atString GetName() const {return m_strTaskAndStateName;}
|
|
#endif
|
|
|
|
#if __BANK
|
|
const char* GetShotTypeName() const;
|
|
#endif //__BANK
|
|
|
|
virtual int GetTaskTypeInternal() const {return CTaskTypes::TASK_NM_SHOT;}
|
|
|
|
virtual void CleanUp();
|
|
virtual aiTask* Copy() const { return rage_new CTaskNMShot(*this); }
|
|
static void AppendWeaponSets(CNmTuningSet* newItem, atHashString key)
|
|
{
|
|
sm_Tunables.m_WeaponSets.Append(newItem,key);
|
|
}
|
|
static void RevertWeaponSets(atHashString key)
|
|
{
|
|
sm_Tunables.m_WeaponSets.Revert(key);
|
|
}
|
|
////////////////////////
|
|
// CTaskFSMClone functions
|
|
virtual CTaskInfo* CreateQueriableState() const;
|
|
|
|
///////////////////////////
|
|
// CTaskNMBehaviour functions
|
|
public:
|
|
virtual void BehaviourFailure(CPed* pPed, ARTFeedbackInterfaceGta* pFeedbackInterface);
|
|
virtual void BehaviourSuccess(CPed* pPed, ARTFeedbackInterfaceGta* pFeedbackInterface);
|
|
virtual void BehaviourFinish(CPed* pPed, ARTFeedbackInterfaceGta* pFeedbackInterface);
|
|
virtual void BehaviourEvent(CPed* pPed, ARTFeedbackInterfaceGta* pFeedbackInterface);
|
|
|
|
protected:
|
|
virtual void StartBehaviour(CPed* pPed);
|
|
virtual void ControlBehaviour(CPed* pPed);
|
|
virtual bool FinishConditions(CPed* pPed);
|
|
|
|
void CreateAnimatedFallbackTask(CPed* pPed, bool bFalling);
|
|
virtual void StartAnimatedFallback(CPed* pPed);
|
|
virtual bool ControlAnimatedFallback(CPed* pPed);
|
|
|
|
//////////////////////////
|
|
// Local functions and data
|
|
public:
|
|
void UpdateShot(CPed* pThisPed, CEntity* pShotBy, u32 nWeaponHash, int nComponent, const Vector3& vecHitPos, const Vector3& vecHitImpulse,
|
|
const Vector3& vecHitPolyNormal);
|
|
|
|
u32 GetWeaponHash() const { return m_nWeaponHash; }
|
|
int GetComponent() const { return m_nComponent; }
|
|
CEntity* GetShotBy() const { return m_pShotBy; }
|
|
const Vector3 & GetWorldImpulse() const { return m_vecOriginalHitImpulseWorldSpace; }
|
|
void GetWorldHitPosition(CPed *pPed, Vector3 & worldHitPos) const;
|
|
bool IsSprinting() const { return m_bSprinting; }
|
|
|
|
virtual bool ShouldContinueAfterDeath() const {return true;}
|
|
virtual bool ShouldAbortForWeaponDamage(CEntity* pFiringEntity, const CWeaponInfo* pWeaponInfo, const f32 UNUSED_PARAM(fWeaponDamage), const fwFlags32& UNUSED_PARAM(flags),
|
|
const bool UNUSED_PARAM(bWasKilledOrInjured), const Vector3& UNUSED_PARAM(vStart), WorldProbe::CShapeTestHitPoint* pResult,
|
|
const Vector3& vRagdollImpulseDir, const f32 fRagdollImpulseMag)
|
|
{
|
|
// Fire and explosion damage override shot reactions
|
|
if(pWeaponInfo->GetDamageType() == DAMAGE_TYPE_FIRE || pWeaponInfo->GetDamageType() == DAMAGE_TYPE_EXPLOSIVE)
|
|
{
|
|
return true;
|
|
}
|
|
// Otherwise, if there's a shape test result, continue this shot reaction
|
|
else if ( pResult )
|
|
{
|
|
UpdateShot(GetPed(), pFiringEntity, pWeaponInfo->GetHash(), pResult->GetHitComponent(), pResult->GetHitPosition(), fRagdollImpulseMag * vRagdollImpulseDir, pResult->GetHitNormal());
|
|
return false;
|
|
}
|
|
// This is some unknown damage source we need to abort for.
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
virtual bool HandleRagdollImpact(float fMag, const CEntity* pEntity, const Vector3& vPedNormal, int nComponent, phMaterialMgr::Id nMaterialId);
|
|
|
|
protected:
|
|
|
|
void HandleNormalShotReaction(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
void HandleShotgunReaction(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
void HandleUnderwaterReaction(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
void HandleBoundAnklesReaction(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
void HandleMeleeReaction(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
void HandleRunningReaction(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
|
|
void GetLocalNormal(CPed* pPed, Vector3 &localHitNormal);
|
|
void CheckState(CPed* pPed);
|
|
void SetShotMessage(CPed* pPed, bool bStartBehaviour, CNmMessageList& list);
|
|
void ImpulseOverride(CPed* pPed);
|
|
void GatherSituationalData(CPed* pPed);
|
|
bool CheckForObjectInPath(CPed* pPed, Vector3 &objectBehindVictimPos, Vector3 &objectBehindVictimNormal);
|
|
void CalculateHealth(CPed* pPed);
|
|
void CheckInputNormalAndHitPosition();
|
|
|
|
void HandleConfigureBalance(CPed* pPed, CNmMessageList& list);
|
|
void HandleConfigureBullets(CPed* pPed, bool bStart = true);
|
|
void HandlePointGun(CPed* pPed, bool bStart, CNmMessageList& list);
|
|
void HandleApplyBulletImpulse(CPed* pPed, bool bSendNewBulletMessage = true, bool bStart = true, bool doKillShot = false, bool wallInImpulsePath = false);
|
|
void HandleNewBullet(CPed* pPed, Vector3 &posLocal, const Vector3 &normalLocal, const Vector3 &impulseWorld);
|
|
void HandleHeadLook(CPed* pPed, CNmMessageList& list);
|
|
void HandleSnap(CPed* pPed, CNmMessageList& list);
|
|
|
|
// Clamps the local hit position to the closest surface point on the bound
|
|
void ClampHitToSurfaceOfBound(CPed* pPed, Vector3 &localPos, int component);
|
|
|
|
void StartAnimatedReachForWound();
|
|
bool ShouldReachForWound(bool& withLeft);
|
|
|
|
bool IsArmoured(CPed* pPed)
|
|
{
|
|
return pPed && (pPed->GetArmour()>0.0f);
|
|
}
|
|
|
|
float GetArmouredRatio(CPed* pPed)
|
|
{
|
|
float armour = 0.0f;
|
|
if (pPed)
|
|
{
|
|
armour = pPed->GetArmour() + pPed->GetArmourLost();
|
|
if (armour>0.0f)
|
|
{
|
|
armour = pPed->GetArmour() / armour;
|
|
}
|
|
armour = ClampRange(armour, 0.0f, 1.0f);
|
|
}
|
|
return armour;
|
|
}
|
|
|
|
float GetHealthRatio(CPed* pPed)
|
|
{
|
|
float healthRatio = 0.0f;
|
|
if (pPed)
|
|
{
|
|
healthRatio = pPed->GetMaxHealth() - pPed->GetInjuredHealthThreshold();
|
|
if (healthRatio>0.0f)
|
|
{
|
|
healthRatio = 1.0f - (pPed->GetHealthLost() / healthRatio);
|
|
}
|
|
healthRatio = ClampRange(healthRatio, 0.0f, 1.0f);
|
|
}
|
|
return healthRatio;
|
|
}
|
|
|
|
bool IsCloneDying(const CPed* pPed) const;
|
|
|
|
bool ShouldBlindFireWeapon(CPed* pPed);
|
|
bool ShouldBlindFireWeaponNetworkCheck(CPed* pPed, Vector3 const& vecStart, Vector3 const& vecEnd);
|
|
|
|
bool IsAutomatic(const atHashString& shotTuningSet) const
|
|
{
|
|
if (shotTuningSet == ATSTRINGHASH("Automatic", 0x74D3AC3B) ||
|
|
shotTuningSet == ATSTRINGHASH("AutomaticMG", 0xBD26D537) ||
|
|
shotTuningSet == ATSTRINGHASH("AutomaticSMG", 0x7183C85F) ||
|
|
shotTuningSet == ATSTRINGHASH("Mini", 0x1289C7C8) ||
|
|
shotTuningSet == ATSTRINGHASH("BurstFire", 0xC48A0A41))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
enum eStates // for internal state machine.
|
|
{
|
|
State_STANDING,
|
|
State_STAGGERING,
|
|
State_FALLING,
|
|
State_ON_GROUND,
|
|
State_PARTIALLY_SUBMERGED, // In water
|
|
State_SUBMERGED, // In water
|
|
State_TEETERING
|
|
};
|
|
eStates m_eState;
|
|
|
|
u32 m_eType;
|
|
|
|
private:
|
|
CThreatenedHelper m_threatenedHelper;
|
|
|
|
WorldProbe::CShapeTestResults m_probeResult;
|
|
|
|
#if !__FINAL
|
|
// For debugging the internal state machine.
|
|
atString m_strTaskAndStateName;
|
|
#endif // !__FINAL
|
|
|
|
Vec3V m_vecOriginalHitPositionBoneSpace; // store the local space position of the wound for later use in animated reach for wound.
|
|
|
|
Vector3 m_vecOriginalHitPositionLocalSpace;
|
|
Vector3 m_vecOriginalHitPolyNormalWorldSpace;
|
|
Vector3 m_vecOriginalHitImpulseWorldSpace;
|
|
|
|
Vector3 m_vEdgeLeft, m_vEdgeRight;
|
|
bool m_FirstTeeterProbeDetectedDrop;
|
|
|
|
RegdEnt m_pShotBy;
|
|
int m_nComponent;
|
|
u32 m_nWeaponHash;
|
|
|
|
u32 m_LastConfigureBulletsCall;
|
|
|
|
u32 m_BiasSideTime;
|
|
|
|
float m_healthRatio;
|
|
|
|
u32 m_nTimeToStopBlindFire;
|
|
u32 m_nTimeTillBlindFireNextShot;
|
|
u32 m_LastStandStartTimeMS;
|
|
u32 m_DisableReachForWoundTimeMS;
|
|
|
|
u16 m_nLookAtArmWoundTime;
|
|
u16 m_CountdownToCatchfall;
|
|
|
|
s16 m_hitCountThisPerformance;
|
|
|
|
u8 m_ThrownOutImpulseCount;
|
|
u8 m_ShotsPerBurst;
|
|
|
|
bool m_bUsingBalance : 1;
|
|
bool m_bBalanceFailed : 1;
|
|
bool m_bUseHeadLook : 1;
|
|
bool m_bUsePointGun : 1;
|
|
bool m_StaggerFallStarted : 1;
|
|
bool m_bSprinting : 1;
|
|
|
|
bool m_bFront : 1;
|
|
bool m_bUpright : 1;
|
|
bool m_RapidFiring : 1;
|
|
bool m_RapidFiringBoostFrame : 1;
|
|
|
|
bool m_ElectricDamage : 1;
|
|
bool m_SettingShotMessageForShotgun : 1;
|
|
bool m_ShotgunMessageSent : 1;
|
|
bool m_HeldWeapon : 1;
|
|
bool m_bMinTimeExtended : 1;
|
|
bool m_stepInInSupportApplied : 1;
|
|
bool m_bLastStandActive : 1;
|
|
bool m_bKnockDownStarted : 1;
|
|
bool m_bKillShotUsed : 1;
|
|
bool m_bFallingToKnees : 1;
|
|
bool m_ReachingWithLeft : 1;
|
|
bool m_ReachingWithRight : 1;
|
|
bool m_DoLegShotFall : 1;
|
|
bool m_FallingOverWall : 1;
|
|
bool m_bTeeterInitd : 1;
|
|
bool m_BiasSide : 1;
|
|
bool m_WasCrouchedOrInLowCover : 1;
|
|
|
|
#if __DEV
|
|
bool m_selected : 1;
|
|
#endif
|
|
|
|
// tunable by widgets
|
|
public:
|
|
|
|
void ChooseParameterSet();
|
|
|
|
static bool IsPoseAppropriateForFiring(CPed* pFiringPed, CAITarget& target, CWeapon* pWeapon, CObject* pWeaponObject);
|
|
|
|
#if !__FINAL
|
|
#if DEBUG_DRAW
|
|
void DebugVisualise (const CPed* pPed) const; // Put here so that it can be called while the game is paused.
|
|
#endif // DEBUG_DRAW
|
|
virtual void Debug() const
|
|
{
|
|
#if DEBUG_DRAW
|
|
// Visualise the hit point and impact vector for debugging.
|
|
if(sm_Tunables.m_bEnableDebugDraw)
|
|
{
|
|
DebugVisualise(GetPed());
|
|
}
|
|
#endif // DEBUG_DRAW
|
|
CTask::Debug();
|
|
}
|
|
#endif // !__FINAL
|
|
|
|
static Tunables sm_Tunables;
|
|
};
|
|
|
|
#endif // ! INC_TASKNMSHOT_H_
|