Refactored code, added more hotkeys #46 #47

This commit is contained in:
Grinch_ 2021-01-18 15:53:24 +06:00
parent 3a909e8aba
commit 2b13546efa
17 changed files with 351 additions and 363 deletions

View File

@ -8,7 +8,9 @@
"${PLUGIN_SDK_DIR}/plugin_sa", "${PLUGIN_SDK_DIR}/plugin_sa",
"${PLUGIN_SDK_DIR}/plugin_sa/game_sa", "${PLUGIN_SDK_DIR}/plugin_sa/game_sa",
"${PLUGIN_SDK_DIR}/shared", "${PLUGIN_SDK_DIR}/shared",
"${PLUGIN_SDK_DIR}/shared/game" "${PLUGIN_SDK_DIR}/shared/game",
"E:/plugin-sdk-master/plugin_sa/game_sa",
"E:/plugin-sdk-master/shared"
], ],
"defines": [ "defines": [
"GTASA", "GTASA",

View File

@ -37,8 +37,8 @@ set(src_files
"src/Menu.cpp" "src/Menu.cpp"
"src/Menu.h" "src/Menu.h"
"src/MenuInfo.h" "src/MenuInfo.h"
"src/NeonAPI.cpp" "src/Neon.cpp"
"src/NeonAPI.h" "src/Neon.h"
"src/Paint.cpp" "src/Paint.cpp"
"src/Paint.h" "src/Paint.h"
"src/pch.cpp" "src/pch.cpp"

View File

@ -18,12 +18,16 @@ int Menu::overlay::selected_pos = 4;
float Menu::overlay::posX = NULL; float Menu::overlay::posX = NULL;
float Menu::overlay::posY = NULL; float Menu::overlay::posY = NULL;
HotKeyData Menu::hotkeys::command_window{};
HotKeyData Menu::hotkeys::menu_open{};
HotKeyData Menu::hotkeys::aim_skin_changer{}; HotKeyData Menu::hotkeys::aim_skin_changer{};
HotKeyData Menu::hotkeys::airbreak{};
HotKeyData Menu::hotkeys::command_window{};
HotKeyData Menu::hotkeys::flip_veh{};
HotKeyData Menu::hotkeys::fix_veh{};
HotKeyData Menu::hotkeys::god_mode{};
HotKeyData Menu::hotkeys::menu_open{};
HotKeyData Menu::hotkeys::quick_ss{}; HotKeyData Menu::hotkeys::quick_ss{};
HotKeyData Menu::hotkeys::quick_tp{}; HotKeyData Menu::hotkeys::quick_tp{};
HotKeyData Menu::hotkeys::airbreak{};
bool Menu::commands::show_menu = false; bool Menu::commands::show_menu = false;
char Menu::commands::input_buffer[INPUT_BUFFER_SIZE] = ""; char Menu::commands::input_buffer[INPUT_BUFFER_SIZE] = "";
@ -62,6 +66,15 @@ Menu::Menu()
hotkeys::command_window.key1 = config.GetValue("hotkey.command_window.key1", VK_LMENU); hotkeys::command_window.key1 = config.GetValue("hotkey.command_window.key1", VK_LMENU);
hotkeys::command_window.key2 = config.GetValue("hotkey.command_window.key2", VK_KEY_C); hotkeys::command_window.key2 = config.GetValue("hotkey.command_window.key2", VK_KEY_C);
hotkeys::flip_veh.key1 = config.GetValue("hotkey.flip_veh.key1", VK_NONE);
hotkeys::flip_veh.key2 = config.GetValue("hotkey.flip_veh.key2", VK_NONE);
hotkeys::fix_veh.key1 = config.GetValue("hotkey.fix_veh.key1", VK_NONE);
hotkeys::fix_veh.key2 = config.GetValue("hotkey.fix_veh.key2", VK_NONE);
hotkeys::god_mode.key1 = config.GetValue("hotkey.god_mode.key1", VK_NONE);
hotkeys::god_mode.key2 = config.GetValue("hotkey.god_mode.key2", VK_NONE);
}; };
} }
@ -316,7 +329,8 @@ void Menu::Main()
} }
if (ImGui::BeginTabItem("Hotkeys")) if (ImGui::BeginTabItem("Hotkeys"))
{ {
ImGui::Spacing();
ImGui::TextWrapped("Right clicking will set hotkey to none. Some are set to none by default. Choose keys for them if you want to use them.");
ImGui::Spacing(); ImGui::Spacing();
ImGui::BeginChild("Hotkeys"); ImGui::BeginChild("Hotkeys");
if (Ui::HotKey("Open/ close cheat menu", hotkeys::menu_open)) if (Ui::HotKey("Open/ close cheat menu", hotkeys::menu_open))
@ -353,6 +367,26 @@ void Menu::Main()
config.SetValue("hotkey.quick_tp.key2", hotkeys::quick_tp.key2); config.SetValue("hotkey.quick_tp.key2", hotkeys::quick_tp.key2);
} }
ImGui::Dummy(ImVec2(0,10));
if (Ui::HotKey("Fix current vehicle", hotkeys::fix_veh))
{
config.SetValue("hotkey.fix_veh.key1", hotkeys::fix_veh.key1);
config.SetValue("hotkey.fix_veh.key2", hotkeys::fix_veh.key2);
}
if (Ui::HotKey("Flip current vehicle", hotkeys::flip_veh))
{
config.SetValue("hotkey.flip_veh.key1", hotkeys::flip_veh.key1);
config.SetValue("hotkey.flip_veh.key2", hotkeys::flip_veh.key2);
}
if (Ui::HotKey("Toggle god mode", hotkeys::god_mode))
{
config.SetValue("hotkey.god_mode.key1", hotkeys::god_mode.key1);
config.SetValue("hotkey.god_mode.key2", hotkeys::god_mode.key2);
}
ImGui::Dummy(ImVec2(0, 10)); ImGui::Dummy(ImVec2(0, 10));
ImGui::EndChild(); ImGui::EndChild();

View File

@ -19,12 +19,15 @@ private:
public: public:
struct hotkeys struct hotkeys
{ {
static HotKeyData command_window;
static HotKeyData menu_open;
static HotKeyData aim_skin_changer; static HotKeyData aim_skin_changer;
static HotKeyData airbreak;
static HotKeyData command_window;
static HotKeyData fix_veh;
static HotKeyData flip_veh;
static HotKeyData god_mode;
static HotKeyData menu_open;
static HotKeyData quick_ss; static HotKeyData quick_ss;
static HotKeyData quick_tp; static HotKeyData quick_tp;
static HotKeyData airbreak;
}; };
struct commands struct commands
{ {

View File

@ -1,11 +1,11 @@
#include "pch.h" #include "pch.h"
#include "NeonAPI.h" #include "Neon.h"
#include "Util.h" #include "Util.h"
VehicleExtendedData<NeonAPI::NeonData> NeonAPI::VehNeon; VehicleExtendedData<Neon::NeonData> Neon::VehNeon;
RwTexture* NeonAPI::neon_texture = nullptr; RwTexture* Neon::neon_texture = nullptr;
NeonAPI::NeonAPI() Neon::Neon()
{ {
Events::initGameEvent += [this] Events::initGameEvent += [this]
{ {
@ -48,27 +48,27 @@ NeonAPI::NeonAPI()
}; };
} }
NeonAPI::~NeonAPI() Neon::~Neon()
{ {
delete neon_texture; delete neon_texture;
} }
bool NeonAPI::IsNeonInstalled(CVehicle *pVeh) bool Neon::IsNeonInstalled(CVehicle *pVeh)
{ {
return VehNeon.Get(pVeh).neon_installed; return VehNeon.Get(pVeh).neon_installed;
} }
bool NeonAPI::IsPulsingEnabled(CVehicle *pVeh) bool Neon::IsPulsingEnabled(CVehicle *pVeh)
{ {
return VehNeon.Get(pVeh).pulsing; return VehNeon.Get(pVeh).pulsing;
} }
void NeonAPI::SetPulsing(CVehicle *pVeh, bool state) void Neon::SetPulsing(CVehicle *pVeh, bool state)
{ {
VehNeon.Get(pVeh).pulsing = state; VehNeon.Get(pVeh).pulsing = state;
} }
void NeonAPI::InstallNeon(CVehicle *pVeh, int red, int green, int blue) void Neon::InstallNeon(CVehicle *pVeh, int red, int green, int blue)
{ {
CRGBA &color = VehNeon.Get(pVeh).color; CRGBA &color = VehNeon.Get(pVeh).color;
@ -80,7 +80,7 @@ void NeonAPI::InstallNeon(CVehicle *pVeh, int red, int green, int blue)
VehNeon.Get(pVeh).neon_installed = true; VehNeon.Get(pVeh).neon_installed = true;
} }
void NeonAPI::RemoveNeon(CVehicle *pVeh) void Neon::RemoveNeon(CVehicle *pVeh)
{ {
VehNeon.Get(pVeh).neon_installed = false; VehNeon.Get(pVeh).neon_installed = false;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
class NeonAPI class Neon
{ {
private: private:
static RwTexture* neon_texture; static RwTexture* neon_texture;
@ -26,8 +26,8 @@ private:
static VehicleExtendedData<NeonData> VehNeon; static VehicleExtendedData<NeonData> VehNeon;
public: public:
NeonAPI(); Neon();
~NeonAPI(); ~Neon();
static void InstallNeon(CVehicle *veh, int red, int green, int blue); static void InstallNeon(CVehicle *veh, int red, int green, int blue);
static bool IsNeonInstalled(CVehicle *veh); static bool IsNeonInstalled(CVehicle *veh);
static bool IsPulsingEnabled(CVehicle *veh); static bool IsPulsingEnabled(CVehicle *veh);

View File

@ -1,3 +1,28 @@
// Portion of this source is taken from MoonAdditions https://github.com/THE-FYP/MoonAdditions
// To keep the licensing simple this file would go under MIT License, GPLv3 won't apply
// Copyright (c) 2012 DK22Pac
// Copyright (c) 2017 FYP
// Copyright (c) 2021 Grinch_
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "pch.h" #include "pch.h"
#include "Paint.h" #include "Paint.h"
#include "NodeName.h" #include "NodeName.h"
@ -5,6 +30,7 @@
std::vector<std::string> Paint::veh_nodes::names_vec{ "Default" }; std::vector<std::string> Paint::veh_nodes::names_vec{ "Default" };
std::string Paint::veh_nodes::selected = "Default"; std::string Paint::veh_nodes::selected = "Default";
VehicleExtendedData<Paint::VehData> Paint::vehdata;
std::map<std::string, std::shared_ptr<RwTexture>> Paint::textures; std::map<std::string, std::shared_ptr<RwTexture>> Paint::textures;
@ -22,14 +48,59 @@ Paint::Paint()
} }
}; };
Events::vehicleRenderEvent.before += [](CVehicle* veh) { Events::vehicleRenderEvent.before += [](CVehicle* veh)
if (veh) {
VehicleRenderer::get()->processRender(veh); VehData& data = vehdata.Get(veh);
// reset custom color if color id changed
if (veh->m_nPrimaryColor != data.primary_color
|| veh->m_nSecondaryColor != data.secondary_color)
{
for (auto& it : data.materialProperties)
data.resetMaterialColor(it.first);
data.primary_color = veh->m_nPrimaryColor;
data.secondary_color = veh->m_nSecondaryColor;
}
for (auto& it : data.materialProperties)
{
if (it.second._recolor)
{
it.second._originalColor = it.first->color;
it.first->color = it.second._color;
it.second._originalGeometryFlags = it.second._geometry->flags;
it.second._geometry->flags |= rpGEOMETRYMODULATEMATERIALCOLOR;
}
if (it.second._retexture)
{
auto tex = it.second._texture.lock();
if (tex)
{
it.second._originalTexture = it.first->texture;
it.first->texture = tex.get();
}
else
{
it.second._retexture = false;
}
}
}
}; };
Events::vehicleResetAfterRender += [](CVehicle* veh) { Events::vehicleResetAfterRender += [](CVehicle* veh) {
if (veh) for (auto& it : vehdata.Get(veh).materialProperties)
VehicleRenderer::get()->postRender(veh); {
if (it.second._recolor)
{
it.first->color = it.second._originalColor;
it.second._geometry->flags = it.second._originalGeometryFlags;
}
if (it.second._retexture)
{
it.first->texture = it.second._originalTexture;
}
}
}; };
} }
@ -37,6 +108,48 @@ Paint::~Paint()
{ {
} }
void Paint::VehData::setMaterialColor(RpMaterial* material, RpGeometry* geometry, RwRGBA color, bool filter_mat)
{
auto& matProps = materialProperties[material];
if ( !filter_mat
|| (material->color.red == 0x3C && material->color.green == 0xFF && material->color.blue == 0x00)
|| (material->color.red == 0xFF && material->color.green == 0x00 && material->color.blue == 0xAF))
{
matProps._recolor = true;
matProps._color = color;
matProps._geometry = geometry;
}
}
void Paint::VehData::setMaterialTexture(RpMaterial* material, std::shared_ptr<RwTexture> texture, bool filter_mat)
{
auto& matProps = materialProperties[material];
if (!filter_mat
|| (material->color.red == 0x3C && material->color.green == 0xFF && material->color.blue == 0x00)
|| (material->color.red == 0xFF && material->color.green == 0x00 && material->color.blue == 0xAF))
{
matProps._retexture = true;
matProps._texture = texture;
}
}
void Paint::VehData::resetMaterialColor(RpMaterial* material)
{
auto& matProps = materialProperties[material];
matProps._recolor = false;
matProps._color = {0, 0, 0, 0};
}
void Paint::VehData::resetMaterialTexture(RpMaterial* material)
{
auto& matProps = materialProperties[material];
matProps._retexture = false;
matProps._texture.reset();
}
void Paint::NodeWrapperRecursive(RwFrame *frame, CVehicle* pVeh, std::function<void(RwFrame*)> func) void Paint::NodeWrapperRecursive(RwFrame *frame, CVehicle* pVeh, std::function<void(RwFrame*)> func)
{ {
if (frame) if (frame)
@ -92,8 +205,10 @@ void Paint::SetNodeColor(CVehicle* pVeh, std::string node_name, CRGBA color, boo
CRGBA* color = &st->_color; CRGBA* color = &st->_color;
bool filter_mat = st->_filter; bool filter_mat = st->_filter;
VehData& data = vehdata.Get(FindPlayerPed()->m_pVehicle);
for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i) for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i)
VehicleRenderer::get()->setMaterialColor(FindPlayerPed()->m_pVehicle, atomic->geometry->matList.materials[i], atomic->geometry, { color->r,color->g,color->b, 255 }, filter_mat); data.setMaterialColor(atomic->geometry->matList.materials[i], atomic->geometry, { color->r,color->g,color->b, 255 }, filter_mat);
} }
return object; return object;
}, &st); }, &st);
@ -129,8 +244,10 @@ void Paint::SetNodeTexture(CVehicle* pVeh, std::string node_name, std::string te
RpAtomic *atomic = reinterpret_cast<RpAtomic*>(object); RpAtomic *atomic = reinterpret_cast<RpAtomic*>(object);
ST* st = reinterpret_cast<ST*>(data); ST* st = reinterpret_cast<ST*>(data);
VehData& data = vehdata.Get(FindPlayerPed()->m_pVehicle);
for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i) for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i)
VehicleRenderer::get()->setMaterialTexture(FindPlayerPed()->m_pVehicle, atomic->geometry->matList.materials[i], st->_textures[st->_texturename], st->_filter); data.setMaterialTexture(atomic->geometry->matList.materials[i], st->_textures[st->_texturename], st->_filter);
} }
return object; return object;
}, &st); }, &st);
@ -152,9 +269,10 @@ void Paint::ResetNodeColor(CVehicle *pVeh, std::string node_name)
if (object->type == rpATOMIC) if (object->type == rpATOMIC)
{ {
RpAtomic *atomic = reinterpret_cast<RpAtomic*>(object); RpAtomic *atomic = reinterpret_cast<RpAtomic*>(object);
VehData& data = vehdata.Get(FindPlayerPed()->m_pVehicle);
for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i) for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i)
VehicleRenderer::get()->resetMaterialColor(FindPlayerPed()->m_pVehicle, atomic->geometry->matList.materials[i]); data.resetMaterialColor(atomic->geometry->matList.materials[i]);
} }
return object; return object;
}, nullptr); }, nullptr);
@ -178,8 +296,10 @@ void Paint::ResetNodeTexture(CVehicle *pVeh, std::string node_name)
{ {
RpAtomic *atomic = reinterpret_cast<RpAtomic*>(object); RpAtomic *atomic = reinterpret_cast<RpAtomic*>(object);
VehData& data = vehdata.Get(FindPlayerPed()->m_pVehicle);
for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i) for (int i = 0; i < atomic->geometry->matList.numMaterials; ++i)
VehicleRenderer::get()->resetMaterialTexture(FindPlayerPed()->m_pVehicle, atomic->geometry->matList.materials[i]); data.resetMaterialTexture(atomic->geometry->matList.materials[i]);
} }
return object; return object;
}, nullptr); }, nullptr);

