Skip to content

Commit ebb2b2a

Browse files
committed
Fix bugs after stream in
1 parent fdddb29 commit ebb2b2a

File tree

4 files changed

+161
-24
lines changed

4 files changed

+161
-24
lines changed

Client/game_sa/CEntitySA.cpp

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ CRect* CEntitySAInterface::GetBoundRect_(CRect* pRect)
6666
return pRect;
6767
}
6868

69-
void CEntitySAInterface::StaticSetHooks()
70-
{
71-
HookInstall(0x534120, &CEntitySAInterface::GetBoundRect_);
72-
}
73-
7469
CEntitySA::CEntitySA()
7570
{
7671
// Set these variables to a constant state
@@ -715,3 +710,77 @@ bool CEntitySA::GetUnderwater()
715710
{
716711
return m_pInterface->bUnderwater;
717712
}
713+
714+
//////////////////////////////////////////////////////////////////////////////////////////
715+
//
716+
// Hook for CEntity::CreateEffects & CEntity::DestroyEffects
717+
//
718+
// Handle modified 2dfx effects during streaming
719+
// This is necessary because once the object is streamed in, the 2dfx effects are loaded from RwStream
720+
// and the default effects are restored even though they have been modified.
721+
//
722+
//////////////////////////////////////////////////////////////////////////////////////////
723+
static void Keep2DFXEffectsBeforeRemove(std::uint32_t modelID)
724+
{
725+
CModelInfo* modelInfo = pGame->GetModelInfo(modelID);
726+
if (!modelInfo)
727+
return;
728+
729+
modelInfo->CopyModified2DFXEffects();
730+
}
731+
732+
#define HOOKPOS_CEntity_DestroyEffects 0x533C01
733+
#define HOOKSIZE_CEntity_DestroyEffects 5
734+
static constexpr DWORD CONTINUE_CEntity_DestroyEffects = 0x533C06;
735+
static void _declspec(naked) HOOK_CEntity_DestroyEffects()
736+
{
737+
_asm
738+
{
739+
pushad
740+
push eax
741+
call Keep2DFXEffectsBeforeRemove
742+
add esp, 4
743+
popad
744+
745+
movzx eax, byte ptr [ecx+0Dh]
746+
push ebp
747+
jmp CONTINUE_CEntity_DestroyEffects
748+
}
749+
}
750+
751+
static void Restore2DFXEffects(std::uint32_t modelID)
752+
{
753+
CModelInfo* modelInfo = pGame->GetModelInfo(modelID);
754+
if (!modelInfo)
755+
return;
756+
757+
modelInfo->RestoreModified2DFXEffects();
758+
}
759+
760+
#define HOOKPOS_CEntity_CreateEffects 0x533BAE
761+
#define HOOKSIZE_CEntity_CreateEffects 9
762+
static constexpr DWORD RETURN_CEntity_CreateEffects = 0x533BB7;
763+
static void _declspec(naked) HOOK_CEntity_CreateEffects()
764+
{
765+
_asm
766+
{
767+
pushad
768+
push [ebp+22h]
769+
call Restore2DFXEffects
770+
add esp, 4
771+
popad
772+
773+
pop edi
774+
pop ebp
775+
pop ebx
776+
add esp, 0C0h
777+
jmp RETURN_CEntity_CreateEffects
778+
}
779+
}
780+
781+
void CEntitySAInterface::StaticSetHooks()
782+
{
783+
HookInstall(0x534120, &CEntitySAInterface::GetBoundRect_);
784+
EZHookInstall(CEntity_DestroyEffects);
785+
EZHookInstall(CEntity_CreateEffects);
786+
}

Client/game_sa/CModelInfoSA.cpp

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ std::unordered_map<DWORD, unsigned short> CModelInfo
3737
std::unordered_map<DWORD, std::pair<float, float>> CModelInfoSA::ms_VehicleModelDefaultWheelSizes;
3838
std::map<unsigned short, int> CModelInfoSA::ms_DefaultTxdIDMap;
3939

40-
std::unordered_map<DWORD, std::unordered_map<C2DEffectSAInterface*, C2DEffectSAInterface*>> CModelInfoSA::ms_DefaultEffectsMap;
41-
static std::unordered_map<CBaseModelInfoSAInterface*, std::uint32_t> m_numCustom2dfxEffects;
42-
static std::vector<C2DEffectSAInterface*> d2fxEffects;
43-
static std::vector<C2DEffectSAInterface*> removedDefaultEffects;
40+
static std::unordered_map<DWORD, std::unordered_map<C2DEffectSAInterface*, C2DEffectSAInterface*>> ms_DefaultEffectsMap;
41+
static std::unordered_map<CBaseModelInfoSAInterface*, std::uint32_t> numCustom2dfxEffects;
42+
static std::vector<C2DEffectSAInterface*> d2fxEffects;
43+
static std::vector<C2DEffectSAInterface*> removedDefault2dfxEffects;
44+
static std::unordered_map<DWORD, std::uint8_t> defaultNumOf2DFXEffects;
45+
static std::unordered_map<DWORD, std::vector<C2DEffectSAInterface*>> tempCopy2dfxEffects;
4446

4547
int C2DEffectSA::effect2dPluginOffset = *(int*)0xC3A1E0; // g2dEffectPluginOffset
4648

@@ -116,7 +118,7 @@ CBaseModelInfoSAInterface* CModelInfoSA::GetInterface()
116118
void CModelInfoSA::SetModelID(DWORD dwModelID)
117119
{
118120
m_dwModelID = dwModelID;
119-
MapSet(m_numCustom2dfxEffects, ppModelInfo[dwModelID], 0);
121+
MapSet(numCustom2dfxEffects, ppModelInfo[dwModelID], 0);
120122
}
121123

122124
bool CModelInfoSA::IsBoat()
@@ -1197,10 +1199,10 @@ void CModelInfoSA::StaticReset2DFXEffects()
11971199
memcpy(innerIter->first, innerIter->second, sizeof(C2DEffectSAInterface));
11981200

11991201
// Increase the counter if this effect was removed
1200-
auto& removedEffect = std::find(removedDefaultEffects.begin(), removedDefaultEffects.end(), innerIter->first);
1201-
if (removedEffect != removedDefaultEffects.end())
1202+
auto& removedEffect = std::find(removedDefault2dfxEffects.begin(), removedDefault2dfxEffects.end(), innerIter->first);
1203+
if (removedEffect != removedDefault2dfxEffects.end())
12021204
{
1203-
removedDefaultEffects.erase(removedEffect);
1205+
removedDefault2dfxEffects.erase(removedEffect);
12041206
modelInfoInterface->ucNumOf2DEffects++;
12051207
}
12061208

@@ -1211,15 +1213,15 @@ void CModelInfoSA::StaticReset2DFXEffects()
12111213
}
12121214

