Código: Selecionar tudo
#include "CAutoPosto.h"
#include <game_sa\RenderWare.h>
#include <fstream>
#include <string>
#include <ctime>
#include "GSXAPI.h"
#include <algorithm>
#include <game_sa\CBike.h>
#pragma pack(push, 1)
struct CStreamedIpl{
//struc; (sizeof = 0x34)
CRect bound; //CRect ? ; CRange2D:
char name[16]; // db 16 dup(? )
int16_t field_20; //dw ?
int16_t m_usBuildingsBegin; // dw ? ; first building index
int16_t m_usBuildingsEnd; // dw ? ; last building index
int16_t m_usDummyBegin; // dw ? ; first dummy index
int16_t m_usDummyEnd; // dw ? ; last dummy index
int16_t m_sTextIPL; //dw ?
int16_t m_bIsInterior; //db ?
bool m_bLoaded; //db ?
bool m_bRequired; //db ?
bool m_bDisableDynamicStreaming; //db ?
bool m_bNotOwnedByMission; // db ?
int16_t _pad1; // db 3 dup(? )
// 00000034 CStreamedIpl .// ends
};
struct CStreamingInfo { //struc; (sizeof = 0x14); XREF:.data : ms_aInfoForModelr
uint16_t ll_usNext;
uint16_t ll_usPrev;
uint16_t usNextOnCd;
uint8_t ucFlags; // db ? ; 0x10 = loading(when); 0x2 = loading(finished); 0x12 = loading
uint8_t ucImgId; // db ?
uint32_t iBlockOffset; /// dd ?
uint32_t iBlockCount; // dd ?
uint8_t uiLoadStatus; // db ? ; 0 - not loaded 2 - requested 3 - loaded 1 - processed(it's loaded yea)
uint8_t _pad1[3]; //db 3 dup(? )
//00000014 CStreamingInfo ends
};
#pragma pack(pop)
VALIDATE_SIZE(CStreamedIpl, 0x34);
VALIDATE_SIZE(CStreamingInfo, 0x14);
std::fstream ipls("ipls", std::ios::out | std::ios::trunc);
double defaultMaxGas = 55000.0;
void CAutoPosto::checkAcScriptData()
{
}
void CAutoPosto::posto::actorWalkTo(int acttorIndex, const Rw3D &pos, float angle, float radius)
{
if (acttorIndex < actors.size())
{
cbStruct ncb;
ncb.pActorID = acttorIndex;
ncb.dataPack = { actors[acttorIndex].handle, 0, pos.x, pos.y, pos.z, angle, radius };
ncb.gassStat = this;
ncb.scriptActionID = 5;
p().cbPool.push_back(ncb);
}
}
CAutoPosto::posto *gassStat = nullptr;
CScriptThread *scrptAP = nullptr;
int pumpID = 0;
int scriptActionID = 0;
int pActorID = 0;
void CAutoPosto::scriptCallBack()
{
switch (scriptActionID)
{
case 0:
if (scrptAP->tls[2].dwParam != -1)
{
actorData act(scrptAP->tls[2].dwParam);
act.action = 0;
gassStat->actors.push_back(act);
//ipls << "Act Push back" << gassStat->actors.size() << std::endl;
}
else
{
//ipls << "fail" << std::endl;
//ipls.flush();
}
break;
case 1:
if (pActorID > 0)
{
//pActorID = gassStat->actors.size() - 1;
//p().callGDataScriptFun(1, { gassStat->actors[pActorID].handle });
gassStat->actors.pop_back();
}
break;
case 2:
break;
case 3:
break;
case 4:
if (scrptAP->tls[2].dwParam != 0)
{
if (gassStat->actors.size() > 0)
{
gassStat->actors.pop_back();
gassStat->ok = false;
}
}
/*if (pActorID > 0 && gassStat->actors.size() > 0)
{
--pActorID;
p().callGDataScriptFun(4, { gassStat->actors[pActorID].handle });
}*/
break;
case 5:
break;
default:
break;
}
p().callGDataScriptFunF();
}
void CAutoPosto::callGDataScriptFun(int funid, const std::vector<SCRIPT_VAR> &dataPack)
{
scriptActionID = funid;
script->tls[0].dwParam = scriptAddrs[funid];
//ipls << "addr " << script->tls[0].dwParam << std::endl;
//ipls.flush();
for (int i = 1; i <= dataPack.size(); ++i)
{
script->tls[i] = dataPack[i - 1];
}
injector::WriteMemory(&script->tls[31], CAutoPosto::scriptCallBack);
scrptAP = script;
}
void CAutoPosto::callGDataScriptFunF()
{
if (cbPool.size() > 0)
{
auto &cb = cbPool[0];
gassStat = cb.gassStat;
pActorID = cb.pActorID;
pumpID = cb.pumpID;
callGDataScriptFun(cb.scriptActionID, cb.dataPack);
cbPool.pop_front();
}
}
void CAutoPosto::posto::checkDeadActors()
{
if (actors.size() > 0)
{
cbStruct ncb;
ncb.pActorID = actors.size() - 1;
ncb.dataPack = { actors[ncb.pActorID].handle };
ncb.gassStat = this;
ncb.scriptActionID = 4;
p().cbPool.push_back(ncb);
}
}
void CAutoPosto::posto::destroyActors()
{
if (actors.size() > 0)
{
cbStruct ncb;
ncb.pActorID = actors.size() - 1;
ncb.dataPack = { actors[ncb.pActorID].handle };
ncb.gassStat = this;
ncb.scriptActionID = 1;
p().cbPool.push_back(ncb);
actors.pop_back();
/*for (auto &actor : actors)
{
//CWorld__destroyPed(actor);
}*/
//actors.clear();
}
}
void CAutoPosto::posto::createActors()
{
if (actors.size() < pumps.size() && ok)
{
CStreamingInfo *ms_aInfoForModel = injector::ReadMemory<CStreamingInfo*>(0x00407B02 + 2);
if (ms_aInfoForModel[7].uiLoadStatus == 1)
{
//ipls << actors.size() << " " << pumps.size() << " " << ms_aInfoForModel[7].uiLoadStatus << std::endl;
//ipls.flush();
float randPosX = (rand() % 360) / 120.0;
randPosX = randPosX < 1.0 ? 1.0 : randPosX;
randPosX = rand() % 2 ? -randPosX : randPosX;
float randPosY = (rand() % 360) / 120.0;
randPosY = randPosY < 1.0 ? 1.0 : randPosY;
randPosY = rand() % 2 ? -randPosY : randPosY;
float posx = pumps[actors.size()].at.x;
float posy = pumps[actors.size()].at.y;
//p().callGDataScriptFun(0, );
cbStruct ncb;
ncb.dataPack = { 7, 0, (float)posx + randPosX, (float)pos.y + randPosY, (float)pos.z };
ncb.pActorID = 0;
ncb.gassStat = this;
ncb.scriptActionID = 0;
p().cbPool.push_back(ncb);
}
else
{
cbStruct ncb;
ncb.dataPack = { 7 };
ncb.pActorID = 0;
ncb.gassStat = this;
ncb.scriptActionID = 2;
p().cbPool.push_back(ncb);
}
}
}
void CAutoPosto::posto::allActorsAction()
{
for (int i = 0, size = actors.size(); i < size; ++i)
{
auto &actor = actors[i];
//ipls << actor.action << std::endl;
//ipls.flush();
switch (actor.action)
{
case 0:
if (i < pumps.size())
{
Rw3D pos = pumps[i].at;
pos.x += 0.5;
pos.y += 0.1;
actorWalkTo(i, pos, 0.0, 3.0);
}
++actor.action;
break;
default:
//++actor.action;
break;
}
}
}
int CAutoPosto::posto::calcNearestPump(const Rw3D &pos, double &dist)
{
int result = -1;
dist = 999999.0;
for (int i = 0, size = pumps.size(); i < size; i++)
{
double rdist = gambi3D::getDistanceBetweenPointsXYZ(pumps[i].at, pos);
if (rdist < dist)
{
dist = rdist;
result = i;
}
}
return result;
}
void CAutoPosto::loadGasStations()
{
CPool<CDummy> *pool = injector::cstd<CPool<CDummy>*()>::call<0x00404580>();
//CPool<CObject> *pool = *injector::ReadMemory<CPool<CObject>**>(0x005510AC + 1);
auto CModelInfo__GetModelInfo = injector::cstd<void*(char *modelName, int *pIndex)>::call<0x004C5940>;
int id0 = 0, id1 = 0, id2 = 0;
//0x008E3FB0;
CModelInfo__GetModelInfo("petrolpump", &id0);
CModelInfo__GetModelInfo("petrolpumpnew", &id1);
CModelInfo__GetModelInfo("washgaspump", &id2);
pumpids.push_back(id0);
pumpids.push_back(id1);
pumpids.push_back(id2);
//ipls << std::to_string(pool->m_Size) << std::endl;
//ipls << "ids " + std::to_string(id0) + " " + std::to_string(id1) + " " + std::to_string(id2) << std::endl;
//std::vector < int > pumps;
for (int i = 0; i < pool->m_Size; ++i)
{
const int modelid = pool->m_Objects[i].m_wModelIndex;
//if (modelid)
// ipls << modelid << std::endl;
//ipls.flush();
if (pool->GetAt(i) && (modelid == id0 || modelid == id1 || modelid == id2))
{
auto &pos = pool->m_Objects[i].m_Placement.m_vPosn;
gambi3D pumpPos(pos.x, pos.y, pos.z);
gambi3D flpumpPos(floor(pos.x), floor(pos.y), floor(pos.z));
double dist = 9999999999.0;
int gasstateid = calcNearestGasStation(pumpPos, dist);
//ipls << "Dist " << dist << std::endl;
if (gasstateid >= 0 && dist < 40.0)
{
double pdist = 9999999.0;
if (dist > plgPumps)
plgPumps = dist;
int pumpid = postos[gasstateid].calcNearestPump(pumpPos, pdist);
if (pumpid >= 0 && pdist < 0.2)
{
}
else
{
pumpdata newpdata;
newpdata.modelID = pool->m_Objects[i].m_wModelIndex;
newpdata.at = pumpPos;
postos[gasstateid].pumps.push_back(newpdata);
}
}
else if (floor(dist) != 0)
{
posto newgsdata;
pumpdata newpdata;
newpdata.modelID = pool->m_Objects[i].m_wModelIndex;
newpdata.at = pumpPos;
newgsdata.pos = pumpPos;
newgsdata.pumps.push_back(newpdata);
postos.push_back(newgsdata);
}
//if (pool->m_Objects[i].m_pCoords)
//ipls << "index " + std::to_string(i) + " modelid " + std::to_string(pool->m_Objects[i].m_wModelIndex) + " " + std::to_string(pool->m_Objects[i].m_Placement.m_vPosn.x) + " " + std::to_string(pool->m_Objects[i].m_Placement.m_vPosn.y) + " " + std::to_string(pool->m_Objects[i].m_Placement.m_vPosn.z) << std::endl;
//pool->GetAt(i)->m_wModelIndex
//ipls.flush();
}
}
}
static int ij = 0;
int hdl = -1;
CVehicle *teststruct = 0;
gambi3D gb3d;
void setVehEngineState(CVehicle *veh, bool state)
{
uint8_t &flags = *(uint8_t*)(((uintptr_t)veh) + 0x0428); // flags
if (state)
flags |= 0x10;
else
flags &= ~0x10;
}
bool getEngineState(CVehicle *veh)
{
uint8_t flags = *(uint8_t*)(((uintptr_t)veh) + 0x0428); // flags
return flags & 0x10;
}
static auto getVehicleModelInfoByID = injector::cstd<CVehicleModelInfo*(int id)>::call<0x00403DA0>;
float GetVehicleSpeedRealistic(CVehicle *vehicle) {
float wheelSpeed = 0.0f;
CVehicleModelInfo * vehicleModelInfo = getVehicleModelInfoByID(vehicle->m_wModelIndex);
if (vehicle->m_dwVehicleSubClass == VEHICLE_BIKE || vehicle->m_dwVehicleSubClass == VEHICLE_BMX) {
CBike *bike = (CBike*)vehicle;
wheelSpeed = ((bike->m_afWheelRotationX[0] * vehicleModelInfo->m_fWheelSizeFront) +
(bike->m_afWheelRotationX[1] * vehicleModelInfo->m_fWheelSizeRear)) / 2.0f;
}
else {
CAutomobile * automobile = (CAutomobile *)vehicle;
wheelSpeed = ((automobile->m_fWheelSpeed[0] + automobile->m_fWheelSpeed[1] * vehicleModelInfo->m_fWheelSizeFront) +
(automobile->m_fWheelSpeed[2] + automobile->m_fWheelSpeed[3] * vehicleModelInfo->m_fWheelSizeRear)) / 4.0f;
}
wheelSpeed /= 2.45f; // tweak based in distance
wheelSpeed *= -186.0f; // tweak based in km/h
return wheelSpeed;
}
//const int size = offsetof(CVehicle, m_vehicleAudio);
float deduceEngineRPM(CVehicle *car)
{
float result = car->m_vehicleAudio.field_148;
if (result <= 0)
{
result = 0.0;
}
switch (car->m_pHandlingData->m_transmissionData.m_nEngineType)
{
case 'P':
result += 950.0;
break;
case 'D':
result += 500.0;
break;
case 'E':
result += 1400.0;
break;
default:
break;
}
return result;
}
/////////////// 0054DFB0
void CAutoPosto::frameUpdate()
{
initCarsPool();
if (!gStationsLoaded && ij > 5)
{
ipls << "Num postos: " << postos.size() << std::endl;
for (auto &posto : postos)
{
//ipls << std::to_string(posto.pos.x) + " " + std::to_string(posto.pos.y) + " " + std::to_string(posto.pos.z) << std::endl;
}
//loadGasStations();
gStationsLoaded = true;
//ij = 0;
//gStationsLoaded = false;
ipls.flush();
}
auto playerPos = getPlayerPos();
double closestGasStationDist = 0.0;
int closestGasStation = calcNearestGasStation(playerPos, closestGasStationDist);
for (int i = 0, size = postos.size(); i < size; i++)
{
double rdist = gambi3D::getDistanceBetweenPointsXYZ(postos[i].pos, playerPos);
if (rdist > 120.0)
{
postos[i].destroyActors();
if (rdist > 240.0)
{
postos[i].ok = true;
postos[i].statMsgIsntOk = false;
}
}
else if (rdist < 100.0)
{
postos[i].createActors();
postos[i].checkDeadActors();
postos[i].allActorsAction();
}
if (rdist < 30.0 && !postos[i].ok)
{
if (!postos[i].statMsgIsntOk)
{
showTextBox("Este posto esta fechado para manutencao", 0, 0, 0);
postos[i].statMsgIsntOk = true;
}
}
}
CPool<CAutomobile> *pool = *injector::ReadMemory<CPool<CAutomobile>**>(0x00467C92 + 2);
refreshCarsPool();
auto p = FindPlayerPed(-1);
auto car = p->m_pVehicle;
for (int i = 0; i < pool->m_Size; ++i)
{
int handle = i;
handle <<= 8;
handle |= pool->m_ByteMap[i].a.uID;
auto carStruct = CPool_CVehicle___atHandle(pool, handle);
if (carStruct)
{
auto &apCar = carsPool.m_Objects[i];
if (apCar.flags == 0)
{
apCar.maxgas = defaultMaxGas;
int maxgas = apCar.maxgas * 100.0;
apCar.gas = ((rand() * 100) % maxgas) / 200.0 + apCar.maxgas / 4.0;
apCar.flags |= 1;
}
double speed = deduceEngineRPM(carStruct);
bool engstate = getEngineState(carStruct);
double consgas = 0.0;
const auto &handlg = carStruct->m_pHandlingData->m_transmissionData;
float nitroV = *(float*)(((uintptr_t)(carStruct)) + 0x8A4);
bool nitror = ((carStruct->m_dwHandlingFlags & VEHICLE_HANDLING_NOS_INST) != 0) && nitroV < 0.0;
bool boostLevel1 = (carStruct->m_dwHandlingFlags & VEHICLE_HANDLING_1G_BOOST) != 0;
bool boostLevel2 = (carStruct->m_dwHandlingFlags & VEHICLE_HANDLING_2G_BOOST) != 0;
double boostIncrease = 1.0;
if (boostLevel1)
boostIncrease *= 1.2;
if (boostLevel2)
boostIncrease *= 1.4;
if (engstate)
{
double aproximatedEngineSpeed = 950.0; // RPM
{
aproximatedEngineSpeed;
}
consgas += 0.02;
consgas += abs(carStruct->m_fGasPedal) * 0.2;
if (carStruct->m_fGasPedal != 0.0)
{
double accspd = (handlg.m_fEngineAcceleration) * 30.0;
double partCalc = accspd;
partCalc *= boostIncrease;
if (carStruct->m_nCurrentGear != 0)
{
double airr = carStruct->m_fAirResistance * 1300.0;
double cmass = (carStruct->m_fMass / 1000.0);
partCalc *= cmass * airr;
partCalc *= handlg.m_fCurrentSpeed;
}
consgas += partCalc;
}
if (nitror)
{
consgas *= 1.2;
if (carStruct->m_fGasPedal)
{
consgas *= 1.5;
}
}
}
if (teststruct == carStruct)
{
//teststruct->m_nPrimaryColor = rand() % 64;
//teststruct->m_nSecondaryColor = rand() % 64;
/*uint32_t t = (uint32_t)carStruct;
auto c = (*(uint32_t*)(t + 0x14));
if (c)
{
Rw3D playerpos = *(Rw3D*)(c + 0x30);
gb3d = playerpos;
}*/
//*(uint8_t*)(t + 0x434) = rand() % 64;
// 006D0460 ; signed int __thiscall CTransmissionData__processTransmissionData(CTransmissionData *this)
static char chb[2048] = {0};
float gearSpeed = carStruct->m_pHandlingData->m_transmissionData.m_aGears[1].m_fMaxVelocity * 60;
char buffer[2048] = {0};
float flt_C1CB54 = *(float*)0x00C1CB54;
for (int i = 0; i < 6; i++)
{
auto &g = carStruct->m_pHandlingData->m_transmissionData.m_aGears[i];
sprintf(buffer,
"%d, max v = %3.2f, up at = %3.2f, down at = %3.2f\n",
i,
1.0 / flt_C1CB54 * g.m_fMaxVelocity,
1.0 / flt_C1CB54 * g.m_fChangeUpVelocity,
1.0 / flt_C1CB54 * g.m_fChangeDownVelocity);
}
strcpy(chb, (std::to_string(speed) + " wheel km/h " + std::to_string(/*carStruct->m_fWheelSpeed[2] */gearSpeed)).c_str());
//strcpy(chb, buffer);
textHighPriority(chb, 4500, 0, 0);
}
if (apCar.gas > 0.0)
{
apCar.gas -= consgas;
}
else
{
apCar.gas = 0.0;
setVehEngineState(carStruct, false);
}
apCar.consumo = consgas;
}else
{
carsPool.m_Objects[i].flags = 0;
}
}
/*for (auto &cars : autoPostoData)
{
}*/
CPool<CDummy> *objpool = injector::cstd<CPool<CDummy>*()>::call<0x00404580>();
//CPool<CObject> *pool = *injector::ReadMemory<CPool<CObject>**>(0x005510AC + 1);
auto CModelInfo__GetModelInfo = injector::cstd<void*(char *modelName, int *pIndex)>::call<0x004C5940>;
int id0 = pumpids[0], id1 = pumpids[1], id2 = pumpids[2];
///// 0054CEE5
/*for (int i = 0; i < objpool->m_Size; ++i)
{
const int modelid = objpool->m_Objects[i].m_wModelIndex;
//if (modelid)
// ipls << modelid << std::endl;
//ipls.flush();
if (objpool->GetAt(i) && (modelid == id0 || modelid == id1 || modelid == id2))
{
auto &pos = objpool->m_Objects[i].m_Placement.m_vPosn;
gambi3D pumpPos(pos.x, pos.y, pos.z);
unsigned char *obj = (unsigned char*)objpool->GetAt(i);
//ipls << *(float*)(obj + 340) << std::endl;
}
}*/
++ij;
callGDataScriptFunF();
}
bool CAutoPosto::comparePumpModels(int model)
{
for (auto &m : pumpids)
{
if (m == model)
return true;
}
return false;
}
extern "C" void __declspec(dllexport) getPosXXXX(Rw3D *g)
{
*g = gb3d;
}
extern "C" void __declspec(dllexport) setStructXXX(CVehicle *strc)
{
teststruct = strc;
}
extern "C" void __declspec(dllexport) getCarGasAndMaxGas(int handle, float *g, float *mg)
{
auto &autop = CAutoPosto::p();
hdl = handle >> 8;
auto car = autop.carsPool.GetAt(hdl);
if (car)
{
*g = car->gas;
*mg = car->maxgas;
}
else
{
*g = 0;
*mg = 0;
}
}
extern "C" void __declspec(dllexport) getCarEconometer(int handle, float *ec)
{
auto &autop = CAutoPosto::p();
hdl = handle >> 8;
auto car = autop.carsPool.GetAt(hdl);
if (car)
{
*ec = static_cast<float>(car->consumo);
}
else
{
*ec = 0;
}
}
void CAutoPosto::refreshCarsPool()
{
CPool<CAutomobile> *pool = *injector::ReadMemory<CPool<CAutomobile>**>(0x0055103C + 1);
if (carsPool.m_Size != pool->m_Size)
{
//*(int*)0 = 0; // TODO...
//ipls << " " << carsPool.m_Size << " " << pool->m_Size << std::endl;
}
carsPool.m_Size = pool->m_Size;
carsPool.m_nFirstFree = pool->m_nFirstFree;
carsPool.m_bOwnsAllocations = false;
carsPool.m_ByteMap = pool->m_ByteMap;
}
int CAutoPosto::calcNearestGasStation(const Rw3D &pos, double &dist)
{
int result = -1;
dist = 999999.0;
for (int i = 0, size = postos.size(); i < size; i++)
{
double rdist = gambi3D::getDistanceBetweenPointsXYZ(postos[i].pos, pos);
if (rdist < dist)
{
dist = rdist;
result = i;
}
}
return result;
}
void CAutoPosto::update()
{
p().frameUpdate();
}
void CAutoPosto::initCarsPool()
{
if (!carsPoolInited)
{
CPool<CAutomobile> *pool = *injector::ReadMemory<CPool<CAutomobile>**>(0x0055103C + 1);
carsPool.m_Objects = static_cast<cardata*>(operator new(sizeof(cardata) * pool->m_Size));
carsPool.m_Size = pool->m_Size;
carsPool.m_nFirstFree = pool->m_nFirstFree;
carsPool.m_bOwnsAllocations = false;
carsPool.m_ByteMap = pool->m_ByteMap;
carsPoolInited = true;
}
}
void callback(const GSX::externalCallbackStructure *test)
{
static CPool<CAutomobile> *pool = *injector::ReadMemory<CPool<CAutomobile>**>(0x00467C92 + 2);
using namespace GSX;
if (test->veh)
{
switch (test->status)
{
case GSX::LOAD_CAR:
{
if (dataToLoadExists(test->veh, "autoPostoFuel"))
{
double *autoPostoFuel = (double*)getSavedData(test->veh, "autoPostoFuel");
double *autoMaxPostoFuel = (double*)getSavedData(test->veh, "autoMaxPostoFuel");
int handle = CPool_CVehicle__handleOf(pool, reinterpret_cast<CAutomobile*>(test->veh));
int phandle = handle >> 8;
auto &obj = CAutoPosto::p().carsPool.m_Objects[phandle];
obj.maxgas = defaultMaxGas;
if (autoMaxPostoFuel != nullptr)
{
obj.maxgas = *autoMaxPostoFuel;
}
if (autoPostoFuel != nullptr)
{
obj.maxgas = defaultMaxGas;
obj.gas = min(obj.maxgas, (*autoPostoFuel));
}
else
{
int maxgas = obj.maxgas * 100.0;
obj.gas = ((rand() * 100) % maxgas) / 200.0 + obj.maxgas / 4.0;
obj.gas = min(obj.maxgas, obj.gas);
}
obj.flags |= 1;
}
else
{
int handle = CPool_CVehicle__handleOf(pool, reinterpret_cast<CAutomobile*>(test->veh));
int phandle = handle >> 8;
auto &obj = CAutoPosto::p().carsPool.m_Objects[phandle];
obj.maxgas = defaultMaxGas;
int maxgas = obj.maxgas * 100.0;
obj.gas = ((rand() * 100) % maxgas) / 200.0 + obj.maxgas / 4.0;
obj.gas = min(obj.maxgas, obj.gas);
obj.flags |= 1;
setDataToSaveLater(test->veh, "autoPostoFuel", sizeof(obj.gas), std::addressof(obj.gas), false);
setDataToSaveLater(test->veh, "autoMaxPostoFuel", sizeof(obj.maxgas), std::addressof(obj.maxgas), false);
}
break;
}
case GSX::SAVE_CAR:
{
{
int handle = CPool_CVehicle__handleOf(pool, reinterpret_cast<CAutomobile*>(test->veh));
int phandle = handle >> 8;
auto &obj = CAutoPosto::p().carsPool.m_Objects[phandle];
setDataToSaveLater(test->veh, "autoPostoFuel", sizeof(obj.gas), std::addressof(obj.gas), true);
setDataToSaveLater(test->veh, "autoMaxPostoFuel", sizeof(obj.maxgas), std::addressof(obj.maxgas), true);
}
break;
}
default:
break;
}
}
}
void CAutoPosto::onload(int i)
{
srand(time(0));
ij = 0;
auto CTheScripts__StartNewScript = injector::cstd<CScriptThread *(unsigned char *)>::call<0x00464C20>;
static unsigned char cleoScript[] = { 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0xa5, 0x0a, 0x01, 0x78, 0x56, 0x34, 0x12, 0x04, 0x00, 0x04, 0x00, 0x00, 0xd6, 0x00,
0x04, 0x00, 0x39, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0xfe, 0xff, 0xff,
0xff, 0x12, 0x34, 0x56, 0x78, 0xff, 0xff, 0xff, 0xff, 0x40, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x34, 0x56,
0x78, 0xd6, 0x00, 0x04, 0x00, 0x48, 0x02, 0x03, 0x01, 0x00, 0x4d, 0x00, 0x01, 0x99, 0xff, 0xff, 0xff, 0x9a, 0x00, 0x04,
0x04, 0x03, 0x01, 0x00, 0x03, 0x03, 0x00, 0x03, 0x04, 0x00, 0x03, 0x05, 0x00, 0x03, 0x02, 0x00, 0x02, 0x00, 0x01, 0x92,
0xff, 0xff, 0xff, 0x06, 0x00, 0x03, 0x02, 0x00, 0x04, 0xff, 0x06, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0xa5, 0x0a, 0x03,
0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x39, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00,
0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xd6, 0x00, 0x04, 0x00, 0x6d, 0x05, 0x03, 0x01, 0x00, 0x4d,
0x00, 0x01, 0x50, 0xff, 0xff, 0xff, 0xc2, 0x01, 0x03, 0x01, 0x00, 0x9b, 0x00, 0x03, 0x01, 0x00, 0x06, 0x00, 0x03, 0x00,
0x00, 0x04, 0x00, 0xa5, 0x0a, 0x03, 0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x39, 0x00, 0x03,
0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0xfe, 0xff, 0xff, 0xff, 0x47, 0x02, 0x03, 0x01,
0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0xa5, 0x0a, 0x03, 0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0xd6, 0x00,
0x04, 0x00, 0x39, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0xfe, 0xff, 0xff,
0xff, 0x49, 0x02, 0x03, 0x01, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0xa5, 0x0a, 0x03, 0x1f, 0x00, 0x04, 0x00,
0x04, 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x39, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x03, 0x00, 0x00, 0x02,
0x00, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xd6, 0x00, 0x04, 0x00, 0x18, 0x01, 0x03, 0x01, 0x00, 0x4d, 0x00, 0x01, 0xab, 0xfe,
0xff, 0xff, 0x4f, 0x03, 0x03, 0x01, 0x00, 0x06, 0x00, 0x03, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, 0x01, 0xa4, 0xfe, 0xff,
0xff, 0x06, 0x00, 0x03, 0x02, 0x00, 0x04, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0xa5, 0x0a, 0x03, 0x1f, 0x00,
0x04, 0x00, 0x04, 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x39, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x03, 0x00,
0x00, 0x02, 0x00, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xcd, 0x07, 0x03, 0x01, 0x00, 0x03, 0x03, 0x00, 0x03, 0x04, 0x00, 0x03,
0x05, 0x00, 0x03, 0x06, 0x00, 0x03, 0x07, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0xa5, 0x0a, 0x03, 0x1f, 0x00,
0x04, 0x00, 0x04, 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x39, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4d, 0x00, 0x03, 0x00,
0x00, 0x02, 0x00, 0x01, 0xfe, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0x6a, 0xff, 0xff, 0xff, 0x28, 0xff, 0xff, 0xff,
0xfb, 0xfe, 0xff, 0xff, 0xce, 0xfe, 0xff, 0xff, 0x7c, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x64, 0x20, 0x62, 0x79, 0x20, 0x46, 0x61, 0x62, 0x69, 0x6f, 0x20, 0x41, 0x75, 0x74,
0x6f, 0x50, 0x6f, 0x73, 0x74, 0x6f, 0x52, 0x65, 0x61, 0x6c, 0x69, 0x73, 0x74, 0x61, 0x2e, 0x61, 0x73, 0x69, 0x00 };
static unsigned char searchData[] = { 0xff, 0xff, 0xff, 0xff, 0x12, 0x34, 0x56, 0x78 };
auto &autop = p();
autop.gStationsLoaded = false;
injector::WriteMemory(&cleoScript[9], update);
for (auto &gstation : autop.postos)
{
gstation.actors.clear();
}
//uint64_t *scrpt = reinterpret_cast<uint64_t*>(cleoScript);
uint64_t val = reinterpret_cast<uint64_t>(searchData);
// uint64_t *ptr = std::find(scrpt, scrpt + (sizeof(cleoScript) / sizeof(uint64_t)), val);
// ipls << "ptr " << ptr << " " << *ptr << " " << val << std::endl;
// ptr++;
autop.script = CTheScripts__StartNewScript(cleoScript);
autop.script->IsExternalThread = true;
strcpy(autop.script->threadName, "BMSAPR");
autop.script->baseIp = cleoScript;
int ptr;
memcpy(&ptr, (void*)&cleoScript[41 + 8], sizeof(autop.scriptAddrs));
ptr = abs(ptr);
autop.scriptAddrs = reinterpret_cast<uint32_t*>(autop.script->baseIp + ptr);
static bool callbackAdded = ([]() {
addNotifyCallback(callback);
return true;
})();
}
void CAutoPosto::onsave(int i)
{
//p().iplInstEntities[0].m_pCoords->at.x;
}
CAutoPosto &CAutoPosto::p()
{
static CAutoPosto autoPosto;
return autoPosto;
}
void *orgCall = nullptr;
static void hookLoadGasStations()
{
CAutoPosto::p().loadGasStations();
}
void *retn;
extern "C" void __declspec(naked) hookCall()
{
__asm
{
pop retn
call orgCall
pushad
call hookLoadGasStations
popad
push retn
retn
}
}
extern "C" void __declspec(naked) hookCall2()
{
__asm
{
pushad
call hookLoadGasStations
popad
push orgCall
retn
}
}
void *orgCall2;
int hookfixret = 0;
void hookfix(injector::reg_pack &r)
{
CEntity &a = *(CEntity*)r.ecx;
CEntity &b = *(CEntity*)r.esi;
if (CAutoPosto::p().comparePumpModels(a.m_wModelIndex) && CModelInfo::IsVehicleModelType(b.m_wModelIndex) < 0)
{
hookfixret = 0;
}
else
hookfixret = 1;
}
void *temp;
extern "C" void __declspec(naked) hookCallHookFix()
{
__asm
{
// Construct the reg_pack structure on the stack
pushad // Pushes general purposes registers to reg_pack
add[esp + 12], 4 // Add 4 to reg_pack::esp 'cuz of our return pointer, let it be as before this func is called
pushfd // Pushes EFLAGS to reg_pack
// Call wrapper sending reg_pack as parameter
push esp
call hookfix
add esp, 4
// Destructs the reg_pack from the stack
sub[esp + 12 + 4], 4 // Fix reg_pack::esp before popping it (doesn't make a difference though) (+4 because eflags)
popfd // Warning: Do not use any instruction that changes EFLAGS after this (-> sub affects EF!! <-)
popad
cmp hookfixret, 0
je retnotcall
jmp orgCall2
retnotcall:
retn 0x14
}
}
CAutoPosto::CAutoPosto()
{
srand(time(0));
carsPoolInited = false;
injector::save_manager::on_load(onload);
injector::save_manager::on_save(onsave);
inited = true;
gStationsLoaded = false;
plgPumps = 0.0;
//static const unsigned int ptr = injector::ReadMemory<uint32_t>((0x004057A0 + 1), true);
orgCall = injector::MakeCALL(0x004060DA, hookCall).get();
scriptAddrs = nullptr;
orgCall2 = injector::MakeCALL(0x0054CEE0, hookCallHookFix).get();
//orgCall = injector::MakeCALL(0x00405817, hookCall).get();
//orgCall = injector::MakeCALL(0x0040581D, hookCall2).get();
/*
injector::MakeInline<0x004057A0>([this](injector::reg_pack &r)
{
r.eax = injector::ReadMemory<uint32_t>(ptr);
loadGasStations();
});*/
/*injector::MakeInline<0x005B930F>([this](injector::reg_pack &r)
{
injector::cstd<void(void)>::call<0x00405780>();
loadGasStations();
});*/
}
Esteja a vontade para pegar coisas nele, acho que nunca vou terminar mesmo.
Uma coisa que eu fiz nesse código é um sistema mais ou menos simples de consumo conforme a situação do veículo, está bem simples e não muito real, mas funciona de certa maneira.
Se quiser, pode usar o GSX para salvar o combustível dos carros salvos nas garagens: