diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 1132c341e94..4f26a3785c7 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -578,6 +578,16 @@ void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const } } +void CPedSA::SetInWaterFlags(bool inWater) +{ + auto* physicalInterface = static_cast(m_pInterface); + if (!physicalInterface) + return; + + physicalInterface->bTouchingWater = inWater; + physicalInterface->bSubmergedInWater = inWater; +} + //////////////////////////////////////////////////////////////// // // CPed_PreRenderAfterTest diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index a17ae306e60..34e2de6f414 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -475,6 +475,8 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA void GetAttachedSatchels(std::vector &satchelsList) const override; + void SetInWaterFlags(bool inWater) override; + static void StaticSetHooks(); private: diff --git a/Client/game_sa/CTaskManagementSystemSA.cpp b/Client/game_sa/CTaskManagementSystemSA.cpp index 4db1ac5dfb3..7354328ff2f 100644 --- a/Client/game_sa/CTaskManagementSystemSA.cpp +++ b/Client/game_sa/CTaskManagementSystemSA.cpp @@ -22,6 +22,7 @@ #include "TaskPhysicalResponseSA.h" #include "TaskSA.h" #include "TaskSecondarySA.h" +#include "TaskSimpleSwimSA.h" extern CGameSA* pGame; @@ -181,6 +182,9 @@ CTaskSA* CTaskManagementSystemSA::CreateAppropriateTask(CTaskSAInterface* pTaskI case TASK_COMPLEX_SUNBATHE: pTaskSA = new CTaskComplexSunbatheSA; break; + case TASK_SIMPLE_SWIM: + pTaskSA = new CTaskSimpleSwimSA; + break; // Car accessories case TASK_SIMPLE_CAR_SET_PED_IN_AS_PASSENGER: diff --git a/Client/game_sa/CTasksSA.cpp b/Client/game_sa/CTasksSA.cpp index 8a180c99bea..25f4d87ee6a 100644 --- a/Client/game_sa/CTasksSA.cpp +++ b/Client/game_sa/CTasksSA.cpp @@ -160,6 +160,13 @@ CTaskSimpleRunNamedAnim* CTasksSA::CreateTaskSimpleRunNamedAnim(const char* pAni return pTask; } +CTaskComplexInWater* CTasksSA::CreateTaskComplexInWater() +{ + CTaskComplexInWaterSA* task = NewTask(); + m_pTaskManagementSystem->AddTask(task); + return task; +} + CTaskComplexDie* CTasksSA::CreateTaskComplexDie(const eWeaponType eMeansOfDeath, const AssocGroupId animGroup, const AnimationId anim, const float fBlendDelta, const float fAnimSpeed, const bool bBeingKilledByStealth, const bool bFallingToDeath, const int iFallToDeathDir, const bool bFallToDeathOverRailing) diff --git a/Client/game_sa/CTasksSA.h b/Client/game_sa/CTasksSA.h index fe1808d0419..fd1d06c5b12 100644 --- a/Client/game_sa/CTasksSA.h +++ b/Client/game_sa/CTasksSA.h @@ -42,6 +42,7 @@ class CTaskSimpleRunNamedAnim; class CTaskSimpleStealthKill; class CTaskSimpleTriggerLookAt; class CTaskSimpleUseGun; +class CTaskComplexInWater; class CTasksSA : public CTasks { @@ -80,6 +81,8 @@ class CTasksSA : public CTasks const int iTime = -1, const bool bDontInterrupt = false, const bool bRunInSequence = false, const bool bOffsetPed = false, const bool bHoldLastFrame = false); + CTaskComplexInWater* CreateTaskComplexInWater(); + CTaskComplexDie* CreateTaskComplexDie(const eWeaponType eMeansOfDeath = WEAPONTYPE_UNARMED, const AssocGroupId animGroup = 0 /*ANIM_STD_PED*/, const AnimationId anim = 0 /*ANIM_STD_KO_FRONT*/, const float fBlendDelta = 4.0f, const float fAnimSpeed = 0.0f, const bool bBeingKilledByStealth = false, const bool bFallingToDeath = false, const int iFallToDeathDir = 0, diff --git a/Client/game_sa/TaskBasicSA.cpp b/Client/game_sa/TaskBasicSA.cpp index d9a3224e651..db429df7a60 100644 --- a/Client/game_sa/TaskBasicSA.cpp +++ b/Client/game_sa/TaskBasicSA.cpp @@ -246,3 +246,13 @@ CTaskComplexFacialSA::CTaskComplexFacialSA() call dwFunc } } + +CTaskComplexInWaterSA::CTaskComplexInWaterSA() +{ + CreateTaskInterface(sizeof(CTaskComplexInWaterSA)); + if (!IsValid()) + return; + + // Call the constructor + ((void(__thiscall*)(CTaskComplexInWaterSAInterface*))0x6350D0)(static_cast(GetInterface())); +} diff --git a/Client/game_sa/TaskBasicSA.h b/Client/game_sa/TaskBasicSA.h index c62b3e1b755..76654708759 100644 --- a/Client/game_sa/TaskBasicSA.h +++ b/Client/game_sa/TaskBasicSA.h @@ -251,3 +251,14 @@ class CTaskComplexFacialSA : public virtual CTaskComplexSA, public virtual CTask public: CTaskComplexFacialSA(); }; + +class CTaskComplexInWaterSAInterface : public CTaskComplexSAInterface +{ +public: +}; + +class CTaskComplexInWaterSA : public virtual CTaskComplexSA, public virtual CTaskComplexInWater +{ +public: + CTaskComplexInWaterSA(); +}; diff --git a/Client/game_sa/TaskSimpleSwimSA.cpp b/Client/game_sa/TaskSimpleSwimSA.cpp new file mode 100644 index 00000000000..d562f037006 --- /dev/null +++ b/Client/game_sa/TaskSimpleSwimSA.cpp @@ -0,0 +1,22 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "TaskSimpleSwimSA.h" +#include "CPedSA.h" + +CTaskSimpleSwimSA::CTaskSimpleSwimSA(CPed* ped, CVector* pos) +{ + CreateTaskInterface(sizeof(CTaskSimpleSAInterface)); + if (!IsValid()) + return; + + // Call the constructor + ((void(__thiscall*)(CTaskSimpleSwimSAInterface*, CVector*, CPedSAInterface*))0x688930)(static_cast(GetInterface()), pos, ped ? ped->GetPedInterface() : nullptr); +} diff --git a/Client/game_sa/TaskSimpleSwimSA.h b/Client/game_sa/TaskSimpleSwimSA.h new file mode 100644 index 00000000000..14ed311b1b0 --- /dev/null +++ b/Client/game_sa/TaskSimpleSwimSA.h @@ -0,0 +1,59 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include "TaskSA.h" +#include +#include +#include + +class CPedSAInterface; +class CEntitySAInterface; + +class CTaskSimpleSwimSAInterface : public CTaskSimpleSAInterface +{ +public: + bool m_finishedBlending; + bool m_animBlockRefAdded; + swimState m_swimState; + int m_animID; + float m_animSpeed; + CVector m_pos; + CPedSAInterface* m_ped; + float m_rotationX; + float m_turningRotationY; + float m_upperTorsoRotationX; + float m_aimingRotation; + float m_stateChanger; + CEntitySAInterface* m_entity; + CVector m_climbPos; + float m_angle; + SurfaceTypes::Enum m_surfaceType; + std::uint8_t m_field4D[3]; + float m_randomMoveBlendRatio; + float m_swimStopTime; + std::uint32_t m_timeStep; + void* m_fxSystem; // FxSystem_cSAInterface* + bool m_triggerWaterSplash; + std::uint8_t m_field61[3]; +}; + +class CTaskSimpleSwimSA : public virtual CTaskSimpleSA, public virtual CTaskSimpleSwim +{ +public: + CTaskSimpleSwimSA() {}; + CTaskSimpleSwimSA(CPed* ped, CVector* pos); + + const CTaskSimpleSwimSAInterface* GetTaskInterface() const { return static_cast(GetInterface()); } + CTaskSimpleSwimSAInterface* GetTaskInterface() { return static_cast(GetInterface()); } + + swimState GetSwimState() const override { return GetTaskInterface()->m_swimState; } +}; diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 98319222477..a76cb8de6e6 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "enums/VehicleType.h" using std::list; @@ -7236,3 +7237,32 @@ void CClientPed::RunClimbingTask() climbTask->SetAsPedTask(m_pPlayerPed, TASK_PRIORITY_PRIMARY, true); } + +CTaskSimpleSwim* CClientPed::GetSwimmingTask() const +{ + if (!m_pPlayerPed) + return nullptr; + + CTask* simplestTask = const_cast(GetTaskManager())->GetSimplestActiveTask(); + if (!simplestTask || simplestTask->GetTaskType() != TASK_SIMPLE_SWIM) + return nullptr; + + auto* swimmingTask = dynamic_cast(simplestTask); + return swimmingTask; +} + +void CClientPed::RunSwimTask() const +{ + if (!m_pPlayerPed || GetSwimmingTask()) + return; + + CTaskComplexInWater* inWaterTask = g_pGame->GetTasks()->CreateTaskComplexInWater(); + if (!inWaterTask) + return; + + // Set physical flags (bTouchingWater, bSubmergedInWater) + m_pPlayerPed->SetInWaterFlags(true); + + inWaterTask->SetAsPedTask(m_pPlayerPed, TASK_PRIORITY_EVENT_RESPONSE_NONTEMP, true); +} + \ No newline at end of file diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 62198493410..e4153ee5b76 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -35,6 +35,7 @@ class CClientPlayerClothes; class CClientProjectile; class CClientVehicle; class CTask; +class CTaskSimpleSwim; enum eDelayedSyncData { @@ -566,6 +567,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void RunClimbingTask(); + CTaskSimpleSwim* GetSwimmingTask() const; + void RunSwimTask() const; + protected: // This constructor is for peds managed by a player. These are unknown to the ped manager. CClientPed(CClientManager* pManager, unsigned long ulModelID, ElementID ID, bool bIsLocalPlayer); diff --git a/Client/mods/deathmatch/logic/CNetAPI.cpp b/Client/mods/deathmatch/logic/CNetAPI.cpp index 6600f341ac0..3f2e18b7365 100644 --- a/Client/mods/deathmatch/logic/CNetAPI.cpp +++ b/Client/mods/deathmatch/logic/CNetAPI.cpp @@ -984,6 +984,9 @@ void CNetAPI::ReadPlayerPuresync(CClientPlayer* pPlayer, NetBitStreamInterface& if (flags.data.hangingDuringClimb && pPlayer->GetMovementState() != eMovementState::MOVEMENTSTATE_HANGING && pPlayer->GetMovementState() != eMovementState::MOVEMENTSTATE_CLIMB) pPlayer->RunClimbingTask(); + if (flags.data.bIsInWater && !pPlayer->IsInWater()) + pPlayer->RunSwimTask(); + // Remember now as the last puresync time pPlayer->SetLastPuresyncTime(CClientTime::GetTime()); pPlayer->SetLastPuresyncPosition(position.data.vecPosition); diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index 3219738e699..7f032596b0b 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -307,4 +307,6 @@ class CPed : public virtual CPhysical virtual void GetAttachedSatchels(std::vector &satchelsList) const = 0; virtual void Say(const ePedSpeechContext& speechId, float probability) = 0; + + virtual void SetInWaterFlags(bool inWater) = 0; }; diff --git a/Client/sdk/game/CTasks.h b/Client/sdk/game/CTasks.h index f5b90e4f556..4211b838519 100644 --- a/Client/sdk/game/CTasks.h +++ b/Client/sdk/game/CTasks.h @@ -46,6 +46,7 @@ class CTaskSimpleRunNamedAnim; class CTaskSimpleStealthKill; class CTaskSimpleTriggerLookAt; class CTaskSimpleUseGun; +class CTaskComplexInWater; class CVector; class CVehicle; @@ -96,6 +97,8 @@ class CTasks const int iTime = -1, const bool bDontInterrupt = false, const bool bRunInSequence = false, const bool bOffsetPed = false, const bool bHoldLastFrame = false) = 0; + virtual CTaskComplexInWater* CreateTaskComplexInWater() = 0; + virtual CTaskComplexDie* CreateTaskComplexDie(const eWeaponType eMeansOfDeath = WEAPONTYPE_UNARMED, const AssocGroupId animGroup = 0 /*ANIM_STD_PED*/, const AnimationId anim = 0 /*ANIM_STD_KO_FRONT*/, const float fBlendDelta = 4.0f, const float fAnimSpeed = 0.0f, const bool bBeingKilledByStealth = false, const bool bFallingToDeath = false, diff --git a/Client/sdk/game/TaskBasic.h b/Client/sdk/game/TaskBasic.h index bd88b855d95..8ec831dc55d 100644 --- a/Client/sdk/game/TaskBasic.h +++ b/Client/sdk/game/TaskBasic.h @@ -95,3 +95,9 @@ class CTaskComplexFacial : public virtual CTaskComplex public: virtual ~CTaskComplexFacial(){}; }; + +class CTaskComplexInWater : public virtual CTaskComplex +{ +public: + virtual ~CTaskComplexInWater(){}; +}; diff --git a/Client/sdk/game/TaskSimpleSwim.h b/Client/sdk/game/TaskSimpleSwim.h new file mode 100644 index 00000000000..11dd2d6354b --- /dev/null +++ b/Client/sdk/game/TaskSimpleSwim.h @@ -0,0 +1,30 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/TaskSimpleSwim.h + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once +#include "Task.h" + +enum swimState : std::uint16_t +{ + SWIM_TREAD = 0, + SWIM_SPRINT, + SWIM_SPRINTING, + SWIM_DIVE_UNDERWATER, + SWIM_UNDERWATER_SPRINTING, + SWIM_BACK_TO_SURFACE, +}; + +class CTaskSimpleSwim : public virtual CTaskSimple +{ +public: + virtual ~CTaskSimpleSwim() {}; + + virtual swimState GetSwimState() const = 0; +}; diff --git a/Shared/sdk/enums/SurfaceType.h b/Shared/sdk/enums/SurfaceType.h new file mode 100644 index 00000000000..fa7bf54ef89 --- /dev/null +++ b/Shared/sdk/enums/SurfaceType.h @@ -0,0 +1,198 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/SurfaceType.h + * PURPOSE: Header for common definitions + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +namespace SurfaceTypes +{ + enum Enum : std::uint8_t + { + SURFACE_DEFAULT = 0, + SURFACE_TARMAC, + SURFACE_TARMAC_FUCKED, + SURFACE_TARMAC_REALLYFUCKED, + SURFACE_PAVEMENT, + SURFACE_PAVEMENT_FUCKED, + SURFACE_GRAVEL, + SURFACE_FUCKED_CONCRETE, + SURFACE_PAINTED_GROUND, + SURFACE_GRASS_SHORT_LUSH, + SURFACE_GRASS_MEDIUM_LUSH, + SURFACE_GRASS_LONG_LUSH, + SURFACE_GRASS_SHORT_DRY, + SURFACE_GRASS_MEDIUM_DRY, + SURFACE_GRASS_LONG_DRY, + SURFACE_GOLFGRASS_ROUGH, + SURFACE_GOLFGRASS_SMOOTH, + SURFACE_STEEP_SLIDYGRASS, + SURFACE_STEEP_CLIFF, + SURFACE_FLOWERBED, + SURFACE_MEADOW, + SURFACE_WASTEGROUND, + SURFACE_WOODLANDGROUND, + SURFACE_VEGETATION, + SURFACE_MUD_WET, + SURFACE_MUD_DRY, + SURFACE_DIRT, + SURFACE_DIRTTRACK, + SURFACE_SAND_DEEP, + SURFACE_SAND_MEDIUM, + SURFACE_SAND_COMPACT, + SURFACE_SAND_ARID, + SURFACE_SAND_MORE, + SURFACE_SAND_BEACH, + SURFACE_CONCRETE_BEACH, + SURFACE_ROCK_DRY, + SURFACE_ROCK_WET, + SURFACE_ROCK_CLIFF, + SURFACE_WATER_RIVERBED, + SURFACE_WATER_SHALLOW, + SURFACE_CORNFIELD, + SURFACE_HEDGE, + SURFACE_WOOD_CRATES, + SURFACE_WOOD_SOLID, + SURFACE_WOOD_THIN, + SURFACE_GLASS, + SURFACE_GLASS_WINDOWS_LARGE, + SURFACE_GLASS_WINDOWS_SMALL, + SURFACE_EMPTY1, + SURFACE_EMPTY2, + SURFACE_GARAGE_DOOR, + SURFACE_THICK_METAL_PLATE, + SURFACE_SCAFFOLD_POLE, + SURFACE_LAMP_POST, + SURFACE_METAL_GATE, + SURFACE_METAL_CHAIN_FENCE, + SURFACE_GIRDER, + SURFACE_FIRE_HYDRANT, + SURFACE_CONTAINER, + SURFACE_NEWS_VENDOR, + SURFACE_WHEELBASE, + SURFACE_CARDBOARDBOX, + SURFACE_PED, + SURFACE_CAR, + SURFACE_CAR_PANEL, + SURFACE_CAR_MOVINGCOMPONENT, + SURFACE_TRANSPARENT_CLOTH, + SURFACE_RUBBER, + SURFACE_PLASTIC, + SURFACE_TRANSPARENT_STONE, + SURFACE_WOOD_BENCH, + SURFACE_CARPET, + SURFACE_FLOORBOARD, + SURFACE_STAIRSWOOD, + SURFACE_P_SAND, + SURFACE_P_SAND_DENSE, + SURFACE_P_SAND_ARID, + SURFACE_P_SAND_COMPACT, + SURFACE_P_SAND_ROCKY, + SURFACE_P_SANDBEACH, + SURFACE_P_GRASS_SHORT, + SURFACE_P_GRASS_MEADOW, + SURFACE_P_GRASS_DRY, + SURFACE_P_WOODLAND, + SURFACE_P_WOODDENSE, + SURFACE_P_ROADSIDE, + SURFACE_P_ROADSIDEDES, + SURFACE_P_FLOWERBED, + SURFACE_P_WASTEGROUND, + SURFACE_P_CONCRETE, + SURFACE_P_OFFICEDESK, + SURFACE_P_711SHELF1, + SURFACE_P_711SHELF2, + SURFACE_P_711SHELF3, + SURFACE_P_RESTUARANTTABLE, + SURFACE_P_BARTABLE, + SURFACE_P_UNDERWATERLUSH, + SURFACE_P_UNDERWATERBARREN, + SURFACE_P_UNDERWATERCORAL, + SURFACE_P_UNDERWATERDEEP, + SURFACE_P_RIVERBED, + SURFACE_P_RUBBLE, + SURFACE_P_BEDROOMFLOOR, + SURFACE_P_KIRCHENFLOOR, + SURFACE_P_LIVINGRMFLOOR, + SURFACE_P_CORRIDORFLOOR, + SURFACE_P_711FLOOR, + SURFACE_P_FASTFOODFLOOR, + SURFACE_P_SKANKYFLOOR, + SURFACE_P_MOUNTAIN, + SURFACE_P_MARSH, + SURFACE_P_BUSHY, + SURFACE_P_BUSHYMIX, + SURFACE_P_BUSHYDRY, + SURFACE_P_BUSHYMID, + SURFACE_P_GRASSWEEFLOWERS, + SURFACE_P_GRASSDRYTALL, + SURFACE_P_GRASSLUSHTALL, + SURFACE_P_GRASSGRNMIX, + SURFACE_P_GRASSBRNMIX, + SURFACE_P_GRASSLOW, + SURFACE_P_GRASSROCKY, + SURFACE_P_GRASSSMALLTREES, + SURFACE_P_DIRTROCKY, + SURFACE_P_DIRTWEEDS, + SURFACE_P_GRASSWEEDS, + SURFACE_P_RIVEREDGE, + SURFACE_P_POOLSIDE, + SURFACE_P_FORESTSTUMPS, + SURFACE_P_FORESTSTICKS, + SURFACE_P_FORRESTLEAVES, + SURFACE_P_DESERTROCKS, + SURFACE_P_FORRESTDRY, + SURFACE_P_SPARSEFLOWERS, + SURFACE_P_BUILDINGSITE, + SURFACE_P_DOCKLANDS, + SURFACE_P_INDUSTRIAL, + SURFACE_P_INDUSTJETTY, + SURFACE_P_CONCRETELITTER, + SURFACE_P_ALLEYRUBISH, + SURFACE_P_JUNKYARDPILES, + SURFACE_P_JUNKYARDGRND, + SURFACE_P_DUMP, + SURFACE_P_CACTUSDENSE, + SURFACE_P_AIRPORTGRND, + SURFACE_P_CORNFIELD, + SURFACE_P_GRASSLIGHT, + SURFACE_P_GRASSLIGHTER, + SURFACE_P_GRASSLIGHTER2, + SURFACE_P_GRASSMID1, + SURFACE_P_GRASSMID2, + SURFACE_P_GRASSDARK, + SURFACE_P_GRASSDARK2, + SURFACE_P_GRASSDIRTMIX, + SURFACE_P_RIVERBEDSTONE, + SURFACE_P_RIVERBEDSHALLOW, + SURFACE_P_RIVERBEDWEEDS, + SURFACE_P_SEAWEED, + SURFACE_DOOR, + SURFACE_PLASTICBARRIER, + SURFACE_PARKGRASS, + SURFACE_STAIRSSTONE, + SURFACE_STAIRSMETAL, + SURFACE_STAIRSCARPET, + SURFACE_FLOORMETAL, + SURFACE_FLOORCONCRETE, + SURFACE_BIN_BAG, + SURFACE_THIN_METAL_SHEET, + SURFACE_METAL_BARREL, + SURFACE_PLASTIC_CONE, + SURFACE_PLASTIC_DUMPSTER, + SURFACE_METAL_DUMPSTER, + SURFACE_WOOD_PICKET_FENCE, + SURFACE_WOOD_SLATTED_FENCE, + SURFACE_WOOD_RANCH_FENCE, + SURFACE_UNBREAKABLE_GLASS, + SURFACE_HAY_BALE, + SURFACE_GORE, + SURFACE_RAILTRACK, + }; +}