Página 1 de 6

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 21:34
por Um_Geek
Beta (0.0.2)

Imagem

Este mod ira adicionar postos de combustível ao jogo através dos modelos das bombas, ou seja. ele ira pegar as bombas de combustíveis e tornar uma areá onde possa abastecer o veiculo.

Características do mod
  • Dois tipos de contador, um com contador giratório e outro por barra.
  • Possibilidade de escolher posição do contador na tela.
  • Possibilidade de ajustar o tamanho do contador giratório na tela.
  • Veículos com tamanhos de tanque diferente.
  • Possibilidade de definir gasto customizado.
  • Possibilidade de definir consumo individual de cada veiculo.
  • Consumo variável de acordo com os eventos de troca de marcha, uso de nitro e trailer.
  • Galão de transporte de combustível (arma).
  • Possibilidade de escolher id da arma galão de combustível.
  • Possibilidade de escolher capacidade do galão.
  • GSX.ASI, Salva combustível no tanque ao deixar o veiculo em garagem (agradecimentos ao fabio que ajudou com o uso do gsx).
  • Possibilidade de desativar uso do gsx.asi. (o mod não ira crashar se não encontrar o gsx.asi)
  • PETROTR. Trailer de transporte de combustível funciona com uma estação móvel de abastecimento.
  • Possibilidade de adicionar um veiculo tanquer adicional.
  • Fix em veículos. Ao deixar o veiculo ligado encontrara ligado, ao deixar desligado encontra desligado.
  • Botões e teclas configuráveis.
  • Postos de combustíveis no radar ao se aproximar.

Em andamento
  • Adicionando funcionamento motos.
  • Vendo se é possível salvar combustível de trailers.

Pode saber se ouve algum problema com o script facilmente se sair do veiculo e marcas dos postos continuarem, por padrão elas não ficam no mapa para não serem salvas, então se perceber isto informe.

Pagina do Download

Correções:
  • Corrigido diferença de gasto de combustível aumentando com fps alto. (relatado por Stealth760)

Qualquer problema encontrado informa, não farei atualização de novas funções por tempo, mas irei corrigir bugs e outros problemas.


Atualizações - 23 Jul 2019

Algumas funções do mod que apresentavam bugs tiveram que serem removidas, ainda com o tempo estou readicionando cada umas. Devido as limitações de icones no radar não esta mostrando os icones dos postos (Que poderia se colocado no próprio mod que adiciona ícones)

Para instalar esta versão, não pode ter outro mod de posto de combustíveis no jogo, isto ira causar conflitos.

Melhorias
  • O mod esta mais organizado, script mais simples.
  • Podera ter atualizações de funções no mod simplesmente as soltando na pasta 'xoomer'
  • Possibilidade de usar diferentes mostradores
  • Mostrador barra e de ponteiro opcional
  • interface imgui para configurar custo individual de cada veiculo. (use o cheat 'XOO')

Imagem

Postos de combustivel Xoomer.rar
(127.87 KiB) Baixado 436 vezes

Galão de combustiveis
SpoilerAbrir
Ainda estou testando. Não possui animações ou sons.
Necessário ir na pasta 'moonloader/xoomer' e tirar o ponto do arquivo .xoomer_galon.lua

Coloque o modelo do galão na pasta do modloader. embora substitui uma arma, pode por como objeto e mudar o id no topo do script.

gun_dildo1 (galão de combustivel).rar
(94.3 KiB) Baixado 349 vezes

Use G + L para ativar, L ou G desativa.

Futuras atualizações e detalhes no meu workshop.

Tanque de transporte de combustível
SpoilerAbrir
Com este script estando conduzindo um tanque de combustível estando no caminhão é possível abastecer um veiculo que esteja parado atras do mesmo.

Nesta versão 'YES' coloca combustível 'NO' retira

Copie o arquivo petrotr_2.lua para a pasta moonloader/xoomer

Imagem

petrotr_2.rar
(932 Bytes) Baixado 322 vezes

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 22:34
por M3h
O combustível dos carros que a gente pega na rua é aleatório ou funciona como no SAMP?

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 22:38
por Um_Geek
E aleatório, mas tem uma quantidade minima para não pegar um carro com tanque quase zerado, se largar o carro e voltar ele tera a mesma quantidade que deixou tambem. se eu conseguir terá como comprar a combustível para transportar como reserva.

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 22:42
por Fabio
Bem interessante, fiz algo parecido no source desse Auto Posto:

.h

