No momento não posso pegar mais nenhum projeto pra tentar fazer porque quero concluir os inacabados. Mas aqui está uma parte do protótipo abandonado do Auto Posto Realista, fiz um código nele que pega as bombas de combustível do jogo e monta um pequeno banco sobre elas, o código deve ajudar nisso.
Código: Selecionar tudo
/*
Fix para o parser do fórum achando que isso é php
*/
void *coisaquenaodeveriaestaraqui = nullptr;
struct naoexiste
{
void *a;
int b;
float c;
double d;
};
std::string ehnaodeuprafixar;
#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();
});*/
}[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]