From 4b9ab8890caf85a9bdc541116f6e8028e5d1e662 Mon Sep 17 00:00:00 2001 From: Grinch_ Date: Thu, 4 Aug 2022 02:15:42 +0600 Subject: [PATCH] Add new car, ped & weapon directly from the menu --- resource/CheatMenuSA/data/particles.toml | 178 ++++++++++--------- resource/common/locale/English.toml | 40 +++-- src/animation.cpp | 65 +++---- src/cheatmenu.cpp | 10 +- src/defines.h | 1 + src/dllmain.cpp | 2 +- src/menu.cpp | 7 +- src/pch.h | 1 + src/ped.cpp | 33 +++- src/resourcestore.cpp | 16 +- src/resourcestore.h | 6 +- src/teleport.cpp | 42 ++--- src/vehicle.cpp | 43 ++++- src/visual.cpp | 2 +- src/weapon.cpp | 21 ++- src/widget.cpp | 214 +++++++++++++++++------ src/widget.h | 5 +- 17 files changed, 450 insertions(+), 236 deletions(-) diff --git a/resource/CheatMenuSA/data/particles.toml b/resource/CheatMenuSA/data/particles.toml index c5a03cc..58d7809 100644 --- a/resource/CheatMenuSA/data/particles.toml +++ b/resource/CheatMenuSA/data/particles.toml @@ -1,93 +1,91 @@ -############################################################################## -# Particle Names -# Example, -# [Category Name] -# particle_name = "" -############################################################################## +[Explosion] +'Barrel explosion' = 'explosion_barrel' +'Crate explosion' = 'explosion_crate' +'Door explosion' = 'explosion_door' +'Fuel car explosion' = 'explosion_fuel_car' +'Large explosion' = 'explosion_large' +'Medium explosion' = 'explosion_medium' +'Molotov explosion' = 'explosion_molotov' +'Small explosion' = 'explosion_small' +'Tiny explosion' = 'explosion_tiny' -[Custom] +[Fire] +Extinguisher = 'extinguisher' +Fire = 'fire' +'Fire bike' = 'fire_bike' +'Fire car' = 'fire_car' +'Fire large' = 'fire_large' +'Fire med' = 'fire_med' +Flame = 'flame' +Flamethrower = 'flamethrower' +'Molotov flame' = 'molotov_flame' +'Prt spark' = 'prt_spark' +'Prt spark2' = 'prt_spark2' -[Main] -prt_blood = "" -prt_boatsplash = "" -prt_bubbles = "" -prt_cardebris = "" -prt_collisionsmoke = "" -prt_glass = "" -prt_gunshell = "" -prt_sand = "" -prt_sand2 = "" -prt_smokeII_3_expand = "" -prt_smoke_huge = "" -prt_spark = "" -prt_spark2 = "" -prt_splash = "" -prt_wake = "" -prt_watersplash = "" -prt_wheeldirt = "" -boat_prop = "" -camflash = "" -exhale = "" -explosion_fuel_car = "" -explosion_large = "" -explosion_medium = "" -explosion_molotov = "" -explosion_small = "" -explosion_tiny = "" -extinguisher = "" -fire = "" -fire_bike = "" -fire_car = "" -fire_large = "" -fire_med = "" -flamethrower = "" -gunflash = "" -gunsmoke = "" -heli_dust = "" -jetpack = "" -jetthrust = "" -molotov_flame = "" -nitro = "" -overheat_car = "" -overheat_car_electric = "" -riot_smoke = "" -spraycan = "" -tank_fire = "" -teargas = "" -teargasAD = "" -water_hydrant = "" -water_ripples = "" -water_speed = "" -water_splash = "" -water_splsh_big = "" -water_splsh_sml = "" -water_swim = "" -cigarette_smoke = "" -flame = "" -insects = "" -smoke30lit = "" -smoke30m = "" -smoke50lit = "" -vent = "" -vent2 = "" -waterfall_end = "" -water_fnt_tme = "" -water_fountain = "" -tree_hit_fir = "" -tree_hit_palm = "" -blood_heli = "" -carwashspray = "" -cement = "" -cloudfast = "" -coke_puff = "" -coke_trail = "" -explosion_barrel = "" -explosion_crate = "" -explosion_door = "" -petrolcan = "" -puke = "" -shootlight = "" -smoke_flare = "" -wallbust = "" -ws_factorysmoke = "" +[Smoke] +'Cigarette smoke' = 'cigarette_smoke' +'Collision smoke' = 'prt_collisionsmoke' +'Factory smoke' = 'ws_factorysmoke' +Gunsmoke = 'gunsmoke' +'Riot smoke' = 'riot_smoke' +'Smoke 1' = 'smoke30lit' +'Smoke 2' = 'smoke30m' +'Smoke 3' = 'smoke50lit' +'Smoke 4' = 'prt_smokeII_3_expand' +'Smoke huge' = 'prt_smoke_huge' +'Smoke flare' = 'smoke_flare' +[Water] +'Prt boatsplash' = 'prt_boatsplash' +'Prt splash' = 'prt_splash' +'Prt watersplash' = 'prt_watersplash' +'Water big splsh' = 'water_splsh_big' +'Water fnt tme' = 'water_fnt_tme' +'Water fountain' = 'water_fountain' +'Water hydrant' = 'water_hydrant' +'Water ripples' = 'water_ripples' +'Water sml splsh' = 'water_splsh_sml' +'Water speed' = 'water_speed' +'Water splash' = 'water_splash' +'Water swim' = 'water_swim' +'Waterfall end' = 'waterfall_end' + +[Misc] +'Blood heli' = 'blood_heli' +'Boat prop' = 'boat_prop' +Camflash = 'camflash' +'Carwash spray' = 'carwashspray' +Cement = 'cement' +Cloudfast = 'cloudfast' +'Coke puff' = 'coke_puff' +'Coke trail' = 'coke_trail' +Exhale = 'exhale' +Gunflash = 'gunflash' +'Heli dust' = 'heli_dust' +Insects = 'insects' +Jetpack = 'jetpack' +Jetthrust = 'jetthrust' +Nitro = 'nitro' +'Overheat car' = 'overheat_car' +'Overheat electric car' = 'overheat_car_electric' +Petrolcan = 'petrolcan' +'Prt blood' = 'prt_blood' +'Prt bubbles' = 'prt_bubbles' +'Prt cardebris' = 'prt_cardebris' +'Prt glass' = 'prt_glass' +'Prt gunshell' = 'prt_gunshell' +'Prt sand' = 'prt_sand' +'Prt sand2' = 'prt_sand2' +'Prt wake' = 'prt_wake' +'Prt wheeldirt' = 'prt_wheeldirt' +Puke = 'puke' +Shootlight = 'shootlight' +Spraycan = 'spraycan' +'Tank fire' = 'tank_fire' +Teargas = 'teargas' +Teargasad = 'teargasAD' +'Tree hit fir' = 'tree_hit_fir' +'Tree hit palm' = 'tree_hit_palm' +Vent = 'vent' +Vent2 = 'vent2' +Wallbust = 'wallbust' \ No newline at end of file diff --git a/resource/common/locale/English.toml b/resource/common/locale/English.toml index 33212bb..52070d1 100644 --- a/resource/common/locale/English.toml +++ b/resource/common/locale/English.toml @@ -5,9 +5,6 @@ ###################################################################### [Animation] -AddAnimation = "Add animation" -AddParticle = "Add particle" -AnimationRemoved = "Animation removed" AnimationTab = "Animation##TABBAR" AnimName = "Anim name" CustomAnimsOnly = "You can only remove custom animations" @@ -22,6 +19,8 @@ LoopCheckbox = "Loop" LoopCheckboxText = "Keep playing the animation on repeat" NoTarget = "No player target found. Aim a ped with a weapon to select it for animation player." ParticleName = "Particle name" +ParticleID = "Particle id" +ParticleAdded = "Particle added" ParticleRemoved = "Particle removed" ParticleTab = "Particle##TABBAR" PedAnim = "Ped anim" @@ -260,6 +259,8 @@ WelcomeMSG = "Welcome to Cheat Menu" [Ped] Accuracy = "Accuracy" +AddPed = "Add ped" +AddPedMSG = "Ped added" BigHead = "Big head effect" ConfigTab = "Config" DownloadExGangWars = "Download ExGangWars" @@ -272,8 +273,10 @@ GangsControl = "Gangs control streets" GangsEverywhere = "Gangs everywhere" Gangs = "Gangs" GangWars = "Gang wars" +GetPlayerModel = "Insert player model" Health = "Health" MaxLimit = "Max limit reached" +Model = "Model" NastyLimbs = "Nasty limbs" NoMove = "Don't move" NoProstitutes = "No prostitutes" @@ -403,9 +406,7 @@ Walking = "Walking" Wasted = "Wasted!" [Teleport] -AddLocation = "Add location" Coordinates = "Coordinates" -CustomLocationRemoveOnly = "You can only remove custom location" CustomMapSize = "Custom map size" CustomMapSizeHint = "Custom game map size for quick teleport. Only needed for Total Conversion mods (SAxVCxLC)" Height = "Height" @@ -434,6 +435,7 @@ NotFound = "No update found" [Vehicle] Abs = "Abs" ADM = "Anti dive multiplier" +AddVehicle = "Add vehicle" AggroDriver = "Aggressive driver" AimDrive = "Aim while driving" All = "All" @@ -502,6 +504,7 @@ ForCurVeh = "For current vehicle," FourWheelDrive = "Four wheel drive" FrontLights = "Front lights" FrontWheelDrive = "Front wheel drive" +GetCurrentVehInfo = "Current vehicle info" GreenLights = "Green traffic lights" HandlingFlags = "Handling flags" HandlingTab = "Handling" @@ -511,12 +514,11 @@ HSTargetTip = "Heat Seaker missile can target this" IDSpawnText = "Spawn with ID (Enter)" InfNitro = "Unlimited nitro" InfNitroTip = """ -Nitro will activate when left clicked - - -Enabling this would disable +Enabling this would disable, All cars have nitro -All taxis have nitro""" +All taxis have nitro + +(Activate nitro with left click)""" InstantStop = "Instant stop" InvalidID = "Invalid model ID" InvisCar = "Invisible car" @@ -531,14 +533,16 @@ Mass = "Mass" MatFilter = "Material filter" MaxVelocity = "Max velocity" MeleeProof = "Melee proof" +Model = "Model" ModelFlags = "Model flags" MonValue = "Monetary value" LockTrainCam = "Lock train cam" NeonsTab = "Neons" NoColl = "Disable collisions" +NoDerail = "No train derail" +NotInVehicle = "Not inside vehicle!" NoNearVeh = "No nearby vehicles!" NoParticles = "Disable particles" -NoDerail = "No train derail" NumGears = "Number of gears" Off = "Off" On = "On" @@ -783,13 +787,27 @@ Weapon3 = "Weapon 3" WeaponTweaksText = """ Weapon tweaks apply globally to every ped weapon type""" +WeaponType = "Weapon type" [Window] +AddEntry = "Add entry" +AddEntryMSG = "Entry added" AddNew = "Add new" +AddNewCustomImg = "How to add custom images for entries?" +AddNewTip = "Providing wrong values might crash your game" +AddNewTip2 = """ +Custom entry images can be added inside texture file. + +1. Open up the 'CheatMenuSA/{}.txd' file using Magic.TXD program. +2. Add your images to that file (Follow aspect ratio & naming format) +3. Save & try in game +""" AnimationPage = "Animation" CheckboxTab = "Checkboxes" CopiedToClipboard = "Copied to clipboard" +CustomRemoveOnly = "You can only remove added entries" Default = "Def" +DownloadMagicTxd = "Download Magic.TXD" Enabled = "Enabled" GamePage = "Game" Info = "Info" diff --git a/src/animation.cpp b/src/animation.cpp index 46d9e5c..d09d79b 100644 --- a/src/animation.cpp +++ b/src/animation.cpp @@ -55,7 +55,7 @@ void Cutscene::Play(std::string& rootKey, std::string& cutsceneId, std::string& } } -void Particle::Play(std::string& rootKey, std::string& particle, std::string& dummy) +void Particle::Play(std::string& cat, std::string& name, std::string& particle) { CPlayerPed* pPlayer = FindPlayerPed(); if (pPlayer) @@ -69,9 +69,9 @@ void Particle::Play(std::string& rootKey, std::string& particle, std::string& du } -void Particle::Remove(std::string& ifp, std::string& particle, std::string& dummy) +void Particle::Remove(std::string& cat, std::string& name, std::string& particle) { - if (ifp == "Custom") + if (cat == "Custom") { Particle::m_Data.m_pData->RemoveKey("Custom", particle.c_str()); Particle::m_Data.m_pData->Save(); @@ -340,27 +340,27 @@ void Animation::ShowPage() } else { - if (ImGui::CollapsingHeader(TEXT("Window.AddNew"))) - { - static char animBuf[INPUT_BUFFER_SIZE]; - static char ifpBuf[INPUT_BUFFER_SIZE]; - - ImGui::InputTextWithHint(TEXT("Animation.IFPName"), "ped", ifpBuf, INPUT_BUFFER_SIZE); - ImGui::InputTextWithHint(TEXT("Animation.AnimName"), "cower", animBuf, INPUT_BUFFER_SIZE); - ImGui::Spacing(); - if (ImGui::Button(TEXT("Animation.AddAnimation"), Widget::CalcSize())) - { - std::string key = std::string("Custom.") + animBuf; - m_AnimData.m_pData->Set(key.c_str(), std::string(ifpBuf)); - m_AnimData.m_pData->Save(); - } - } ImGui::Spacing(); if (ImGui::BeginChild("Anims Child")) { ImGui::Spacing(); - Widget::DataList(m_AnimData, Play, Remove); + Widget::DataList(m_AnimData, Play, Remove, + [](){ + static char animBuf[INPUT_BUFFER_SIZE]; + static char ifpBuf[INPUT_BUFFER_SIZE]; + + ImGui::InputTextWithHint(TEXT("Animation.IFPName"), "ped", ifpBuf, INPUT_BUFFER_SIZE); + ImGui::InputTextWithHint(TEXT("Animation.AnimName"), "cower", animBuf, INPUT_BUFFER_SIZE); + ImGui::Spacing(); + if (ImGui::Button(TEXT("Window.AddEntry"), Widget::CalcSize())) + { + std::string key = std::string("Custom.") + animBuf; + m_AnimData.m_pData->Set(key.c_str(), std::string(ifpBuf)); + m_AnimData.m_pData->Save(); + Util::SetMessage("Window.AddEntryMSG"); + } + }); ImGui::EndChild(); } } @@ -474,23 +474,24 @@ void Animation::ShowPage() pPlayer->m_nPedFlags.bDontRender = (pPlayer->m_nPedFlags.bDontRender == 1) ? 0 : 1; } ImGui::Spacing(); - if (ImGui::CollapsingHeader(TEXT("Window.AddNew"))) - { - static char buf[INPUT_BUFFER_SIZE]; - ImGui::InputTextWithHint(TEXT("Animation.ParticleName"), "kkjj_on_fire", buf, INPUT_BUFFER_SIZE); - ImGui::Spacing(); - if (ImGui::Button(TEXT("Animation.AddParticle"), Widget::CalcSize())) - { - std::string key = std::string("Custom.") + buf; - m_AnimData.m_pData->Set(key.c_str(), std::string("Dummy")); - Particle::m_Data.m_pData->Save(); - } - } ImGui::Spacing(); if (ImGui::BeginChild("Anims Child")) { ImGui::Spacing(); - Widget::DataList(Particle::m_Data, Particle::Play, Particle::Remove); + Widget::DataList(Particle::m_Data, Particle::Play, Particle::Remove, + [](){ + static char name[INPUT_BUFFER_SIZE], particle[INPUT_BUFFER_SIZE]; + ImGui::InputTextWithHint(TEXT("Animation.ParticleName"), "KKJJ fire particle", name, INPUT_BUFFER_SIZE); + ImGui::InputTextWithHint(TEXT("Animation.ParticleID"), "kkjj_on_fire", particle, INPUT_BUFFER_SIZE); + ImGui::Spacing(); + if (ImGui::Button(TEXT("Window.AddEntry"), Widget::CalcSize())) + { + std::string key = std::string("Custom.") + name; + Particle::m_Data.m_pData->Set(key.c_str(), std::string(particle)); + Particle::m_Data.m_pData->Save(); + Util::SetMessage(TEXT("Window.AddEntryMSG")); + } + }); ImGui::EndChild(); } ImGui::EndTabItem(); diff --git a/src/cheatmenu.cpp b/src/cheatmenu.cpp index 3ecbf8e..7cb8350 100644 --- a/src/cheatmenu.cpp +++ b/src/cheatmenu.cpp @@ -312,12 +312,12 @@ void CheatMenu::ShowAnniversaryPage() if (ImGui::Button(TEXT("Menu.DiscordServer"), ImVec2(Widget::CalcSize(3)))) { - ShellExecute(nullptr, "open", DISCORD_INVITE, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(DISCORD_INVITE); } ImGui::SameLine(); if (ImGui::Button(TEXT("Menu.GitHubRepo"), ImVec2(Widget::CalcSize(3)))) { - ShellExecute(nullptr, "open", GITHUB_LINK, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(GITHUB_LINK); } } @@ -333,12 +333,12 @@ void CheatMenu::ShowWelcomePage() ImGui::NewLine(); if (ImGui::Button(TEXT("Menu.DiscordServer"), ImVec2(Widget::CalcSize(2)))) { - ShellExecute(nullptr, "open", DISCORD_INVITE, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(DISCORD_INVITE); } ImGui::SameLine(); if (ImGui::Button(TEXT("Menu.GitHubRepo"), ImVec2(Widget::CalcSize(2)))) { - ShellExecute(nullptr, "open", GITHUB_LINK, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(GITHUB_LINK); } ImGui::NewLine(); ImGui::TextWrapped(TEXT("Menu.BugDisclaimer")); @@ -361,7 +361,7 @@ void CheatMenu::ShowUpdatePage() ImGui::Dummy(ImVec2(0, 5)); if (ImGui::Button(TEXT("Menu.DiscordServer"), ImVec2(Widget::CalcSize(2)))) { - ShellExecute(nullptr, "open", DISCORD_INVITE, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(DISCORD_INVITE); } ImGui::SameLine(); diff --git a/src/defines.h b/src/defines.h index 3888dbc..7c4f259 100644 --- a/src/defines.h +++ b/src/defines.h @@ -23,6 +23,7 @@ #define FILE_NAME BY_GAME("CheatMenuSA" , "CheatMenuVC", "CheatMenuIII") #define MENU_DATA_PATH(x) (PLUGIN_PATH((char*)FILE_NAME##"/"##x)) #define MENU_DATA_EXISTS(x) (std::filesystem::exists(MENU_DATA_PATH(x))) +#define OPEN_LINK(x) ShellExecute(nullptr, "open", x, nullptr, nullptr, SW_SHOWNORMAL) diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 0a4315a..6fc1334 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -45,7 +45,7 @@ void MenuThread(void* param) if (msgID == IDOK) { - ShellExecute(nullptr, "open", "https://gtaforums.com/topic/669045-silentpatch/", nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK("https://gtaforums.com/topic/669045-silentpatch/"); }; return; } diff --git a/src/menu.cpp b/src/menu.cpp index 8bca597..b10f3bc 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -32,7 +32,8 @@ void Menu::ShowPage() && !FontMgr::IsSupportPackageInstalled()) { ImGui::Spacing(); - ImGui::TextWrapped("Font support package is required to display this language! This may take a while depending on your connection."); + ImGui::TextWrapped("Font support package is required to display this language!" +" This may take a while depending on your internet connection.\n\nIt's recommended NOT to install unless you want to use this language! (Affects game loading time)"); ImGui::Spacing(); if (ImGui::Button("Install package", ImVec2(Widget::CalcSize(2)))) { @@ -288,14 +289,14 @@ void Menu::ShowPage() if (ImGui::Button(TEXT("Menu.DiscordServer"), ImVec2(Widget::CalcSize(3)))) { - ShellExecute(nullptr, "open", DISCORD_INVITE, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(DISCORD_INVITE); } ImGui::SameLine(); if (ImGui::Button(TEXT("Menu.GitHubRepo"), ImVec2(Widget::CalcSize(3)))) { - ShellExecute(nullptr, "open", GITHUB_LINK, nullptr, nullptr, SW_SHOWNORMAL); + OPEN_LINK(GITHUB_LINK); } ImGui::Spacing(); diff --git a/src/pch.h b/src/pch.h index 9d46441..605be08 100644 --- a/src/pch.h +++ b/src/pch.h @@ -80,6 +80,7 @@ extern DataStore gConfig; typedef void(*ArgCallback3)(std::string&, std::string&, std::string&); typedef void(*ArgCallback)(std::string&); +typedef void(*ArgCallbackNone)(); typedef std::string(*ArgCallbackRtn)(std::string&); typedef bool(*ArgCallbackRtnBool)(std::string&); diff --git a/src/ped.cpp b/src/ped.cpp index f3c1e15..bcb7d26 100644 --- a/src/ped.cpp +++ b/src/ped.cpp @@ -306,9 +306,38 @@ void Ped::ShowPage() ImGui::Spacing(); #ifdef GTASA Widget::ImageList(m_PedData, SpawnPed, - [](std::string& str) - { + [](std::string& str){ return m_PedData.m_pData->Get(str.c_str(), "Unknown"); + }, nullptr, + [](){ + static char name[8]; + static int model = 0; + ImGui::InputTextWithHint(TEXT("Menu.Name"), "PEDNAME", name, 7); + Widget::InputInt(TEXT("Ped.Model"), &model, 1, 0, 999999); + ImGui::Spacing(); + ImVec2 sz = Widget::CalcSize(2); + if (ImGui::Button(TEXT("Ped.AddPed"), sz)) + { + Command(model); + Command(); + if (Command(model)) + { + std::string key = std::format("Custom.{} (Added)", name); + m_PedData.m_pData->Set(key.c_str(), std::to_string(model)); + m_PedData.m_pData->Save(); + Util::SetMessage(TEXT("Ped.AddPedMSG")); + Command(model); + } + else + { + Util::SetMessage(TEXT("Vehicle.InvalidID")); + } + } + ImGui::SameLine(); + if (ImGui::Button(TEXT("Ped.GetPlayerModel"), sz)) + { + model = FindPlayerPed()->m_nModelIndex; + } }); #else Widget::DataList(m_PedData, SpawnPed, nullptr); diff --git a/src/resourcestore.cpp b/src/resourcestore.cpp index e9c5acf..ca4fc9e 100644 --- a/src/resourcestore.cpp +++ b/src/resourcestore.cpp @@ -2,7 +2,7 @@ #include "pch.h" ResourceStore::ResourceStore(const char* text, eResourceType type, ImVec2 imageSize) - : m_ImageSize(imageSize), m_Type(type) + : m_ImageSize(imageSize), m_Type(type), m_FileName(text) { if (m_Type != eResourceType::TYPE_IMAGE) { @@ -50,7 +50,7 @@ RwTexDictionary* LoadTexDictionary(char const* filename) { return plugin::CallAndReturnDynGlobal(0x5B3860, filename); } -RwTexture* ResourceStore::FindTextureByName(std::string&& name) +RwTexture* ResourceStore::FindRwTextureByName(const std::string& name) { for (auto& item: m_ImagesList) { @@ -62,6 +62,16 @@ RwTexture* ResourceStore::FindTextureByName(std::string&& name) return nullptr; } +IDirect3DTexture9** ResourceStore::FindTextureByName(const std::string& name) +{ + RwTexture *pTex = FindRwTextureByName(name); + if (pTex) + { + return GetTextureFromRaster(pTex); + } + return nullptr; +} + void ResourceStore::LoadTextureResource(std::string&& name) { std::string fullPath = PLUGIN_PATH((char*)FILE_NAME "\\") + name + ".txd"; @@ -78,7 +88,7 @@ void ResourceStore::LoadTextureResource(std::string&& name) { RwLinkList *pRLL = (RwLinkList*)pRwTexDictionary->texturesInDict.link.next; RwTexDictionary *pEndDic; - bool addCategories = (m_Categories.size() < 2); // "All" + bool addCategories = (m_Categories.size() < 3); // "All", "Custom" do { pEndDic = (RwTexDictionary*)pRLL->link.next; diff --git a/src/resourcestore.h b/src/resourcestore.h index a721f23..57259f2 100644 --- a/src/resourcestore.h +++ b/src/resourcestore.h @@ -57,8 +57,9 @@ private: public: ImGuiTextFilter m_Filter = ""; - std::vector m_Categories = {"All"}; + std::vector m_Categories = {"All", "Custom"}; std::string m_Selected = "All"; + std::string m_FileName; std::unique_ptr m_pData; std::vector> m_ImagesList; ImVec2 m_ImageSize; @@ -67,5 +68,6 @@ public: ResourceStore(const char* text, eResourceType type = TYPE_IMAGE, ImVec2 imageSize = ImVec2(64, 64)); - RwTexture* FindTextureByName(std::string&& name); + RwTexture* FindRwTextureByName(const std::string& name); + IDirect3DTexture9** FindTextureByName(const std::string& name); }; \ No newline at end of file diff --git a/src/teleport.cpp b/src/teleport.cpp index 83528ec..45b3a30 100644 --- a/src/teleport.cpp +++ b/src/teleport.cpp @@ -59,7 +59,7 @@ void Teleport::Init() static CSprite2d map; if (!map.m_pTexture) { - map.m_pTexture = gTextureList.FindTextureByName("map"); + map.m_pTexture = gTextureList.FindRwTextureByName("map"); } float height = screen::GetScreenHeight(); float width = screen::GetScreenWidth(); @@ -309,27 +309,6 @@ void Teleport::ShowPage() #ifdef GTASA FetchRadarSpriteData(); #endif - ImGui::Spacing(); - if (ImGui::CollapsingHeader(TEXT("Window.AddNew"))) - { - ImGui::Spacing(); - ImGui::InputTextWithHint(TEXT("Teleport.Location"), TEXT("Teleport.LocationHint"), locBuf, INPUT_BUFFER_SIZE); - ImGui::InputTextWithHint(TEXT("Teleport.Coordinates"), "x, y, z", inBuf, INPUT_BUFFER_SIZE); - ImGui::Spacing(); - if (ImGui::Button(TEXT("Teleport.AddLocation"), Widget::CalcSize())) - { - std::string key = std::string("Custom.") + locBuf; - m_locData.m_pData->Set(key.c_str(), ("0, " + std::string(inBuf))); - - #ifdef GTASA - // Clear the Radar coordinates - m_locData.m_pData->RemoveTable("Radar"); - #endif - - m_locData.m_pData->Save(); - } - } - ImGui::Spacing(); Widget::DataList(m_locData, [](std::string& unk1, std::string& unk2, std::string& loc){ @@ -353,7 +332,24 @@ void Teleport::ShowPage() } else { - Util::SetMessage(TEXT("Teleport.CustomLocationRemoveOnly")); + Util::SetMessage(TEXT("Window.CustomRemoveOnly")); + } + }, + [](){ + ImGui::InputTextWithHint(TEXT("Teleport.Location"), TEXT("Teleport.LocationHint"), locBuf, INPUT_BUFFER_SIZE); + ImGui::InputTextWithHint(TEXT("Teleport.Coordinates"), "x, y, z", inBuf, INPUT_BUFFER_SIZE); + ImGui::Spacing(); + if (ImGui::Button(TEXT("Window.AddEntry"), Widget::CalcSize())) + { + std::string key = std::string("Custom.") + locBuf; + m_locData.m_pData->Set(key.c_str(), ("0, " + std::string(inBuf))); +#ifdef GTASA + // Clear the Radar coordinates + m_locData.m_pData->RemoveTable("Radar"); +#endif + + m_locData.m_pData->Save(); + Util::SetMessage(TEXT("Window.AddEntryMSG")); } }); ImGui::EndTabItem(); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index dc50021..90c89e9 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1139,9 +1139,46 @@ void Vehicle::ShowPage() ImGui::InputTextWithHint("##LicenseText", TEXT("Vehicle.PlateText"), Spawner::m_nLicenseText, 9); Widget::ImageList(Spawner::m_VehData, SpawnVehicle, - [](std::string& str) - { + [](std::string& str){ return GetNameFromModel(std::stoi(str)); + }, nullptr, + [](){ + static char name[INPUT_BUFFER_SIZE]; + static int model = 0; + ImGui::InputTextWithHint(TEXT("Menu.Name"), "Cheetah", name, INPUT_BUFFER_SIZE); + Widget::InputInt(TEXT("Vehicle.Model"), &model, 1, 0, 999999); + ImGui::Spacing(); + ImVec2 sz = Widget::CalcSize(2); + if (ImGui::Button(TEXT("Window.AddEntry"), sz)) + { + if (Command(model)) + { + std::string key = std::format("Custom.{} (Added)", name); + Spawner::m_VehData.m_pData->Set(key.c_str(), std::to_string(model)); + Spawner::m_VehData.m_pData->Save(); + Util::SetMessage(TEXT("Window.AddEntryMSG")); + } + else + { + Util::SetMessage(TEXT("Vehicle.InvalidID")); + } + } + ImGui::SameLine(); + if (ImGui::Button(TEXT("Vehicle.GetCurrentVehInfo"), sz)) + { + CPlayerPed *pPlayer = FindPlayerPed(); + int hPlayer = CPools::GetPedRef(pPlayer); + if (Command(hPlayer)) + { + model = pPlayer->m_pVehicle->m_nModelIndex; + std::string str = Vehicle::GetNameFromModel(model); + strcpy(name, str.c_str()); + } + else + { + Util::SetMessage(TEXT("Vehicle.NotInVehicle")); + } + } }); #else Widget::DataList(Spawner::m_VehData, SpawnVehicle, nullptr); @@ -1399,7 +1436,7 @@ void Vehicle::ShowPage() [](std::string& str) { return str; - }); + }, nullptr, [](){}); ImGui::EndTabItem(); } diff --git a/src/visual.cpp b/src/visual.cpp index a61f9c0..be2ec41 100644 --- a/src/visual.cpp +++ b/src/visual.cpp @@ -716,7 +716,7 @@ void Visual::ShowPage() { static float var = 0.000001f; static CSprite2d sprite; - sprite.m_pTexture = gTextureList.FindTextureByName("radardisc"); + sprite.m_pTexture = gTextureList.FindRwTextureByName("radardisc"); // rediect to our texture patch::Set(0x58A8C9, &sprite); diff --git a/src/weapon.cpp b/src/weapon.cpp index 5cfaeed..7dbd4a1 100644 --- a/src/weapon.cpp +++ b/src/weapon.cpp @@ -367,6 +367,21 @@ void Weapon::ShowPage() [](std::string& str) { return str != "0"; /*Unarmed*/ + }, + [](){ + static char name[INPUT_BUFFER_SIZE]; + static int model = 0; + ImGui::InputTextWithHint(TEXT("Menu.Name"), "Minigun", name, INPUT_BUFFER_SIZE); + Widget::InputInt(TEXT("Weapon.WeaponType"), &model, 1, 0, 999999); + ImGui::Spacing(); + ImVec2 sz = Widget::CalcSize(1); + if (ImGui::Button(TEXT("Window.AddEntry"), sz)) + { + std::string key = std::format("Custom.{} (Added)", name); + m_WeaponData.m_pData->Set(key.c_str(), std::to_string(model)); + m_WeaponData.m_pData->Save(); + Util::SetMessage(TEXT("Window.AddEntryMSG")); + } }); #else Widget::DataList(m_WeaponData, GiveWeaponToPlayer, nullptr); @@ -390,12 +405,10 @@ void Weapon::ShowPage() ImGui::Text(TEXT("Weapon.CurrentWeapon"), m_WeaponData.m_pData->Get(key.c_str(), "Unknown").c_str()); ImGui::Spacing(); Widget::ImageList(m_WeaponData, SetGangWeapon, - [](std::string& str) - { + [](std::string& str){ return m_WeaponData.m_pData->Get(str.c_str(), "Unknown"); }, - [](std::string& str) - { + [](std::string& str){ return str != "-1"; /*Jetpack*/ }); ImGui::EndTabItem(); diff --git a/src/widget.cpp b/src/widget.cpp index 94c88ce..488558f 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -7,6 +7,7 @@ static struct std::string root, key, val; void* func = nullptr; bool show = false; + bool added = false; } contextMenu; ImVec2 Widget::CalcSize(short count, bool spacing) @@ -75,7 +76,7 @@ void Widget::Filter(const char* label, ImGuiTextFilter& filter, const char* hint } } -void Widget::DataList(ResourceStore& data, ArgCallback3 clickFunc, ArgCallback3 removeFunc) +void Widget::DataList(ResourceStore& data, ArgCallback3 clickFunc, ArgCallback3 removeFunc, ArgCallbackNone addFunc) { if (ImGui::IsMouseClicked(1)) { @@ -207,37 +208,54 @@ void Widget::DataList(ResourceStore& data, ArgCallback3 clickFunc, ArgCallback3 ImGui::EndChild(); ImGui::EndTabItem(); } + if (addFunc) + { + if (ImGui::BeginTabItem(TEXT("Window.AddNew"))) + { + ImGui::Spacing(); + ImGui::BeginChild("AddNew2"); + ImGui::TextWrapped(TEXT("Window.AddNewTip")); + ImGui::Dummy(ImVec2(0, 5)); + addFunc(); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + } ImGui::EndTabBar(); } } -static bool RoundedImageButton(ImTextureID user_texture_id, ImVec2& size, const char* hover_text) +static bool RoundedImageButton(ImTextureID textureID, ImVec2& size, const char* hoverText, bool alwaysHovered = false) { // Default to using texture ID as ID. User can still push string/integer prefixes. // Creating a invisible button as placeholder - ImGui::InvisibleButton(hover_text, size); + ImGui::InvisibleButton(hoverText, size); ImVec2 min = ImGui::GetItemRectMin(); ImVec2 max = ImGui::GetItemRectMax(); ImDrawList *drawList = ImGui::GetWindowDrawList(); - drawList->AddImageRounded(user_texture_id, min, max, ImVec2(0, 0), ImVec2(1, 1), ImGui::GetColorU32(ImVec4(1, 1, 1, 1)), 5.0f); + drawList->AddImageRounded(textureID, min, max, ImVec2(0, 0), ImVec2(1, 1), ImGui::GetColorU32(ImVec4(1, 1, 1, 1)), 5.0f); // Add selection overlay and stuff on hover - if (ImGui::IsItemHovered()) + bool isHovered = ImGui::IsItemHovered(); + if (isHovered || alwaysHovered) { - drawList->AddRectFilled(min, max, ImGui::GetColorU32(ImGuiCol_ModalWindowDimBg), 5.6f); + if (isHovered) + { + drawList->AddRectFilled(min, max, ImGui::GetColorU32(ImGuiCol_ModalWindowDimBg), 5.6f); + } // Calculating and drawing text over the image - ImVec2 textSize = ImGui::CalcTextSize(hover_text); + ImVec2 textSize = ImGui::CalcTextSize(hoverText); if (textSize.x < size.x) { float offsetX = (ImGui::GetItemRectSize().x - textSize.x) / 2; - drawList->AddText(ImVec2(min.x + offsetX, min.y + 10), ImGui::GetColorU32(ImGuiCol_Text), hover_text); + drawList->AddText(ImVec2(min.x + offsetX, min.y + 10), ImGui::GetColorU32(ImGuiCol_Text), hoverText); } else { std::string buf = ""; - std::stringstream ss(hover_text); + std::stringstream ss(hoverText); short count = 1; while (ss >> buf) @@ -254,8 +272,14 @@ static bool RoundedImageButton(ImTextureID user_texture_id, ImVec2& size, const return ImGui::IsItemClicked(0); } -void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc, ArgCallbackRtnBool verifyFunc) +/* + Here we go again... + This direly needs a refactor oof +*/ +void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc, + ArgCallbackRtnBool verifyFunc, ArgCallbackNone addFunc) { + static IDirect3DTexture9 **pDefaultTex = nullptr; ImGuiStyle& style = ImGui::GetStyle(); /* Trying to scale images based on resolutions @@ -316,30 +340,55 @@ void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackR && (verifyFunc == nullptr || verifyFunc(text)) ) { - /* - Couldn't figure out how to laod images for Dx11 - Using texts for now - */ - if (showImages) + if (showImages ? RoundedImageButton(store.m_ImagesList[i]->m_pTexture, m_ImageSize, modelName.c_str()) + : ImGui::MenuItem(modelName.c_str()) + ) { - if (RoundedImageButton(store.m_ImagesList[i]->m_pTexture, m_ImageSize, modelName.c_str())) - { - clickFunc(text); - } - - } - else - { - if (ImGui::MenuItem(modelName.c_str())) - { - clickFunc(text); - } + clickFunc(text); } // Right click popup if (ImGui::IsItemClicked(1)) { contextMenu.show = true; + contextMenu.added = false; + contextMenu.val = text; + contextMenu.key = modelName; + } + + if (showImages) + { + if (imageCount % imagesInRow != 0) + { + ImGui::SameLine(0.0, style.ItemInnerSpacing.x); + } + } + imageCount++; + } + } + for (auto [k, v] : *store.m_pData->GetTable("Custom")) + { + if (!pDefaultTex) + { + pDefaultTex = gTextureList.FindTextureByName("placeholder"); + } + std::string modelName = std::string(k.str()); + std::string text = v.as_string()->value_or("0"); + if (store.m_Filter.PassFilter(modelName.c_str()) + && (store.m_Selected == "Custom" || store.m_Selected == "All")) + { + if (showImages ? RoundedImageButton(pDefaultTex, m_ImageSize, modelName.c_str(), true) + : ImGui::MenuItem(modelName.c_str()) + ) + { + clickFunc(text); + } + + // Right click popup + if (ImGui::IsItemClicked(1)) + { + contextMenu.show = true; + contextMenu.added = (addFunc != nullptr); contextMenu.val = text; contextMenu.key = modelName; } @@ -362,10 +411,16 @@ void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackR ImGui::Separator(); if (ImGui::MenuItem(TEXT("Menu.Favourites"))) { - store.m_pData->Set(std::format("Favourites.{}", contextMenu.val).c_str(), contextMenu.key); + store.m_pData->Set(std::format("Favourites.{}", contextMenu.key).c_str(), contextMenu.val); store.m_pData->Save(); Util::SetMessage(TEXT("Menu.FavouritesText")); } + if (contextMenu.added && ImGui::MenuItem(TEXT("Menu.Remove"))) + { + store.m_pData->RemoveKey("Custom", contextMenu.key.c_str()); + store.m_pData->RemoveKey("Favourites", contextMenu.key.c_str()); + store.m_pData->Save(); + } if (ImGui::MenuItem(TEXT("Menu.Close"))) { contextMenu.show = false; @@ -388,39 +443,26 @@ void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackR for (auto [k, v] : *store.m_pData->GetTable("Favourites")) { - std::string val = std::string(k.str()); - - for (uint i = 0; i < store.m_ImagesList.size(); ++i) + auto str = k.str(); + bool state = str.find("Added") != std::string::npos; + if (state) { - std::string text = store.m_ImagesList[i]->m_FileName; - std::string modelName = getNameFunc(text); - - if (text == val && store.m_Filter.PassFilter(modelName.c_str()) && (verifyFunc == nullptr || verifyFunc(text))) + std::string modelName = std::string(k.str()); + std::string text = v.as_string()->value_or("0"); + if (store.m_Filter.PassFilter(modelName.c_str())) { - /* - Couldn't figure out how to laod images for Dx11 - Using texts for now - */ - if (showImages) + if (showImages ? RoundedImageButton(pDefaultTex, m_ImageSize, modelName.c_str(), true) + : ImGui::MenuItem(modelName.c_str()) + ) { - if (RoundedImageButton(store.m_ImagesList[i]->m_pTexture, m_ImageSize, modelName.c_str())) - { - clickFunc(text); - } - - } - else - { - if (ImGui::MenuItem(modelName.c_str())) - { - clickFunc(text); - } + clickFunc(text); } // Right click popup if (ImGui::IsItemClicked(1)) { contextMenu.show = true; + contextMenu.added = false; contextMenu.val = text; contextMenu.key = modelName; } @@ -435,6 +477,42 @@ void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackR imageCount++; } } + else + { + for (uint i = 0; i < store.m_ImagesList.size(); ++i) + { + std::string text = store.m_ImagesList[i]->m_FileName; + std::string modelName = getNameFunc(text); + + if (modelName == k.str() && store.m_Filter.PassFilter(modelName.c_str()) && (verifyFunc == nullptr || verifyFunc(text))) + { + if (showImages ? RoundedImageButton(store.m_ImagesList[i]->m_pTexture, m_ImageSize, modelName.c_str()) + : ImGui::MenuItem(modelName.c_str()) + ) + { + clickFunc(text); + } + + // Right click popup + if (ImGui::IsItemClicked(1)) + { + contextMenu.show = true; + contextMenu.added = false; + contextMenu.val = text; + contextMenu.key = modelName; + } + + if (showImages) + { + if (imageCount % imagesInRow != 0) + { + ImGui::SameLine(0.0, style.ItemInnerSpacing.x); + } + } + imageCount++; + } + } + } } if (store.m_pData->GetTable("Favourites")->size() == 0) { @@ -448,13 +526,14 @@ void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackR ImGui::Separator(); if (ImGui::MenuItem(TEXT("Menu.FavouritesRemove"))) { - store.m_pData->RemoveKey("Favourites", contextMenu.val.c_str()); + store.m_pData->RemoveKey("Favourites", contextMenu.key.c_str()); store.m_pData->Save(); Util::SetMessage(TEXT("Menu.FavouritesRemoveText")); } if (ImGui::MenuItem(TEXT("Menu.Close"))) { contextMenu.show = false; + contextMenu.added = false; } ImGui::EndPopup(); @@ -463,9 +542,36 @@ void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackR ImGui::EndChild(); ImGui::EndTabItem(); } + if (addFunc) + { + if (ImGui::BeginTabItem(TEXT("Window.AddNew"))) + { + ImGui::Spacing(); + ImGui::TextWrapped(TEXT("Window.AddNewTip")); + ImGui::Dummy(ImVec2(0, 5)); + + ImGui::BeginChild("AddNew2"); + addFunc(); + + ImGui::Dummy(ImVec2(0.0f, 10.0f)); + if (ImGui::CollapsingHeader(TEXT("Window.AddNewCustomImg"))) + { + ImGui::Spacing(); + ImGui::TextWrapped(std::vformat(TEXT("Window.AddNewTip2"), std::make_format_args(store.m_FileName)).c_str()); + ImGui::Spacing(); + if (ImGui::Button(TEXT("Window.DownloadMagicTxd"), Widget::CalcSize())) + { + OPEN_LINK("https://gtaforums.com/topic/851436-relopensrc-magictxd/"); + } + ImGui::Spacing(); + ImGui::Separator(); + } + ImGui::EndChild(); + ImGui::EndTabItem(); + } + } ImGui::EndTabBar(); } - if (showImages) { diff --git a/src/widget.h b/src/widget.h index d8553d2..c3ba150 100644 --- a/src/widget.h +++ b/src/widget.h @@ -41,7 +41,8 @@ public: static bool ColorBtn(int colorId, std::vector& color, ImVec2 size); // Draws DataStore data in the interface - static void DataList(ResourceStore& data, ArgCallback3 clickFunc, ArgCallback3 removeFunc); + static void DataList(ResourceStore& data, ArgCallback3 clickFunc, ArgCallback3 removeFunc, + ArgCallbackNone addFunc = nullptr); // Draws a dropdown editor for memory address template @@ -70,7 +71,7 @@ public: // Draws ResourceStore images in the interface static void ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc, - ArgCallbackRtnBool verifyFunc = nullptr); + ArgCallbackRtnBool verifyFunc = nullptr, ArgCallbackNone addFunc = nullptr); // Draws a dropdown listbox static bool ListBox(const char* label, VecStr& allItems, int& selected);