Refactor animation, particle, scene etc classes
This commit is contained in:
parent
fc0e8ac739
commit
1b793f2f05
@ -4,7 +4,7 @@
|
|||||||
# Author: Grinch_
|
# Author: Grinch_
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
[Animation]
|
[Scene]
|
||||||
AnimationTab = "Animation##TABBAR"
|
AnimationTab = "Animation##TABBAR"
|
||||||
AnimName = "Anim name"
|
AnimName = "Anim name"
|
||||||
CustomAnimsOnly = "You can only remove custom animations"
|
CustomAnimsOnly = "You can only remove custom animations"
|
||||||
@ -824,6 +824,7 @@ RemoveEntry = "Entry removed"
|
|||||||
Search = "Search"
|
Search = "Search"
|
||||||
LocationsTab = "Locations"
|
LocationsTab = "Locations"
|
||||||
FavouritesTab = "Favourites"
|
FavouritesTab = "Favourites"
|
||||||
|
ScenePage = "Scene"
|
||||||
SetValue = "Set value"
|
SetValue = "Set value"
|
||||||
SpawnTab = "Spawn"
|
SpawnTab = "Spawn"
|
||||||
TeleportPage = "Teleport"
|
TeleportPage = "Teleport"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Author: @_4l150n
|
# Author: @_4l150n
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
[Animation]
|
[Scene]
|
||||||
AddAnimation = "Adicionar animação"
|
AddAnimation = "Adicionar animação"
|
||||||
AddParticle = "Adicionar partícula"
|
AddParticle = "Adicionar partícula"
|
||||||
AnimationRemoved = "Animação removida"
|
AnimationRemoved = "Animação removida"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Author: Ruben Viera
|
# Author: Ruben Viera
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
[Animation]
|
[Scene]
|
||||||
AddAnimation = "Añadir animación"
|
AddAnimation = "Añadir animación"
|
||||||
AddParticle = "Añadir particula"
|
AddParticle = "Añadir particula"
|
||||||
AnimationRemoved = "Animación removida"
|
AnimationRemoved = "Animación removida"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
[Animation]
|
[Scene]
|
||||||
AddAnimation = "添加动画"
|
AddAnimation = "添加动画"
|
||||||
AddParticle = "添加粒子"
|
AddParticle = "添加粒子"
|
||||||
AnimationRemoved = "动画已删除"
|
AnimationRemoved = "动画已删除"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "utils/d3dhook.h"
|
#include "utils/d3dhook.h"
|
||||||
#include "utils/util.h"
|
#include "utils/util.h"
|
||||||
#include "utils/overlay.h"
|
#include "utils/overlay.h"
|
||||||
#include "pages/animation.h"
|
#include "pages/scene.h"
|
||||||
#include "pages/game.h"
|
#include "pages/game.h"
|
||||||
#include "pages/menu.h"
|
#include "pages/menu.h"
|
||||||
#include "pages/ped.h"
|
#include "pages/ped.h"
|
||||||
@ -216,7 +216,7 @@ void CheatMenu::GenHeaderList()
|
|||||||
{TEXT_S("Window.TeleportPage"), &Teleport::ShowPage, eMenuPages::TELEPORT},
|
{TEXT_S("Window.TeleportPage"), &Teleport::ShowPage, eMenuPages::TELEPORT},
|
||||||
{TEXT_S("Window.PlayerPage"), &Player::ShowPage, eMenuPages::PLAYER},
|
{TEXT_S("Window.PlayerPage"), &Player::ShowPage, eMenuPages::PLAYER},
|
||||||
{TEXT_S("Window.PedPage"), &Ped::ShowPage, eMenuPages::PED},
|
{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.VehiclePage"), &Vehicle::ShowPage, eMenuPages::VEHICLE},
|
||||||
{TEXT_S("Window.WeaponPage"), &Weapon::ShowPage, eMenuPages::WEAPON},
|
{TEXT_S("Window.WeaponPage"), &Weapon::ShowPage, eMenuPages::WEAPON},
|
||||||
{TEXT_S("Window.GamePage"), &Game::ShowPage, eMenuPages::GAME},
|
{TEXT_S("Window.GamePage"), &Game::ShowPage, eMenuPages::GAME},
|
||||||
@ -252,7 +252,6 @@ void CheatMenu::Init()
|
|||||||
GenHeaderList();
|
GenHeaderList();
|
||||||
|
|
||||||
// Init menu parts
|
// Init menu parts
|
||||||
Animation::Init();
|
|
||||||
Game::Init();
|
Game::Init();
|
||||||
Menu::Init();
|
Menu::Init();
|
||||||
Player::Init();
|
Player::Init();
|
||||||
|
@ -10,7 +10,7 @@ class CheatMenu
|
|||||||
private:
|
private:
|
||||||
enum class eMenuPages
|
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
|
struct HeaderData
|
||||||
{
|
{
|
||||||
|
244
src/custom/animation.cpp
Normal file
244
src/custom/animation.cpp
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "animation.h"
|
||||||
|
#include "utils/widget.h"
|
||||||
|
|
||||||
|
#ifdef GTAVC
|
||||||
|
#include "kiero/minhook/MinHook.h"
|
||||||
|
#include <CAnimationStyleDescriptor.h>
|
||||||
|
#include <CAnimManager.h>
|
||||||
|
#include "eAnimations.h"
|
||||||
|
#include <CAnimBlendAssociation.h>
|
||||||
|
#elif GTA3
|
||||||
|
#include <RpAnimBlend.h>
|
||||||
|
#include <CAnimationStyleDescriptor.h>
|
||||||
|
#include <CAnimManager.h>
|
||||||
|
#include "eAnimations.h"
|
||||||
|
#include <CAnimBlendAssociation.h>
|
||||||
|
#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<Commands::REQUEST_ANIMATION>(ifp.c_str());
|
||||||
|
Command<Commands::LOAD_ALL_MODELS_NOW>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Command<Commands::CLEAR_CHAR_TASKS>(hPed);
|
||||||
|
if (m_bSecondary)
|
||||||
|
{
|
||||||
|
Command<Commands::TASK_PLAY_ANIM_SECONDARY>(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Command<Commands::TASK_PLAY_ANIM>(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ifp != "PED")
|
||||||
|
{
|
||||||
|
Command<Commands::REMOVE_ANIMATION>(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<Commands::CLEAR_CHAR_TASKS>(CPools::GetPedRef(ped));
|
||||||
|
#else
|
||||||
|
_PlayAnim(ped->m_pRwClump, ANIM_GROUP_MAN, ANIM_MAN_IDLE_STANCE, 4.0f, false, false);
|
||||||
|
#endif
|
||||||
|
}
|
38
src/custom/animation.h
Normal file
38
src/custom/animation.h
Normal file
@ -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<AnimationMgr>
|
||||||
|
{
|
||||||
|
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;
|
@ -15,7 +15,7 @@ void CutsceneMgr::Play(std::string& rootKey, std::string& cutsceneId, std::strin
|
|||||||
{
|
{
|
||||||
if (CCutsceneMgr::ms_running)
|
if (CCutsceneMgr::ms_running)
|
||||||
{
|
{
|
||||||
Util::SetMessage(TEXT("Animation.CutsceneRunning"));
|
Util::SetMessage(TEXT("Scene.CutsceneRunning"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "utils/resourcestore.h"
|
#include "utils/resourcestore.h"
|
||||||
#include "interface/icheat.hpp"
|
#include "interface/icheat.hpp"
|
||||||
|
|
||||||
extern class CVehicle;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Cutscene Player Class for SA
|
Cutscene Player Class for SA
|
||||||
|
47
src/custom/particle_sa.cpp
Normal file
47
src/custom/particle_sa.cpp
Normal file
@ -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<Commands::CREATE_FX_SYSTEM>(particle.c_str(), pos.x, pos.y, pos.z, 1, &handle);
|
||||||
|
Command<Commands::PLAY_FX_SYSTEM>(handle);
|
||||||
|
m_nList.push_back(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleMgr::RemoveAll()
|
||||||
|
{
|
||||||
|
for (int& p : m_nList)
|
||||||
|
{
|
||||||
|
Command<Commands::KILL_FX_SYSTEM>(p);
|
||||||
|
}
|
||||||
|
m_nList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleMgr::RemoveLatest()
|
||||||
|
{
|
||||||
|
Command<Commands::KILL_FX_SYSTEM>(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"));
|
||||||
|
}
|
||||||
|
}
|
34
src/custom/particle_sa.h
Normal file
34
src/custom/particle_sa.h
Normal file
@ -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<ParticleMgr>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<int> 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;
|
@ -9,7 +9,7 @@
|
|||||||
#define MENU_NAME "Cheat Menu"
|
#define MENU_NAME "Cheat Menu"
|
||||||
#define MENU_VERSION_NUMBER "3.3"
|
#define MENU_VERSION_NUMBER "3.3"
|
||||||
#define MENU_VERSION MENU_VERSION_NUMBER"-beta"
|
#define MENU_VERSION MENU_VERSION_NUMBER"-beta"
|
||||||
#define BUILD_NUMBER "20220805"
|
#define BUILD_NUMBER "20220810"
|
||||||
#define MENU_TITLE MENU_NAME " v" MENU_VERSION
|
#define MENU_TITLE MENU_NAME " v" MENU_VERSION
|
||||||
|
|
||||||
#ifdef GTASA
|
#ifdef GTASA
|
||||||
|
@ -1,455 +0,0 @@
|
|||||||
#include "pch.h"
|
|
||||||
#include "animation.h"
|
|
||||||
#include "utils/widget.h"
|
|
||||||
#include "utils/util.h"
|
|
||||||
|
|
||||||
#ifdef GTA3
|
|
||||||
#include <RpAnimBlend.h>
|
|
||||||
#include <CAnimationStyleDescriptor.h>
|
|
||||||
#include <CAnimManager.h>
|
|
||||||
#include "eAnimations.h"
|
|
||||||
#include <CAnimBlendAssociation.h>
|
|
||||||
#elif GTAVC
|
|
||||||
#include "kiero/minhook/MinHook.h"
|
|
||||||
#include <CAnimationStyleDescriptor.h>
|
|
||||||
#include <CAnimManager.h>
|
|
||||||
#include "eAnimations.h"
|
|
||||||
#include <CAnimBlendAssociation.h>
|
|
||||||
#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<Commands::CREATE_FX_SYSTEM>(particle.c_str(), pos.x, pos.y, pos.z, 1, &handle);
|
|
||||||
Command<Commands::PLAY_FX_SYSTEM>(handle);
|
|
||||||
m_nList.push_back(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Particle::RemoveAll()
|
|
||||||
{
|
|
||||||
for (int& p : Particle::m_nList)
|
|
||||||
{
|
|
||||||
Command<Commands::KILL_FX_SYSTEM>(p);
|
|
||||||
}
|
|
||||||
Particle::m_nList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Particle::RemoveLatest()
|
|
||||||
{
|
|
||||||
Command<Commands::KILL_FX_SYSTEM>(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<Commands::REQUEST_ANIMATION>(ifp.c_str());
|
|
||||||
Command<Commands::LOAD_ALL_MODELS_NOW>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Command<Commands::CLEAR_CHAR_TASKS>(hPed);
|
|
||||||
if (m_bSecondary)
|
|
||||||
{
|
|
||||||
Command<Commands::TASK_PLAY_ANIM_SECONDARY>(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Command<Commands::TASK_PLAY_ANIM>(hPed, anim.c_str(), ifp.c_str(), 4.0, m_Loop, 0, 0, 0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifp != "PED")
|
|
||||||
{
|
|
||||||
Command<Commands::REMOVE_ANIMATION>(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<Commands::CLEAR_CHAR_TASKS>(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<std::string> 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<Commands::GIVE_MELEE_ATTACK_TO_CHAR>(hPlayer, fightStyle + 4, 6);
|
|
||||||
Util::SetMessage(TEXT("Animation.FightingStyleSet"));
|
|
||||||
}
|
|
||||||
if (Widget::ListBox(TEXT("Animation.WalkingStyle"), walkStyles, walkStyle))
|
|
||||||
{
|
|
||||||
if (walkStyle == "default")
|
|
||||||
{
|
|
||||||
patch::Set<DWORD>(0x609A4E, 0x4D48689);
|
|
||||||
patch::Set<WORD>(0x609A52, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
patch::Nop(0x609A4E, 6);
|
|
||||||
Command<Commands::REQUEST_ANIMATION>(walkStyle.c_str());
|
|
||||||
Command<Commands::LOAD_ALL_MODELS_NOW>();
|
|
||||||
Command<Commands::SET_ANIM_GROUP_FOR_CHAR>(hPlayer, walkStyle.c_str());
|
|
||||||
Command<Commands::REMOVE_ANIMATION>(walkStyle.c_str());
|
|
||||||
}
|
|
||||||
Util::SetMessage(TEXT("Animation.WalkingStyleSet"));
|
|
||||||
}
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ImGui::EndTabBar();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<int> 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();
|
|
||||||
};
|
|
@ -325,10 +325,8 @@ void Menu::ShowPage()
|
|||||||
|
|
||||||
ImGui::Dummy(ImVec2(0, 10));
|
ImGui::Dummy(ImVec2(0, 10));
|
||||||
ImGui::TextWrapped(TEXT("Menu.BugDisclaimer"));
|
ImGui::TextWrapped(TEXT("Menu.BugDisclaimer"));
|
||||||
ImGui::Spacing();
|
|
||||||
Widget::TextCentered(TEXT("Menu.PatreonText"));
|
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0, 10));
|
ImGui::Dummy(ImVec2(0, 10));
|
||||||
|
Widget::TextCentered(TEXT("Menu.PatreonText"));
|
||||||
Widget::TextCentered(TEXT("Menu.CopyrightDisclaimer"));
|
Widget::TextCentered(TEXT("Menu.CopyrightDisclaimer"));
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(0, 30));
|
ImGui::Dummy(ImVec2(0, 30));
|
||||||
|
188
src/pages/scene.cpp
Normal file
188
src/pages/scene.cpp
Normal file
@ -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<std::string> 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<Commands::GIVE_MELEE_ATTACK_TO_CHAR>(hPlayer, fightStyle + 4, 6);
|
||||||
|
Util::SetMessage(TEXT("Scene.FightingStyleSet"));
|
||||||
|
}
|
||||||
|
if (Widget::ListBox(TEXT("Scene.WalkingStyle"), walkStyles, walkStyle))
|
||||||
|
{
|
||||||
|
if (walkStyle == "default")
|
||||||
|
{
|
||||||
|
patch::Set<DWORD>(0x609A4E, 0x4D48689);
|
||||||
|
patch::Set<WORD>(0x609A52, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
patch::Nop(0x609A4E, 6);
|
||||||
|
Command<Commands::REQUEST_ANIMATION>(walkStyle.c_str());
|
||||||
|
Command<Commands::LOAD_ALL_MODELS_NOW>();
|
||||||
|
Command<Commands::SET_ANIM_GROUP_FOR_CHAR>(hPlayer, walkStyle.c_str());
|
||||||
|
Command<Commands::REMOVE_ANIMATION>(walkStyle.c_str());
|
||||||
|
}
|
||||||
|
Util::SetMessage(TEXT("Scene.WalkingStyleSet"));
|
||||||
|
}
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
14
src/pages/scene.h
Normal file
14
src/pages/scene.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Scene Player class
|
||||||
|
*/
|
||||||
|
class ScenePage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScenePage() = delete;
|
||||||
|
ScenePage(const ScenePage&) = delete;
|
||||||
|
|
||||||
|
static void Draw();
|
||||||
|
};
|
14
src/pch.h
14
src/pch.h
@ -78,11 +78,15 @@ extern eRenderer gRenderer;
|
|||||||
extern DataStore gConfig;
|
extern DataStore gConfig;
|
||||||
|
|
||||||
typedef std::string str;
|
typedef std::string str;
|
||||||
typedef void(*ArgCallback3)(str&, str&, str&);
|
typedef void(*fArg3_t)(str&, str&, str&);
|
||||||
typedef void(*ArgCallback)(str&);
|
typedef void(*fArg1_t)(str&);
|
||||||
typedef void(*ArgCallbackNone)();
|
typedef void(*fArgNone_t)();
|
||||||
typedef std::string(*ArgCallbackRtn)(str&);
|
typedef std::string(*fRtnArg1_t)(str&);
|
||||||
typedef bool(*ArgCallbackRtnBool)(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
|
#ifdef GTASA
|
||||||
extern const char* taskNames[1802];
|
extern const char* taskNames[1802];
|
||||||
|
@ -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))
|
if (ImGui::IsMouseClicked(1))
|
||||||
{
|
{
|
||||||
@ -305,8 +305,8 @@ static bool RoundedImageButton(ImTextureID textureID, ImVec2& size, const char*
|
|||||||
Here we go again...
|
Here we go again...
|
||||||
This direly needs a refactor oof
|
This direly needs a refactor oof
|
||||||
*/
|
*/
|
||||||
void Widget::ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc,
|
void Widget::ImageList(ResourceStore &store, fArg1_t clickFunc, fRtnArg1_t getNameFunc,
|
||||||
ArgCallbackRtnBool verifyFunc, ArgCallbackNone addFunc)
|
fRtnBoolArg1_t verifyFunc, fArgNone_t addFunc)
|
||||||
{
|
{
|
||||||
static IDirect3DTexture9 **pDefaultTex = nullptr;
|
static IDirect3DTexture9 **pDefaultTex = nullptr;
|
||||||
ImGuiStyle& style = ImGui::GetStyle();
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
static bool ColorBtn(int colorId, std::vector<float>& color, ImVec2 size);
|
static bool ColorBtn(int colorId, std::vector<float>& color, ImVec2 size);
|
||||||
|
|
||||||
// Draws DataStore data in the interface
|
// 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
|
// Draws a dropdown editor for memory address
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -69,8 +69,8 @@ public:
|
|||||||
static bool InputInt(const char* label, int *val, int min = -1, int max = -1);
|
static bool InputInt(const char* label, int *val, int min = -1, int max = -1);
|
||||||
|
|
||||||
// Draws ResourceStore images in the interface
|
// Draws ResourceStore images in the interface
|
||||||
static void ImageList(ResourceStore &store, ArgCallback clickFunc, ArgCallbackRtn getNameFunc,
|
static void ImageList(ResourceStore &store, fArg1_t clickFunc, fRtnArg1_t getNameFunc,
|
||||||
ArgCallbackRtnBool verifyFunc = nullptr, ArgCallbackNone addFunc = nullptr);
|
fRtnBoolArg1_t verifyFunc = nullptr, fArgNone_t addFunc = nullptr);
|
||||||
|
|
||||||
// Draws a dropdown listbox
|
// Draws a dropdown listbox
|
||||||
static bool ListBox(const char* label, VecStr& allItems, int& selected);
|
static bool ListBox(const char* label, VecStr& allItems, int& selected);
|
||||||
|
Loading…
Reference in New Issue
Block a user