#include "pch.h" #include "animation.h" #include "ui.h" #include "widget.h" #include "util.h" #ifdef GTA3 #include #include #include #include "eAnimations.h" #include #elif GTAVC #include "../depend/kiero/minhook/MinHook.h" #include #include #include "eAnimations.h" #include #endif #ifdef GTASA void Cutscene::Play(std::string& rootKey, std::string& cutsceneId, std::string& interior) { if (Util::IsOnCutscene()) { SetHelpMessage(TEXT("Animation.CutsceneRunning")); return; } CPlayerPed* pPlayer = FindPlayerPed(); if (pPlayer) { m_SceneName = cutsceneId; Command(cutsceneId.c_str()); m_nInterior = pPlayer->m_nAreaCode; pPlayer->m_nAreaCode = std::stoi(interior); Command(pPlayer->m_nAreaCode); } } void Particle::Play(std::string& rootKey, std::string& particle, std::string& dummy) { 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_nParticleList.push_back(handle); } } void Particle::Remove(std::string& ifp, std::string& particle, std::string& dummy) { if (ifp == "Custom") { Particle::m_Data.m_pData->RemoveKey("Custom", particle.c_str()); Particle::m_Data.m_pData->Save(); SetHelpMessage(TEXT("Animation.ParticleRemoved")); } else { SetHelpMessage(TEXT("Animation.CustomParticlesOnly")); } } #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& ifp, std::string& anim, std::string& _) { CPed *pPed = m_PedAnim ? 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::Remove(std::string& ifp, std::string& anim, std::string& ifpRepeat) { if (ifp == "Custom") { m_AnimData.m_pData->RemoveKey("Custom", anim.c_str()); m_AnimData.m_pData->Save(); SetHelpMessage(TEXT("Animation.AnimationRemoved")); } else { SetHelpMessage(TEXT("Animation.CustomAnimsOnly")); } } void Animation::Init() { #ifdef GTASA Events::processScriptsEvent += [] { CPlayerPed* pPlayer = FindPlayerPed(); if (Cutscene::m_bRunning) { if (Command()) { if (!pPlayer) { return; } pPlayer->m_nAreaCode = Cutscene::m_nInterior; Command(pPlayer->m_nAreaCode); Cutscene::m_nInterior = 0; TheCamera.Fade(0, 1); } } else { if (Cutscene::m_SceneName != "" && Command()) { Command(); Cutscene::m_bRunning = true; } } 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); MH_CreateHook((void*)0x40D6E0, NEW_CStreaming_RemoveModel, (void**)&OLD_CStreaming_RemoveModel); MH_EnableHook((void*)0x40D6E0); #endif } void Animation::ShowPage() { if (ImGui::BeginTabBar("Animation", ImGuiTabBarFlags_NoTooltip + ImGuiTabBarFlags_FittingPolicyScroll)) { ImGui::Spacing(); CPlayerPed* pPlayer = FindPlayerPed(); int hPlayer = CPools::GetPedRef(pPlayer); ImGui::Spacing(); 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); Ui::CheckboxWithHint(TEXT("Animation.LoopCheckbox"), &m_Loop, TEXT("Animation.LoopCheckboxText")); Ui::CheckboxWithHint(TEXT("Animation.SecondaryCheckbox"), &m_bSecondary, TEXT("Animation.SecondaryCheckboxText")); ImGui::NextColumn(); #ifdef GTASA Ui::CheckboxWithHint(TEXT("Animation.PedAnim"), &m_PedAnim, TEXT("Animation.PedAnimText")); #endif ImGui::Columns(1); ImGui::Spacing(); if (m_PedAnim && !m_pTarget) { ImGui::TextWrapped(TEXT("Animation.NoTarget")); } 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); ImGui::EndChild(); } } ImGui::EndTabItem(); } #ifdef GTASA if (ImGui::BeginTabItem(TEXT("Animation.CutsceneTab"))) { ImGui::Spacing(); if (ImGui::Button(TEXT("Animation.StopCutscene"), Widget::CalcSize())) { if (Cutscene::m_bRunning) { Command(); Cutscene::m_bRunning = false; Cutscene::m_SceneName = ""; CPlayerPed* player = FindPlayerPed(); player->m_nAreaCode = Cutscene::m_nInterior; Command(player->m_nAreaCode); Cutscene::m_nInterior = 0; TheCamera.Fade(0, 1); } } ImGui::Spacing(); if (ImGui::BeginChild("Cutscene Child")) { ImGui::Spacing(); Widget::DataList(Cutscene::m_Data, Cutscene::Play, nullptr); ImGui::EndChild(); } ImGui::EndTabItem(); } if (ImGui::BeginTabItem(TEXT("Animation.ParticleTab"))) { ImGui::Spacing(); if (ImGui::Button(TEXT("Animation.RemoveAll"), Widget::CalcSize(2))) { for (int& p : Particle::m_nParticleList) { Command(p); } Particle::m_nParticleList.clear(); } ImGui::SameLine(); if (ImGui::Button(TEXT("Animation.RemoveLatest"), Widget::CalcSize(2))) { Command(Particle::m_nParticleList.back()); // stop if anything is running Particle::m_nParticleList.pop_back(); } ImGui::Spacing(); if (Ui::CheckboxBitFlag(TEXT("Animation.InvisiblePlayer"), pPlayer->m_nPedFlags.bDontRender)) { 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); 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); SetHelpMessage(TEXT("Animation.FightingStyleSet")); } if (Ui::ListBoxStr(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()); } SetHelpMessage(TEXT("Animation.WalkingStyleSet")); } ImGui::EndTabItem(); } #endif ImGui::EndTabBar(); } }