View File

@ -1,19 +1,91 @@
// Portion of this source is taken from MoonAdditions https://github.com/THE-FYP/MoonAdditions
// To keep the licensing simple this file would go under MIT License, GPLv3 won't apply
// Copyright (c) 2012 DK22Pac
// Copyright (c) 2017 FYP
// Copyright (c) 2021 Grinch_
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once #pragma once
#include "vendor/moon/vehicle_renderer.h"
class Paint : VehicleRenderer class Paint
{ {
public:
Paint();
~Paint();
private:
// store vehicle specific data
struct VehData
{
struct MaterialProperties
{
MaterialProperties() :
_color{0, 0, 0, 0},
_recolor(false),
_retexture(false),
_originalColor{0, 0, 0, 0},
_originalTexture(nullptr),
_originalGeometryFlags(0),
_geometry(nullptr)
{
}
RwRGBA _color;
std::weak_ptr<RwTexture> _texture;
bool _recolor;
bool _retexture;
RpGeometry* _geometry;
RwRGBA _originalColor;
RwTexture* _originalTexture;
RwInt32 _originalGeometryFlags;
};
// carcols color id
uchar primary_color = 0;
uchar secondary_color = 0;
std::unordered_map<RpMaterial*, MaterialProperties> materialProperties;
VehData(CVehicle* veh)
{
primary_color = veh->m_nPrimaryColor;
secondary_color = veh->m_nSecondaryColor;
}
void setMaterialColor(RpMaterial* material, RpGeometry* geometry, RwRGBA color, bool filter_mat = false);
void setMaterialTexture(RpMaterial* material, std::shared_ptr<RwTexture> texture9, bool filter_mat = false);
void resetMaterialColor(RpMaterial* material);
void resetMaterialTexture(RpMaterial* material);
};
static VehicleExtendedData<VehData> vehdata;
protected:
static std::map<std::string, std::shared_ptr<RwTexture>> textures;
struct veh_nodes struct veh_nodes
{ {
static std::vector<std::string> names_vec; static std::vector<std::string> names_vec;
static std::string selected; static std::string selected;
}; };
static std::map<std::string, std::shared_ptr<RwTexture>> textures;
Paint();
~Paint();
static void UpdateNodeListRecursive(CVehicle* pVeh); static void UpdateNodeListRecursive(CVehicle* pVeh);
static void NodeWrapperRecursive(RwFrame * frame, CVehicle* pVeh, std::function<void(RwFrame*)> func); static void NodeWrapperRecursive(RwFrame * frame, CVehicle* pVeh, std::function<void(RwFrame*)> func);
static void SetNodeColor(CVehicle* pVeh, std::string node_name, CRGBA color, bool filter_mat = false); static void SetNodeColor(CVehicle* pVeh, std::string node_name, CRGBA color, bool filter_mat = false);

View File

@ -107,6 +107,27 @@ Player::Player()
Util::ClearCharTasksVehCheck(player); Util::ClearCharTasksVehCheck(player);
} }
} }
if (Ui::HotKeyPressed(Menu::hotkeys::god_mode))
{
if (god_mode)
{
CHud::SetHelpMessage("God mode disabled",false,false,false);
patch::Set<bool>(0x96916D, god_mode, false);
player->m_nPhysicalFlags.bBulletProof = false;
player->m_nPhysicalFlags.bCollisionProof = false;
player->m_nPhysicalFlags.bExplosionProof = false;
player->m_nPhysicalFlags.bFireProof = false;
player->m_nPhysicalFlags.bMeeleProof = false;
god_mode = false;
}
else
{
CHud::SetHelpMessage("God mode enabled",false,false,false);
god_mode = true;
}
}
}; };
} }

