Skip to content
Permalink
Browse files

Add possibility of modifying dynamic objects behavior (#784)

* Basic implementation of required classes

* Possibility to get object properties group from CModelInfo

* Ability to change model id -> object properties group relations

* enum definition

* moved function to the end of CGame*, small cleanup

* Fixed issues with not starting, a lot of changes

- changed the way of how backup ObjectDynamicInfo works
- added functions to get/set/restore model dynamic properties group
- some other small changes

* Basic functions, starting renaming

* The giant renaming

* model update

* model/naming changes, rest of setters from lua.

* naming, code shortening thanks to botder

* Enums cleanup, to their own namespace they go

also added missing property change

* Added missing restore function, naming changes

* enums namespace change

* Ability to get properties from lua

* enum memory layout issues fix

* Added ability to change fx system used by object group

* Additional safety checks in lua functions

* Restore object data changes, refactored lua methods

* adjust properties count to real 160, instead of 255,

* Ability to restore default group properties from lua

* Enum class name change

* Stuff i've noticed when making pull request

* Moved stuff

* Formatting fix

* Clean up project comments

* Changes recommended in code review

1. Added const modfier to functions where possible
2. Changed constructor to use initializer list
3. Removed unnecessary call to ChangeSafeguard() from one of the getters

* Changes suggested in pull request review

Calling of internal functions without _asm blocks
Const specifier in range loops where needed
Replaced pointers with std::unique_ptrs
Fixed inconsistency with bad arguments checking in some lua functions

* Change warnings to errors
  • Loading branch information...
forkerer authored and patrikjuvonen committed Sep 2, 2019
1 parent 901ed44 commit 03b49141f96d01ba6086fa1facd9cddc0c22dc23
@@ -67,6 +67,18 @@ void CFxManagerSA::OnFxSystemSAInterfaceDestroyed(CFxSystemSAInterface* pFxSyste
delete pFxSystemSA;
}

CFxSystemBPSAInterface* CFxManagerSA::GetFxSystemBlueprintByName(SString sName)
{
using func_t = CFxSystemBPSAInterface*(__thiscall*)(CFxManagerSAInterface * pInterface, const char* pChars);
auto func = reinterpret_cast<func_t>(FUNC_FxManager_c__GetSystemByName);
return func(m_pInterface, sName);
}

bool CFxManagerSA::IsValidFxSystemBlueprintName(SString sName)
{
return GetFxSystemBlueprintByName(sName) != nullptr;
}

//
// AddToList/RemoveFromList called from CFxSystemSA constructor/destructor
//
@@ -14,6 +14,7 @@

#define FUNC_FxManager_c__CreateFxSystem 0x4A9BE0
#define FUNC_FxManager_c__DestroyFxSystem 0x4A9810
#define FUNC_FxManager_c__GetSystemByName 0x4A9360

class CFxSystemBPSAInterface;
class CFxSystemSAInterface;
@@ -61,10 +62,12 @@ class CFxManagerSA : public CFxManager
public:
CFxManagerSA(CFxManagerSAInterface* pInterface) { m_pInterface = pInterface; }
// CFxManager interface
CFxSystem* CreateFxSystem(const char* szBlueprint, const CVector& vecPosition, RwMatrix* pRwMatrixTag, unsigned char bSkipCameraFrustumCheck,
bool bSoundEnable);
void DestroyFxSystem(CFxSystem* pFxSystem);
void OnFxSystemSAInterfaceDestroyed(CFxSystemSAInterface* pFxSystemSAInterface);
CFxSystem* CreateFxSystem(const char* szBlueprint, const CVector& vecPosition, RwMatrix* pRwMatrixTag, unsigned char bSkipCameraFrustumCheck,
bool bSoundEnable);
void DestroyFxSystem(CFxSystem* pFxSystem);
void OnFxSystemSAInterfaceDestroyed(CFxSystemSAInterface* pFxSystemSAInterface);
CFxSystemBPSAInterface* GetFxSystemBlueprintByName(SString sName);
bool IsValidFxSystemBlueprintName(SString sName);

// CFxManagerSA methods
CFxSystemSA* GetFxSystem(CFxSystemSAInterface* pFxSystemSAInterface);
@@ -65,6 +65,12 @@ CGameSA::CGameSA()
ModelInfo[i].SetModelID(i);
}

// Prepare all object dynamic infos for CObjectGroupPhysicalPropertiesSA instances
for (int i = 0; i < OBJECTDYNAMICINFO_MAX; i++)
{
ObjectGroupsInfo[i].SetGroup(i);
}

DEBUG_TRACE("CGameSA::CGameSA()");
this->m_pAudioEngine = new CAudioEngineSA((CAudioEngineSAInterface*)CLASS_CAudioEngine);
this->m_pAEAudioHardware = new CAEAudioHardwareSA((CAEAudioHardwareSAInterface*)CLASS_CAEAudioHardware);
@@ -464,6 +470,9 @@ void CGameSA::Reset()

