Skip to content

Commit 27697ae

Browse files
committed
Added updater
1 parent 8a15230 commit 27697ae

4 files changed

Lines changed: 144 additions & 49 deletions

File tree

ModelVariations/FuncUtil.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ inline void vectorUnion(std::vector<unsigned short>& vec1, std::vector<unsigned
2121
inline std::string bytesToString(unsigned int address, int nBytes)
2222
{
2323
std::stringstream ss;
24+
unsigned char* c = reinterpret_cast<unsigned char*>(address);
2425

2526
for (int i = 0; i < nBytes; i++, ss << " ")
26-
ss << std::hex << (unsigned int)(((unsigned char*)address)[i]);
27+
ss << std::hex << static_cast<unsigned int>(c[i]);
2728

28-
std::string retString(ss.str());
29-
30-
return retString;
29+
return ss.str();
3130
}

ModelVariations/Hooks.hpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,16 @@ inline void callOriginal(Args... args)
3535
{
3636
auto it = hookedCalls.find(address);
3737
if (it != hookedCalls.end())
38-
{
39-
unsigned int originalCall = (unsigned int)(it->second.originalFunction);
40-
reinterpret_cast<void(__cdecl*)(Args...)>(originalCall)(args...);
41-
}
38+
reinterpret_cast<void(__cdecl*)(Args...)>(it->second.originalFunction)(args...);
4239
}
4340

4441
template <typename Ret, unsigned int address, typename... Args>
4542
inline Ret callOriginalAndReturn(Args... args)
4643
{
4744
auto it = hookedCalls.find(address);
4845
if (it != hookedCalls.end())
49-
{
50-
unsigned int originalCall = (unsigned int)(it->second.originalFunction);
51-
return reinterpret_cast<Ret(__cdecl*)(Args...)>(originalCall)(args...);
52-
}
46+
return reinterpret_cast<Ret(__cdecl*)(Args...)>(it->second.originalFunction)(args...);
47+
5348
return 0;
5449
}
5550

@@ -59,20 +54,15 @@ inline void callMethodOriginal(C _this, Args... args)
5954
{
6055
auto it = hookedCalls.find(address);
6156
if (it != hookedCalls.end())
62-
{
63-
unsigned int originalCall = (unsigned int)(it->second.originalFunction);
64-
reinterpret_cast<void(__thiscall*)(C, Args...)>(originalCall)(_this, args...);
65-
}
57+
reinterpret_cast<void(__thiscall*)(C, Args...)>(it->second.originalFunction)(_this, args...);
6658
}
6759

6860
template <typename Ret, unsigned int address, typename C, typename... Args>
6961
inline Ret callMethodOriginalAndReturn(C _this, Args... args)
7062
{
7163
auto it = hookedCalls.find(address);
7264
if (it != hookedCalls.end())
73-
{
74-
unsigned int originalCall = (unsigned int)(it->second.originalFunction);
75-
return reinterpret_cast<Ret(__thiscall*)(C, Args...)>(originalCall)(_this, args...);
76-
}
65+
return reinterpret_cast<Ret(__thiscall*)(C, Args...)>(it->second.originalFunction)(_this, args...);
66+
7767
return 0;
7868
}

ModelVariations/ModelVariations.cpp

Lines changed: 128 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@
2424
#include <stack>
2525
#include <unordered_set>
2626
#include <ctime>
27+
#include <urlmon.h>
2728

2829
#include <Psapi.h>
2930
#include <shlwapi.h>
3031

32+
#pragma comment(lib, "urlmon.lib")
33+
3134
using namespace plugin;
3235

3336
const int MAX_PED_ID = 300;
@@ -71,7 +74,7 @@ std::map<unsigned short, std::pair<CVector, float>> LightPositions;
7174
std::map<unsigned short, rgba> LightColors;
7275
std::map<unsigned short, rgba> LightColors2;
7376
std::map<unsigned short, int> pedTimeSinceLastSpawned;
74-
std::map<unsigned short, unsigned short> pedOriginalModels;
77+
std::map<unsigned short, std::vector<unsigned short>> pedOriginalModels;
7578
std::map<unsigned short, std::array<std::vector<unsigned short>, 6>> vehGroupWantedVariations;
7679
std::map<unsigned short, std::string> wepVariationModels;
7780
std::map<unsigned short, std::vector<unsigned short>> vehCurrentTuning;
@@ -86,13 +89,13 @@ std::set<unsigned short> vehMergeZones;
8689
std::set<unsigned short> pedHasVariations;
8790
std::set<unsigned short> vehHasVariations;
8891
std::set<unsigned int> modifiedAddresses;
89-
std::set<unsigned short> cloneRemoverIncludeVariations;
9092

9193
std::stack<CPed*> pedStack;
9294
std::stack<CVehicle*> vehStack;
9395
std::stack<std::pair<CVehicle*, std::array<std::vector<unsigned short>, 17>>> tuningStack;
9496
//std::stack<std::pair<CVehicle*, std::array<int, 16>>> tuningStack;
9597

98+
std::vector<unsigned short> cloneRemoverIncludeVariations;
9699
std::vector<unsigned short> cloneRemoverExclusions;
97100
std::vector<unsigned short> pedCurrentVariations[MAX_PED_ID];
98101
std::vector<unsigned short> vehCurrentVariations[212];
@@ -129,6 +132,8 @@ int spawnDelay = 3;
129132

130133
bool keyDown = false;
131134

135+
int timeUpdate = 8001;
136+
132137
void getLoadedModules()
133138
{
134139
modulesSet.clear();
@@ -146,6 +151,93 @@ void getLoadedModules()
146151
}
147152
}
148153

