mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-13 00:00:54 +01:00
192 lines
5.4 KiB
C++
192 lines
5.4 KiB
C++
|
|
#include <TiltedOnlinePCH.h>
|
||
|
|
|
||
|
|
#include <Games/References.h>
|
||
|
|
|
||
|
|
#include <Forms/BGSAction.h>
|
||
|
|
#include <Forms/TESIdleForm.h>
|
||
|
|
|
||
|
|
#include <Structs/ActionEvent.h>
|
||
|
|
|
||
|
|
#include <Games/Animation/ActorMediator.h>
|
||
|
|
#include <Games/Animation/TESActionData.h>
|
||
|
|
|
||
|
|
#include <Misc/BSFixedString.h>
|
||
|
|
|
||
|
|
#include <World.h>
|
||
|
|
|
||
|
|
TP_THIS_FUNCTION(TPerformAction, uint8_t, ActorMediator, TESActionData* apAction);
|
||
|
|
static TPerformAction* RealPerformAction;
|
||
|
|
|
||
|
|
// TODO: make scoped override
|
||
|
|
thread_local bool g_forceAnimation = false;
|
||
|
|
|
||
|
|
uint8_t TP_MAKE_THISCALL(HookPerformAction, ActorMediator, TESActionData* apAction)
|
||
|
|
{
|
||
|
|
auto pActor = apAction->actor;
|
||
|
|
const auto pExtension = pActor->GetExtension();
|
||
|
|
|
||
|
|
if (!pExtension->IsRemote() || g_forceAnimation)
|
||
|
|
{
|
||
|
|
ActionEvent action;
|
||
|
|
action.State1 = pActor->actorState.flags1;
|
||
|
|
action.State2 = pActor->actorState.flags2;
|
||
|
|
action.Type = apAction->unkInput | (apAction->someFlag ? 0x4 : 0);
|
||
|
|
action.Tick = World::Get().GetTick();
|
||
|
|
action.ActorId = pActor->formID;
|
||
|
|
action.ActionId = apAction->action->formID;
|
||
|
|
action.TargetId = apAction->target ? apAction->target->formID : 0;
|
||
|
|
|
||
|
|
pActor->SaveAnimationVariables(action.Variables);
|
||
|
|
|
||
|
|
const auto res = TiltedPhoques::ThisCall(RealPerformAction, apThis, apAction);
|
||
|
|
|
||
|
|
// spdlog::debug("Action event name: {}, target name: {}", apAction->eventName.AsAscii(), apAction->targetEventName.AsAscii());
|
||
|
|
|
||
|
|
// This is a weird case where it gets spammed and doesn't do much, not sure if it still needs to be sent over the network
|
||
|
|
if (apAction->someFlag == 1 || g_forceAnimation)
|
||
|
|
return res;
|
||
|
|
|
||
|
|
action.EventName = apAction->eventName.AsAscii();
|
||
|
|
action.TargetEventName = apAction->targetEventName.AsAscii();
|
||
|
|
action.IdleId = apAction->idleForm ? apAction->idleForm->formID : 0;
|
||
|
|
|
||
|
|
// Save for later
|
||
|
|
if (res)
|
||
|
|
{
|
||
|
|
pExtension->LatestAnimation = action;
|
||
|
|
}
|
||
|
|
|
||
|
|
World::Get().GetRunner().Trigger(action);
|
||
|
|
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
ActorMediator* ActorMediator::Get() noexcept
|
||
|
|
{
|
||
|
|
POINTER_SKYRIMSE(ActorMediator*, s_actorMediator, 403567);
|
||
|
|
|
||
|
|
return *(s_actorMediator.Get());
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ActorMediator::PerformAction(TESActionData* apAction) noexcept
|
||
|
|
{
|
||
|
|
if (apAction->actor->formID == 0x13482)
|
||
|
|
{
|
||
|
|
/*static Set<uint32_t> s_ids;
|
||
|
|
|
||
|
|
spdlog::error("New frame");
|
||
|
|
for(auto i = 0; i < action.Variables.size(); ++i)
|
||
|
|
{
|
||
|
|
auto& oldVars = pExtension->LatestVariables.Variables;
|
||
|
|
auto& newVars = action.Variables;
|
||
|
|
if(oldVars[i] != newVars[i] && s_ids.count(i) == 0)
|
||
|
|
{
|
||
|
|
//s_ids.insert(i);
|
||
|
|
spdlog::info("Var {} changed from {} to {}", i, oldVars[i], newVars[i]);
|
||
|
|
}
|
||
|
|
}*/
|
||
|
|
// spdlog::info("Play animation name: {} with idle {:X} and target {:X} and unk {:X}", apAction->action->keyword.AsAscii(), (apAction->idleForm ? apAction->idleForm->formID : 0), (apAction->target ? apAction->target->formID : 0), apAction->unkInput);
|
||
|
|
}
|
||
|
|
|
||
|
|
const auto res = TiltedPhoques::ThisCall(RealPerformAction, this, apAction);
|
||
|
|
// const auto res = RePerformAction(apAction, aValue);
|
||
|
|
|
||
|
|
if (res && apAction->actor->formID == 0x13482)
|
||
|
|
{
|
||
|
|
// spdlog::info("Passed !");
|
||
|
|
}
|
||
|
|
|
||
|
|
return res != 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool ActorMediator::ForceAction(TESActionData* apAction) noexcept
|
||
|
|
{
|
||
|
|
TP_THIS_FUNCTION(TAnimationStep, uint8_t, ActorMediator, TESActionData*);
|
||
|
|
using TApplyAnimationVariables = void*(void*, TESActionData*);
|
||
|
|
|
||
|
|
POINTER_SKYRIMSE(TApplyAnimationVariables, ApplyAnimationVariables, 39004);
|
||
|
|
POINTER_SKYRIMSE(TAnimationStep, PerformComplexAction, 38953);
|
||
|
|
POINTER_SKYRIMSE(void*, qword_142F271B8, 403566);
|
||
|
|
|
||
|
|
uint8_t result = 0;
|
||
|
|
|
||
|
|
auto pActor = static_cast<Actor*>(apAction->actor);
|
||
|
|
if (pActor)
|
||
|
|
{
|
||
|
|
result = TiltedPhoques::ThisCall(PerformComplexAction, this, apAction);
|
||
|
|
|
||
|
|
ApplyAnimationVariables(*qword_142F271B8.Get(), apAction);
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
ActionInput::ActionInput(uint32_t aParam1, Actor* apActor, BGSAction* apAction, TESObjectREFR* apTarget)
|
||
|
|
{
|
||
|
|
// skip vtable as we never use this directly
|
||
|
|
actor = apActor;
|
||
|
|
target = apTarget;
|
||
|
|
action = apAction;
|
||
|
|
unkInput = aParam1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ActionInput::Release()
|
||
|
|
{
|
||
|
|
actor.Release();
|
||
|
|
target.Release();
|
||
|
|
}
|
||
|
|
|
||
|
|
ActionOutput::ActionOutput()
|
||
|
|
: eventName("")
|
||
|
|
, targetEventName("")
|
||
|
|
{
|
||
|
|
// skip vtable as we never use this directly
|
||
|
|
|
||
|
|
result = 0;
|
||
|
|
targetIdleForm = nullptr;
|
||
|
|
idleForm = nullptr;
|
||
|
|
unk1 = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ActionOutput::Release()
|
||
|
|
{
|
||
|
|
eventName.Release();
|
||
|
|
targetEventName.Release();
|
||
|
|
}
|
||
|
|
|
||
|
|
BGSActionData::BGSActionData(uint32_t aParam1, Actor* apActor, BGSAction* apAction, TESObjectREFR* apTarget)
|
||
|
|
: ActionInput(aParam1, apActor, apAction, apTarget)
|
||
|
|
{
|
||
|
|
// skip vtable as we never use this directly
|
||
|
|
someFlag = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
TESActionData::TESActionData(uint32_t aParam1, Actor* apActor, BGSAction* apAction, TESObjectREFR* apTarget)
|
||
|
|
: BGSActionData(aParam1, apActor, apAction, apTarget)
|
||
|
|
{
|
||
|
|
POINTER_SKYRIMSE(void*, s_vtbl, 188603);
|
||
|
|
|
||
|
|
someFlag = false;
|
||
|
|
|
||
|
|
*reinterpret_cast<void**>(this) = s_vtbl.Get();
|
||
|
|
}
|
||
|
|
|
||
|
|
TESActionData::~TESActionData()
|
||
|
|
{
|
||
|
|
ActionOutput::Release();
|
||
|
|
ActionInput::Release();
|
||
|
|
}
|
||
|
|
|
||
|
|
static TiltedPhoques::Initializer s_animationHook(
|
||
|
|
[]()
|
||
|
|
{
|
||
|
|
POINTER_SKYRIMSE(TPerformAction, performAction, 38949);
|
||
|
|
|
||
|
|
RealPerformAction = performAction.Get();
|
||
|
|
|
||
|
|
TP_HOOK(&RealPerformAction, HookPerformAction);
|
||
|
|
});
|