Pesquisa resultou em 14 ocorrências

por Fabio
08 Jan 2019, 15:25
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

Re: [Lua]Postos de combustiveis

Um_Geek escreveu:
08 Jan 2019, 15:09
Fabio escreveu:
08 Jan 2019, 03:30
Não testei muito, mas espero que esteja funcionando corretamente: f5-scripts-codigos/t214-gsx-garage-save ... s45#p11572

isto pode ser vir a ser muito útil e fácil de usar.

Sim, só usar a ffi para receber o valor como uint64_t* conferir se não veio um nullptr (se vier um nullptr para a _hash deve ter algum problema no GSX, me avise) e então ler o valor.

:herp:
Lua não vai ter problema com int de 64 bits porque por padrão os valores dela são 64 bits.
por Fabio
08 Jan 2019, 03:30
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

Re: [Lua]Postos de combustiveis

Não testei muito, mas espero que esteja funcionando corretamente: f5-scripts-codigos/t214-gsx-garage-save ... s45#p11572
por Fabio
08 Jan 2019, 01:46
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

Re: [Lua]Postos de combustiveis

Um_Geek escreveu:
07 Jan 2019, 23:36
Fabio escreveu:
07 Jan 2019, 21:39
Um_Geek escreveu:
07 Jan 2019, 18:59
Fabio escreveu:
07 Jan 2019, 17:37
Seria bom se tivesse os logs para que eu pudesse arrumar o GSX.

É um erro raro que da quando o mod solicita informação, provavelmente algo que eu deixei passar ao fazer o mod.

Posso tentar programar o código do GSX nele alguma hora para testar então. :philo:

Ainda acho que deveria ter um mod que adicionasse uma numeração própria no veiculo a primeira vez que ele fosse salvo ou o próprio gsx fazer isto, então uma única função poderia ser usada em diversos mods para pegar este numero.

Por exemplo:
Eu tenho um flash com id A986543EF salvo na garagem da casa da grove e só quero saber se é este carro que estou usando


Vou fazer algo assim.


Um_Geek escreveu:
07 Jan 2019, 18:59
Fabio escreveu:
07 Jan 2019, 17:37
Seria bom se tivesse os logs para que eu pudesse arrumar o GSX.

É um erro raro que da quando o mod solicita informação, provavelmente algo que eu deixei passar ao fazer o mod.

Acabei de pensar uma coisa: Lembrou de testar se não recebeu um nullptr (0) da função? Pode acontecer caso o dado não exista.
por Fabio
07 Jan 2019, 21:39
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

Re: [Lua]Postos de combustiveis

Um_Geek escreveu:
07 Jan 2019, 18:59
Fabio escreveu:
07 Jan 2019, 17:37
Seria bom se tivesse os logs para que eu pudesse arrumar o GSX.

É um erro raro que da quando o mod solicita informação, provavelmente algo que eu deixei passar ao fazer o mod.

Posso tentar programar o código do GSX nele alguma hora para testar então. :philo:
por Fabio
07 Jan 2019, 17:37
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

Re: [Lua]Postos de combustiveis

Um_Geek escreveu:
06 Jan 2019, 14:33
Me disseram que a versão anterior estava dando crash, possivelmente algo ligado ao gsx. como eu sempre arrumava e logo que aparecia outro mod que usa o gsx voltava então achei melhor retirar a opção de salvar combustível nas garagens.

Imagem

https://gta-geek.blogspot.com/2019/01/g ... mples.html

Seria bom se tivesse os logs para que eu pudesse arrumar o GSX.
por Fabio
09 Mai 2018, 13:39
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

Você viu minha mensagem no tópico do GSX? f5-scripts-codigos/t214-gsx-garage-save-extender#p2824


Nesse caso é aceitável você usar a função pushDirectlyToSavedData, não precisa manter alocado memória extra, depois quando precisar atualizar a informação é só chamar ela novamente que o dado anterior será substituído.

Mas em casos onde você realmente possui memória alocada de forma mais ou menos permanente (ou até o carro ser destruído ou salvo), a setDataToSaveLaterVehPtr é a melhor escolha mesmo.

Você pode olhar a solução que eu usei no meu código em C++, onde eu reproduzi o funcionamento da pool de veículos do jogo, mas com dados que eu escolhi, assim a handle dos carros do jogo pode ser usada na pool que eu fiz. Assim sendo, vai existir dados alocados em posições permanentes e úteis.
por Fabio
02 Mai 2018, 13:47
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

ceec escreveu: Diesel tem uma explosão mais forte

https://en.wikipedia.org/wiki/Energy_density

Foi o que eu disse, diesel possui mais energia concentrada.

ceec escreveu:
02 Mai 2018, 13:43
isso gera torque em baixa rotação

Nem tem muito como alcançar altas rotações com diesel, a taxa de expansão é bem maior que a da gasolina.
por Fabio
02 Mai 2018, 13:39
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

Um_Geek escreveu: Talvez o consumo eu deixe para o jogador mesmo definir, o handling do jogo não tem nenhum parâmetro confiável para estimar consumo de combustível, por exemplo peso e velocidade máxima comparando a dozer e o rdtrain, a dozer não andaria 1km por litro, alem de no jogo ter carros movido a energia pelo que vi a um tempo.

São a diesel, diesel oferece mais energia por ml @_@
Mas sim, existem veículos que fazem 1/1km, geralmente aqueles ônibus super pesados.


Um_Geek escreveu: Da para por para todos os carros do jogo usarem o sistema de combustível, no entanto isto obrigaria a todos terem que irem no posto, o que causaria entupimento nos postos ou com um tempo de jogo veículos parados por todo canto. Então como o player não tem como saber a quantidade que aquele veiculo tem isto só passa a ser valido depois dele entrar nele uma vez, isto vale para todos os carros e até mais de 1 por vez.

Ao menos daria mais vida ao jogo :fts:

Com uma quantia mínima no sistema aleatório fica difícil o tráfego ficar sem combustível tão rápido, a menos que o player passe a seguir sem parar, já que eles dão despawn rapidamente.
por Fabio
02 Mai 2018, 02:08
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

Junior_Djjr escreveu: Se bobear gastava até por deixar o carro parado desligado durante meses :fts:

Eu não tinha pensado nisso, mas é uma ideia. :5!!: :5!!: :5!!:

Se for a gasolina pior ainda, pois a gasolina envelhece com o tempo.
por Fabio
02 Mai 2018, 01:55
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

Junior_Djjr escreveu: O código do Fabio tinha cálculo de consumo até pelo uso do nitro :feel:

E uma dedução de consumo pelos atributos de handling do carro. :herp:

Inclusive, todos os carros do jogo trabalham no sistema de combustível realista, ou seja, é possível você ver carros ficando sem combustível depois de algum tempo. :fts:
por Fabio
29 Abr 2018, 20:31
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

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:
por Fabio
28 Abr 2018, 23:27
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

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:
por Fabio
28 Abr 2018, 23:21
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

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.
por Fabio
28 Abr 2018, 22:42
Fórum: Scripts & Códigos
Tópico: [Lua]Postos de combustiveis
Respostas: 80
Exibições: 13841
Gênero:

[Lua]Postos de combustiveis

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)

Voltar para “[Lua]Postos de combustiveis”