add invisible water, no water, disable hydrant improvements

This commit is contained in:
Grinch_ 2021-08-28 09:12:20 +06:00
parent bd75524368
commit c0869efcae
9 changed files with 452 additions and 315 deletions

225
src/FileHandler.cpp Normal file
View File

@ -0,0 +1,225 @@
#include "pch.h"
#include "FileHandler.h"
#include "Visual.h"
// TODO: Clean up this mess, use structures instead?
void FileHandler::GenerateHandlingFile(int pHandling, std::map<int, std::string>& storeMap)
{
FILE* fp = fopen("handling.txt", "w");
std::string handlingId = storeMap[FindPlayerPed()->m_pVehicle->m_nModelIndex];
float fMass = patch::Get<float>(pHandling + 0x4);
float fTurnMass = patch::Get<float>(pHandling + 0xC);
float fDragMult = patch::Get<float>(pHandling + 0x10);
float CentreOfMassX = patch::Get<float>(pHandling + 0x14);
float CentreOfMassY = patch::Get<float>(pHandling + 0x18);
float CentreOfMassZ = patch::Get<float>(pHandling + 0x1C);
int nPercentSubmerged = patch::Get<int>(pHandling + 0x20);
float fTractionMultiplier = patch::Get<float>(pHandling + 0x28);
float fTractionLoss = patch::Get<float>(pHandling + 0xA4);
float TractionBias = patch::Get<float>(pHandling + 0xA8);
float fEngineAcceleration = patch::Get<float>(pHandling + 0x7C) * 12500;
float fEngineInertia = patch::Get<float>(pHandling + 0x80);
int nDriveType = patch::Get<BYTE>(pHandling + 0x74);
int nEngineType = patch::Get<BYTE>(pHandling + 0x75);
float BrakeDeceleration = patch::Get<float>(pHandling + 0x94) * 2500;
float BrakeBias = patch::Get<float>(pHandling + 0x98);
int ABS = patch::Get<BYTE>(pHandling + 0x9C);
float SteeringLock = patch::Get<float>(pHandling + 0xA0);
float SuspensionForceLevel = patch::Get<float>(pHandling + 0xAC);
float SuspensionDampingLevel = patch::Get<float>(pHandling + 0xB0);
float SuspensionHighSpdComDamp = patch::Get<float>(pHandling + 0xB4);
float Suspension_upper_limit = patch::Get<float>(pHandling + 0xB8);
float Suspension_lower_limit = patch::Get<float>(pHandling + 0xBC);
float Suspension_bias = patch::Get<float>(pHandling + 0xC0);
float Suspension_anti_dive_multiplier = patch::Get<float>(pHandling + 0xC4);
float fCollisionDamageMultiplier = patch::Get<float>(pHandling + 0xC8) * 0.338;
int nMonetaryValue = patch::Get<int>(pHandling + 0xD8);
int MaxVelocity = patch::Get<float>(pHandling + 0x84);
MaxVelocity = MaxVelocity * 206 + (MaxVelocity - 0.918668) * 1501;
int modelFlags = patch::Get<int>(pHandling + 0xCC);
int handlingFlags = patch::Get<int>(pHandling + 0xD0);
int front_lights = patch::Get<BYTE>(pHandling + 0xDC);
int rear_lights = patch::Get<BYTE>(pHandling + 0xDD);
int vehicle_anim_group = patch::Get<BYTE>(pHandling + 0xDE);
int nNumberOfGears = patch::Get<BYTE>(pHandling + 0x76);
float fSeatOffsetDistance = patch::Get<float>(pHandling + 0xD4);
// TODO: make this more readable
fprintf(
fp,
"\n%s\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%d\t%.5g\t%.5g\t%.5g\t%d\t%d\t%.5g\t%.5g\t%c\t%c\t%.5g\t%.5g\t%d\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%d\t%d\t%d\t%d\t%d\t%d",
handlingId.c_str(), fMass, fTurnMass, fDragMult, CentreOfMassX, CentreOfMassY, CentreOfMassZ, nPercentSubmerged,
fTractionMultiplier, fTractionLoss, TractionBias, nNumberOfGears,
MaxVelocity, fEngineAcceleration, fEngineInertia, nDriveType, nEngineType, BrakeDeceleration, BrakeBias, ABS,
SteeringLock, SuspensionForceLevel, SuspensionDampingLevel,
SuspensionHighSpdComDamp, Suspension_upper_limit, Suspension_lower_limit, Suspension_bias,
Suspension_anti_dive_multiplier, fSeatOffsetDistance,
fCollisionDamageMultiplier, nMonetaryValue, modelFlags, handlingFlags, front_lights, rear_lights,
vehicle_anim_group);
fclose(fp);
}
void FileHandler::FetchColorData(std::vector<std::vector<float>>& storeVec,
std::map<std::string, std::vector<int>>& storeMap)
{
std::string m_FilePath = GAME_PATH((char*)"/data/carcols.dat");
if (std::filesystem::exists(m_FilePath))
{
std::ifstream file(m_FilePath);
std::string line;
bool bIsCar = false;
bool bIsCol = false;
int nLineCount = 0;
while (getline(file, line))
{
// skip commented & emety lines
if (line[0] == '#' || line == "")
{
continue;
}
// section blocks
if (line[0] == 'c' && line[1] == 'a' && line[2] == 'r')
{
bIsCar = true;
continue;
}
if (line[0] == 'c' && line[1] == 'o' && line[2] == 'l')
{
bIsCol = true;
continue;
}
if (line[0] == 'e' && line[1] == 'n' && line[2] == 'd')
{
bIsCar = false;
bIsCol = false;
continue;
}
if (bIsCol)
{
try
{
std::string temp;
std::stringstream ss(line);
// fix one instance where . is used instead of ,
std::replace(temp.begin(), temp.end(), '.', ',');
// Format: red, green, blue
int r,g,b;
getline(ss, temp, ',');
r = std::stoi(temp);
getline(ss, temp, ',');
g = std::stoi(temp);
getline(ss, temp, ',');
b = std::stoi(temp);
storeVec.push_back({r / 255.0f, g / 255.0f, b / 255.0f});
++nLineCount;
}
catch (...)
{
flog << "Error parsing carcols.dat, " << line << std::endl;
}
}
if (bIsCar)
{
std::string temp;
std::stringstream ss(line);
// Format: modelname, colorindex1, colorindex2,...
getline(ss, temp, ',');
std::string name = temp;
while (getline(ss, temp, ','))
{
try
{
std::for_each(name.begin(), name.end(), [](char& c)
{
c = ::toupper(c);
});
int val = std::stoi(temp);
if (!(std::find(storeMap[name].begin(), storeMap[name].end(), val) !=
storeMap[name].end()))
{
storeMap[name].push_back(val);
}
}
catch (...)
{
flog << "Error parsing carcols.dat, " << line << std::endl;
}
}
}
}
file.close();
}
else
{
flog << "Carcols.dat not found";
}
}
void FileHandler::FetchHandlingID(std::map<int, std::string>& storeMap)
{
std::string m_FilePath = GAME_PATH((char*)"/data/vehicles.ide");
if (std::filesystem::exists(m_FilePath))
{
std::ifstream file(m_FilePath);
std::string line;
while (getline(file, line))
{
/*
Format: model, modelname, txdname, type, handlingId, ...
Skip if first thing isn't model id
*/
if (line[0] <= '0' || line[0] >= '9')
{
continue;
}
// running inside try block to handle user errors, mostly commas
try
{
std::string temp;
std::stringstream ss(line);
// get model
getline(ss, temp, ',');
int model = std::stoi(temp);
// get modelname, txd, type, handlingId
getline(ss, temp, ',');
getline(ss, temp, ',');
getline(ss, temp, ',');
getline(ss, temp, ',');
temp.erase(std::remove_if(temp.begin(), temp.end(), ::isspace), temp.end());
storeMap[model] = temp;
}
catch (...)
{
flog << "Error parsing vehicles.ide, " << line << std::endl;
}
}
file.close();
}
else
{
flog << "Vehicle.ide not found";
}
}