View File

@ -791,7 +791,7 @@ bool Ui::HotKey(const char* label, HotKeyData& key_data)
{ {
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
for (int key = 2; key != 90; ++key) for (int key = 3; key != 90; ++key)
{ {
if (KeyPressed(key)) if (KeyPressed(key))
{ {
@ -800,7 +800,7 @@ bool Ui::HotKey(const char* label, HotKeyData& key_data)
} }
} }
for (int key = 90; key != 2; --key) for (int key = 90; key != 3; --key)
{ {
if (KeyPressed(key)) if (KeyPressed(key))
{ {
@ -810,7 +810,13 @@ bool Ui::HotKey(const char* label, HotKeyData& key_data)
} }
} }
std::string text = key_names[key_data.key1-1];
std::string text;
if (key_data.key1 != VK_NONE)
text = key_names[key_data.key1-1];
else
text = "None";
if (key_data.key1 != key_data.key2) if (key_data.key1 != key_data.key2)
text += (" + " + key_names[key_data.key2-1]); text += (" + " + key_names[key_data.key2-1]);
@ -825,6 +831,13 @@ bool Ui::HotKey(const char* label, HotKeyData& key_data)
else else
current_hotkey = label;; current_hotkey = label;;
} }
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(1)) // right click
{
key_data.key1 = VK_NONE;
key_data.key2 = VK_NONE;
}
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text(label); ImGui::Text(label);
@ -850,7 +863,12 @@ bool Ui::HotKeyPressed(HotKeyData& hotkey)
std::string Ui::GetHotKeyNameString(HotKeyData& hotkey) std::string Ui::GetHotKeyNameString(HotKeyData& hotkey)
{ {
std::string text = key_names[hotkey.key1 - 1]; std::string text;
if (hotkey.key1 != VK_NONE)
text = key_names[hotkey.key1-1];
else
text = "None";
if (hotkey.key1 != hotkey.key2) if (hotkey.key1 != hotkey.key2)
text += (" + " + key_names[hotkey.key2 - 1]); text += (" + " + key_names[hotkey.key2 - 1]);

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#define VK_NONE -1
#define VK_KEY_0 0x30 #define VK_KEY_0 0x30
#define VK_KEY_1 0x31 #define VK_KEY_1 0x31
#define VK_KEY_2 0x32 #define VK_KEY_2 0x32

View File

@ -1,5 +1,6 @@
#include "pch.h" #include "pch.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "Menu.h"
#include "Ui.h" #include "Ui.h"
#include "Util.h" #include "Util.h"
@ -89,7 +90,23 @@ Vehicle::Vehicle()
if (player && veh) if (player && veh)
{ {
int hveh = CPools::GetVehicleRef(veh); int hveh = CPools::GetVehicleRef(veh);
if (Ui::HotKeyPressed(Menu::hotkeys::flip_veh))
{
float roll;
Command<Commands::GET_CAR_ROLL>(hveh, &roll);
roll += 180;
Command<Commands::SET_CAR_ROLL>(hveh, roll);
Command<Commands::SET_CAR_ROLL>(hveh, roll); // z rot fix
}
if (Ui::HotKeyPressed(Menu::hotkeys::fix_veh))
{
player->m_pVehicle->Fix();
player->m_pVehicle->m_fHealth = 1000.0f;
CHud::SetHelpMessage("Vehicle fixed",false,false,false);
}
if (veh_nodmg) if (veh_nodmg)
{ {
veh->m_nPhysicalFlags.bBulletProof = true; veh->m_nPhysicalFlags.bBulletProof = true;
@ -135,7 +152,7 @@ Vehicle::Vehicle()
int red, green, blue; int red, green, blue;
Util::RainbowValues(red, green, blue, 0.25); Util::RainbowValues(red, green, blue, 0.25);
NeonAPI::InstallNeon(veh, red, green, blue); InstallNeon(veh, red, green, blue);
neon::rainbow_timer = timer; neon::rainbow_timer = timer;
} }
} }
@ -156,8 +173,8 @@ Vehicle::Vehicle()
if (veh->m_nVehicleClass == CLASS_EXECUTIVE) // Executive if (veh->m_nVehicleClass == CLASS_EXECUTIVE) // Executive
chance = rand() % 3 + 1; chance = rand() % 3 + 1;
if (chance == 1 && !NeonAPI::IsNeonInstalled(veh) && veh->m_pDriver != player) if (chance == 1 && !IsNeonInstalled(veh) && veh->m_pDriver != player)
NeonAPI::InstallNeon(veh, rand() % 255, rand() % 255, rand() % 255); InstallNeon(veh, rand() % 255, rand() % 255, rand() % 255);
} }
neon::traffic_timer = timer; neon::traffic_timer = timer;
} }
@ -716,11 +733,11 @@ void Vehicle::Main()
if (Ui::CheckboxWithHint("Explosion proof", &state, nullptr, veh_nodmg)) if (Ui::CheckboxWithHint("Explosion proof", &state, nullptr, veh_nodmg))
pVeh->m_nPhysicalFlags.bExplosionProof = state; pVeh->m_nPhysicalFlags.bExplosionProof = state;
ImGui::NextColumn();
state = pVeh->m_nPhysicalFlags.bFireProof; state = pVeh->m_nPhysicalFlags.bFireProof;
if (Ui::CheckboxWithHint("Fire proof", &state, nullptr, veh_nodmg)) if (Ui::CheckboxWithHint("Fire proof", &state, nullptr, veh_nodmg))
pVeh->m_nPhysicalFlags.bFireProof = state; pVeh->m_nPhysicalFlags.bFireProof = state;
ImGui::NextColumn();
state = pVeh->m_nVehicleFlags.bVehicleCanBeTargettedByHS; state = pVeh->m_nVehicleFlags.bVehicleCanBeTargettedByHS;
if (Ui::CheckboxWithHint("HS targetable", &state, "Heat Seaker missile can target this")) if (Ui::CheckboxWithHint("HS targetable", &state, "Heat Seaker missile can target this"))
@ -747,6 +764,14 @@ void Vehicle::Main()
if (Ui::CheckboxWithHint("Melee proof", &state, nullptr, veh_nodmg)) if (Ui::CheckboxWithHint("Melee proof", &state, nullptr, veh_nodmg))
pVeh->m_nPhysicalFlags.bMeeleProof = state; pVeh->m_nPhysicalFlags.bMeeleProof = state;
state = pVeh->m_nVehicleFlags.bPetrolTankIsWeakPoint;
if (Ui::CheckboxWithHint("Petrol tank blow", &state, "Vehicle will blow up if petrol tank is shot"))
pVeh->m_nVehicleFlags.bPetrolTankIsWeakPoint = state;
state = pVeh->m_nVehicleFlags.bSirenOrAlarm;
if (Ui::CheckboxWithHint("Siren", &state))
pVeh->m_nVehicleFlags.bSirenOrAlarm = state;
state = pVeh->m_nVehicleFlags.bTakeLessDamage; state = pVeh->m_nVehicleFlags.bTakeLessDamage;
if (Ui::CheckboxWithHint("Take less dmg", &state, nullptr)) if (Ui::CheckboxWithHint("Take less dmg", &state, nullptr))
pVeh->m_nVehicleFlags.bTakeLessDamage = state; pVeh->m_nVehicleFlags.bTakeLessDamage = state;
@ -1036,16 +1061,16 @@ void Vehicle::Main()
ImGui::Spacing(); ImGui::Spacing();
if (ImGui::Button("Remove neon", ImVec2(Ui::GetSize()))) if (ImGui::Button("Remove neon", ImVec2(Ui::GetSize())))
{ {
NeonAPI::RemoveNeon(veh); RemoveNeon(veh);
CHud::SetHelpMessage("Neon removed", false, false, false); CHud::SetHelpMessage("Neon removed", false, false, false);
} }
ImGui::Spacing(); ImGui::Spacing();
ImGui::Columns(2, NULL, false); ImGui::Columns(2, NULL, false);
bool pulsing = NeonAPI::IsPulsingEnabled(veh); bool pulsing = IsPulsingEnabled(veh);
if (Ui::CheckboxWithHint("Pulsing neons", &pulsing)) if (Ui::CheckboxWithHint("Pulsing neons", &pulsing))
NeonAPI::SetPulsing(veh,pulsing); SetPulsing(veh,pulsing);
Ui::CheckboxWithHint("Rainbow neons", &neon::rainbow, "Rainbow effect to neon lights"); Ui::CheckboxWithHint("Rainbow neons", &neon::rainbow, "Rainbow effect to neon lights");
ImGui::NextColumn(); ImGui::NextColumn();
@ -1056,7 +1081,7 @@ Only some vehicles will have them.");
ImGui::Spacing(); ImGui::Spacing();
if (ImGui::ColorEdit3("Color picker", neon::color_picker)) if (ImGui::ColorEdit3("Color picker", neon::color_picker))
NeonAPI::InstallNeon(veh, neon::color_picker[0] * 255, neon::color_picker[1] * 255, neon::color_picker[2] * 255); InstallNeon(veh, neon::color_picker[0] * 255, neon::color_picker[1] * 255, neon::color_picker[2] * 255);
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Select neon preset:"); ImGui::Text("Select neon preset:");
@ -1073,7 +1098,7 @@ Only some vehicles will have them.");
if (Ui::ColorButton(color_id, carcols_color_values[color_id], ImVec2(btn_size, btn_size))) if (Ui::ColorButton(color_id, carcols_color_values[color_id], ImVec2(btn_size, btn_size)))
{ {
std::vector<float> &color = carcols_color_values[color_id]; std::vector<float> &color = carcols_color_values[color_id];
NeonAPI::InstallNeon(veh, color[0]*255, color[1]*255, color[2]*255); InstallNeon(veh, color[0]*255, color[1]*255, color[2]*255);
} }
if ((color_id + 1) % btns_in_row != 0) if ((color_id + 1) % btns_in_row != 0)

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "NeonAPI.h" #include "Neon.h"
#include "Paint.h" #include "Paint.h"
class Vehicle : Paint, NeonAPI class Vehicle : Paint, Neon
{ {
private: private:
static bool bike_fly; static bool bike_fly;

View File

@ -38,9 +38,6 @@ set(vendor_files
"kiero/minhook/trampoline.c" "kiero/minhook/trampoline.c"
"kiero/minhook/hde/hde32.c" "kiero/minhook/hde/hde32.c"
"kiero/minhook/trampoline.c" "kiero/minhook/trampoline.c"
"moon/pool_object_extender.h"
"moon/vehicle_renderer.h"
"moon/vehicle_renderer.cpp"
) )
add_library(${PROJECT_NAME} STATIC ${vendor_files}) add_library(${PROJECT_NAME} STATIC ${vendor_files})

View File

@ -1,73 +0,0 @@
// This source is taken from MoonAdditions https://github.com/THE-FYP/MoonAdditions
// MIT License
// Copyright (c) 2012 DK22Pac
// Copyright (c) 2017 FYP
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <unordered_map>
template<typename ObjT, typename DataT>
class ExtendedObjectDataPool
{
public:
auto begin()
{
return _pool.begin();
}
auto end()
{
return _pool.end();
}
bool exists(const ObjT* obj) const
{
return _pool.find(obj) != _pool.end();
}
DataT& get(const ObjT* obj)
{
if (_pool.find(obj) != _pool.end())
return *_pool.find(obj)->second;
return *(_pool[obj] = std::make_unique<DataT>(obj));
}
void remove(const ObjT* obj)
{
_pool.erase(obj);
}
private:
std::unordered_map<const ObjT*, std::unique_ptr<DataT>> _pool;
};
template<typename T>
class VehicleDataExtended : public ExtendedObjectDataPool<CVehicle, T>
{
public:
VehicleDataExtended()
{
plugin::Events::vehicleDtorEvent.after += [this](CVehicle* veh) {
this->remove(veh);
};
}
};

View File

@ -1,145 +0,0 @@
// This source is taken from MoonAdditions https://github.com/THE-FYP/MoonAdditions
// MIT License
// Copyright (c) 2012 DK22Pac
// Copyright (c) 2017 FYP
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "plugin.h"
#include "vehicle_renderer.h"
auto& VehicleRenderer::getVehicleData(CVehicle* veh)
{
if (!_vehicleData)
_vehicleData = std::make_unique<VehicleDataExtended<VehicleData>>();
return _vehicleData->get(veh);
}
auto& VehicleRenderer::getVehicleMaterialProperties(CVehicle* veh)
{
return getVehicleData(veh)._materialProperties;
}
void VehicleRenderer::setMaterialColor(CVehicle* veh, RpMaterial* material, RpGeometry* geometry, RwRGBA color, bool filter_mat)
{
auto& matProps = getVehicleMaterialProperties(veh)[material];
if ( !filter_mat
|| (material->color.red == 0x3C && material->color.green == 0xFF && material->color.blue == 0x00)
|| (material->color.red == 0xFF && material->color.green == 0x00 && material->color.blue == 0xAF))
{
matProps._recolor = true;
matProps._color = color;
matProps._geometry = geometry;
}
}
void VehicleRenderer::setMaterialTexture(CVehicle* veh, RpMaterial* material, std::shared_ptr<RwTexture> texture, bool filter_mat)
{
auto& matProps = getVehicleMaterialProperties(veh)[material];
if (!filter_mat
|| (material->color.red == 0x3C && material->color.green == 0xFF && material->color.blue == 0x00)
|| (material->color.red == 0xFF && material->color.green == 0x00 && material->color.blue == 0xAF))
{
matProps._retexture = true;
matProps._texture = texture;
}
}
void VehicleRenderer::resetMaterialColor(CVehicle* veh, RpMaterial* material)
{
if (isInitialized() && _vehicleData->exists(veh))
{
auto& matProps = getVehicleMaterialProperties(veh)[material];
matProps._recolor = false;
matProps._color = {0, 0, 0, 0};
}
}
void VehicleRenderer::resetMaterialTexture(CVehicle* veh, RpMaterial* material)
{
if (isInitialized() && _vehicleData->exists(veh))
{
auto& matProps = getVehicleMaterialProperties(veh)[material];
matProps._retexture = false;
matProps._texture.reset();
}
}
void VehicleRenderer::processRender(CVehicle* veh)
{
if (isInitialized() && _vehicleData->exists(veh))
{
// reset custom color if color id changed
if (veh->m_nPrimaryColor != getVehicleData(veh).primary_color
|| veh->m_nSecondaryColor != getVehicleData(veh).secondary_color)
{
for (auto& it : _vehicleData->get(veh)._materialProperties)
resetMaterialColor(veh, it.first);
getVehicleData(veh).primary_color = veh->m_nPrimaryColor;
getVehicleData(veh).secondary_color = veh->m_nSecondaryColor;
}
for (auto& it : _vehicleData->get(veh)._materialProperties)
{
if (it.second._recolor)
{
it.second._originalColor = it.first->color;
it.first->color = it.second._color;
it.second._originalGeometryFlags = it.second._geometry->flags;
it.second._geometry->flags |= rpGEOMETRYMODULATEMATERIALCOLOR;
}
if (it.second._retexture)
{
auto tex = it.second._texture.lock();
if (tex)
{
it.second._originalTexture = it.first->texture;
it.first->texture = tex.get();
}
else
{
it.second._retexture = false;
}
}
}
}
}
void VehicleRenderer::postRender(CVehicle* veh)
{
if (isInitialized() && _vehicleData->exists(veh))
{
for (auto& it : _vehicleData->get(veh)._materialProperties)
{
if (it.second._recolor)
{
it.first->color = it.second._originalColor;
it.second._geometry->flags = it.second._originalGeometryFlags;
}
if (it.second._retexture)
{
it.first->texture = it.second._originalTexture;
}
}
}
}

View File

@ -1,87 +0,0 @@
// This source is taken from MoonAdditions https://github.com/THE-FYP/MoonAdditions
// MIT License
// Copyright (c) 2012 DK22Pac
// Copyright (c) 2017 FYP
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include "pool_object_extender.h"
class VehicleRenderer
{
struct MaterialProperties
{
MaterialProperties() :
_color{0, 0, 0, 0},
_recolor(false),
_retexture(false),
_originalColor{0, 0, 0, 0},
_originalTexture(nullptr),
_originalGeometryFlags(0),
_geometry(nullptr)
{
}
RwRGBA _color;
std::weak_ptr<RwTexture> _texture;
bool _recolor;
bool _retexture;
RpGeometry* _geometry;
RwRGBA _originalColor;
RwTexture* _originalTexture;
RwInt32 _originalGeometryFlags;
};
struct VehicleData
{
VehicleData(const CVehicle* veh)
{
primary_color = veh->m_nPrimaryColor;
secondary_color = veh->m_nSecondaryColor;
}
// carcols color id
uchar primary_color;
uchar secondary_color;
std::unordered_map<RpMaterial*, MaterialProperties> _materialProperties;
};
public:
void setMaterialColor(CVehicle* veh, RpMaterial* material, RpGeometry* geometry, RwRGBA color, bool filter_mat = false);
void setMaterialTexture(CVehicle* veh, RpMaterial* material, std::shared_ptr<RwTexture> texture9, bool filter_mat = false);
void resetMaterialColor(CVehicle* veh, RpMaterial* material);
void resetMaterialTexture(CVehicle* veh, RpMaterial* material);
void processRender(CVehicle* veh);
void postRender(CVehicle* veh);
bool isInitialized() const { return _vehicleData != nullptr; }
static VehicleRenderer* get()
{
static std::unique_ptr<VehicleRenderer> instance = std::make_unique<VehicleRenderer>();
return instance.get();
}
private:
auto& getVehicleMaterialProperties(CVehicle* veh);
auto& getVehicleData(CVehicle* veh);
std::unique_ptr<VehicleDataExtended<VehicleData>> _vehicleData;
};