154+
bool checkForUpdate()
155+
{
156+
auto funcFail = []() {
157+
if (logfile.is_open())
158+
logfile << "Check for updates failed." << std::endl;
159+
160+
return false;
161+
};
162+
163+
IStream* stream;
164+
165+
if (URLOpenBlockingStream(0, "http://api.github.com/repos/ViperJohnGR/ModelVariations/tags", &stream, 0, 0) != S_OK)
166+
return funcFail();
167+
168+
std::string str(51, 0);
169+
if (stream->Read(&str[0], 50, NULL) != S_OK)
170+
return funcFail();
171+
172+
stream->Release();
173+
str = str.substr(11, 10);
174+
str.erase(str.find('"'));
175+
176+
const char *newV = str.c_str();
177+
const char *oldV = MOD_VERSION;
178+
179+
return std::lexicographical_compare(oldV, oldV+strlen(oldV), newV, newV+strlen(newV));
180+
}
181+
182+
bool pedDelaySpawn(unsigned short model, bool includeParentModels)
183+
{
184+
if (!includeParentModels)
185+
{
186+
if (pedTimeSinceLastSpawned.find(model) != pedTimeSinceLastSpawned.end())
187+
return true;
188+
}
189+
else
190+
{
191+
auto it = pedOriginalModels.find(model);
192+
if (it != pedOriginalModels.end())
193+
for (auto &i : it->second)
194+
if (pedTimeSinceLastSpawned.find(i) != pedTimeSinceLastSpawned.end())
195+
return true;
196+
}
197+
return false;
198+
}
199+
200+
void insertPedSpawnedOriginalModels(unsigned short model)
201+
{
202+
auto it = pedOriginalModels.find(model);
203+
if (it != pedOriginalModels.end())
204+
for (auto& i : it->second)
205+
pedTimeSinceLastSpawned.insert({ i, clock() });
206+
}
207+
208+
bool compareOriginalModels(unsigned short model1, unsigned short model2)
209+
{
210+
if (model1 == model2)
211+
return true;
212+
213+
auto it1 = pedOriginalModels.find(model1);
214+
auto it2 = pedOriginalModels.find(model2);
215+
if (it1 != pedOriginalModels.end() && it2 != pedOriginalModels.end())
216+
return std::find_first_of(it1->second.begin(), it1->second.end(), it2->second.begin(), it2->second.end()) != it1->second.end();
217+
else
218+
{
219+
unsigned short model = 0;
220+
std::vector<unsigned short> *vec = NULL;
221+
if (it1 != pedOriginalModels.end())
222+
{
223+
model = model2;
224+
vec = &it1->second;
225+
}
226+
else if (it2 != pedOriginalModels.end())
227+
{
228+
model = model1;
229+
vec = &it2->second;
230+
}
231+
else
232+
return false;
233+
234+
if (std::find(vec->begin(), vec->end(), model) != vec->end())
235+
return true;
236+
}
237+
238+
return false;
239+
}
240+
149241
void filterWantedVariations(std::vector<unsigned short>& vec, std::vector<unsigned short>& wantedVec)
150242
{
151243
bool matchFound = false;
@@ -165,15 +257,6 @@ void filterWantedVariations(std::vector<unsigned short>& vec, std::vector<unsign
165257
vec = vec2;
166258
}
167259

168-
static unsigned short getVariationOriginalModel(unsigned short model)
169-
{
170-
auto it = pedOriginalModels.find(model);
171-
if (it != pedOriginalModels.end())
172-
return it->second;
173-
174-
return model;
175-
}
176-
177260
bool IdExists(std::vector<unsigned short>& vec, int id)
178261
{
179262
if (vec.size() < 1)
@@ -187,7 +270,7 @@ bool IdExists(std::vector<unsigned short>& vec, int id)
187270

188271
bool isValidPedId(int id)
189272
{
190-
if (id <= 0 && id >= MAX_PED_ID)
273+
if (id <= 0 || id >= MAX_PED_ID)
191274
return false;
192275
if (id >= 190 && id <= 195)
193276
return false;
@@ -543,17 +626,22 @@ void loadIniData(bool firstTime)
543626

544627
for (unsigned int j = 0; j < 16; j++)
545628
for (unsigned int k = 0; k < pedVariations[i][j].size(); k++)
546-
if (pedVariations[i][j][k] > 0 && pedVariations[i][j][k] < 32000 && pedVariations[i][j][k] != i)
547-
pedOriginalModels.insert({ pedVariations[i][j][k], i });
629+
if (pedVariations[i][j][k] > 0 && pedVariations[i][j][k] != i)
630+
{
631+
if (pedOriginalModels.find(pedVariations[i][j][k]) != pedOriginalModels.end())
632+
pedOriginalModels[pedVariations[i][j][k]].push_back((unsigned short)i);
633+
else
634+
pedOriginalModels.insert({ pedVariations[i][j][k], {(unsigned short)i} });
635+
}
636+
637+
for (auto it : pedOriginalModels)
638+
std::sort(it.second.begin(), it.second.end());
548639

549640
if (iniPed.ReadInteger(section, "MergeZonesWithCities", 0) == 1)
550641
pedMergeZones.insert((unsigned short)i);
551642

552643
if (iniPed.ReadInteger(section, "DontInheritBehaviour", 0) == 1)
553644
dontInheritBehaviourModels.insert((unsigned short)i);
554-
555-
if (iniPed.ReadInteger(section, "CloneRemoverIncludeVariations", 0) == 1)
556-
cloneRemoverIncludeVariations.insert((unsigned short)i);
557645
}
558646
}
559647

@@ -568,6 +656,8 @@ void loadIniData(bool firstTime)
568656
wepVariationModels.insert({ modelid, section });
569657
}
570658

