diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index 6f15dc87e1..aecd125f59 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -322,6 +322,7 @@ void CBuildingsPoolSA::RemovePedsContactEnityLinks() CPedSAInterface* ped = pedLinks->pEntity->GetPedInterface(); ped->m_pCollidedEntity = nullptr; ped->pContactEntity = nullptr; + ped->pLastContactEntity = nullptr; ped->pLastContactedEntity[0] = nullptr; ped->pLastContactedEntity[1] = nullptr; ped->pLastContactedEntity[2] = nullptr; diff --git a/Client/game_sa/CFxSA.cpp b/Client/game_sa/CFxSA.cpp index dca7844fdf..b063cb927d 100644 --- a/Client/game_sa/CFxSA.cpp +++ b/Client/game_sa/CFxSA.cpp @@ -239,3 +239,93 @@ void CFxSA::TriggerFootSplash(CVector& vecPosition) call dwFunc } } + +void CFxSA::AddParticle(eFxParticleSystems eFxParticle, const CVector& vecPosition, const CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife) +{ + // Init our own FxPrtMult struct + FxPrtMult_c fxPrt{{fR,fG,fB,fA}, fSize, 0, fLife}; + CVector newDirection; + + FxSystem_c* fxParticleSystem; + + switch (eFxParticle) + { + case eFxParticleSystems::PRT_BLOOD: + fxParticleSystem = m_pInterface->m_fxSysBlood; + break; + case eFxParticleSystems::PRT_BOATSPLASH: + fxParticleSystem = m_pInterface->m_fxSysBoatSplash; + break; + case eFxParticleSystems::PRT_BUBBLE: + fxParticleSystem = m_pInterface->m_fxSysBubble; + break; + case eFxParticleSystems::PRT_DEBRIS: + fxParticleSystem = m_pInterface->m_fxSysDebris; + break; + case eFxParticleSystems::PRT_GUNSHELL: + fxParticleSystem = m_pInterface->m_fxSysGunshell; + break; + case eFxParticleSystems::PRT_SAND: + fxParticleSystem = m_pInterface->m_fxSysSand; + break; + case eFxParticleSystems::PRT_SAND2: + fxParticleSystem = m_pInterface->m_fxSysSand2; + break; + case eFxParticleSystems::PRT_SMOKE: + fxParticleSystem = m_pInterface->m_fxSysSmoke; + break; + case eFxParticleSystems::PRT_SMOKEHUGE: + fxParticleSystem = m_pInterface->m_fxSysSmokeHuge; + break; + case eFxParticleSystems::PRT_SMOKE2: + fxParticleSystem = m_pInterface->m_fxSysSmoke2; + break; + case eFxParticleSystems::PRT_SPARK: + fxParticleSystem = m_pInterface->m_fxSysSpark; + break; + case eFxParticleSystems::PRT_SPARK2: + fxParticleSystem = m_pInterface->m_fxSysSpark2; + break; + case eFxParticleSystems::PRT_SPLASH: + fxParticleSystem = m_pInterface->m_fxSysSplash; + break; + case eFxParticleSystems::PRT_WAKE: + fxParticleSystem = m_pInterface->m_fxSysWake; + break; + case eFxParticleSystems::PRT_WATERSPLASH: + fxParticleSystem = m_pInterface->m_fxSysWaterSplash; + break; + case eFxParticleSystems::PRT_WHEELDIRT: + fxParticleSystem = m_pInterface->m_fxSysWheelDirt; + break; + case eFxParticleSystems::PRT_GLASS: + fxParticleSystem = m_pInterface->m_fxSysGlass; + break; + default: + fxParticleSystem = m_pInterface->m_fxSysBlood; + } + + for (size_t i = 0; i < iCount; i++) + { + if (bRandomizeColors) + { + // 0x49EECB + fxPrt.m_color.red = (rand() % 10000) * 0.0001f * fR + 0.13f; + fxPrt.m_color.green = (rand() % 10000) * 0.0001f * fG + 0.12f; + fxPrt.m_color.blue = (rand() % 10000) * 0.0001f * fB + 0.04f; + } + + if (bRandomizeSizes) + // 0x49EF21 - Calculate random size for each particle + fxPrt.m_fSize = (rand() % 10000) * 0.0001f * fSize + 0.3f; + + // 0x49EF4C - Calculate random direction for each particle + newDirection = CVector(vecDirection.fX * 4, vecDirection.fY * 4, vecDirection.fZ * 4); + newDirection.fX = (rand() % 10000) * 0.0001f * 4 - 2 + newDirection.fX; + newDirection.fY = (rand() % 10000) * 0.0001f * 4 - 2 + newDirection.fY; + newDirection.fZ = (rand() % 10000) * 0.0001f * 4 - 2 + newDirection.fZ; + + // Call FxSystem_c::AddParticle + ((int(__thiscall*)(FxSystem_c*, const CVector*, const CVector*, float, FxPrtMult_c*, float, float, float, int))FUNC_FXSystem_c_AddParticle)(fxParticleSystem, &vecPosition, &newDirection, 0, &fxPrt, -1.0f, fBrightness, 0, 0); + } +} diff --git a/Client/game_sa/CFxSA.h b/Client/game_sa/CFxSA.h index 55b56b83f2..7d61c1759a 100644 --- a/Client/game_sa/CFxSA.h +++ b/Client/game_sa/CFxSA.h @@ -14,6 +14,7 @@ #include struct RwColor; +class FxSystem_c; #define FUNC_CFx_AddBlood 0x49eb00 #define FUNC_CFx_AddWood 0x49ee10 @@ -29,10 +30,30 @@ struct RwColor; #define FUNC_CFx_TriggerWaterSplash 0x4a1070 #define FUNC_CFx_TriggerBulletSplash 0x4a10e0 #define FUNC_CFx_TriggerFootSplash 0x4a1150 +#define FUNC_FXSystem_c_AddParticle 0x4AA440 class CFxSAInterface { public: + FxSystem_c* m_fxSysBlood; + FxSystem_c* m_fxSysBoatSplash; + FxSystem_c* m_fxSysBubble; + FxSystem_c* m_fxSysDebris; + FxSystem_c* m_fxSysSmoke; + FxSystem_c* m_fxSysGunshell; + FxSystem_c* m_fxSysSand; + FxSystem_c* m_fxSysSand2; + FxSystem_c* m_fxSysSmokeHuge; + FxSystem_c* m_fxSysSmoke2; + FxSystem_c* m_fxSysSpark; + FxSystem_c* m_fxSysSpark2; + FxSystem_c* m_fxSysSplash; + FxSystem_c* m_fxSysWake; + FxSystem_c* m_fxSysWaterSplash; + FxSystem_c* m_fxSysWheelDirt; + FxSystem_c* m_fxSysGlass; + +private: }; class CFxSA : public CFx @@ -55,7 +76,23 @@ class CFxSA : public CFx void TriggerWaterSplash(CVector& vecPosition); void TriggerBulletSplash(CVector& vecPosition); void TriggerFootSplash(CVector& vecPosition); + void AddParticle(eFxParticleSystems eFxParticle, const CVector& vecPosition, const CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife); private: CFxSAInterface* m_pInterface; + + struct FxPrtMult_c + { + struct + { + float red; + float green; + float blue; + float alpha; + } m_color; + + float m_fSize; + float unk; + float m_fLife; + }; }; diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 5082eca7f9..5d7c8044ed 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -242,11 +242,11 @@ class CPedSAInterface : public CPhysicalSAInterface // +1420 = curre float fTargetRotation; float fRotationSpeed; float fMoveAnim; - CPedSAInterface* unkPed; + CEntitySAInterface* pContactEntity; CVector unk_56C; CVector unk_578; - CEntitySAInterface* pContactEntity; + CEntitySAInterface* pLastContactEntity; CVehicleSAInterface* pLastVehicle; CVehicleSAInterface* pVehicle; diff --git a/Client/mods/deathmatch/logic/CClientSound.cpp b/Client/mods/deathmatch/logic/CClientSound.cpp index dc10132e4b..052071a97a 100644 --- a/Client/mods/deathmatch/logic/CClientSound.cpp +++ b/Client/mods/deathmatch/logic/CClientSound.cpp @@ -147,6 +147,10 @@ bool CClientSound::Create() m_pAudio->SetPanEnabled(m_bPan); m_pAudio->SetPan(m_fPan); + // Also check and transfer if paused + if (m_bPaused) + m_pAudio->SetPaused(m_bPaused); + // Transfer play position if it was being simulated EndSimulationOfPlayPositionAndApply(); diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index c42156883b..fd0a2dcd76 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -7926,6 +7926,12 @@ bool CStaticFunctionDefinitions::FxAddFootSplash(CVector& vecPosition) return true; } +bool CStaticFunctionDefinitions::FxCreateParticle(eFxParticleSystems eFxParticle, CVector& vecPosition, CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife) +{ + g_pGame->GetFx()->AddParticle(eFxParticle, vecPosition, vecDirection, fR, fG, fB, fA, bRandomizeColors, iCount, fBrightness, fSize, bRandomizeSizes, fLife); + return true; +} + CClientEffect* CStaticFunctionDefinitions::CreateEffect(CResource& Resource, const SString& strFxName, const CVector& vecPosition, bool bSoundEnable) { CClientEffect* pFx = m_pManager->GetEffectManager()->Create(strFxName, vecPosition, INVALID_ELEMENT_ID, bSoundEnable); diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 437e4503f6..2ffe1ff0a5 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -729,6 +729,7 @@ class CStaticFunctionDefinitions static bool FxAddWaterSplash(CVector& vecPosition); static bool FxAddBulletSplash(CVector& vecPosition); static bool FxAddFootSplash(CVector& vecPosition); + static bool FxCreateParticle(eFxParticleSystems eFxParticle, CVector& vecPosition, CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife); static CClientEffect* CreateEffect(CResource& Resource, const SString& strFxName, const CVector& vecPosition, bool bSoundEnable); // Sound funcs diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index e037494a1b..2ff7d9bd7d 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -853,6 +853,26 @@ ADD_ENUM(ePools::ENV_MAP_ATOMIC_POOL, "env-map-atomic") ADD_ENUM(ePools::SPEC_MAP_MATERIAL_POOL, "spec-map-material") IMPLEMENT_ENUM_END("gta-pool") +IMPLEMENT_ENUM_CLASS_BEGIN(eFxParticleSystems) +ADD_ENUM(eFxParticleSystems::PRT_BLOOD, "blood") +ADD_ENUM(eFxParticleSystems::PRT_BOATSPLASH, "boat_splash") +ADD_ENUM(eFxParticleSystems::PRT_BUBBLE, "bubble") +ADD_ENUM(eFxParticleSystems::PRT_DEBRIS, "car_debris") +ADD_ENUM(eFxParticleSystems::PRT_SMOKE, "collision_smoke") +ADD_ENUM(eFxParticleSystems::PRT_GUNSHELL, "gunshell") +ADD_ENUM(eFxParticleSystems::PRT_SAND, "sand") +ADD_ENUM(eFxParticleSystems::PRT_SAND2, "sand2") +ADD_ENUM(eFxParticleSystems::PRT_SMOKEHUGE, "huge_smoke") +ADD_ENUM(eFxParticleSystems::PRT_SMOKE2, "smoke") +ADD_ENUM(eFxParticleSystems::PRT_SPARK, "spark") +ADD_ENUM(eFxParticleSystems::PRT_SPARK2, "spark2") +ADD_ENUM(eFxParticleSystems::PRT_SPLASH, "splash") +ADD_ENUM(eFxParticleSystems::PRT_WAKE, "wake") +ADD_ENUM(eFxParticleSystems::PRT_WATERSPLASH, "water_splash") +ADD_ENUM(eFxParticleSystems::PRT_WHEELDIRT, "wheel_dirt") +ADD_ENUM(eFxParticleSystems::PRT_GLASS, "glass") +IMPLEMENT_ENUM_CLASS_END("particle-system") + // // CResource from userdata // diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index 3c8af2144c..aae4e759e5 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -82,6 +82,7 @@ DECLARE_ENUM_CLASS(eSoundEffectParams::Reverb); DECLARE_ENUM_CLASS(eModelIdeFlag); DECLARE_ENUM_CLASS(_D3DFORMAT); DECLARE_ENUM_CLASS(eRenderStage); +DECLARE_ENUM_CLASS(eFxParticleSystems); DECLARE_ENUM(ePools); class CRemoteCall; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp index 5b9940a01a..fb1a5e3dfe 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.cpp @@ -10,6 +10,7 @@ *****************************************************************************/ #include "StdInc.h" +#include "lua/CLuaFunctionParser.h" void CLuaEffectDefs::LoadFunctions() { @@ -33,6 +34,7 @@ void CLuaEffectDefs::LoadFunctions() {"getEffectSpeed", GetEffectSpeed}, {"setEffectDensity", SetEffectDensity}, {"getEffectDensity", GetEffectDensity}, + {"fxCreateParticle", ArgumentParser}, }; // Add functions @@ -59,6 +61,7 @@ void CLuaEffectDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "addWaterHydrant", "fxAddWaterHydrant"); lua_classfunction(luaVM, "addWaterSplash", "fxAddWaterSplash"); lua_classfunction(luaVM, "addWood", "fxAddWood"); + lua_classfunction(luaVM, "createParticle", "fxCreateParticle"); lua_classfunction(luaVM, "setDensity", "setEffectDensity"); lua_classfunction(luaVM, "setSpeed", "setEffectSpeed"); @@ -639,3 +642,8 @@ int CLuaEffectDefs::SetEffectDensity(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +bool CLuaEffectDefs::FxCreateParticle(eFxParticleSystems eParticleSystem, CVector vecPosition, CVector vecDirection, float fR, float fG, float fB, float fA, std::optional bRandomizeColors, std::optional iCount, std::optional fBrightness, std::optional fSize, std::optional bRandomizeSizes, std::optional fLife) +{ + return CStaticFunctionDefinitions::FxCreateParticle(eParticleSystem, vecPosition, vecDirection, fR/255, fG/255, fB/255, fA/255, bRandomizeColors.value_or(false), iCount.value_or(1), fBrightness.value_or(1.0f), fSize.value_or(0.3f), bRandomizeSizes.value_or(false), fLife.value_or(1.0f)); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h index e2f4c07fe1..e8e00df41f 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEffectDefs.h @@ -37,4 +37,6 @@ class CLuaEffectDefs : public CLuaDefs LUA_DECLARE(GetEffectSpeed); LUA_DECLARE(SetEffectDensity); LUA_DECLARE(GetEffectDensity); + + static bool FxCreateParticle(eFxParticleSystems eParticleSystem, CVector vecPosition, CVector vecDirection, float fR, float fG, float fB, float fA, std::optional bRandomizeColors, std::optional iCount, std::optional fBrightness, std::optional fSize, std::optional bRandomizeSizes, std::optional fLife); }; diff --git a/Client/sdk/game/CFx.h b/Client/sdk/game/CFx.h index 8b4460357d..861cfa31e2 100644 --- a/Client/sdk/game/CFx.h +++ b/Client/sdk/game/CFx.h @@ -11,6 +11,8 @@ #pragma once +#include "Common.h" + class CEntity; class CVector; class CVehicle; @@ -34,4 +36,5 @@ class CFx virtual void TriggerWaterSplash(CVector& vecPosition) = 0; virtual void TriggerBulletSplash(CVector& vecPosition) = 0; virtual void TriggerFootSplash(CVector& vecPosition) = 0; + virtual void AddParticle(eFxParticleSystems eFxParticle, const CVector& vecPosition, const CVector& vecDirection, float fR, float fG, float fB, float fA, bool bRandomizeColors, std::uint32_t iCount, float fBrightness, float fSize, bool bRandomizeSizes, float fLife) = 0; }; diff --git a/Client/sdk/game/Common.h b/Client/sdk/game/Common.h index 14108f5210..d746ddb93e 100644 --- a/Client/sdk/game/Common.h +++ b/Client/sdk/game/Common.h @@ -1599,3 +1599,24 @@ namespace eSoundEffectParams HIGH_FREQ_RT_RATIO, }; } // namespace eSoundEffectParams + +enum class eFxParticleSystems +{ + PRT_BLOOD, + PRT_BOATSPLASH, + PRT_BUBBLE, + PRT_DEBRIS, + PRT_SMOKE, + PRT_GUNSHELL, + PRT_SAND, + PRT_SAND2, + PRT_SMOKEHUGE, + PRT_SMOKE2, + PRT_SPARK, + PRT_SPARK2, + PRT_SPLASH, + PRT_WAKE, + PRT_WATERSPLASH, + PRT_WHEELDIRT, + PRT_GLASS, +}; diff --git a/Server/mods/deathmatch/acl.xml b/Server/mods/deathmatch/acl.xml index a3ecc8f9a7..5e4d1292c3 100644 --- a/Server/mods/deathmatch/acl.xml +++ b/Server/mods/deathmatch/acl.xml @@ -21,6 +21,7 @@ +