#ifndef __PEDSA #define __PEDSA #include "GeneralSA.h" class CEntryExit; class CEvent; class CPed; // This structure is very incomplete, but it is good enough for now class __declspec(novtable) CTask { public: virtual ~CTask(); virtual CTask* Clone() const = 0; virtual CTask* GetSubTask() const = 0; virtual bool IsSimpleTask() const = 0; virtual int GetTaskType() const = 0; virtual void StopTimer(const CEvent*) { } virtual bool MakeAbortable(CPed*, int, const CEvent*) = 0; public: CTask* m_parentTask; }; static_assert(sizeof(CTask) == 0x8, "Wrong size: CTask"); class __declspec(novtable) CTaskSimple : public CTask { public: virtual bool IsSimpleTask() const override { return true; } virtual bool SetPedPosition(CPed*) { return false; } }; class __declspec(novtable) CTaskComplex : public CTask { public: virtual bool IsSimpleTask() const override { return false; } virtual void SetSubTask(CTask*); virtual CTask* CreateNextSubTask(CPed*) = 0; virtual CTask* CreateFirstSubTask(CPed*) = 0; virtual CTask* ControlSubTask(CPed*) = 0; }; // Stub class __declspec(novtable) CTaskSimpleJetPack : public CTaskSimple { public: void RenderJetPack(class CPed* pPed); }; class __declspec(novtable) CTaskComplexSequence : public CTaskComplex { public: bool Contains(int taskID) const; public: std::byte __pad1[8]; CTask* m_taskSequence[8]; std::byte __pad2[16]; }; static_assert(sizeof(CTaskComplexSequence) == 0x40, "Wrong size: CTaskComplexSequence"); class CTaskManager { public: CTask* m_primaryTasks[5]; CTask* m_secondaryTasks[6]; CPed* m_pPed; }; static_assert(sizeof(CTaskManager) == 0x30, "Wrong size: CTaskManager"); class CPedIntelligence { public: CPed* m_pPed; CTaskManager m_taskManager; public: class CTaskSimpleJetPack* GetTaskJetPack() const; }; class CPedFlags { public: unsigned int bIsStanding : 1; // is ped standing on something unsigned int bWasStanding : 1; // was ped standing on something unsigned int bIsLooking : 1; // is ped looking at something or in a direction unsigned int bIsRestoringLook : 1; // is ped restoring head postion from a look unsigned int bIsAimingGun : 1; // is ped aiming gun unsigned int bIsRestoringGun : 1; // is ped moving gun back to default posn unsigned int bCanPointGunAtTarget : 1; // can ped point gun at target unsigned int bIsTalking : 1; // is ped talking(see Chat()) unsigned int bInVehicle : 1; // is in a vehicle unsigned int bIsInTheAir : 1; // is in the air unsigned int bIsLanding : 1; // is landing after being in the air unsigned int bHitSomethingLastFrame : 1; // has been in a collision last fram unsigned int bIsNearCar : 1; // has been in a collision last fram unsigned int bRenderPedInCar : 1; // has been in a collision last fram unsigned int bUpdateAnimHeading : 1; // update ped heading due to heading change during anim sequence unsigned int bRemoveHead : 1; // waiting on AntiSpazTimer to remove head unsigned int bFiringWeapon : 1; // is pulling trigger unsigned int bHasACamera : 1; // does ped possess a camera to document accidents unsigned int bPedIsBleeding : 1; // Ped loses a lot of blood if true unsigned int bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun unsigned int bIsPedDieAnimPlaying : 1; // is ped die animation finished so can dead now unsigned int bStayInSamePlace :1; // when set, ped stays put unsigned int bKindaStayInSamePlace :1; // when set, ped doesn't seek out opponent or cover large distances. Will still shuffle and look for cover unsigned int bBeingChasedByPolice :1; // use nodes for routefind unsigned int bNotAllowedToDuck :1; // Is this ped allowed to duck at all? unsigned int bCrouchWhenShooting :1; // duck behind cars etc unsigned int bIsDucking :1; // duck behind cars etc unsigned int bGetUpAnimStarted :1; // don't want to play getup anim if under something unsigned int bDoBloodyFootprints :1; // unsigned int bIsLeader :1; unsigned int bDontDragMeOutCar :1; unsigned int bStillOnValidPoly :1; // set if the polygon the ped is on is still valid for collision unsigned int bAllowMedicsToReviveMe :1; unsigned int bResetWalkAnims :1; unsigned int bOnBoat :1; // flee but only using nodes unsigned int bBusJacked :1; // flee but only using nodes unsigned int bFadeOut :1; // set if you want ped to fade out unsigned int bKnockedUpIntoAir :1; // has ped been knocked up into the air by a car collision unsigned int bHitSteepSlope :1; // has ped collided/is standing on a steep slope (surface type) unsigned int bCullExtraFarAway :1; // special ped only gets culled if it's extra far away (for roadblocks) unsigned int bTryingToReachDryLand :1; // has ped just exited boat and trying to get to dry land unsigned int bCollidedWithMyVehicle :1; unsigned int bRichFromMugging :1; // ped has lots of cash cause they've been mugging people unsigned int bChrisCriminal :1; // Is a criminal as killed during Chris' police mission (should be counted as such) unsigned int bShakeFist :1; // test shake hand at look entity unsigned int bNoCriticalHits : 1; // ped cannot be killed by a single bullet unsigned int bHasAlreadyBeenRecorded : 1; // Used for replays unsigned int bUpdateMatricesRequired : 1; // if PedIK has altered bones so matrices need updated this frame unsigned int bFleeWhenStanding :1; // unsigned int bMiamiViceCop :1; // unsigned int bMoneyHasBeenGivenByScript :1; // unsigned int bHasBeenPhotographed :1; // unsigned int bIsDrowning : 1; unsigned int bDrownsInWater : 1; unsigned int bHeadStuckInCollision : 1; unsigned int bDeadPedInFrontOfCar :1; unsigned int bStayInCarOnJack :1; unsigned int bDontFight :1; unsigned int bDoomAim :1; unsigned int bCanBeShotInVehicle : 1; unsigned int bPushedAlongByCar :1; // ped is getting pushed along by car collision (so don't take damage from horz velocity) unsigned int bNeverEverTargetThisPed :1; unsigned int bThisPedIsATargetPriority :1; unsigned int bCrouchWhenScared :1; unsigned int bKnockedOffBike :1; unsigned int bDonePositionOutOfCollision :1; unsigned int bDontRender : 1; unsigned int bHasBeenAddedToPopulation :1; unsigned int bHasJustLeftCar :1; unsigned int bIsInDisguise :1; unsigned int bDoesntListenToPlayerGroupCommands :1; unsigned int bIsBeingArrested :1; unsigned int bHasJustSoughtCover :1; unsigned int bKilledByStealth :1; unsigned int bDoesntDropWeaponsWhenDead :1; unsigned int bCalledPreRender :1; unsigned int bBloodPuddleCreated : 1; // Has a static puddle of blood been created yet unsigned int bPartOfAttackWave :1; unsigned int bClearRadarBlipOnDeath :1; unsigned int bNeverLeavesGroup :1; // flag that we want to test 3 extra spheres on col model unsigned int bTestForBlockedPositions :1; // this sets these indicator flags for various posisions on the front of the ped unsigned int bRightArmBlocked :1; unsigned int bLeftArmBlocked :1; unsigned int bDuckRightArmBlocked :1; unsigned int bMidriffBlockedForJump :1; unsigned int bFallenDown :1; unsigned int bUseAttractorInstantly :1; unsigned int bDontAcceptIKLookAts :1; unsigned int bHasAScriptBrain : 1; unsigned int bWaitingForScriptBrainToLoad : 1; unsigned int bHasGroupDriveTask :1; unsigned int bCanExitCar :1; unsigned int CantBeKnockedOffBike :2; // 0=Default(harder for mission peds) 1=Never 2=Always normal(also for mission peds) unsigned int bHasBeenRendered : 1; unsigned int bIsCached :1; unsigned int bPushOtherPeds :1; // GETS RESET EVERY FRAME - SET IN TASK: want to push other peds around (eg. leader of a group or ped trying to get in a car) unsigned int bHasBulletProofVest :1; unsigned int bUsingMobilePhone :1; unsigned int bUpperBodyDamageAnimsOnly :1; unsigned int bStuckUnderCar :1; unsigned int bKeepTasksAfterCleanUp :1; // If true ped will carry on with task even after cleanup unsigned int bIsDyingStuck :1; unsigned int bIgnoreHeightCheckOnGotoPointTask :1; // set when walking round buildings, reset when task quits unsigned int bForceDieInCar:1; unsigned int bCheckColAboveHead:1; unsigned int bIgnoreWeaponRange : 1; unsigned int bDruggedUp : 1; unsigned int bWantedByPolice : 1; // if this is set, the cops will always go after this ped when they are doing a KillCriminal task unsigned int bSignalAfterKill: 1; unsigned int bCanClimbOntoBoat :1; unsigned int bPedHitWallLastFrame: 1; // useful to store this so that AI knows (normal will still be available) unsigned int bIgnoreHeightDifferenceFollowingNodes: 1; unsigned int bMoveAnimSpeedHasBeenSetByTask: 1; unsigned int bGetOutUpsideDownCar :1; unsigned int bJustGotOffTrain :1; unsigned int bDeathPickupsPersist :1; unsigned int bTestForShotInVehicle :1; unsigned int bUsedForReplay : 1; // This ped is controlled by replay and should be removed when replay is done. }; class CVehicle; class CPed; class CPlayerPedData { public: class CWanted* m_Wanted; // 0x0 void* m_pClothes; // 0x4 CPed* m_ArrestingOfficer; // 0x8 CVector2D m_vecFightMovement; // 0xC float m_moveBlendRatio; // 0x14 float m_fSprintEnergy; // 0x18 float m_fSprintControlCounter; // 0x1C BYTE m_nChosenWeapon; // 0x20 BYTE m_nCarDangerCounter; // 0x21 DWORD m_nStandStillTimer; // 0x24 DWORD m_nHitAnimDelayTimer; // 0x28 float m_fAttackButtonCounter; // 0x2C void *m_pDangerCar; // 0x30 DWORD m_bStoppedMoving : 1; // 0x34 DWORD m_bAdrenaline : 1; DWORD m_bHaveTargetSelected : 1; DWORD m_bFreeAiming : 1; DWORD bCanBeDamaged : 1; DWORD bAllMeleeAttackPtsBlocked : 1; DWORD m_JustBeenSnacking : 1; DWORD m_bRequireHandleBreath : 1; DWORD m_GroupStuffDisabled : 1; // 0x35 DWORD m_GroupAlwaysFollow : 1; DWORD m_GroupNeverFollow : 1; DWORD m_bInVehicleDontAllowWeaponChange : 1; DWORD m_bRenderWeapon : 1; DWORD m_bUnused1 : 1; DWORD m_bUnused2 : 1; DWORD m_bUnused3 : 1; DWORD m_bCopMode : 1; // 0x36 DWORD m_PlayerGroup; // 0x38 DWORD m_AdrenalineEndTime; // 0x3C BYTE m_nDrunkenness; // 0x40 BYTE m_bFadeDrunkenness; // 0x41 BYTE m_nDrugLevel; // 0x42 BYTE m_nScriptLimitToGangSize; // 0x43 float m_fBreath; // 0x44 DWORD m_MeleeWeaponAnimReferenced; // 0x48 DWORD m_MeleeWeaponAnimReferencedExtra; // 0x4C float m_fFPSMoveHeading; // 0x50 float m_fLookPitch; // 0x54 float m_fSkateBoardSpeed; // 0x58 float m_fSkateBoardLean; // 0x5C void *m_pSpecialAtomic; // 0x60 float m_fGunSpinSpeed; // 0x64 float m_fGunSpinAngle; // 0x68 DWORD m_LastTimeFiring; // 0x6C DWORD m_nTargetBone; // 0x70 CVector m_vecTargetBoneOffset; // 0x74 DWORD m_busFaresCollected; // 0x80 BYTE m_bPlayerSprintDisabled; // 0x84 BYTE m_bDontAllowWeaponChange; // 0x85 BYTE m_bForceInteriorLighting; // 0x86 WORD m_DPadDownPressedInMilliseconds; // 0x88 WORD m_DPadUpPressedInMilliseconds; // 0x8A BYTE m_wetness; // 0x8C BYTE m_playersGangActive; // 0x8D BYTE m_waterCoverPerc; // 0x8E FLOAT m_waterHeight; // 0x90 DWORD m_FireHSMissilePressedTime; // 0x94 void* m_LastHSMissileTarget; DWORD m_nModelIndexOfLastBuildingShot; DWORD m_LastHSMissileLOSTime :31; DWORD m_bLastHSMissileLOS :1; void* m_pCurrentProstitutePed; void* m_pLastProstituteShagged; }; class NOVMT CPed : public CPhysical { public: BYTE __pad1[820]; CPedFlags pedFlags; class CPedIntelligence* pPedIntelligence; CPlayerPedData* pPlayerData; unsigned char PedCreatedBy; BYTE __pad7[76]; int iMoveAnimGroup; BYTE __pad2[28]; RwObject* m_pWeaponObject; RwFrame* m_pMuzzleFlashFrame; BYTE __pad10[68]; float fHealth; float fMaxHealth; float fArmour; BYTE __pad8[12]; float m_fCurrentRotation; float m_fTargetRotation; BYTE __pad3[44]; CVehicle* pVehicle; BYTE __pad9[8]; DWORD pedType; BYTE __pad4[4]; CWeapon weaponSlots[13]; BYTE __pad5[12]; BYTE m_bActiveWeapon; BYTE __pad65[20]; unsigned char bFightingStyle, bFightingStyleExtra; BYTE __pad6[92]; CEntryExit* pCurrentEntryExit; BYTE __pad64[12]; public: inline bool Save_Stub() { return CPed::Save(); } inline bool Load_Stub() { return CPed::Load(); } virtual bool Save(); virtual bool Load(); inline DWORD GetPedType() { return pedType; }; inline CPedFlags& GetPedFlags() { return pedFlags; }; inline CVehicle* GetVehiclePtr() { return pVehicle; }; inline CWeapon* GetWeaponSlots() { return weaponSlots; }; inline int GetMoveAnimGroup() { return iMoveAnimGroup; }; inline void SetMoveAnimGroup(int a) { iMoveAnimGroup = a; }; inline CPedIntelligence* GetPedIntelligencePtr() { return pPedIntelligence; }; inline float GetHealth() { return fHealth; }; inline float GetArmour() { return fArmour; }; inline CPlayerPedData* GetPlayerData() { return pPlayerData; }; inline BYTE GetActiveWeapon() { return m_bActiveWeapon; }; inline void SetCurrentHeading(float fVal) { m_fCurrentRotation = fVal; } inline void SetTargetHeading(float fVal) { m_fTargetRotation = fVal; } bool IsPlayer() const { return pedType == 0 || pedType == 1; } uint8_t GetWeaponSkill(); void ResetGunFlashAlpha(); void SetGunFlashAlpha(bool bSecondWeapon); void Say(uint16_t phrase, uint32_t param2 = 0, float volume = 1.0f, bool param4 = false, bool param5 = false, bool param6 = false); void RenderWeapon(bool bWeapon, bool bMuzzleFlash, bool bForShadow); void RenderForShadow(); static void (CPed::*orgGiveWeapon)(uint32_t weapon, uint32_t ammo, bool flag); void GiveWeapon_SP( uint32_t weapon, uint32_t ammo, bool flag ); // Extension to accommodate for SA-MP hooking GetWeaponSkill in RenderWeaponPedsForPC dynamically static inline uint8_t (CPed::*orgGetWeaponSkillForRenderWeaponPedsForPC)() = &GetWeaponSkill; uint8_t GetWeaponSkillForRenderWeaponPedsForPC() { return std::invoke( orgGetWeaponSkillForRenderWeaponPedsForPC, this ); } uint8_t GetWeaponSkillForRenderWeaponPedsForPC_SAMP(); static inline void (CPed::*orgSay)(uint16_t phrase, uint32_t param2, float volume, bool param4, bool param5, bool param6); template void Say_SampleBlackList(uint16_t phrase, uint32_t param2 = 0, float volume = 1.0f, bool param4 = false, bool param5 = false, bool param6 = false) { if ( !(phrase == blackSample) ) { std::invoke(orgSay, this, phrase, param2, volume, param4, param5, param6); } } }; constexpr uint16_t CONTEXT_GLOBAL_CAR_HIT_PED = 36; // CPed::Say enum class NOVMT CPlayerPed : public CPed { private: CPed* m_pMouseLockOnRecruitPed; int m_iMouseLockOnRecruitTimer; public: static void (CPlayerPed::*orgDoStuffToGoOnFire)(); void DoStuffToGoOnFire() { (this->*orgDoStuffToGoOnFire)(); } }; static_assert(sizeof(CPed) == 0x79C, "Wrong size: CPed"); static_assert(sizeof(CPlayerPed) == 0x7A4, "Wrong size: CPlayerPed"); class CClothes { public: static void (*RebuildPlayer)(CPlayerPed* ped, bool bForReplay); }; #endif