659+
cloneRemoverIncludeVariations = iniPed.ReadLine("Settings", "CloneRemoverIncludeVariations", READ_PEDS);
660+
571661
if (firstTime)
572662
{
573663
enableCloneRemover = iniPed.ReadInteger("Settings", "EnableCloneRemover", 0);
@@ -771,6 +861,9 @@ class ModelVariations {
771861

772862
Events::initRwEvent += []
773863
{
864+
//if (checkForUpdate())
865+
//MessageBox(NULL, "Model Variations: New version available!\nhttps://github.com/ViperJohnGR/ModelVariations", "Update available", MB_ICONINFORMATION);
866+
774867
loadIniData(true);
775868
installHooks();
776869

@@ -804,6 +897,11 @@ class ModelVariations {
804897

805898
if (logfile.is_open())
806899
getLoadedModules();
900+
901+
if (checkForUpdate())
902+
timeUpdate = clock();
903+
else
904+
timeUpdate = -1;
807905
};
808906

809907
Events::processScriptsEvent += []
@@ -854,6 +952,11 @@ class ModelVariations {
854952

855953
Events::gameProcessEvent += []
856954
{
955+
if (timeUpdate > -1 && ((clock() - timeUpdate) / CLOCKS_PER_SEC > 6))
956+
{
957+
CMessages::AddMessageJumpQ((char*)"~y~Model Variations~s~: Update available.", 4000, 0, false);
958+
timeUpdate = -1;
959+
}
857960

858961
if (disableKey > 0 && KeyPressed(disableKey))
859962
{
@@ -1062,8 +1165,8 @@ class ModelVariations {
10621165

10631166
if (IsPedPointerValid(ped) && enableCloneRemover == 1 && ped->m_nCreatedBy != 2 && CPools::ms_pPedPool && pedRemoved == false) //Clone remover
10641167
{
1065-
bool includeVariations = cloneRemoverIncludeVariations.find(ped->m_nModelIndex) != cloneRemoverIncludeVariations.end();
1066-
if (pedTimeSinceLastSpawned.find((includeVariations) ? getVariationOriginalModel(ped->m_nModelIndex) : ped->m_nModelIndex) != pedTimeSinceLastSpawned.end()) //Delete peds spawned before SpawnTime
1168+
bool includeVariations = std::find(cloneRemoverIncludeVariations.begin(), cloneRemoverIncludeVariations.end(), ped->m_nModelIndex) != cloneRemoverIncludeVariations.end();
1169+
if (pedDelaySpawn(ped->m_nModelIndex, includeVariations)) //Delete peds spawned before SpawnTime
10671170
{
10681171
if (!IsVehiclePointerValid(ped->m_pVehicle))
10691172
{
@@ -1105,11 +1208,14 @@ class ModelVariations {
11051208

11061209
if (!pedRemoved && IsPedPointerValid(ped) && !IdExists(cloneRemoverExclusions, ped->m_nModelIndex) && ped->m_nModelIndex > 0) //Delete peds already spawned
11071210
{
1108-
pedTimeSinceLastSpawned.insert({ ((includeVariations) ? getVariationOriginalModel(ped->m_nModelIndex) : ped->m_nModelIndex), clock() });
1211+
if (includeVariations)
1212+
insertPedSpawnedOriginalModels(ped->m_nModelIndex);
1213+
else
1214+
pedTimeSinceLastSpawned.insert({ ped->m_nModelIndex, clock() });
1215+
11091216
for (CPed* ped2 : CPools::ms_pPedPool)
11101217
if ( IsPedPointerValid(ped2) && ped2 != ped && ((includeVariations) ?
1111-
(getVariationOriginalModel(ped->m_nModelIndex) == getVariationOriginalModel(ped2->m_nModelIndex)) :
1112-
(ped->m_nModelIndex == ped2->m_nModelIndex)) )
1218+
(compareOriginalModels(ped->m_nModelIndex, ped2->m_nModelIndex)) : (ped->m_nModelIndex == ped2->m_nModelIndex)) )
11131219
{
11141220
if (!IsVehiclePointerValid(ped->m_pVehicle))
11151221
{

ModelVariations/Vehicles.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -516,9 +516,9 @@ void readVehicleIni(bool firstTime)
516516
if (!vec.empty())
517517
vehPassengers.insert({ modelid, vec });
518518

519-
unsigned short parentID = (unsigned short)iniVeh.ReadInteger(i.first, "ParentID", 0);
520-
if (parentID >= 400)
521-
vehOriginalModels[modelid] = parentID;
519+
vec = iniVeh.ReadLine(i.first, "ParentModel", READ_VEHICLES);
520+
if (!vec.empty() && vec[0] >= 400)
521+
vehOriginalModels[modelid] = vec[0];
522522
}
523523
}
524524

@@ -532,7 +532,7 @@ void readVehicleIni(bool firstTime)
532532
}
533533

534534
template <unsigned int address, typename... Args>
535-
void changeModel(std::string funcName, unsigned short oldModel, int newModel, std::vector<unsigned short*> addresses, Args... args)
535+
void changeModel(const char *funcName, unsigned short oldModel, int newModel, std::vector<unsigned short*> addresses, Args... args)
536536
{
537537
if (newModel < 400 || newModel > 65535)
538538
{
@@ -543,7 +543,7 @@ void changeModel(std::string funcName, unsigned short oldModel, int newModel, st
543543
for (auto& i : addresses)
544544
if (*i != oldModel)
545545
{
546-
logModified((unsigned int)i, printToString("Modified method detected : %s - 0x%X is %u", funcName.c_str(), i, *i));
546+
logModified((unsigned int)i, printToString("Modified method detected : %s - 0x%X is %u", funcName, i, *i));
547547
return callMethodOriginal<address>(args...);
548548
}
549549

@@ -555,7 +555,7 @@ void changeModel(std::string funcName, unsigned short oldModel, int newModel, st
555555
}
556556

557557
template <typename T, unsigned int address, typename... Args>
558-
T changeModelAndReturn(std::string funcName, unsigned short oldModel, int newModel, std::vector<unsigned short*> addresses, Args... args)
558+
T changeModelAndReturn(const char* funcName, unsigned short oldModel, int newModel, std::vector<unsigned short*> addresses, Args... args)
559559
{
560560
if (newModel < 400 || newModel > 65535)
561561
{
@@ -565,7 +565,7 @@ T changeModelAndReturn(std::string funcName, unsigned short oldModel, int newMod
565565
for (auto& i : addresses)
566566
if (*i != oldModel)
567567
{
568-
logModified((unsigned int)i, printToString("Modified method detected : %s - 0x%X is %u", funcName.c_str(), i, *i));
568+
logModified((unsigned int)i, printToString("Modified method detected : %s - 0x%X is %u", funcName, i, *i));
569569
return callMethodOriginalAndReturn<T, address>(args...);
570570
}
571571

0 commit comments

Comments
 (0)