Código: Selecionar tudo

#pragma once
#ifndef CAUTOPOSTO_H
#define CAUTOPOSTO_H

#include "saving.hpp"
#include <map>
#include <unordered_map>
#include <deque>
#include "script.h"
#include <injector\injector.hpp>
#include <injector\assembly.hpp>
#include <injector\calling.hpp>
#include <game_sa\CEntity.h>
#include <functional>
#include <memory>
#include <algorithm>
#include <game_sa\CPool.h>
#include <game_sa\CDummy.h>
#include <game_sa\CObject.h>
#include <game_sa\CVehicle.h>
#include <game_sa\CPed.h>
#include <game_sa\CAutomobile.h>
#include <vector>
#include <game_sa\CModelInfo.h>

static auto FindPlayerPed = injector::cstd<CPed*(int32_t)>::call<0x0056E210>;
static auto getGamePanelActiveRow = injector::cstd <char(unsigned __int8 a1)>::call<0x005807E0>;
static auto getGamePanelSelectedRow = injector::cstd <char(unsigned __int8 a1)>::call<0x005807C0>;
static auto removeGamePanel = injector::cstd <char(unsigned __int8 a1)>::call<0x00580750>;
static auto textLowPriority = injector::cstd <void(const char *text, unsigned time, bool flag1, bool flag2)>::call<0x00580750>;
static auto textHighPriority = injector::cstd <void(const char *text, unsigned time, bool flag1, bool flag2)>::call<0x0069F0B0>;
static auto CStreaming__RequestModel = injector::cstd <char(int, int)>::call<0x004087E0>;
static auto showTextBox = injector::cstd<char(const char *, char, char, char)>::call<0x00588BE0>;
static auto CWorld__destroyPed = injector::cstd<int(uintptr_t)>::call<0x00486240>; // //00486240     ; int __cdecl CWorld::destroyPed(CPed *ped)
static auto CRadar__SetEntityBlip = injector::cstd<DWORD(int, int, unsigned int, int, char *)>::call<0x005839A0>;
static auto CRadar__ChangeBlipScale = injector::cstd<signed int(int a1, __int16 a2)>::call<0x00583CC0>;
static auto CPool_CVehicle___atHandle = injector::thiscall<CAutomobile *(void *, DWORD handle)>::call<0x004048E0>;
static auto CRunningScript__Process = injector::thiscall<bool(CScriptThread *)>::call<0x00469F00>;
static auto CPool_CVehicle__handleOf = injector::thiscall<int(void *, CAutomobile *)>::call<0x00424160>;

struct vec3dd
{
	double x, y, z;
};

struct Rw3D
{
	float x, y, z;
};

inline static Rw3D getPlayerPos()
{
	uint32_t player = (uint32_t)FindPlayerPed(-1);

	Rw3D playerpos = *(Rw3D*)((*(uint32_t*)(player + 0x14)) + 0x30);

	return playerpos;
}

struct gambi3D
{
	double x, y, z;

	gambi3D()
	{
		x = y = z = 0.0;
	}

	gambi3D(double px, double py, double pz)
	{
		x = px;
		y = py;
		z = pz;
	}

	gambi3D(const Rw3D &c)
	{
		x = c.x;
		y = c.y;
		z = c.z;
	}

	gambi3D(const CVector &c)
	{
		x = c.x;
		y = c.y;
		z = c.z;
	}

	operator Rw3D()
	{
		Rw3D r;
		r.x = x;
		r.y = y;
		r.z = z;

		return r;
	}

	gambi3D &operator-=(const gambi3D &g)
	{
		x -= g.x;
		y -= g.y;
		z -= g.z;

		return *this;
	}

	gambi3D operator-(const gambi3D &g) const
	{
		gambi3D g0 = *this;

		g0.x -= g.x;
		g0.y -= g.y;
		g0.z -= g.z;

		return g0;
	}

	static inline double getDistanceBetweenPointsXYZ(const gambi3D &d0, const gambi3D &d1)
	{
		gambi3D data = d0 - d1;

		data.x = pow(data.x, 2.0);
		data.y = pow(data.y, 2.0);
		data.z = pow(data.z, 2.0);

		return sqrt(data.x + data.y + data.z);
	}

	static inline double getDistanceBetweenPointsXY(const gambi3D &d0, const gambi3D &d1)
	{
		gambi3D data = d0 - d1;

		data.x = pow(data.x, 2.0);
		data.y = pow(data.y, 2.0);

		return sqrt(data.x + data.y);
	}

