From 1b793f2f0596bfd5e78959a5f3b5e26b4b366a51 Mon Sep 17 00:00:00 2001 From: Grinch_ Date: Fri, 12 Aug 2022 08:17:48 +0600 Subject: [PATCH] Refactor animation, particle, scene etc classes --- resource/common/locale/English.toml | 3 +- resource/common/locale/Portuguese.toml | 2 +- resource/common/locale/Spanish.toml | 2 +- resource/common/locale/chinese.toml | 2 +- src/cheatmenu.cpp | 5 +- src/cheatmenu.h | 2 +- src/custom/animation.cpp | 244 +++++++++++++ src/custom/animation.h | 38 +++ src/custom/cutscene_sa.cpp | 2 +- src/custom/cutscene_sa.h | 1 - src/custom/particle_sa.cpp | 47 +++ src/custom/particle_sa.h | 34 ++ src/defines.h | 2 +- src/pages/animation.cpp | 455 ------------------------- src/pages/animation.h | 58 ---- src/pages/menu.cpp | 4 +- src/pages/scene.cpp | 188 ++++++++++ src/pages/scene.h | 14 + src/pch.h | 14 +- src/utils/widget.cpp | 6 +- src/utils/widget.h | 6 +- 21 files changed, 591 insertions(+), 538 deletions(-) create mode 100644 src/custom/animation.cpp create mode 100644 src/custom/animation.h create mode 100644 src/custom/particle_sa.cpp create mode 100644 src/custom/particle_sa.h delete mode 100644 src/pages/animation.cpp delete mode 100644 src/pages/animation.h create mode 100644 src/pages/scene.cpp create mode 100644 src/pages/scene.h diff --git a/resource/common/locale/English.toml b/resource/common/locale/English.toml index 5abfab3..9c21e82 100644 --- a/resource/common/locale/English.toml +++ b/resource/common/locale/English.toml @@ -4,7 +4,7 @@ # Author: Grinch_ ###################################################################### -[Animation] +[Scene] AnimationTab = "Animation##TABBAR" AnimName = "Anim name" CustomAnimsOnly = "You can only remove custom animations" @@ -824,6 +824,7 @@ RemoveEntry = "Entry removed" Search = "Search" LocationsTab = "Locations" FavouritesTab = "Favourites" +ScenePage = "Scene" SetValue = "Set value" SpawnTab = "Spawn" TeleportPage = "Teleport" diff --git a/resource/common/locale/Portuguese.toml b/resource/common/locale/Portuguese.toml index bae8449..6b8f012 100644 --- a/resource/common/locale/Portuguese.toml +++ b/resource/common/locale/Portuguese.toml @@ -4,7 +4,7 @@ # Author: @_4l150n ###################################################################### -[Animation] +[Scene] AddAnimation = "Adicionar animação" AddParticle = "Adicionar partícula" AnimationRemoved = "Animação removida" diff --git a/resource/common/locale/Spanish.toml b/resource/common/locale/Spanish.toml index 30ccff5..fb0c8cd 100644 --- a/resource/common/locale/Spanish.toml +++ b/resource/common/locale/Spanish.toml @@ -4,7 +4,7 @@ # Author: Ruben Viera ###################################################################### -[Animation] +[Scene] AddAnimation = "Añadir animación" AddParticle = "Añadir particula" AnimationRemoved = "Animación removida" diff --git a/resource/common/locale/chinese.toml b/resource/common/locale/chinese.toml index 9c8153d..9b0d9a5 100644 --- a/resource/common/locale/chinese.toml +++ b/resource/common/locale/chinese.toml @@ -1,5 +1,5 @@ -[Animation] +[Scene] AddAnimation = "添加动画" AddParticle = "添加粒子" AnimationRemoved = "动画已删除" diff --git a/src/cheatmenu.cpp b/src/cheatmenu.cpp index 47f7454..60a4e9f 100644 --- a/src/cheatmenu.cpp +++ b/src/cheatmenu.cpp @@ -6,7 +6,7 @@ #include "utils/d3dhook.h" #include "utils/util.h" #include "utils/overlay.h" -#include "pages/animation.h" +#include "pages/scene.h" #include "pages/game.h" #include "pages/menu.h" #include "pages/ped.h" @@ -216,7 +216,7 @@ void CheatMenu::GenHeaderList() {TEXT_S("Window.TeleportPage"), &Teleport::ShowPage, eMenuPages::TELEPORT}, {TEXT_S("Window.PlayerPage"), &Player::ShowPage, eMenuPages::PLAYER}, {TEXT_S("Window.PedPage"), &Ped::ShowPage, eMenuPages::PED}, - {TEXT_S("Window.AnimationPage"), &Animation::ShowPage, eMenuPages::ANIMATION}, + {TEXT_S("Window.ScenePage"), &ScenePage::Draw, eMenuPages::SCENE}, {TEXT_S("Window.VehiclePage"), &Vehicle::ShowPage, eMenuPages::VEHICLE}, {TEXT_S("Window.WeaponPage"), &Weapon::ShowPage, eMenuPages::WEAPON}, {TEXT_S("Window.GamePage"), &Game::ShowPage, eMenuPages::GAME}, @@ -252,7 +252,6 @@ void CheatMenu::Init() GenHeaderList(); // Init menu parts - Animation::Init(); Game::Init(); Menu::Init(); Player::Init(); diff --git a/src/cheatmenu.h b/src/cheatmenu.h index 8acea97..630684d 100644 --- a/src/cheatmenu.h +++ b/src/cheatmenu.h @@ -10,7 +10,7 @@ class CheatMenu private: enum class eMenuPages { - ANIMATION, ANNIVERSARY, GAME, MENU, NONE, PED, PLAYER, TELEPORT, UPDATE, VEHICLE, VISUAL, WEAPON, WELCOME + ANNIVERSARY, GAME, MENU, NONE, PED, PLAYER, SCENE, TELEPORT, UPDATE, VEHICLE, VISUAL, WEAPON, WELCOME }; struct HeaderData { diff --git a/src/custom/animation.cpp b/src/custom/animation.cpp new file mode 100644 index 0000000..b7d9947 --- /dev/null +++ b/src/custom/animation.cpp @@ -0,0 +1,244 @@ +#include "pch.h" +#include "animation.h" +#include "utils/widget.h" + +#ifdef GTAVC +#include "kiero/minhook/MinHook.h" +#include +#include +#include "eAnimations.h" +#include +#elif GTA3 +#include +#include +#include +#include "eAnimations.h" +#include +#endif + +AnimationMgr& Animation = *AnimationMgr::Get(); + +AnimationMgr::AnimationMgr() +{ +#ifdef GTASA + Events::processScriptsEvent += [&] + { + CPlayerPed* pPlayer = FindPlayerPed(); + + if (pPlayer && pPlayer->m_pPlayerTargettedPed) + { + m_pTarget = pPlayer->m_pPlayerTargettedPed; + } + + if (m_pTarget && !m_pTarget->IsAlive()) + { + m_pTarget = nullptr; + } + }; +#elif GTAVC + // mov al, 01 + // ret + // nop (2x) + patch::SetRaw(0x40C9C0, (void*)"\xB0\x01\xC3\x90\x90", 5); + // // ret + // // nop (3x) + patch::SetRaw(0x404950, (void*)"\xC3\x90\x90\x90", 4); + + // Fix crash at 0x4019EA + static bool hookInjected = false; + Events::initGameEvent.before += [&hookInjected]() + { + if (hookInjected) + { + MH_DisableHook((void*)0x40D6E0); + } + }; + + Events::initGameEvent.after += [&hookInjected]() + { + MH_CreateHook((void*)0x40D6E0, NEW_CStreaming_RemoveModel, (void**)&OLD_CStreaming_RemoveModel); + MH_EnableHook((void*)0x40D6E0); + hookInjected = true; + }; +#endif +} + +#ifdef GTAVC +// Thanks to codenulls(https://github.com/codenulls/) +static auto OLD_CStreaming_RemoveModel = (bool(__cdecl*)(int))0x40D6E0; +static bool NEW_CStreaming_RemoveModel(int modelID) +{ + // Check if it's IFP animation block + if (modelID >= 7916 && modelID <= 7950) + { + // Do not unload the animation block + return true; + } + return OLD_CStreaming_RemoveModel(modelID); +} + +bool _LoadAnimationBlock(const char* szBlockName) +{ + CAnimBlock* pAnimBlock = CAnimManager::GetAnimationBlock(szBlockName); + if (pAnimBlock) + { + if (!pAnimBlock->bLoaded) + { + int animIndex = ((unsigned char*)pAnimBlock - (unsigned char*)CAnimManager::ms_aAnimBlocks) / 32; + CStreaming::RequestModel(7916 + animIndex, 0x20 | MISSION_REQUIRED | PRIORITY_REQUEST); + CStreaming::LoadAllRequestedModels(true); + if (pAnimBlock->bLoaded) + { + return true; + } + } + else + { + return true; + } + } + return false; +} + +void _PlayAnim(RpClump* pClump, int animGroup, int animID, float blend, bool loop, bool secondary) +{ + if (animGroup < CAnimManager::ms_numAnimAssocDefinitions) + { + CAnimationStyleDescriptor* pAnimDef = &CAnimManager::ms_aAnimAssocDefinitions[animGroup]; + if (pAnimDef) + { + if (!_LoadAnimationBlock(pAnimDef->blockName)) + { + return; + } + } + } + + CAnimBlendAssociation* pAnimAssoc = RpAnimBlendClumpGetFirstAssociation(pClump); + while (pAnimAssoc) + { + if (pAnimAssoc->m_nAnimId == animID && pAnimAssoc->m_nAnimGroup == animGroup) + { + // Destroy the animation + pAnimAssoc->~CAnimBlendAssociation(); + break; + } + pAnimAssoc = RpAnimBlendGetNextAssociation(pAnimAssoc); + } + pAnimAssoc = CAnimManager::BlendAnimation(pClump, animGroup, animID, blend); + pAnimAssoc->m_nFlags = ANIMATION_STARTED | ANIMATION_MOVEMENT; + + if (loop) + { + pAnimAssoc->m_nFlags |= ANIMATION_LOOPED; + } + + if (secondary) + { + pAnimAssoc->m_nFlags |= ANIMATION_PARTIAL; + } +} +#elif GTA3 +void _PlayAnim(RpClump* pClump, int animGroup, int animID, float blend, bool loop, bool secondary) +{ + CAnimBlendAssociation* pAnimStaticAssoc = CAnimManager::GetAnimAssociation(animGroup, animID); + CAnimBlendAssociation* pAnimAssoc = RpAnimBlendClumpGetFirstAssociation(pClump); + while (pAnimAssoc) + { + if (pAnimAssoc->m_nAnimID == pAnimStaticAssoc->m_nAnimID && pAnimAssoc->m_pAnimBlendHierarchy == pAnimStaticAssoc->m_pAnimBlendHierarchy) + { + // Destroy the animation + pAnimAssoc->FreeAnimBlendNodeArray(); + break; + } + pAnimAssoc = RpAnimBlendGetNextAssociation(pAnimAssoc); + } + pAnimAssoc = CAnimManager::BlendAnimation(pClump, animGroup, animID, blend); + pAnimAssoc->m_nFlags = 0x1 | 0x20; + + if (loop) + { + pAnimAssoc->m_nFlags |= 0x2; + } + + if (secondary) + { + pAnimAssoc->m_nFlags |= 0x10; + } +} +#endif + +void AnimationMgr::Play(std::string& cat, std::string& anim, std::string& ifp) +{ + CPed *pPed = m_bPedAnim ? m_pTarget : FindPlayerPed(); + if (!pPed) + { + return; + } + +#ifdef GTASA + int hPed = CPools::GetPedRef(pPed); + + if (ifp != "PED") + { + Command(ifp.c_str()); + Command(); + } + + Command(hPed); + if (m_bSecondary) + { + Command(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1); + } + else + { + Command(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1); + } + + if (ifp != "PED") + { + Command(ifp.c_str()); + } + +#else + int groupID, animID; + sscanf(ifp.c_str(), "%d$%d,", &groupID, &animID); + _PlayAnim(pPed->m_pRwClump, groupID, animID, 4.0f, m_Loop, m_bSecondary); +#endif +} + +void AnimationMgr::AddNew() +{ + static char animBuf[INPUT_BUFFER_SIZE]; + static char ifpBuf[INPUT_BUFFER_SIZE]; + + ImGui::InputTextWithHint(TEXT("Scene.IFPName"), "ped", ifpBuf, INPUT_BUFFER_SIZE); + ImGui::InputTextWithHint(TEXT("Scene.AnimName"), "cower", animBuf, INPUT_BUFFER_SIZE); + ImGui::Spacing(); + if (ImGui::Button(TEXT("Window.AddEntry"), Widget::CalcSize())) + { + std::string key = std::string("Custom.") + animBuf; + m_Data.m_pData->Set(key.c_str(), std::string(ifpBuf)); + m_Data.m_pData->Save(); + Util::SetMessage("Window.AddEntryMSG"); + } +} + +bool AnimationMgr::IsTargetFound() +{ + return m_bPedAnim && !m_pTarget; +} + +void AnimationMgr::StopImmediately(CPed *ped) +{ + if (!ped) + { + return; + } + +#ifdef GTASA + Command(CPools::GetPedRef(ped)); +#else + _PlayAnim(ped->m_pRwClump, ANIM_GROUP_MAN, ANIM_MAN_IDLE_STANCE, 4.0f, false, false); +#endif +} \ No newline at end of file diff --git a/src/custom/animation.h b/src/custom/animation.h new file mode 100644 index 0000000..4c21c13 --- /dev/null +++ b/src/custom/animation.h @@ -0,0 +1,38 @@ +#pragma once +#include "utils/resourcestore.h" +#include "interface/icheat.hpp" + +/* + Animation Player Class + Plays animatins on player & peds +*/ +class AnimationMgr : public ICheat +{ +private: + CPed *m_pTarget = nullptr; // target ped pointer + + friend class ICheat; + AnimationMgr(); + AnimationMgr(const AnimationMgr&); + +public: + bool m_Loop; // keep playing animation in a loop + bool m_bSecondary; // play animation alongside another + bool m_bPedAnim; // play the animation on a target ped + + ResourceStore m_Data{ "animations", eResourceType::TYPE_TEXT }; + + // Add a custom animation entry + void AddNew(); + + // Retuns true if a ped target is found + bool IsTargetFound(); + + // Play the animation + void Play(std::string& cat, std::string& key, std::string& val); + + // Stops whatever action char is doing + void StopImmediately(CPed *ped); +}; + +extern AnimationMgr& Animation; \ No newline at end of file diff --git a/src/custom/cutscene_sa.cpp b/src/custom/cutscene_sa.cpp index 8f7bee0..4a23eaa 100644 --- a/src/custom/cutscene_sa.cpp +++ b/src/custom/cutscene_sa.cpp @@ -15,7 +15,7 @@ void CutsceneMgr::Play(std::string& rootKey, std::string& cutsceneId, std::strin { if (CCutsceneMgr::ms_running) { - Util::SetMessage(TEXT("Animation.CutsceneRunning")); + Util::SetMessage(TEXT("Scene.CutsceneRunning")); return; } diff --git a/src/custom/cutscene_sa.h b/src/custom/cutscene_sa.h index 09aeda2..9cd6e8f 100644 --- a/src/custom/cutscene_sa.h +++ b/src/custom/cutscene_sa.h @@ -2,7 +2,6 @@ #include "utils/resourcestore.h" #include "interface/icheat.hpp" -extern class CVehicle; /* Cutscene Player Class for SA diff --git a/src/custom/particle_sa.cpp b/src/custom/particle_sa.cpp new file mode 100644 index 0000000..dbb3835 --- /dev/null +++ b/src/custom/particle_sa.cpp @@ -0,0 +1,47 @@ +#include "pch.h" +#include "particle_sa.h" +#include "utils/widget.h" + +ParticleMgr& Particle = *ParticleMgr::Get(); +void ParticleMgr::Play(std::string& cat, std::string& name, std::string& particle) +{ + CPlayerPed* pPlayer = FindPlayerPed(); + if (pPlayer) + { + CVector pos = pPlayer->GetPosition(); + int handle; + Command(particle.c_str(), pos.x, pos.y, pos.z, 1, &handle); + Command(handle); + m_nList.push_back(handle); + } +} + +void ParticleMgr::RemoveAll() +{ + for (int& p : m_nList) + { + Command(p); + } + m_nList.clear(); +} + +void ParticleMgr::RemoveLatest() +{ + Command(m_nList.back()); // stop if anything is running + m_nList.pop_back(); +} + +void ParticleMgr::AddNew() +{ + static char name[INPUT_BUFFER_SIZE], particle[INPUT_BUFFER_SIZE]; + ImGui::InputTextWithHint(TEXT("Scene.ParticleName"), "KKJJ fire particle", name, INPUT_BUFFER_SIZE); + ImGui::InputTextWithHint(TEXT("Scene.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")); + } +} \ No newline at end of file diff --git a/src/custom/particle_sa.h b/src/custom/particle_sa.h new file mode 100644 index 0000000..faf4004 --- /dev/null +++ b/src/custom/particle_sa.h @@ -0,0 +1,34 @@ +#pragma once +#include "utils/resourcestore.h" +#include "interface/icheat.hpp" + +/* + Particle Player Class for SA + Spawns particles in the world +*/ +class ParticleMgr : public ICheat +{ +private: + std::vector m_nList; + + friend class ICheat; + ParticleMgr(){}; + ParticleMgr(const ParticleMgr&); + +public: + ResourceStore m_Data{ "particles", eResourceType::TYPE_TEXT }; // names + + // Plays a particle + void Play(std::string& cat, std::string& key, std::string& val); + + // Adds new particle to data + void AddNew(); + + // Removes all spawned particles + void RemoveAll(); + + // Removes the most recent spawned particle + void RemoveLatest(); +}; + +extern ParticleMgr& Particle; \ No newline at end of file diff --git a/src/defines.h b/src/defines.h index 2b41d94..99bcb12 100644 --- a/src/defines.h +++ b/src/defines.h @@ -9,7 +9,7 @@ #define MENU_NAME "Cheat Menu" #define MENU_VERSION_NUMBER "3.3" #define MENU_VERSION MENU_VERSION_NUMBER"-beta" -#define BUILD_NUMBER "20220805" +#define BUILD_NUMBER "20220810" #define MENU_TITLE MENU_NAME " v" MENU_VERSION #ifdef GTASA diff --git a/src/pages/animation.cpp b/src/pages/animation.cpp deleted file mode 100644 index 38aae33..0000000 --- a/src/pages/animation.cpp +++ /dev/null @@ -1,455 +0,0 @@ -#include "pch.h" -#include "animation.h" -#include "utils/widget.h" -#include "utils/util.h" - -#ifdef GTA3 -#include -#include -#include -#include "eAnimations.h" -#include -#elif GTAVC -#include "kiero/minhook/MinHook.h" -#include -#include -#include "eAnimations.h" -#include -#endif - -#ifdef GTASA -#include "utils/overlay.h" -#include "custom/cutscene_sa.h" - -void Particle::Play(std::string& cat, std::string& name, std::string& particle) -{ - CPlayerPed* pPlayer = FindPlayerPed(); - if (pPlayer) - { - CVector pos = pPlayer->GetPosition(); - int handle; - Command(particle.c_str(), pos.x, pos.y, pos.z, 1, &handle); - Command(handle); - m_nList.push_back(handle); - } -} - -void Particle::RemoveAll() -{ - for (int& p : Particle::m_nList) - { - Command(p); - } - Particle::m_nList.clear(); -} - -void Particle::RemoveLatest() -{ - Command(Particle::m_nList.back()); // stop if anything is running - Particle::m_nList.pop_back(); -} - -#elif GTAVC - -// Thanks to codenulls(https://github.com/codenulls/) -static auto OLD_CStreaming_RemoveModel = (bool(__cdecl*)(int))0x40D6E0; -static bool NEW_CStreaming_RemoveModel(int modelID) -{ - // Check if it's IFP animation block - if (modelID >= 7916 && modelID <= 7950) - { - // Do not unload the animation block - return true; - } - return OLD_CStreaming_RemoveModel(modelID); -} - -bool _LoadAnimationBlock(const char* szBlockName) -{ - CAnimBlock* pAnimBlock = CAnimManager::GetAnimationBlock(szBlockName); - if (pAnimBlock) - { - if (!pAnimBlock->bLoaded) - { - int animIndex = ((unsigned char*)pAnimBlock - (unsigned char*)CAnimManager::ms_aAnimBlocks) / 32; - CStreaming::RequestModel(7916 + animIndex, 0x20 | MISSION_REQUIRED | PRIORITY_REQUEST); - CStreaming::LoadAllRequestedModels(true); - if (pAnimBlock->bLoaded) - { - return true; - } - } - else - { - return true; - } - } - return false; -} - -void _PlayAnim(RpClump* pClump, int animGroup, int animID, float blend, bool loop, bool secondary) -{ - if (animGroup < CAnimManager::ms_numAnimAssocDefinitions) - { - CAnimationStyleDescriptor* pAnimDef = &CAnimManager::ms_aAnimAssocDefinitions[animGroup]; - if (pAnimDef) - { - if (!_LoadAnimationBlock(pAnimDef->blockName)) - { - return; - } - } - } - - CAnimBlendAssociation* pAnimAssoc = RpAnimBlendClumpGetFirstAssociation(pClump); - while (pAnimAssoc) - { - if (pAnimAssoc->m_nAnimId == animID && pAnimAssoc->m_nAnimGroup == animGroup) - { - // Destroy the animation - pAnimAssoc->~CAnimBlendAssociation(); - break; - } - pAnimAssoc = RpAnimBlendGetNextAssociation(pAnimAssoc); - } - pAnimAssoc = CAnimManager::BlendAnimation(pClump, animGroup, animID, blend); - pAnimAssoc->m_nFlags = ANIMATION_STARTED | ANIMATION_MOVEMENT; - - if (loop) - { - pAnimAssoc->m_nFlags |= ANIMATION_LOOPED; - } - - if (secondary) - { - pAnimAssoc->m_nFlags |= ANIMATION_PARTIAL; - } -} - -#else - -void _PlayAnim(RpClump* pClump, int animGroup, int animID, float blend, bool loop, bool secondary) -{ - CAnimBlendAssociation* pAnimStaticAssoc = CAnimManager::GetAnimAssociation(animGroup, animID); - CAnimBlendAssociation* pAnimAssoc = RpAnimBlendClumpGetFirstAssociation(pClump); - while (pAnimAssoc) - { - if (pAnimAssoc->m_nAnimID == pAnimStaticAssoc->m_nAnimID && pAnimAssoc->m_pAnimBlendHierarchy == pAnimStaticAssoc->m_pAnimBlendHierarchy) - { - // Destroy the animation - pAnimAssoc->FreeAnimBlendNodeArray(); - break; - } - pAnimAssoc = RpAnimBlendGetNextAssociation(pAnimAssoc); - } - pAnimAssoc = CAnimManager::BlendAnimation(pClump, animGroup, animID, blend); - pAnimAssoc->m_nFlags = 0x1 | 0x20; - - if (loop) - { - pAnimAssoc->m_nFlags |= 0x2; - } - - if (secondary) - { - pAnimAssoc->m_nFlags |= 0x10; - } -} -#endif - -void Animation::Play(std::string& cat, std::string& anim, std::string& ifp) -{ - CPed *pPed = m_bPedAnim ? m_pTarget : FindPlayerPed(); - if (!pPed) - { - return; - } - -#ifdef GTASA - int hPed = CPools::GetPedRef(pPed); - - if (ifp != "PED") - { - Command(ifp.c_str()); - Command(); - } - - Command(hPed); - if (m_bSecondary) - { - Command(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1); - } - else - { - Command(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1); - } - - if (ifp != "PED") - { - Command(ifp.c_str()); - } - -#else - int groupID, animID; - sscanf(ifp.c_str(), "%d$%d,", &groupID, &animID); - _PlayAnim(pPed->m_pRwClump, groupID, animID, 4.0f, m_Loop, m_bSecondary); -#endif -} - -void Animation::Init() -{ -#ifdef GTASA - Events::processScriptsEvent += [] - { - CPlayerPed* pPlayer = FindPlayerPed(); - - if (pPlayer && pPlayer->m_pPlayerTargettedPed) - { - m_pTarget = pPlayer->m_pPlayerTargettedPed; - } - - if (m_pTarget && !m_pTarget->IsAlive()) - { - m_pTarget = nullptr; - } - }; -#elif GTAVC - // mov al, 01 - // ret - // nop (2x) - patch::SetRaw(0x40C9C0, (void*)"\xB0\x01\xC3\x90\x90", 5); - // // ret - // // nop (3x) - patch::SetRaw(0x404950, (void*)"\xC3\x90\x90\x90", 4); - - // Fix crash at 0x4019EA - static bool hookInjected = false; - Events::initGameEvent.before += []() - { - if (hookInjected) - { - MH_DisableHook((void*)0x40D6E0); - } - }; - - Events::initGameEvent.after += []() - { - MH_CreateHook((void*)0x40D6E0, NEW_CStreaming_RemoveModel, (void**)&OLD_CStreaming_RemoveModel); - MH_EnableHook((void*)0x40D6E0); - hookInjected = true; - }; - -#endif -} - -void Animation::ShowPage() -{ - if (ImGui::BeginTabBar("Animation", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll)) - { - ImGui::Spacing(); - CPlayerPed* pPlayer = FindPlayerPed(); - int hPlayer = CPools::GetPedRef(pPlayer); - - if (ImGui::BeginTabItem(TEXT("Animation.AnimationTab"))) - { - ImGui::Spacing(); - if (ImGui::Button(TEXT("Animation.StopAnimation"), Widget::CalcSize())) - { - if (hPlayer) - { -#ifdef GTASA - Command(hPlayer); -#else - _PlayAnim(pPlayer->m_pRwClump, ANIM_GROUP_MAN, ANIM_MAN_IDLE_STANCE, 4.0f, m_Loop, m_bSecondary); -#endif - } - } - ImGui::Spacing(); - - ImGui::Columns(2, nullptr, false); - Widget::Checkbox(TEXT("Animation.LoopCheckbox"), &m_Loop, TEXT("Animation.LoopCheckboxText")); - Widget::Checkbox(TEXT("Animation.SecondaryCheckbox"), &m_bSecondary, TEXT("Animation.SecondaryCheckboxText")); - ImGui::NextColumn(); -#ifdef GTASA - Widget::Checkbox(TEXT("Animation.PedAnim"), &m_bPedAnim, TEXT("Animation.PedAnimText")); -#endif - ImGui::Columns(1); - ImGui::Spacing(); - - if (m_bPedAnim && !m_pTarget) - { - ImGui::TextWrapped(TEXT("Animation.NoTarget")); - } - else - { - ImGui::Spacing(); - - if (ImGui::BeginChild("Anims Child")) - { - ImGui::Spacing(); - Widget::DataList(m_AnimData, Play, - [](){ - 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(); - } - } - ImGui::EndTabItem(); - } -#ifdef GTASA - if (ImGui::BeginTabItem(TEXT("Animation.Tasks"))) - { - ImGui::Spacing(); - Widget::Checkbox(TEXT("Menu.ShowPedTasks"), &Overlay::m_bPedTasks); - ImGui::Spacing(); - if (pPlayer) - { - ImGui::BeginChild("TasksList"); - ImGui::Text(TEXT("Animation.PrimaryTasks")); - ImGui::Separator(); - for (size_t i = 0; i != TASK_PRIMARY_MAX; ++i) - { - CTask *pTask = pPlayer->m_pIntelligence->m_TaskMgr.m_aPrimaryTasks[i]; - if (pTask) - { - const char *name = taskNames[pTask->GetId()]; - if (ImGui::MenuItem(name)) - { - ImGui::SetClipboardText(name); - Util::SetMessage(TEXT("Window.CopiedToClipboard")); - } - } - } - - ImGui::Dummy(ImVec2(0, 25)); - - ImGui::Text(TEXT("Animation.SecondaryTasks")); - ImGui::Separator(); - for (size_t i = 0; i != TASK_SECONDARY_MAX; ++i) - { - CTask *pTask = pPlayer->m_pIntelligence->m_TaskMgr.m_aSecondaryTasks[i]; - if (pTask) - { - const char *name = taskNames[pTask->GetId()]; - if (ImGui::MenuItem(name)) - { - ImGui::SetClipboardText(name); - Util::SetMessage(TEXT("Window.CopiedToClipboard")); - } - } - } - ImGui::EndChild(); - } - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem(TEXT("Animation.CutsceneTab"))) - { - ImGui::Spacing(); - if (ImGui::Button(TEXT("Animation.StopCutscene"), Widget::CalcSize())) - { - Cutscene.Stop(); - } - ImGui::Spacing(); - - if (ImGui::BeginChild("Cutscene Child")) - { - ImGui::Spacing(); - Widget::DataList(Cutscene.m_Data, [](std::string& a, std::string& b, std::string& c){Cutscene.Play(a, b, c);}); - ImGui::EndChild(); - } - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem(TEXT("Animation.ParticleTab"))) - { - ImGui::Spacing(); - if (ImGui::Button(TEXT("Animation.RemoveAll"), Widget::CalcSize(2))) - { - Particle::RemoveAll(); - } - ImGui::SameLine(); - if (ImGui::Button(TEXT("Animation.RemoveLatest"), Widget::CalcSize(2))) - { - Particle::RemoveLatest(); - } - ImGui::Spacing(); - if (Widget::CheckboxBits(TEXT("Animation.InvisiblePlayer"), pPlayer->m_nPedFlags.bDontRender)) - { - pPlayer->m_nPedFlags.bDontRender = (pPlayer->m_nPedFlags.bDontRender == 1) ? 0 : 1; - } - ImGui::Spacing(); - ImGui::Spacing(); - if (ImGui::BeginChild("Anims Child")) - { - ImGui::Spacing(); - Widget::DataList(Particle::m_Data, Particle::Play, - [](){ - 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(); - } - if (ImGui::BeginTabItem(TEXT("Animation.Styles"))) - { - ImGui::Spacing(); - - static int fightStyle; - static const char* fightStyles = "Default\0Boxing\0Kung Fu\0Kick Boxing\0Punch Kick\0"; - static std::string walkStyle = "default"; - static std::vector walkStyles = - { - "default", "man", "shuffle", "oldman", "gang1", "gang2", "oldfatman", - "fatman", "jogger", "drunkman", "blindman", "swat", "woman", "shopping", "busywoman", - "sexywoman", "pro", "oldwoman", "fatwoman", "jogwoman", "oldfatwoman", "skate" - }; - - if (ImGui::Combo(TEXT("Animation.FightingStyle"), &fightStyle, fightStyles)) - { - Command(hPlayer, fightStyle + 4, 6); - Util::SetMessage(TEXT("Animation.FightingStyleSet")); - } - if (Widget::ListBox(TEXT("Animation.WalkingStyle"), walkStyles, walkStyle)) - { - if (walkStyle == "default") - { - patch::Set(0x609A4E, 0x4D48689); - patch::Set(0x609A52, 0); - } - else - { - patch::Nop(0x609A4E, 6); - Command(walkStyle.c_str()); - Command(); - Command(hPlayer, walkStyle.c_str()); - Command(walkStyle.c_str()); - } - Util::SetMessage(TEXT("Animation.WalkingStyleSet")); - } - ImGui::EndTabItem(); - } -#endif - ImGui::EndTabBar(); - } -} \ No newline at end of file diff --git a/src/pages/animation.h b/src/pages/animation.h deleted file mode 100644 index 29c0fd5..0000000 --- a/src/pages/animation.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include "pch.h" - -#ifdef GTASA - - -/* - Particle Player Class for SA - Spawns particles in the world -*/ -class Particle -{ -private: - static inline std::vector m_nList; - -public: - static inline ResourceStore m_Data{ "particles", eResourceType::TYPE_TEXT }; // names - - Particle() = delete; - Particle(const Particle&) = delete; - - // Plays a particle - static void Play(std::string& cat, std::string& key, std::string& val); - - // Removes all spawned particles - static void RemoveAll(); - - // Removes the most recent spawned particle - static void RemoveLatest(); -}; -#endif - -/* - Animation Player Class - Plays animatins on player & peds -*/ -class Animation -{ -private: - static inline ResourceStore m_AnimData{ "animations", eResourceType::TYPE_TEXT }; - static inline bool m_Loop; // keep playing animation in a loop - static inline bool m_bSecondary; // play animation alongside another - static inline bool m_bPedAnim; // play the animation on a target ped - static inline CPed *m_pTarget = nullptr; // target ped pointer - - // Plays a particular animation - static void Play(std::string& cat, std::string& key, std::string& val); - -public: - Animation() = delete; - Animation(const Animation&) = delete; - - // Initializes hooks & stuff - static void Init(); - - // Displays animation menu page - static void ShowPage(); -}; \ No newline at end of file diff --git a/src/pages/menu.cpp b/src/pages/menu.cpp index d29bea0..8c185d9 100644 --- a/src/pages/menu.cpp +++ b/src/pages/menu.cpp @@ -325,10 +325,8 @@ void Menu::ShowPage() ImGui::Dummy(ImVec2(0, 10)); ImGui::TextWrapped(TEXT("Menu.BugDisclaimer")); - ImGui::Spacing(); - Widget::TextCentered(TEXT("Menu.PatreonText")); - ImGui::Dummy(ImVec2(0, 10)); + Widget::TextCentered(TEXT("Menu.PatreonText")); Widget::TextCentered(TEXT("Menu.CopyrightDisclaimer")); ImGui::Dummy(ImVec2(0, 30)); diff --git a/src/pages/scene.cpp b/src/pages/scene.cpp new file mode 100644 index 0000000..5356a4f --- /dev/null +++ b/src/pages/scene.cpp @@ -0,0 +1,188 @@ +#include "pch.h" +#include "scene.h" +#include "utils/widget.h" +#include "utils/util.h" +#include "custom/animation.h" + +#ifdef GTASA +#include "utils/overlay.h" +#include "custom/cutscene_sa.h" +#include "custom/particle_sa.h" +#endif + +void ScenePage::Draw() +{ + if (ImGui::BeginTabBar("Animation", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll)) + { + ImGui::Spacing(); + CPlayerPed* pPlayer = FindPlayerPed(); + int hPlayer = CPools::GetPedRef(pPlayer); + + if (ImGui::BeginTabItem(TEXT("Scene.AnimationTab"))) + { + ImGui::Spacing(); + if (ImGui::Button(TEXT("Scene.StopAnimation"), Widget::CalcSize())) + { + Animation.StopImmediately(pPlayer); + } + ImGui::Spacing(); + + ImGui::Columns(2, nullptr, false); + Widget::Checkbox(TEXT("Scene.LoopCheckbox"), &Animation.m_Loop, TEXT("Scene.LoopCheckboxText")); + Widget::Checkbox(TEXT("Scene.SecondaryCheckbox"), &Animation.m_bSecondary, TEXT("Scene.SecondaryCheckboxText")); + ImGui::NextColumn(); +#ifdef GTASA + Widget::Checkbox(TEXT("Scene.PedAnim"), &Animation.m_bPedAnim, TEXT("Scene.PedAnimText")); +#endif + ImGui::Columns(1); + ImGui::Spacing(); + + if (Animation.IsTargetFound()) + { + ImGui::TextWrapped(TEXT("Scene.NoTarget")); + } + else + { + ImGui::Spacing(); + + if (ImGui::BeginChild("Anims Child")) + { + ImGui::Spacing(); + Widget::DataList(Animation.m_Data, fArg3Wrapper(Animation.Play), fArgNoneWrapper(Animation.AddNew)); + ImGui::EndChild(); + } + } + ImGui::EndTabItem(); + } +#ifdef GTASA + if (ImGui::BeginTabItem(TEXT("Scene.Tasks"))) + { + ImGui::Spacing(); + Widget::Checkbox(TEXT("Menu.ShowPedTasks"), &Overlay::m_bPedTasks); + ImGui::Spacing(); + if (pPlayer) + { + ImGui::BeginChild("TasksList"); + ImGui::Text(TEXT("Scene.PrimaryTasks")); + ImGui::Separator(); + for (size_t i = 0; i != TASK_PRIMARY_MAX; ++i) + { + CTask *pTask = pPlayer->m_pIntelligence->m_TaskMgr.m_aPrimaryTasks[i]; + if (pTask) + { + const char *name = taskNames[pTask->GetId()]; + if (ImGui::MenuItem(name)) + { + ImGui::SetClipboardText(name); + Util::SetMessage(TEXT("Window.CopiedToClipboard")); + } + } + } + + ImGui::Dummy(ImVec2(0, 25)); + + ImGui::Text(TEXT("Scene.SecondaryTasks")); + ImGui::Separator(); + for (size_t i = 0; i != TASK_SECONDARY_MAX; ++i) + { + CTask *pTask = pPlayer->m_pIntelligence->m_TaskMgr.m_aSecondaryTasks[i]; + if (pTask) + { + const char *name = taskNames[pTask->GetId()]; + if (ImGui::MenuItem(name)) + { + ImGui::SetClipboardText(name); + Util::SetMessage(TEXT("Window.CopiedToClipboard")); + } + } + } + ImGui::EndChild(); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem(TEXT("Scene.CutsceneTab"))) + { + ImGui::Spacing(); + if (ImGui::Button(TEXT("Scene.StopCutscene"), Widget::CalcSize())) + { + Cutscene.Stop(); + } + ImGui::Spacing(); + + if (ImGui::BeginChild("Cutscene Child")) + { + ImGui::Spacing(); + Widget::DataList(Cutscene.m_Data, fArg3Wrapper(Cutscene.Play)); + ImGui::EndChild(); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem(TEXT("Scene.ParticleTab"))) + { + ImGui::Spacing(); + if (ImGui::Button(TEXT("Scene.RemoveAll"), Widget::CalcSize(2))) + { + Particle.RemoveAll(); + } + ImGui::SameLine(); + if (ImGui::Button(TEXT("Scene.RemoveLatest"), Widget::CalcSize(2))) + { + Particle.RemoveLatest(); + } + ImGui::Spacing(); + if (Widget::CheckboxBits(TEXT("Scene.InvisiblePlayer"), pPlayer->m_nPedFlags.bDontRender)) + { + pPlayer->m_nPedFlags.bDontRender = (pPlayer->m_nPedFlags.bDontRender == 1) ? 0 : 1; + } + ImGui::Spacing(); + ImGui::Spacing(); + if (ImGui::BeginChild("Anims Child")) + { + ImGui::Spacing(); + Widget::DataList(Particle.m_Data, fArg3Wrapper(Particle.Play), fArgNoneWrapper(Particle.AddNew)); + ImGui::EndChild(); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem(TEXT("Scene.Styles"))) + { + ImGui::Spacing(); + + static int fightStyle; + static const char* fightStyles = "Default\0Boxing\0Kung Fu\0Kick Boxing\0Punch Kick\0"; + static std::string walkStyle = "default"; + static std::vector walkStyles = + { + "default", "man", "shuffle", "oldman", "gang1", "gang2", "oldfatman", + "fatman", "jogger", "drunkman", "blindman", "swat", "woman", "shopping", "busywoman", + "sexywoman", "pro", "oldwoman", "fatwoman", "jogwoman", "oldfatwoman", "skate" + }; + + if (ImGui::Combo(TEXT("Scene.FightingStyle"), &fightStyle, fightStyles)) + { + Command(hPlayer, fightStyle + 4, 6); + Util::SetMessage(TEXT("Scene.FightingStyleSet")); + } + if (Widget::ListBox(TEXT("Scene.WalkingStyle"), walkStyles, walkStyle)) + { + if (walkStyle == "default") + { + patch::Set(0x609A4E, 0x4D48689); + patch::Set(0x609A52, 0); + } + else + { + patch::Nop(0x609A4E, 6); + Command(walkStyle.c_str()); + Command(); + Command(hPlayer, walkStyle.c_str()); + Command(walkStyle.c_str()); + } + Util::SetMessage(TEXT("Scene.WalkingStyleSet")); + } + ImGui::EndTabItem(); + } +#endif + ImGui::EndTabBar(); + } +} \ No newline at end of file diff --git a/src/pages/scene.h b/src/pages/scene.h new file mode 100644 index 0000000..9718ebe --- /dev/null +++ b/src/pages/scene.h @@ -0,0 +1,14 @@ +#pragma once +#include "pch.h" + +/* + Scene Player class +*/ +class ScenePage +{ +public: + ScenePage() = delete; + ScenePage(const ScenePage&) = delete; + + static void Draw(); +}; \ No newline at end of file diff --git a/src/pch.h b/src/pch.h index 9e03d6e..06f3384 100644 --- a/src/pch.h +++ b/src/pch.h @@ -78,11 +78,15 @@ extern eRenderer gRenderer; extern DataStore gConfig; typedef std::string str; -typedef void(*ArgCallback3)(str&, str&, str&); -typedef void(*ArgCallback)(str&); -typedef void(*ArgCallbackNone)(); -typedef std::string(*ArgCallbackRtn)(str&); -typedef bool(*ArgCallbackRtnBool)(str&); +typedef void(*fArg3_t)(str&, str&, str&); +typedef void(*fArg1_t)(str&); +typedef void(*fArgNone_t)(); +typedef std::string(*fRtnArg1_t)(str&); +typedef bool(*fRtnBoolArg1_t)(str&); + +#define fArg3Wrapper(x) [](str& a, str& b, str& c){x(a, b, c);} +#define fArgWrapper(x) [](str& a){x(a);} +#define fArgNoneWrapper(x) [](){x();} #ifdef GTASA extern const char* taskNames[1802]; diff --git a/src/utils/widget.cpp b/src/utils/widget.cpp index e920da8..deb1211 100644 --- a/src/utils/widget.cpp +++ b/src/utils/widget.cpp @@ -75,7 +75,7 @@ void Widget::Filter(const char* label, ImGuiTextFilter& filter, const char* hint } } -void Widget::DataList(ResourceStore& data, ArgCallback3 clickFunc, ArgCallbackNone addFunc, bool isEditItem) +void Widget::DataList(ResourceStore& data, fArg3_t clickFunc, fArgNone_t addFunc, bool isEditItem) { if (ImGui::IsMouseClicked(1)) { @@ -305,8 +305,8 @@ static bool RoundedImageButton(ImTextureID textureID, ImVec2& size, const char* Here we go again... This direly needs a refactor oof */ -void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc, - ArgCallbackRtnBool verifyFunc, ArgCallbackNone addFunc) +void Widget::ImageList(ResourceStore &store, fArg1_t clickFunc, fRtnArg1_t getNameFunc, + fRtnBoolArg1_t verifyFunc, fArgNone_t addFunc) { static IDirect3DTexture9 **pDefaultTex = nullptr; ImGuiStyle& style = ImGui::GetStyle(); diff --git a/src/utils/widget.h b/src/utils/widget.h index fbed189..5b6e8f2 100644 --- a/src/utils/widget.h +++ b/src/utils/widget.h @@ -41,7 +41,7 @@ public: static bool ColorBtn(int colorId, std::vector& color, ImVec2 size); // Draws DataStore data in the interface - static void DataList(ResourceStore& data, ArgCallback3 clickFunc = nullptr, ArgCallbackNone addFunc = nullptr, bool isEditItem = false); + static void DataList(ResourceStore& data, fArg3_t clickFunc = nullptr, fArgNone_t addFunc = nullptr, bool isEditItem = false); // Draws a dropdown editor for memory address template @@ -69,8 +69,8 @@ public: static bool InputInt(const char* label, int *val, int min = -1, int max = -1); // Draws ResourceStore images in the interface - static void ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc, - ArgCallbackRtnBool verifyFunc = nullptr, ArgCallbackNone addFunc = nullptr); + static void ImageList(ResourceStore &store, fArg1_t clickFunc, fRtnArg1_t getNameFunc, + fRtnBoolArg1_t verifyFunc = nullptr, fArgNone_t addFunc = nullptr); // Draws a dropdown listbox static bool ListBox(const char* label, VecStr& allItems, int& selected);