12131215
// Decrement the counter by the number of custom effects
1214-
auto customEffectsCount = MapGet(m_numCustom2dfxEffects, modelInfoInterface);
1216+
auto customEffectsCount = MapGet(numCustom2dfxEffects, modelInfoInterface);
12151217
if (customEffectsCount && customEffectsCount > 0)
12161218
modelInfoInterface->ucNumOf2DEffects -= customEffectsCount;
12171219

1218-
MapSet(m_numCustom2dfxEffects, modelInfoInterface, 0);
1220+
MapSet(numCustom2dfxEffects, modelInfoInterface, 0);
12191221
}
12201222

12211223
// Clear maps
1222-
removedDefaultEffects.clear();
1224+
removedDefault2dfxEffects.clear();
12231225
ms_DefaultEffectsMap.clear();
12241226
d2fxEffects.clear();
12251227
}
@@ -2118,6 +2120,9 @@ void CModelInfoSA::StoreDefault2DFXEffect(C2DEffectSAInterface* effect)
21182120
if (MapContains(ms_DefaultEffectsMap, m_dwModelID) && MapContains(MapGet(ms_DefaultEffectsMap, m_dwModelID), effect))
21192121
return;
21202122

2123+
if (!MapContains(defaultNumOf2DFXEffects, m_dwModelID))
2124+
MapSet(defaultNumOf2DFXEffects, m_dwModelID, ppModelInfo[m_dwModelID]->ucNumOf2DEffects);
2125+
21212126
// Copy an existing default effect
21222127
C2DEffectSAInterface* copy = new C2DEffectSAInterface();
21232128
memcpy(copy, effect, sizeof(C2DEffectSAInterface));
@@ -2158,10 +2163,10 @@ bool CModelInfoSA::Reset2DFXEffects(bool removeCustomEffects)
21582163
memcpy(it->first, it->second, sizeof(C2DEffectSAInterface));
21592164

21602165
// Increase the counter if this effect was removed
2161-
auto& removedEffect = std::find(removedDefaultEffects.begin(), removedDefaultEffects.end(), it->first);
2162-
if (removedEffect != removedDefaultEffects.end())
2166+
auto& removedEffect = std::find(removedDefault2dfxEffects.begin(), removedDefault2dfxEffects.end(), it->first);
2167+
if (removedEffect != removedDefault2dfxEffects.end())
21632168
{
2164-
removedDefaultEffects.erase(removedEffect);
2169+
removedDefault2dfxEffects.erase(removedEffect);
21652170
m_pInterface->ucNumOf2DEffects++;
21662171
}
21672172

@@ -2205,7 +2210,7 @@ C2DEffectSAInterface* CModelInfoSA::Add2DFXEffect(const CVector& position, const
22052210

22062211
// Update counters
22072212
m_pInterface->ucNumOf2DEffects = m_pInterface->ucNumOf2DEffects ? m_pInterface->ucNumOf2DEffects + 1 : 1;
2208-
MapGet(m_numCustom2dfxEffects, m_pInterface)++;
2213+
MapGet(numCustom2dfxEffects, m_pInterface)++;
22092214

22102215
// Save our effect
22112216
d2fxEffects.push_back(effectInterface);
@@ -2233,7 +2238,7 @@ bool CModelInfoSA::Remove2DFX(C2DEffectSAInterface* effect, bool includeDefault)
22332238
m_pInterface->ucNumOf2DEffects--;
22342239
if (isCustomEffect)
22352240
{
2236-
MapGet(m_numCustom2dfxEffects, m_pInterface)--;
2241+
MapGet(numCustom2dfxEffects, m_pInterface)--;
22372242
d2fxEffects.erase(it);
22382243
}
22392244

@@ -2307,7 +2312,7 @@ bool CModelInfoSA::Remove2DFX(C2DEffectSAInterface* effect, bool includeDefault)
23072312
effect = nullptr;
23082313
}
23092314
else
2310-
removedDefaultEffects.push_back(effect);
2315+
removedDefault2dfxEffects.push_back(effect);
23112316
}
23122317

23132318
bool CModelInfoSA::Remove2DFXEffectAtIndex(std::uint32_t index, bool includeDefault)
@@ -2410,7 +2415,7 @@ static C2DEffectSAInterface* Get2dEffect(CBaseModelInfoSAInterface* modelInfo, R
24102415

24112416
static auto* storedEffects = reinterpret_cast<C2DEffectInfoStoreSAInterface*>(ARRAY_2DFXInfoStore);
24122417

2413-
std::uint32_t numCustomEffects = m_numCustom2dfxEffects[modelInfo];
2418+
std::uint32_t numCustomEffects = numCustom2dfxEffects[modelInfo];
24142419
std::uint32_t numStoredEffects = modelInfo->ucNumOf2DEffects - numPluginEffects - numCustomEffects;
24152420

24162421
if (index < numStoredEffects)
@@ -2447,6 +2452,64 @@ static void _declspec(naked) HOOK_Get2dEffect()
24472452
}
24482453
}
24492454