	static inline double getDistanceBetweenPointsXZ(const gambi3D &d0, const gambi3D &d1)
	{
		gambi3D data = d0 - d1;

		data.x = pow(data.x, 2.0);
		data.z = pow(data.z, 2.0);

		return sqrt(data.x + data.z);
	}


	static inline double getDistanceBetweenPointsYZ(const gambi3D &d0, const gambi3D &d1)
	{
		gambi3D data = d0 - d1;

		data.y = pow(data.y, 2.0);
		data.z = pow(data.z, 2.0);

		return sqrt(data.y + data.z);
	}
};

class CAutoPosto
{
	friend class posto;
	class posto;

	struct cbStruct
	{
		CAutoPosto::posto *gassStat;
		//CScriptThread *scrptAP;
		int pumpID;
		int scriptActionID;
		int pActorID;
		std::vector<SCRIPT_VAR> dataPack;
	};

	std::deque< cbStruct > cbPool;

	CScriptThread *script;

	uint32_t *scriptAddrs;

	void checkAcScriptData();

	void callGDataScriptFun(int funid, const std::vector<SCRIPT_VAR> &dataPack);
	void callGDataScriptFunF();

	void frameUpdate();
	static void update();

	bool inited;

	bool gStationsLoaded;

	void initCarsPool();
	void refreshCarsPool();

	static void scriptCallBack();

public:
	void loadGasStations();

	struct actorData
	{
		int action;
		int modelID;
		unsigned int handle;

		actorData()
		{
			action = 0;
			modelID = handle = 0;
		}

		actorData(unsigned int hd)
		{
			action = 0;
			handle = hd;
			modelID = 0;
		}
	};

	struct cardata
	{
		double gas, maxgas, consumo;
		int flags;

		inline cardata()
		{
			maxgas = 60.0;
			gas = 10.0;
			flags = 0;
			consumo = 0;
		}
	};

	struct pumpdata{
		Rw3D at;
		int modelID;

	};

	class posto
	{

	public:
		gambi3D pos;
		int type;
		bool ok, statMsgIsntOk;
		std::vector < actorData > actors;
		std::deque< pumpdata > pumps;

		int calcNearestPump(const Rw3D &pos, double &dist);

		void checkDeadActors();
		void destroyActors();
		void createActors();
		void allActorsAction();
		void actorWalkTo(int acttorIndex, const Rw3D &pos, float angle, float radius);

		inline posto()
		{
			pos.x = pos.y = pos.z = 0.0;
			type = 0;
			ok = true;
			statMsgIsntOk = false;
		}
	};

	inline bool init()
	{
		return inited;
	}

	double plgPumps;

	bool carsPoolInited;
	CPool < cardata > carsPool;
	std::vector < posto > postos;

	std::deque < int > pumpids;

	bool comparePumpModels(int model);

	int calcNearestGasStation(const Rw3D &pos, double &dist);

	static void onload(int i);
	static void onsave(int i);

	static CAutoPosto &p();

private:
	CAutoPosto(CAutoPosto&) = delete;
	CAutoPosto(CAutoPosto&&) = delete;
	CAutoPosto();
};

#endif

.cpp

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. :fts:



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: f5-scripts-codigos/t214-gsx-garage-save-extender#p1391 (existe meio que um protótipo dessa funcionalidade no source acima)

http://brmodstudio.forumeiros.com/t6959 ... nte#267755 (no post desse link tem um teste compilado do código acima)

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 22:59
por M3h
Um_Geek escreveu: E aleatório, mas tem uma quantidade minima para não pegar um carro com tanque quase zerado, se largar o carro e voltar ele tera a mesma quantidade que deixou tambem. se eu conseguir terá como comprar a combustível para transportar como reserva.
Com isso, já supera muitos mods de consumo de gasolina que tem poraí
 
Fabio escreveu: [i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i]Uma coisa que eu fiz nesse código é um sistema mais ou menos simples de consumo conforme a situação do veículo[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]
Isso seria muito interessante, talvez também mais simples alterar o modo de consumo de acordo com o modelo do veículo.
Fazer os dois seria bacana

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 23:21
por Fabio
M3h escreveu:
Fabio escreveu: [i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i]Uma coisa que eu fiz nesse código é um sistema mais ou menos simples de consumo conforme a situação do veículo[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]
Isso seria muito interessante, talvez também mais simples alterar o modo de consumo de acordo com o modelo do veículo.
Fazer os dois seria bacana

