Skip to content

Commit

Permalink
Add random remap feature
Browse files Browse the repository at this point in the history
  • Loading branch information
user-grinch committed Jan 22, 2024
1 parent 404c3e7 commit 5517c28
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,4 @@ build/obj/Win32/Release/ModelExtras.tlog/link.command.1.tlog
build/obj/Win32/Release/ModelExtras.tlog/link.read.1.tlog
build/obj/Win32/Release/ModelExtras.tlog/link.write.1.tlog
build/obj/Win32/Release/ModelExtras.tlog/ModelExtras.lastbuildstate
build/obj/Win32/Debug/randomremap.obj
6 changes: 6 additions & 0 deletions src/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "features/weapon/bodystate.h"
#include "features/weapon/bloodremap.h"
#include "features/common/randomizer.h"
#include "features/common/randomremap.h"
#include "soundsystem.h"

static ThiscallEvent <AddressList<0x5E7859, H_CALL>, PRIORITY_BEFORE, ArgPickN<CPed*, 0>, void(CPed*)> weaponRenderEvent;
Expand All @@ -30,12 +31,14 @@ static void ProcessNodesRecursive(RwFrame * frame, void* pEntity, eNodeEntityTyp
GearLever.Process(frame, pVeh);
GearSound.Process(frame, pVeh);
Randomizer.Process(frame, static_cast<void*>(pVeh), type);
RandomRemap.Process(frame, static_cast<void*>(pVeh), type);
} else if (type == eNodeEntityType::Weapon) {
CWeapon *pWep = static_cast<CWeapon*>(pEntity);
BodyState.Process(frame, pWep);
BodyState.ProcessZen(frame, pWep);
BloodRemap.Process(frame, pWep);
Randomizer.Process(frame, static_cast<void*>(pWep), type);
RandomRemap.Process(frame, static_cast<void*>(pWep), type);
} else if (type == eNodeEntityType::Object) {

/*
Expand All @@ -44,6 +47,9 @@ static void ProcessNodesRecursive(RwFrame * frame, void* pEntity, eNodeEntityTyp
CWeapon *pWep = static_cast<CWeapon*>(pEntity);
BodyState.Process(frame, pWep);
BodyState.ProcessZen(frame, pWep);
} else if (type == eNodeEntityType::Ped) {
Randomizer.Process(frame, pEntity, type);
RandomRemap.Process(frame, pEntity, type);
}
}
// LicensePlate.Process(frame, pVeh);
Expand Down
25 changes: 25 additions & 0 deletions src/extender.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include "pch.h"
#include <vector>
#include <map>

template <class T, class Y>
class Extender {
private:
inline static std::vector<std::pair<T, Y>> data{};

public:
Extender(const Extender&) = delete;
Extender() {}

Y& Get(T ptr) {
for (auto it = data.begin(); it < data.end(); ++it) {
if (it->first == ptr) {
return it->second;
}
}

data.push_back({ ptr, Y(ptr) });
return data.back().second;
}
};
3 changes: 2 additions & 1 deletion src/features/common/randomizer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "pch.h"
#include "randomizer.h"
#define NODE_ID "x_randomizer"

RandomizerFeature Randomizer;

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

void RandomizerFeature::Process(RwFrame* frame, void* ptr, eNodeEntityType type) {
std::string name = GetFrameNodeName(frame);
if (name.find("x_randomizer") != std::string::npos) {
if (name.find(NODE_ID) != std::string::npos) {
if (std::find(frameStore.begin(), frameStore.end(), frame) == frameStore.end()) {
Initialize(frame);
frameStore.push_back(frame);
Expand Down
78 changes: 78 additions & 0 deletions src/features/common/randomremap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "pch.h"
#include "randomremap.h"
#include <TxdDef.h>
#include <CTxdStore.h>
#include <CKeyGen.h>
#define MAX_REMAPS 32
#define NODE_ID "x_ranmap"

RandomRemapFeature RandomRemap;

struct RemapData {
bool m_bInit;
unsigned int rand;
std::vector<RwTexture*> m_pTextures;
};

void RandomRemapFeature::Process(RwFrame* frame, void* ptr, eNodeEntityType type) {
FrameData &data = xFrame.Get(frame);

if (data.m_bInit) {
return;
}

std::string name = GetFrameNodeName(frame);
if (name.find(NODE_ID) != std::string::npos) {
std::string str = Util::GetRegexVal(name, NODE_ID"_(.*)", "");

RpClump *pClump;
RemapData remapData;

CBaseModelInfo *pModelInfo = nullptr;
if (type == eNodeEntityType::Weapon) {
CWeaponInfo* pWeaponInfo = CWeaponInfo::GetWeaponInfo(reinterpret_cast<CWeapon*>(ptr)->m_eWeaponType,
FindPlayerPed()->GetWeaponSkill(reinterpret_cast<CWeapon*>(ptr)->m_eWeaponType));
if (pWeaponInfo){
pModelInfo = CModelInfo::GetModelInfo(pWeaponInfo->m_nModelId1);
}
} else {
pModelInfo = CModelInfo::GetModelInfo(reinterpret_cast<CEntity*>(ptr)->m_nModelIndex);
}


if (pModelInfo) {
pClump = pModelInfo->m_pRwClump;

TxdDef pedTxd = CTxdStore::ms_pTxdPool->m_pObjects[pModelInfo->m_nTxdIndex];
RwTexDictionary *pedTxdDic = pedTxd.m_pRwDictionary;
if (pedTxdDic) {
RwTexture *ptr = RwTexDictionaryFindHashNamedTexture(pedTxdDic, CKeyGen::GetUppercaseKey(str.c_str()));
remapData.m_pTextures.push_back(ptr);
for (int i = 1; i != MAX_REMAPS; i++) {
RwTexture *ptr = RwTexDictionaryFindHashNamedTexture(pedTxdDic,
CKeyGen::GetUppercaseKey((str + "_" + std::to_string(i)).c_str()));

if (ptr) {
remapData.m_pTextures.push_back(ptr);
}
}
}
}

remapData.rand = Random(0u, remapData.m_pTextures.size()-1);
RpClumpForAllAtomics(pClump, [](RpAtomic *atomic, void *data) {
if (atomic->geometry) {
RpGeometryForAllMaterials(atomic->geometry, [](RpMaterial *material, void *data) {
RemapData *pData = reinterpret_cast<RemapData*>(data);
if (material->texture == pData->m_pTextures[0]) {
material->texture = pData->m_pTextures[pData->rand];
}
return material;
}, data);
}
return atomic;
}, &remapData);

data.m_bInit = true;
}
}
21 changes: 21 additions & 0 deletions src/features/common/randomremap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include "plugin.h"
#include "../../interface/ifeature.hpp"
#include "../../extender.h"

class RandomRemapFeature : public IFeature {
private:
struct FrameData {
bool m_bInit = false;
FrameData(RwFrame*) {}
~FrameData() {}
};
Extender<RwFrame*, FrameData> xFrame;

public:
RandomRemapFeature () {};

void Process(RwFrame* frame, void* ptr, eNodeEntityType type);
};

extern RandomRemapFeature RandomRemap;
6 changes: 3 additions & 3 deletions src/features/weapon/bloodremap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
BloodRemapFeature BloodRemap;

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

Expand Down Expand Up @@ -40,7 +40,7 @@ void BloodRemapFeature::Initialize(RwFrame* pFrame, CWeapon* pWeapon) {
}

void BloodRemapFeature::Process(RwFrame* frame, CWeapon *pWeapon) {
WepData &data = xData.Get(pWeapon);
FrameData &data = xData.Get(pWeapon);
std::string name = GetFrameNodeName(frame);
data.m_CurNode = name;
if (name.find("x_remap") != std::string::npos) {
Expand Down Expand Up @@ -75,7 +75,7 @@ void BloodRemapFeature::Process(RwFrame* frame, CWeapon *pWeapon) {
RpClumpForAllAtomics(pWeaponModelInfo->m_pRwClump, [](RpAtomic *atomic, void *data) {
if (atomic->geometry) {
RpGeometryForAllMaterials(atomic->geometry, [](RpMaterial *material, void *data) {
WepData *pData = reinterpret_cast<WepData*>(data);
FrameData *pData = reinterpret_cast<FrameData*>(data);
if (material->texture == pData->m_Textures[pData->m_CurNode].m_pFrames[0]) {
material->texture = pData->m_Textures[pData->m_CurNode].m_pFrames[pData->m_Textures[pData->m_CurNode].m_nCurRemap];
}
Expand Down
10 changes: 5 additions & 5 deletions src/features/weapon/bloodremap.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once
#include "plugin.h"
#include "../../interface/ifeature.hpp"
#include "../../weaponextender.h"
#include "../../weaponExtender.h"
#include <map>

struct TextureData {
Expand All @@ -11,17 +11,17 @@ struct TextureData {
std::vector<RwTexture*> m_pFrames;
};

struct WepData {
struct FrameData {
std::string m_CurNode = "";
CPed* m_pLastKilledEntity = nullptr;
std::map<std::string, TextureData> m_Textures;

WepData(CWeapon*) {}
~WepData() {}
FrameData(CWeapon*) {}
~FrameData() {}
};

class BloodRemapFeature : public IFeature {
WeaponExtender<WepData> xData;
WeaponExtender<FrameData> xData;
public:
void Initialize(RwFrame* frame, CWeapon* pWeapon);
void Process(RwFrame* frame, CWeapon *pWeapon);
Expand Down
2 changes: 1 addition & 1 deletion src/features/weapon/bodystate.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once
#include "plugin.h"
#include "../../interface/ifeature.hpp"
#include "../../weaponextender.h"
#include "../../weaponExtender.h"
#include <vector>

enum class eBodyState {
Expand Down

0 comments on commit 5517c28

Please sign in to comment.