// Restore model dummies' positions
CModelInfoSA::ResetAllVehicleDummies();
CModelInfoSA::RestoreAllObjectsPropertiesGroups();
// restore default properties of all CObjectGroupPhysicalPropertiesSA instances
CObjectGroupPhysicalPropertiesSA::RestoreDefaultValues();
}
}

@@ -862,3 +871,12 @@ CPed* CGameSA::GetPedContext()
m_pPedContext = pGame->GetPools()->GetPedFromRef((DWORD)1);
return m_pPedContext;
}

CObjectGroupPhysicalProperties* CGameSA::GetObjectGroupPhysicalProperties(unsigned char ucObjectGroup)
{
DEBUG_TRACE("CObjectGroupPhysicalProperties * CGameSA::GetObjectGroupPhysicalProperties(unsigned char ucObjectGroup)");
if (ucObjectGroup < OBJECTDYNAMICINFO_MAX && ObjectGroupsInfo[ucObjectGroup].IsValid())
return &ObjectGroupsInfo[ucObjectGroup];

return nullptr;
}
@@ -12,6 +12,7 @@
#pragma once

#include "CModelInfoSA.h"
#include "CObjectGroupPhysicalPropertiesSA.h"
#include "CFxManagerSA.h"

#define MAX_MEMORY_OFFSET_1_0 0xCAF008
@@ -33,6 +34,7 @@
#define NUM_WeaponInfosTotal (NUM_WeaponInfosStdSkill + (3*NUM_WeaponInfosOtherSkill)) // std, (poor, pro, special)

#define MODELINFO_MAX 26000 // Actual max is 25755
#define OBJECTDYNAMICINFO_MAX 160

#define FUNC_GetLevelFromPosition 0x4DD300

@@ -103,6 +105,7 @@ class CGameSA : public CGame
private:
CWeaponInfo* WeaponInfos[NUM_WeaponInfosTotal];
CModelInfoSA ModelInfo[MODELINFO_MAX];
CObjectGroupPhysicalPropertiesSA ObjectGroupsInfo[OBJECTDYNAMICINFO_MAX];

public:
ZERO_ON_NEW
@@ -305,8 +308,9 @@ class CGameSA : public CGame
CRenderWareSA* GetRenderWareSA() { return m_pRenderWare; }
CFxManagerSA* GetFxManagerSA() { return m_pFxManager; }

CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD);
CModelInfo* GetModelInfo(DWORD dwModelID);
CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD);
CModelInfo* GetModelInfo(DWORD dwModelID);
CObjectGroupPhysicalProperties* GetObjectGroupPhysicalProperties(unsigned char ucObjectGroup);