25
src/FileHandler.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <map>
#include <vector>
#include <string>
class FileHandler
{
public:
FileHandler() = delete;
FileHandler(FileHandler&) = delete;
/*
Parses data/carcols.dat file and stores color data per vehicle
TODO: Implement something that also parses modloader data
*/
static void FetchColorData(std::vector<std::vector<float>>& storeVec,
std::map<std::string, std::vector<int>>& storeMap);
/*
Parses data/vehicles.ide file and stores handingId in a map
TODO: Implement something that also parses modloader data
*/
static void FetchHandlingID(std::map<int, std::string>& storeMap);
static void GenerateHandlingFile(int pHandling, std::map<int, std::string>& storeMap);
};

View File

@ -249,27 +249,30 @@ void Player::ChangePlayerCloth(std::string& name)
std::string model = temp.c_str();
getline(ss, temp, '$');
std::string texture9 = temp.c_str();
std::string texName = temp.c_str();
CPlayerPed* player = FindPlayerPed();
if (texture9 == "cutoffchinosblue")
if (texName == "cutoffchinosblue")
{
player->m_pPlayerData->m_pPedClothesDesc->SetTextureAndModel(-697413025, 744365350, body_part);
}
else
{
if (texture9 == "sneakerbincblue")
if (texName == "sneakerbincblue")
{
player->m_pPlayerData->m_pPedClothesDesc->SetTextureAndModel(-915574819, 2099005073, body_part);
}
else
{
if (texture9 == "12myfac")
if (texName == "12myfac")
{
player->m_pPlayerData->m_pPedClothesDesc->SetTextureAndModel(-1750049245, 1393983095, body_part);
}
else
player->m_pPlayerData->m_pPedClothesDesc->
SetTextureAndModel(texture9.c_str(), model.c_str(), body_part);
{
player->m_pPlayerData->m_pPedClothesDesc->SetTextureAndModel(texName.c_str(), model.c_str(), body_part);
}
}
}
CClothes::RebuildPlayer(player, false);