2455+
void CModelInfoSA::CopyModified2DFXEffects()
2456+
{
2457+
CBaseModelInfoSAInterface* modelInfo = ppModelInfo[m_dwModelID];
2458+
if (!modelInfo || modelInfo->ucNumOf2DEffects == 0)
2459+
return;
2460+
2461+
// Has modified effects?
2462+
if (!MapContains(ms_DefaultEffectsMap, m_dwModelID))
2463+
return;
2464+
2465+
auto tempVec = std::vector<C2DEffectSAInterface*>();
2466+
std::uint32_t numEffects = MapGet(defaultNumOf2DFXEffects, m_dwModelID);
2467+
for (std::uint32_t i = 0; i < numEffects; i++)
2468+
{
2469+
auto effect = ((C2DEffectSAInterface * (__thiscall*)(CBaseModelInfoSAInterface*, std::uint32_t index))FUNC_CBaseModelInfo_Get2dEffect)(modelInfo, i);
2470+
if (!effect)
2471+
continue;
2472+
2473+
// Copy effect
2474+
auto copy = new C2DEffectSAInterface();
2475+
memcpy(copy, effect, sizeof(C2DEffectSAInterface));
2476+
tempVec.push_back(copy);
2477+
}
2478+
2479+
MapSet(tempCopy2dfxEffects, m_dwModelID, tempVec);
2480+
}
2481+
2482+
void CModelInfoSA::RestoreModified2DFXEffects()
2483+
{
2484+
if (!MapContains(tempCopy2dfxEffects, m_dwModelID))
2485+
return;
2486+
2487+
CBaseModelInfoSAInterface* modelInfo = ppModelInfo[m_dwModelID];
2488+
if (!modelInfo)
2489+
return;
2490+
2491+
std::uint32_t numEffects = MapGet(defaultNumOf2DFXEffects, m_dwModelID);
2492+
auto& tempVec = MapGet(tempCopy2dfxEffects, m_dwModelID);
2493+
if (tempVec.size() > 0)
2494+
{
2495+
for (std::uint32_t i = 0; i < numEffects; i++)
2496+
{
2497+
auto effect = ((C2DEffectSAInterface * (__thiscall*)(CBaseModelInfoSAInterface*, std::uint32_t index))FUNC_CBaseModelInfo_Get2dEffect)(modelInfo, i);
2498+
if (!effect)
2499+
continue;
2500+
2501+
if (tempVec[i])
2502+
{
2503+
memcpy(effect, tempVec[i], sizeof(C2DEffectSAInterface));
2504+
delete tempVec[i];
2505+
}
2506+
}
2507+
}
2508+
2509+
tempVec.clear();
2510+
tempCopy2dfxEffects.erase(m_dwModelID);
2511+
}
2512+
24502513
//////////////////////////////////////////////////////////////////////////////////////////
24512514
//
24522515
// Setup hooks

Client/game_sa/CModelInfoSA.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ class CModelInfoSA : public CModelInfo
333333
static std::unordered_map<DWORD, std::pair<float, float>> ms_VehicleModelDefaultWheelSizes;
334334
static std::map<unsigned short, int> ms_DefaultTxdIDMap;
335335
SVehicleSupportedUpgrades m_ModelSupportedUpgrades;
336-
static std::unordered_map<DWORD, std::unordered_map<C2DEffectSAInterface*, C2DEffectSAInterface*>> CModelInfoSA::ms_DefaultEffectsMap;
337336

338337
public:
339338
CModelInfoSA();
@@ -482,6 +481,9 @@ class CModelInfoSA : public CModelInfo
482481
bool Reset2DFXEffects(bool removeCustomEffects = false);
483482
static void StaticReset2DFXEffects();
484483

484+
void CopyModified2DFXEffects();
485+
void RestoreModified2DFXEffects();
486+
485487
bool IsDynamic() { return m_pInterface ? m_pInterface->usDynamicIndex != 0xffff : false; };
486488

487489
private:

Client/sdk/game/CModelInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ class CModelInfo
356356
virtual void StoreDefault2DFXEffect(C2DEffectSAInterface* effect) = 0;
357357
virtual bool Reset2DFXEffects(bool removeCustomEffects = false) = 0;
358358

359+
virtual void CopyModified2DFXEffects() = 0;
360+
virtual void RestoreModified2DFXEffects() = 0;
361+
359362
virtual unsigned int GetParentID() = 0;
360363
virtual bool IsDynamic() = 0;
361364
};

0 commit comments

Comments
 (0)