DWORD GetSystemTime()
{
@@ -429,39 +433,40 @@ class CGameSA : public CGame
TaskSimpleBeHitHandler* m_pTaskSimpleBeHitHandler;

private:
CPools* m_pPools;
CPlayerInfo* m_pPlayerInfo;
CProjectileInfo* m_pProjectileInfo;
CRadar* m_pRadar;
CRestart* m_pRestart;
CClock* m_pClock;
CCoronas* m_pCoronas;
CCheckpoints* m_pCheckpoints;
CEventList* m_pEventList;
CFireManager* m_pFireManager;
CGarages* m_pGarages;
CHud* m_pHud;
CWanted* m_pWanted;
CWeather* m_pWeather;
CWorld* m_pWorld;
CCamera* m_pCamera;
CModelInfo* m_pModelInfo;
CPickups* m_pPickups;
CWeaponInfo* m_pWeaponInfo;
CExplosionManager* m_pExplosionManager;
C3DMarkers* m_p3DMarkers;
CRenderWareSA* m_pRenderWare;
CHandlingManager* m_pHandlingManager;
CAnimManager* m_pAnimManager;
CStreaming* m_pStreaming;
CVisibilityPlugins* m_pVisibilityPlugins;
CKeyGen* m_pKeyGen;
CRopes* m_pRopes;
CFx* m_pFx;
CFxManagerSA* m_pFxManager;
CWaterManager* m_pWaterManager;
CWeaponStatManager* m_pWeaponStatsManager;
CPointLights* m_pPointLights;
CPools* m_pPools;
CPlayerInfo* m_pPlayerInfo;
CProjectileInfo* m_pProjectileInfo;
CRadar* m_pRadar;
CRestart* m_pRestart;
CClock* m_pClock;
CCoronas* m_pCoronas;
CCheckpoints* m_pCheckpoints;
CEventList* m_pEventList;
CFireManager* m_pFireManager;
CGarages* m_pGarages;
CHud* m_pHud;
CWanted* m_pWanted;
CWeather* m_pWeather;
CWorld* m_pWorld;
CCamera* m_pCamera;
CModelInfo* m_pModelInfo;
CPickups* m_pPickups;
CWeaponInfo* m_pWeaponInfo;
CExplosionManager* m_pExplosionManager;
C3DMarkers* m_p3DMarkers;
CRenderWareSA* m_pRenderWare;
CHandlingManager* m_pHandlingManager;
CAnimManager* m_pAnimManager;
CStreaming* m_pStreaming;
CVisibilityPlugins* m_pVisibilityPlugins;
CKeyGen* m_pKeyGen;
CRopes* m_pRopes;
CFx* m_pFx;
CFxManagerSA* m_pFxManager;
CWaterManager* m_pWaterManager;
CWeaponStatManager* m_pWeaponStatsManager;
CPointLights* m_pPointLights;
CObjectGroupPhysicalProperties* m_pObjectGroupPhysicalProperties;

CPad* m_pPad;
CTheCarGenerators* m_pTheCarGenerators;
@@ -20,6 +20,7 @@ std::map<unsigned short, int>
std::map<DWORD, float> CModelInfoSA::ms_ModelDefaultLodDistanceMap;
std::map<DWORD, BYTE> CModelInfoSA::ms_ModelDefaultAlphaTransparencyMap;
std::unordered_map<CVehicleModelInfoSAInterface*, std::map<eVehicleDummies, CVector>> CModelInfoSA::ms_ModelDefaultDummiesPosition;
std::unordered_map<DWORD, unsigned short> CModelInfoSA::ms_OriginalObjectPropertiesGroups;

CModelInfoSA::CModelInfoSA()
{
@@ -1373,6 +1374,46 @@ void CModelInfoSA::ResetSupportedUpgrades()
m_ModelSupportedUpgrades.Reset();
}

void CModelInfoSA::SetObjectPropertiesGroup(unsigned short usNewGroup)
{
unsigned short usOrgGroup = GetObjectPropertiesGroup();
if (usOrgGroup == usNewGroup)
return;

if (!MapFind(ms_OriginalObjectPropertiesGroups, m_dwModelID))
MapSet(ms_OriginalObjectPropertiesGroups, m_dwModelID, usOrgGroup);

GetInterface()->usDynamicIndex = usNewGroup;
}

unsigned short CModelInfoSA::GetObjectPropertiesGroup()
{
unsigned short usGroup = GetInterface()->usDynamicIndex;
if (usGroup == 0xFFFF)
usGroup = 0;

return usGroup;
}

void CModelInfoSA::RestoreObjectPropertiesGroup()
{
unsigned short* usGroupInMap = MapFind(ms_OriginalObjectPropertiesGroups, m_dwModelID);
if (usGroupInMap)
{
GetInterface()->usDynamicIndex = *usGroupInMap;
MapRemove(ms_OriginalObjectPropertiesGroups, m_dwModelID);
}
}

void CModelInfoSA::RestoreAllObjectsPropertiesGroups()
{
for (const auto& pair : ms_OriginalObjectPropertiesGroups)
{
pGame->GetModelInfo(pair.first)->GetInterface()->usDynamicIndex = pair.second;
}
ms_OriginalObjectPropertiesGroups.clear();
}

eModelInfoType CModelInfoSA::GetModelType()
{
return ((eModelInfoType(*)())m_pInterface->VFTBL->GetModelType)();
@@ -139,16 +139,7 @@ class CBaseModelInfoSAInterface
unsigned char ucNumOf2DEffects : 8; // +13
unsigned short usUnknown : 16; // +14 Something with 2d effects

unsigned char ucDynamicIndex : 8; // +16

unsigned char dwUnknownFlag9 : 1; // +17
unsigned char dwUnknownFlag10 : 1;
unsigned char dwUnknownFlag11 : 1;
unsigned char dwUnknownFlag12 : 1;
unsigned char dwUnknownFlag13 : 1;
unsigned char dwUnknownFlag14 : 1;
unsigned char dwUnknownFlag15 : 1;
unsigned char dwUnknownFlag16 : 1;
unsigned short usDynamicIndex : 16; // +16

// Flags used by CBaseModelInfo
unsigned char bHasBeenPreRendered : 1; // +18
@@ -277,6 +268,7 @@ class CModelInfoSA : public CModelInfo
static std::map<DWORD, float> ms_ModelDefaultLodDistanceMap;
static std::map<DWORD, BYTE> ms_ModelDefaultAlphaTransparencyMap;
static std::unordered_map<CVehicleModelInfoSAInterface*, std::map<eVehicleDummies, CVector>> ms_ModelDefaultDummiesPosition;
static std::unordered_map<DWORD, unsigned short> ms_OriginalObjectPropertiesGroups;
bool m_bAddedRefForCollision;
SVehicleSupportedUpgrades m_ModelSupportedUpgrades;

@@ -375,6 +367,11 @@ class CModelInfoSA : public CModelInfo
void InitialiseSupportedUpgrades(RpClump* pClump);
void ResetSupportedUpgrades();

void SetObjectPropertiesGroup(unsigned short usObjectGroup);
unsigned short GetObjectPropertiesGroup();
void RestoreObjectPropertiesGroup();
static void RestoreAllObjectsPropertiesGroups();

private:
void RwSetSupportedUpgrades(RwFrame* parent, DWORD dwModel);
};

0 comments on commit 03b4914

Please sign in to comment.
You can’t perform that action at this time.