View File

@ -59,7 +59,7 @@ void ResourceStore::LoadTextureResource(std::string&& name)
pEndDic = (RwTexDictionary*)pRLL->link.next;
RwTexture *pTex = (RwTexture*)&pRLL[-1];
m_ImagesList.push_back(std::make_unique<STextureResource>());
m_ImagesList.push_back(std::make_unique<TextureResource>());
m_ImagesList.back().get()->m_pRwTexture = pTex;
// Fetch IDirec9Texture9* from RwTexture*

View File

@ -28,7 +28,7 @@ struct RwRasterEx : public RwRaster
RwD3D9Raster *m_pRenderResource;
};
struct STextureResource
struct TextureResource
{
std::string m_FileName;
std::string m_CategoryName;
@ -43,7 +43,7 @@ enum eResourceType
TYPE_BOTH,
};
using TextureResourceList = std::vector<std::unique_ptr<STextureResource>>;
using TextureResourceList = std::vector<std::unique_ptr<TextureResource>>;
class ResourceStore
{
private:

View File

@ -3,6 +3,7 @@
#include "Menu.h"
#include "Ui.h"
#include "Util.h"
#include "FileHandler.h"
#include <CPopulation.h>
#include <CDamageManager.h>
@ -31,15 +32,15 @@ void Vehicle::FixVehicle(CVehicle *pVeh)
Vehicle::Vehicle()
{
#ifdef GTASA
ParseVehiclesIDE();
FileHandler::FetchHandlingID(m_VehicleIDE);
#endif
ParseCarcolsDAT();
FileHandler::FetchColorData(m_CarcolsColorData, m_CarcolsCarData);
Events::processScriptsEvent += [this]
{
uint timer = CTimer::m_snTimeInMilliseconds;
CPlayerPed* pPlayer = FindPlayerPed();
CVehicle* pVeh = pPlayer->m_pVehicle;
CVehicle* pVeh = FindPlayerVehicle(-1, false);
if (pPlayer && pVeh)
{
@ -159,13 +160,19 @@ Vehicle::Vehicle()
int chance = 0;
if (veh->m_nVehicleClass == CLASS_NORMAL) // Normal
{
chance = Random(1, 20);
}
if (veh->m_nVehicleClass == CLASS_RICHFAMILY) // Rich family
{
chance = Random(1, 4);
}
if (veh->m_nVehicleClass == CLASS_EXECUTIVE) // Executive
{
chance = Random(1, 3);
}
if (chance == 1 && !IsNeonInstalled(veh) && veh->m_pDriver != pPlayer)
{
@ -228,7 +235,9 @@ void Vehicle::RemoveComponent(const std::string& component, const bool display_m
player->m_pVehicle->RemoveVehicleUpgrade(icomp);
if (display_message)
{
SetHelpMessage("Component removed", false, false, false);
}
}
catch (...)
{
@ -267,220 +276,8 @@ int Vehicle::GetRandomTrainIdForModel(int model)
int id = Random(_start, _end);
return train_ids[id];
}
// Get vehicle HandlingId
void Vehicle::ParseVehiclesIDE()
{
std::string m_FilePath = std::string(paths::GetGameDirPathA()) + "/data/vehicles.ide";
if (fs::exists(m_FilePath))
{
std::ifstream file(m_FilePath);
std::string line;
while (getline(file, line))
{
if (line[0] <= '0' || line[0] >= '9')
{
continue;
}
try
{
std::string temp;
std::stringstream ss(line);
// model
getline(ss, temp, ',');
int model = std::stoi(temp);
// modelname, txd, type, handlingId
getline(ss, temp, ',');
getline(ss, temp, ',');
getline(ss, temp, ',');
getline(ss, temp, ',');
temp.erase(std::remove_if(temp.begin(), temp.end(), ::isspace), temp.end());
m_VehicleIDE[model] = temp;
}
catch (...)
{
flog << "Error while parsing line, " << line << std::endl;
}
}
file.close();
}
else flog << "Vehicle.ide file not found";
}
void Vehicle::GenerateHandlingDataFile(int phandling)
{
FILE* fp = fopen("handling.txt", "w");
std::string handlingId = m_VehicleIDE[FindPlayerPed()->m_pVehicle->m_nModelIndex];
float fMass = patch::Get<float>(phandling + 0x4);
float fTurnMass = patch::Get<float>(phandling + 0xC);
float fDragMult = patch::Get<float>(phandling + 0x10);
float CentreOfMassX = patch::Get<float>(phandling + 0x14);
float CentreOfMassY = patch::Get<float>(phandling + 0x18);
float CentreOfMassZ = patch::Get<float>(phandling + 0x1C);
int nPercentSubmerged = patch::Get<int>(phandling + 0x20);
float fTractionMultiplier = patch::Get<float>(phandling + 0x28);
float fTractionLoss = patch::Get<float>(phandling + 0xA4);
float TractionBias = patch::Get<float>(phandling + 0xA8);
float fEngineAcceleration = patch::Get<float>(phandling + 0x7C) * 12500;
float fEngineInertia = patch::Get<float>(phandling + 0x80);
int nDriveType = patch::Get<BYTE>(phandling + 0x74);
int nEngineType = patch::Get<BYTE>(phandling + 0x75);
float BrakeDeceleration = patch::Get<float>(phandling + 0x94) * 2500;
float BrakeBias = patch::Get<float>(phandling + 0x98);
int ABS = patch::Get<BYTE>(phandling + 0x9C);
float SteeringLock = patch::Get<float>(phandling + 0xA0);
float SuspensionForceLevel = patch::Get<float>(phandling + 0xAC);
float SuspensionDampingLevel = patch::Get<float>(phandling + 0xB0);
float SuspensionHighSpdComDamp = patch::Get<float>(phandling + 0xB4);
float Suspension_upper_limit = patch::Get<float>(phandling + 0xB8);
float Suspension_lower_limit = patch::Get<float>(phandling + 0xBC);
float Suspension_bias = patch::Get<float>(phandling + 0xC0);
float Suspension_anti_dive_multiplier = patch::Get<float>(phandling + 0xC4);
float fCollisionDamageMultiplier = patch::Get<float>(phandling + 0xC8) * 0.338;
int nMonetaryValue = patch::Get<int>(phandling + 0xD8);
int MaxVelocity = patch::Get<float>(phandling + 0x84);
MaxVelocity = MaxVelocity * 206 + (MaxVelocity - 0.918668) * 1501;
int modelFlags = patch::Get<int>(phandling + 0xCC);
int handlingFlags = patch::Get<int>(phandling + 0xD0);
int front_lights = patch::Get<BYTE>(phandling + 0xDC);
int rear_lights = patch::Get<BYTE>(phandling + 0xDD);
int vehicle_anim_group = patch::Get<BYTE>(phandling + 0xDE);
int nNumberOfGears = patch::Get<BYTE>(phandling + 0x76);
float fSeatOffsetDistance = patch::Get<float>(phandling + 0xD4);
fprintf(
fp,
"\n%s\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%d\t%.5g\t%.5g\t%.5g\t%d\t%d\t%.5g\t%.5g\t%c\t%c\t%.5g\t%.5g\t%d\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%.5g\t%d\t%d\t%d\t%d\t%d\t%d",
handlingId.c_str(), fMass, fTurnMass, fDragMult, CentreOfMassX, CentreOfMassY, CentreOfMassZ, nPercentSubmerged,
fTractionMultiplier, fTractionLoss, TractionBias, nNumberOfGears,
MaxVelocity, fEngineAcceleration, fEngineInertia, nDriveType, nEngineType, BrakeDeceleration, BrakeBias, ABS,
SteeringLock, SuspensionForceLevel, SuspensionDampingLevel,
SuspensionHighSpdComDamp, Suspension_upper_limit, Suspension_lower_limit, Suspension_bias,
Suspension_anti_dive_multiplier, fSeatOffsetDistance,
fCollisionDamageMultiplier, nMonetaryValue, modelFlags, handlingFlags, front_lights, rear_lights,
vehicle_anim_group);
fclose(fp);
}
#endif
void Vehicle::ParseCarcolsDAT()
{
std::string m_FilePath = GAME_PATH((char*)"/data/carcols.dat");
if (fs::exists(m_FilePath))
{
std::ifstream file(m_FilePath);
std::string line;
bool car_section = false;
bool col_section = false;
int count = 0;
while (getline(file, line))
{
if (line[0] == '#' || line == "")
continue;
if (line[0] == 'c' && line[1] == 'a' && line[2] == 'r')
{
car_section = true;
continue;
}
if (line[0] == 'c' && line[1] == 'o' && line[2] == 'l')
{
col_section = true;
continue;
}
if (line[0] == 'e' && line[1] == 'n' && line[2] == 'd')
{
car_section = false;
col_section = false;
continue;
}
if (col_section)
{
try
{
std::string temp;
std::stringstream ss(line);
std::replace(temp.begin(), temp.end(), '.', ','); // fix one instance where . is used instead of ,
// red, green, blue
getline(ss, temp, ',');
int red = std::stoi(temp);
getline(ss, temp, ',');
int green = std::stoi(temp);
getline(ss, temp, ',');
int blue = std::stoi(temp);
std::vector<float> color = { red / 255.0f, green / 255.0f, blue / 255.0f };
m_CarcolsColorData.push_back(color);
++count;
}
catch (...)
{
flog << "Error while parsing car line, " << line << std::endl;
}
}
if (car_section)
{
std::string temp;
std::stringstream ss(line);
getline(ss, temp, ',');
std::string name = temp;
while (getline(ss, temp, ','))
{
try
{
std::for_each(name.begin(), name.end(), [](char& c)
{
c = ::toupper(c);
});
int val = std::stoi(temp);
if (!(std::find(m_CarcolsCarData[name].begin(), m_CarcolsCarData[name].end(), val) !=
m_CarcolsCarData[name].end()))
m_CarcolsCarData[name].push_back(val);
}
catch (...)
{
flog << "Error while parsing car line, " << line << std::endl;
}
}
}
}
file.close();
}
else
{
flog << "Error locating Vehicle.ide";
}
}
#ifdef GTASA
void Vehicle::SpawnVehicle(std::string& smodel)
#elif GTAVC
@ -752,6 +549,29 @@ void Vehicle::Draw()
}
#ifdef GTASA
Ui::CheckboxAddress("Decreased traffic", 0x96917A);
// if (Ui::CheckboxWithHint("Disable collisions", &m_bDisableColDetection))
// {
// if (m_bDisableColDetection)
// {
// patch::SetUChar(0x56717B, 0x7D);
// patch::SetUChar(0x56725D, 0x7D);
// }
// // update flags for exising vehicles
// for (auto veh : CPools::ms_pVehiclePool)
// {
// if (veh == FindPlayerVehicle(-1, false))
// {
// continue;
// }
// if (m_bDisableColDetection)
// {
// CCollisionData* pColData = veh->GetColModel()->m_pColData;
// // pColData->m_nNumSpheres = 0;
// pColData->m_nNumBoxes = 0;
// pColData->m_nNumTriangles = 0;
// }
// }
// }
#endif
ImGui::NextColumn();
#ifdef GTASA
@ -1372,7 +1192,7 @@ void Vehicle::Draw()
if (ImGui::Button("Save to file", ImVec2(Ui::GetSize(3))))
{
GenerateHandlingDataFile(pHandling);
FileHandler::GenerateHandlingFile(pHandling, m_VehicleIDE);
SetHelpMessage("Handling saved", false, false, false);
}

View File

@ -3,7 +3,9 @@
#ifdef GTASA
#include "Neon.h"
#include "Paint.h"
#endif
#ifdef GTASA
class Vehicle : public Paint, public Neon
#elif GTAVC
class Vehicle
@ -32,6 +34,7 @@ private:
};
#ifdef GTASA
inline static bool m_bDisableColDetection;
inline static std::map<int, std::string> m_VehicleIDE;
struct m_Neon
{
@ -92,10 +95,8 @@ private:
static void AddComponent(const std::string& component, bool display_message = true);
static void RemoveComponent(const std::string& component, bool display_message = true);
static int GetRandomTrainIdForModel(int model);
static void ParseVehiclesIDE();
static void GenerateHandlingDataFile(int phandling);
#endif
static void ParseCarcolsDAT();
public:
#ifdef GTASA

View File

@ -29,94 +29,6 @@ Visual::Visual()
};
}
int Visual::CalcArrayIndex()
{
int hour = CClock::ms_nGameClockHours;
#ifdef GTASA
int result = 0;
if (m_nTimecycHour == 24)
{
result = hour;
}
else
{
if (hour < 5) result = 0;
if (hour == 5) result = 1;
if (hour == 6) result = 2;
if (7 <= hour && hour < 12) result = 3;
if (12 <= hour && hour < 19) result = 4;
if (hour == 19) result = 5;
if (hour == 20 || hour == 21) result = 6;
if (hour == 22 || hour == 23) result = 7;
}
return 23 * result + CWeather::OldWeatherType;
#elif GTAVC
return 7 * hour + CWeather::OldWeatherType;
#endif
}
bool Visual::TimeCycColorEdit3(const char* label, uchar* r, uchar* g, uchar* b, ImGuiColorEditFlags flags)
{
bool rtn = false;
int val = CalcArrayIndex();
#ifdef GTASA
auto red = static_cast<uchar*>(patch::GetPointer(int(r)));
auto green = static_cast<uchar*>(patch::GetPointer(int(g)));
auto blue = static_cast<uchar*>(patch::GetPointer(int(b)));
#elif GTAVC
auto red = static_cast<uchar*>(r);
auto green = static_cast<uchar*>(g);
auto blue = static_cast<uchar*>(b);
#endif
float col[3]{ red[val] / 255.0f, green[val] / 255.0f, blue[val] / 255.0f };
if (ImGui::ColorEdit3(label, col, flags))
{
red[val] = col[0] * 255;
green[val] = col[1] * 255;
blue[val] = col[2] * 255;
rtn = true;
}
return rtn;
}
bool Visual::TimeCycColorEdit4(const char* label, uchar* r, uchar* g, uchar* b, uchar* a, ImGuiColorEditFlags flags)
{
bool rtn = false;
int val = CalcArrayIndex();
#ifdef GTASA
auto red = static_cast<uchar*>(patch::GetPointer(int(r)));
auto green = static_cast<uchar*>(patch::GetPointer(int(g)));
auto blue = static_cast<uchar*>(patch::GetPointer(int(b)));
auto alpha = static_cast<uchar*>(patch::GetPointer(int(a)));
#elif GTAVC
auto red = static_cast<uchar*>(r);
auto green = static_cast<uchar*>(g);
auto blue = static_cast<uchar*>(b);
auto alpha = static_cast<uchar*>(a);
#endif
float col[4]{ red[val] / 255.0f, green[val] / 255.0f, blue[val] / 255.0f, alpha[val] / 255.0f };
if (ImGui::ColorEdit4(label, col, flags))
{
red[val] = col[0] * 255;
green[val] = col[1] * 255;
blue[val] = col[2] * 255;
alpha[val] = col[3] * 255;
rtn = true;
}
return rtn;
}
template <typename T>
int GetTCVal(T* addr, int index)
{
@ -259,6 +171,99 @@ void Visual::GenerateTimecycFile()
#endif
}
int Visual::CalcArrayIndex()
{
int hour = CClock::ms_nGameClockHours;
#ifdef GTASA
int result = 0;
if (m_nTimecycHour == 24)
{
result = hour;
}
else
{
if (hour < 5) result = 0;
if (hour == 5) result = 1;
if (hour == 6) result = 2;
if (7 <= hour && hour < 12) result = 3;
if (12 <= hour && hour < 19) result = 4;
if (hour == 19) result = 5;
if (hour == 20 || hour == 21) result = 6;
if (hour == 22 || hour == 23) result = 7;
}
return 23 * result + CWeather::OldWeatherType;
#elif GTAVC
return 7 * hour + CWeather::OldWeatherType;
#endif
}
bool Visual::TimeCycColorEdit3(const char* label, uchar* r, uchar* g, uchar* b, ImGuiColorEditFlags flags)
{
bool rtn = false;
int val = CalcArrayIndex();
#ifdef GTASA
auto red = static_cast<uchar*>(patch::GetPointer(int(r)));
auto green = static_cast<uchar*>(patch::GetPointer(int(g)));
auto blue = static_cast<uchar*>(patch::GetPointer(int(b)));
#elif GTAVC
auto red = static_cast<uchar*>(r);
auto green = static_cast<uchar*>(g);
auto blue = static_cast<uchar*>(b);
#endif
float col[3]{ red[val] / 255.0f, green[val] / 255.0f, blue[val] / 255.0f };
if (ImGui::ColorEdit3(label, col, flags))
{
red[val] = col[0] * 255;
green[val] = col[1] * 255;
blue[val] = col[2] * 255;
rtn = true;
}
return rtn;
}
char __cdecl GetWaterLevelNoWaves(float x, float y, float z, int a4, __int64 a5)
{
return 0;
}
bool Visual::TimeCycColorEdit4(const char* label, uchar* r, uchar* g, uchar* b, uchar* a, ImGuiColorEditFlags flags)
{
bool rtn = false;
int val = CalcArrayIndex();
#ifdef GTASA
auto red = static_cast<uchar*>(patch::GetPointer(int(r)));
auto green = static_cast<uchar*>(patch::GetPointer(int(g)));
auto blue = static_cast<uchar*>(patch::GetPointer(int(b)));
auto alpha = static_cast<uchar*>(patch::GetPointer(int(a)));
#elif GTAVC
auto red = static_cast<uchar*>(r);
auto green = static_cast<uchar*>(g);
auto blue = static_cast<uchar*>(b);
auto alpha = static_cast<uchar*>(a);
#endif
float col[4]{ red[val] / 255.0f, green[val] / 255.0f, blue[val] / 255.0f, alpha[val] / 255.0f };
if (ImGui::ColorEdit4(label, col, flags))
{
red[val] = col[0] * 255;
green[val] = col[1] * 255;
blue[val] = col[2] * 255;
alpha[val] = col[3] * 255;
rtn = true;
}
return rtn;
}
void Visual::Draw()
{
if (ImGui::BeginTabBar("Visual", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll))
@ -273,6 +278,18 @@ void Visual::Draw()
Ui::CheckboxAddress("Armour percentage", 0x589125);
Ui::CheckboxAddress("Breath border", 0x589207);
Ui::CheckboxAddress("Breath percentage", 0x589209);
if (Ui::CheckboxWithHint("Disable hydrant splash", &m_bDisableHydrant))
{
if (m_bDisableHydrant)
{
// don't call Fx_c::TriggerWaterHydrant
plugin::patch::Nop(0x4A0D70, 5);
}
else
{
plugin::patch::SetRaw(0x4A0D70, (char*)"\xE9\x94\x3F\xF6\xFF", 5);
}
}
Ui::CheckboxAddress("Gray radar", 0xA444A4);
Ui::CheckboxAddress("Health border", 0x589353);
Ui::CheckboxAddress("Health percentage", 0x589355);
@ -290,11 +307,52 @@ void Visual::Draw()
}
Ui::CheckboxAddressEx("Hide wanted level", 0x58DD1B, 0x90, 1);
if (Ui::CheckboxWithHint("Invisible water", &m_bInvisibleWater))
{
if (!m_bNoWater)
{
if (m_bInvisibleWater)
{
// don't call CWaterLevel::RenderWater()
plugin::patch::Nop(0x53E004, 5);
plugin::patch::Nop(0x53E142, 5);
}
else
{
// restore call CWaterLevel::RenderWater()
plugin::patch::SetRaw(0x53E004, (char*)"\xE8\x47\x16\x1B\x00", 5);
plugin::patch::SetRaw(0x53E142, (char*)"\xE8\x09\x15\x1B\x00", 5);
}
}
}
if (Ui::CheckboxWithHint("Lock weather", &m_bLockWeather))
{
m_nBacWeatherType = CWeather::OldWeatherType;
}
if (Ui::CheckboxWithHint("No water", &m_bNoWater))
{
if (m_bNoWater)
{
// don't call CWaterLevel::RenderWater()
plugin::patch::Nop(0x53E004, 5);
plugin::patch::Nop(0x53E142, 5);
// rtn CWaterLevel::GetWaterLevelNoWaves
plugin::patch::SetRaw(0x6E8580, (char*)"\x32\xC0\xC3", 3);
}
else
{
// restore call CWaterLevel::RenderWater()
plugin::patch::SetRaw(0x53E004, (char*)"\xE8\x47\x16\x1B\x00", 5);
plugin::patch::SetRaw(0x53E142, (char*)"\xE8\x09\x15\x1B\x00", 5);
// restore CWaterLevel::GetWaterLevelNoWaves
plugin::patch::SetRaw(0x6E8580, (char*)"\x51\xD9\x44", 3);
}
}
bool radar_state = (patch::Get<BYTE>(0xBA676C) != 2);
if (Ui::CheckboxWithHint("Show radar", &radar_state))
{

View File

@ -6,6 +6,11 @@ private:
inline static bool m_bLockWeather;
inline static int m_nBacWeatherType;
#ifdef GTASA
inline static bool m_bInvisibleWater;
inline static bool m_bNoWater;
inline static bool m_bDisableHydrant;
#endif
// Timecyc
inline static int m_nTimecycHour = 8;
inline static std::vector<std::string> m_WeatherNames