Além de outras coisas que se integram a isso, como por exemplo o consumo mínimo se o carro estiver ligado sem fazer nada, ou então consumir mais se tiver acelerando muito, em subidas, etc.

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 23:24
por Um_Geek
Fabio escreveu: Bem interessante, fiz algo parecido no source desse Auto Posto:

Faz tempo que espero este mod sair e nem sabia que seria em asi, se concluir sera bem legal. Não entendo muito de c++, mas verei se consigo usar algo, principalmente o gsx para salvar o combustível.

[Lua]Postos de combustiveis

Enviado: 28 Abr 2018, 23:27
por Fabio
Um_Geek escreveu:
Fabio escreveu: Bem interessante, fiz algo parecido no source desse Auto Posto:

Faz tempo que espero este mod sair e nem sabia que seria em asi, se concluir sera bem legal. Não entendo muito de c++, mas verei se consigo usar algo, principalmente o gsx para salvar o combustível.

Seria, mas eu fiquei com uma enorme preguiça de terminar quando notei que os actors estavam fazendo tudo explodir as vezes. :fts:

[Lua]Postos de combustiveis

Enviado: 29 Abr 2018, 18:06
por Um_Geek
Fabio escreveu: Seria, mas eu fiquei com uma enorme preguiça de terminar quando notei que os actors estavam fazendo tudo explodir as vezes. :fts:

Não teria como desativar as bombas de combustível de explodirem? De qualquer forma não farei algo grande porque se tu terminar este em asi sera de melhor escolha.


Coloquei do veiculo perder combustível se esquecer ele ligado, então se deixar o carro ligado e demorar voltar pode o encontrar de tanque vazio :herp:

o Hue uma vez deu uma dica sobre empurrar veículos leves, talvez eu também coloque junto.

[Lua]Postos de combustiveis

Enviado: 29 Abr 2018, 20:31
por Fabio
Um_Geek escreveu:
Fabio escreveu: Seria, mas eu fiquei com uma enorme preguiça de terminar quando notei que os actors estavam fazendo tudo explodir as vezes. :fts:

Não teria como desativar as bombas de combustível de explodirem? De qualquer forma não farei algo grande porque se tu terminar este em asi sera de melhor escolha.

Acredito que sim, deve ser só uma flag na linha do IDE. :herp:

Vou ver o que posso fazer então, talvez mudar o sistema que estava controlando os actors também, me parece bem gambiarra de certa forma.

Um_Geek escreveu:
29 Abr 2018, 18:06
Coloquei do veiculo perder combustível se esquecer ele ligado, então se deixar o carro ligado e demorar voltar pode o encontrar de tanque vazio :herp:

:herp:

[Lua]Postos de combustiveis

Enviado: 29 Abr 2018, 21:03
por Stealth760
Caramba vai ser bem completo esse mod.
Se algum dia lançar vai pra minha pasta "coisas que nao podem faltar no gta", na internet tem varios mas duvido que algum seja realmente bem feito.

[Lua]Postos de combustiveis

Enviado: 01 Mai 2018, 11:23
por Um_Geek
Imagem

Fase 1 pronta (funcionalidade), agora indo para parte de da mais vida aos postos.


Stealth760 escreveu: Caramba vai ser bem completo esse mod.
Se algum dia lançar vai pra minha pasta "coisas que nao podem faltar no gta", na internet tem varios mas duvido que algum seja realmente bem feito.
Não sei se ficara tão bom assim, mas vai ter o básico.

[Lua]Postos de combustiveis

Enviado: 01 Mai 2018, 14:43
por Junior_Djjr
MUITA gente quer mods assim. Foi quase uma BMS Sound na época que foi anunciado a ideia antiga.

[Lua]Postos de combustiveis

Enviado: 01 Mai 2018, 14:47
por VtrVictor
Um_Geek escreveu: Imagem

Fase 1 pronta (funcionalidade), agora indo para parte de da mais vida aos postos.
Isso foi incrível, de longe já esta melhor que todos os mods de posto que vi ate hoje.

Vou dar uma ideia, poderia ser interessante se fosse possível por .ini escolher o consumo dos carros por id, assim com a ajuda de muitos fosse escolhido o consumo de cada carro analisando a aceleração e velocidade, porem pode ser complicado isso ou não. 

[Lua]Postos de combustiveis

Enviado: 01 Mai 2018, 15:45
por Junior_Djjr
O código do Fabio tinha cálculo de consumo até pelo uso do nitro  :feel: