Skip to content

Commit 5517c28

Browse files
committed
Add random remap feature
1 parent 404c3e7 commit 5517c28

File tree

9 files changed

+142
-10
lines changed

9 files changed

+142
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,4 @@ build/obj/Win32/Release/ModelExtras.tlog/link.command.1.tlog
245245
build/obj/Win32/Release/ModelExtras.tlog/link.read.1.tlog
246246
build/obj/Win32/Release/ModelExtras.tlog/link.write.1.tlog
247247
build/obj/Win32/Release/ModelExtras.tlog/ModelExtras.lastbuildstate
248+
build/obj/Win32/Debug/randomremap.obj

src/dllmain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "features/weapon/bodystate.h"
88
#include "features/weapon/bloodremap.h"
99
#include "features/common/randomizer.h"
10+
#include "features/common/randomremap.h"
1011
#include "soundsystem.h"
1112

1213
static ThiscallEvent <AddressList<0x5E7859, H_CALL>, PRIORITY_BEFORE, ArgPickN<CPed*, 0>, void(CPed*)> weaponRenderEvent;
@@ -30,12 +31,14 @@ static void ProcessNodesRecursive(RwFrame * frame, void* pEntity, eNodeEntityTyp
3031
GearLever.Process(frame, pVeh);
3132
GearSound.Process(frame, pVeh);
3233
Randomizer.Process(frame, static_cast<void*>(pVeh), type);
34+
RandomRemap.Process(frame, static_cast<void*>(pVeh), type);
3335
} else if (type == eNodeEntityType::Weapon) {
3436
CWeapon *pWep = static_cast<CWeapon*>(pEntity);
3537
BodyState.Process(frame, pWep);
3638
BodyState.ProcessZen(frame, pWep);
3739
BloodRemap.Process(frame, pWep);
3840
Randomizer.Process(frame, static_cast<void*>(pWep), type);
41+
RandomRemap.Process(frame, static_cast<void*>(pWep), type);
3942
} else if (type == eNodeEntityType::Object) {
4043

4144
/*
@@ -44,6 +47,9 @@ static void ProcessNodesRecursive(RwFrame * frame, void* pEntity, eNodeEntityTyp
4447
CWeapon *pWep = static_cast<CWeapon*>(pEntity);
4548
BodyState.Process(frame, pWep);
4649
BodyState.ProcessZen(frame, pWep);
50+
} else if (type == eNodeEntityType::Ped) {
51+
Randomizer.Process(frame, pEntity, type);
52+
RandomRemap.Process(frame, pEntity, type);
4753
}
4854
}
4955
// LicensePlate.Process(frame, pVeh);

src/extender.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
#include "pch.h"
3+
#include <vector>
4+
#include <map>
5+
6+
template <class T, class Y>
7+
class Extender {
8+
private:
9+
inline static std::vector<std::pair<T, Y>> data{};
10+
11+
public:
12+
Extender(const Extender&) = delete;
13+
Extender() {}
14+
15+
Y& Get(T ptr) {
16+
for (auto it = data.begin(); it < data.end(); ++it) {
17+
if (it->first == ptr) {
18+
return it->second;
19+
}
20+
}
21+
22+
data.push_back({ ptr, Y(ptr) });
23+
return data.back().second;
24+
}
25+
};

src/features/common/randomizer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "pch.h"
22
#include "randomizer.h"
3+
#define NODE_ID "x_randomizer"
34

45
RandomizerFeature Randomizer;
56

@@ -17,7 +18,7 @@ void RandomizerFeature::Initialize(RwFrame* pFrame) {
1718

1819
void RandomizerFeature::Process(RwFrame* frame, void* ptr, eNodeEntityType type) {
1920
std::string name = GetFrameNodeName(frame);
20-
if (name.find("x_randomizer") != std::string::npos) {
21+
if (name.find(NODE_ID) != std::string::npos) {
2122
if (std::find(frameStore.begin(), frameStore.end(), frame) == frameStore.end()) {
2223
Initialize(frame);
2324
frameStore.push_back(frame);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "pch.h"
2+
#include "randomremap.h"
3+
#include <TxdDef.h>
4+
#include <CTxdStore.h>
5+
#include <CKeyGen.h>
6+
#define MAX_REMAPS 32
7+
#define NODE_ID "x_ranmap"
8+
9+
RandomRemapFeature RandomRemap;
10+
11+
struct RemapData {
12+
bool m_bInit;
13+
unsigned int rand;
14+
std::vector<RwTexture*> m_pTextures;
15+
};
16+
17+
void RandomRemapFeature::Process(RwFrame* frame, void* ptr, eNodeEntityType type) {
18+
FrameData &data = xFrame.Get(frame);
19+
20+
if (data.m_bInit) {
21+
return;
22+
}
23+
24+
std::string name = GetFrameNodeName(frame);
25+
if (name.find(NODE_ID) != std::string::npos) {
26+
std::string str = Util::GetRegexVal(name, NODE_ID"_(.*)", "");
27+
28+
RpClump *pClump;
29+
RemapData remapData;
30+
31+
CBaseModelInfo *pModelInfo = nullptr;
32+
if (type == eNodeEntityType::Weapon) {
33+
CWeaponInfo* pWeaponInfo = CWeaponInfo::GetWeaponInfo(reinterpret_cast<CWeapon*>(ptr)->m_eWeaponType,
34+
FindPlayerPed()->GetWeaponSkill(reinterpret_cast<CWeapon*>(ptr)->m_eWeaponType));
35+
if (pWeaponInfo){
36+
pModelInfo = CModelInfo::GetModelInfo(pWeaponInfo->m_nModelId1);
37+
}
38+
} else {
39+
pModelInfo = CModelInfo::GetModelInfo(reinterpret_cast<CEntity*>(ptr)->m_nModelIndex);
40+
}
41+
42+
43+
if (pModelInfo) {
44+
pClump = pModelInfo->m_pRwClump;
45+
46+
TxdDef pedTxd = CTxdStore::ms_pTxdPool->m_pObjects[pModelInfo->m_nTxdIndex];
47+
RwTexDictionary *pedTxdDic = pedTxd.m_pRwDictionary;
48+
if (pedTxdDic) {
49+
RwTexture *ptr = RwTexDictionaryFindHashNamedTexture(pedTxdDic, CKeyGen::GetUppercaseKey(str.c_str()));
50+
remapData.m_pTextures.push_back(ptr);
51+
for (int i = 1; i != MAX_REMAPS; i++) {
52+
RwTexture *ptr = RwTexDictionaryFindHashNamedTexture(pedTxdDic,
53+
CKeyGen::GetUppercaseKey((str + "_" + std::to_string(i)).c_str()));
54+
55+
if (ptr) {
56+
remapData.m_pTextures.push_back(ptr);
57+
}
58+
}
59+
}
60+
}
61+
62+
remapData.rand = Random(0u, remapData.m_pTextures.size()-1);
63+
RpClumpForAllAtomics(pClump, [](RpAtomic *atomic, void *data) {
64+
if (atomic->geometry) {
65+
RpGeometryForAllMaterials(atomic->geometry, [](RpMaterial *material, void *data) {
66+
RemapData *pData = reinterpret_cast<RemapData*>(data);
67+
if (material->texture == pData->m_pTextures[0]) {
68+
material->texture = pData->m_pTextures[pData->rand];
69+
}
70+
return material;
71+
}, data);
72+
}
73+
return atomic;
74+
}, &remapData);
75+
76+
data.m_bInit = true;
77+
}
78+
}

src/features/common/randomremap.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
#include "plugin.h"
3+
#include "../../interface/ifeature.hpp"
4+
#include "../../extender.h"
5+
6+
class RandomRemapFeature : public IFeature {
7+
private:
8+
struct FrameData {
9+
bool m_bInit = false;
10+
FrameData(RwFrame*) {}
11+
~FrameData() {}
12+
};
13+
Extender<RwFrame*, FrameData> xFrame;
14+
15+
public:
16+
RandomRemapFeature () {};
17+
18+
void Process(RwFrame* frame, void* ptr, eNodeEntityType type);
19+
};
20+
21+
extern RandomRemapFeature RandomRemap;

src/features/weapon/bloodremap.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
BloodRemapFeature BloodRemap;
1010

1111
void BloodRemapFeature::Initialize(RwFrame* pFrame, CWeapon* pWeapon) {
12-
WepData &data = xData.Get(pWeapon);
12+
FrameData &data = xData.Get(pWeapon);
1313
std::string name = GetFrameNodeName(pFrame);
1414
std::string str = Util::GetRegexVal(name, "x_remap_(.*)", "");
1515

@@ -40,7 +40,7 @@ void BloodRemapFeature::Initialize(RwFrame* pFrame, CWeapon* pWeapon) {
4040
}
4141

4242
void BloodRemapFeature::Process(RwFrame* frame, CWeapon *pWeapon) {
43-
WepData &data = xData.Get(pWeapon);
43+
FrameData &data = xData.Get(pWeapon);
4444
std::string name = GetFrameNodeName(frame);
4545
data.m_CurNode = name;
4646
if (name.find("x_remap") != std::string::npos) {
@@ -75,7 +75,7 @@ void BloodRemapFeature::Process(RwFrame* frame, CWeapon *pWeapon) {
7575
RpClumpForAllAtomics(pWeaponModelInfo->m_pRwClump, [](RpAtomic *atomic, void *data) {
7676
if (atomic->geometry) {
7777
RpGeometryForAllMaterials(atomic->geometry, [](RpMaterial *material, void *data) {
78-
WepData *pData = reinterpret_cast<WepData*>(data);
78+
FrameData *pData = reinterpret_cast<FrameData*>(data);
7979
if (material->texture == pData->m_Textures[pData->m_CurNode].m_pFrames[0]) {
8080
material->texture = pData->m_Textures[pData->m_CurNode].m_pFrames[pData->m_Textures[pData->m_CurNode].m_nCurRemap];
8181
}

src/features/weapon/bloodremap.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22
#include "plugin.h"
33
#include "../../interface/ifeature.hpp"
4-
#include "../../weaponextender.h"
4+
#include "../../weaponExtender.h"
55
#include <map>
66

77
struct TextureData {
@@ -11,17 +11,17 @@ struct TextureData {
1111
std::vector<RwTexture*> m_pFrames;
1212
};
1313

14-
struct WepData {
14+
struct FrameData {
1515
std::string m_CurNode = "";
1616
CPed* m_pLastKilledEntity = nullptr;
1717
std::map<std::string, TextureData> m_Textures;
1818

19-
WepData(CWeapon*) {}
20-
~WepData() {}
19+
FrameData(CWeapon*) {}
20+
~FrameData() {}
2121
};
2222

2323
class BloodRemapFeature : public IFeature {
24-
WeaponExtender<WepData> xData;
24+
WeaponExtender<FrameData> xData;
2525
public:
2626
void Initialize(RwFrame* frame, CWeapon* pWeapon);
2727
void Process(RwFrame* frame, CWeapon *pWeapon);

src/features/weapon/bodystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22
#include "plugin.h"
33
#include "../../interface/ifeature.hpp"
4-
#include "../../weaponextender.h"
4+
#include "../../weaponExtender.h"
55
#include <vector>
66

77
enum class eBodyState {

0 commit comments

Comments
 (0)