mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-13 00:00:54 +01:00
429 lines
12 KiB
C++
429 lines
12 KiB
C++
#include <TiltedOnlinePCH.h>
|
|
|
|
thread_local const char* g_animErrorCode = "";
|
|
|
|
#include <Games/Animation/TESActionData.h>
|
|
#include <Games/References.h>
|
|
|
|
#include <Misc/BSFixedString.h>
|
|
#include <DefaultObjectManager.h>
|
|
#include <BSAnimationGraphManager.h>
|
|
#include <DefaultStringManager.h>
|
|
#include <Games/Animation/ActorMediator.h>
|
|
|
|
#include <World.h>
|
|
|
|
#include <Havok/hkbCharacter.h>
|
|
#include <Havok/hkbBehaviorGraph.h>
|
|
#include <Havok/bhkWorldM.h>
|
|
#include <Havok/BShkbAnimationGraph.h>
|
|
#include <Havok/CharacterContext.h>
|
|
#include <Havok/hkbSymbolIdMap.h>
|
|
#include <Havok/hkEventContext.h>
|
|
#include <Havok/hkEventType.h>
|
|
#include <Havok/hkbGenerator.h>
|
|
#include <Havok/BShkbHkxDB.h>
|
|
|
|
#pragma optimize("", off)
|
|
|
|
using TApplyAnimationVariables = void*(void*, TESActionData*);
|
|
POINTER_SKYRIMSE(TApplyAnimationVariables, ApplyAnimationVariables, 39004);
|
|
|
|
POINTER_SKYRIMSE(void*, qword_142F271B8, 403566);
|
|
|
|
extern thread_local bool g_forceAnimation;
|
|
|
|
struct Class142F3A1E8
|
|
{
|
|
uint8_t SendGraphAction(TESActionData* apAction);
|
|
};
|
|
|
|
void hkbBehaviorGraph::ReSendEvent(hkEventContext& aContext, hkEventType& aType)
|
|
{
|
|
TP_THIS_FUNCTION(THandleEvents, void*, hkbBehaviorGraph, hkEventContext&, hkEventType&);
|
|
POINTER_SKYRIMSE(THandleEvents, HandleEvents, 58377);
|
|
|
|
if (!aContext.behaviorGraph)
|
|
{
|
|
// The game makes a copy, might as well do the same
|
|
hkEventType type(aType);
|
|
|
|
ReHandleEvent(aContext, type);
|
|
}
|
|
}
|
|
|
|
void hkbBehaviorGraph::ReHandleEvent(hkEventContext& aContext, hkEventType& aType)
|
|
{
|
|
auto pContext = aContext.characterContext;
|
|
if (!pContext)
|
|
pContext = aContext.character->characterContext;
|
|
|
|
const auto cpSymbolId = pContext->symbolIdMap;
|
|
const auto cbyte20 = pContext->byte20;
|
|
const auto cbyte30 = aContext.byte30;
|
|
|
|
const auto counter = struct98->count;
|
|
for (auto i = 0; i < counter; ++i)
|
|
{
|
|
const auto pSomeData = &struct98->data[i];
|
|
if (!pSomeData->byte84)
|
|
{
|
|
const auto pGraph = pSomeData->behaviorGraph;
|
|
auto pGenerator = pSomeData->generator;
|
|
|
|
pContext->symbolIdMap = pGraph->symbolIdMap;
|
|
pContext->byte20 = 1;
|
|
|
|
auto eventType = aType.type;
|
|
|
|
if (pGraph->symbolIdMap && eventType >= 0)
|
|
{
|
|
TP_THIS_FUNCTION(Tsub_1409CA9D0, int32_t, void, int32_t, int64_t);
|
|
POINTER_SKYRIMSE(Tsub_1409CA9D0, sub_1409CA9D0, 57185);
|
|
|
|
eventType = TiltedPhoques::ThisCall(sub_1409CA9D0, &pGraph->symbolIdMap->pointer20, eventType + 1, -1ll);
|
|
}
|
|
if (eventType != -1)
|
|
{
|
|
aContext.behaviorGraph = pGraph;
|
|
|
|
hkEventType type(eventType);
|
|
type.behaviorGraph = aType.behaviorGraph;
|
|
|
|
if (pSomeData->byte85 == 0)
|
|
{
|
|
TP_THIS_FUNCTION(Tsub_140A13150, int32_t, hkEventContext, hkbGenerator*, hkEventType&, SomeData*);
|
|
POINTER_SKYRIMSE(Tsub_140A13150, sub_140A13150, 59310);
|
|
|
|
TiltedPhoques::ThisCall(sub_140A13150, &aContext, pGenerator, type, pSomeData);
|
|
}
|
|
else
|
|
{
|
|
pGenerator->SendEvent(aContext, type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// dis magic fixes animations
|
|
if (g_forceAnimation)
|
|
aContext.byte30 = 1;
|
|
|
|
pContext->symbolIdMap = cpSymbolId;
|
|
pContext->byte20 = cbyte20;
|
|
|
|
// auto result = 1;
|
|
if (!(aContext.byte30 & 1))
|
|
{
|
|
TP_THIS_FUNCTION(Tsub_1409F3EF0, void, hkbBehaviorGraph, hkEventContext&, hkEventType&);
|
|
POINTER_SKYRIMSE(Tsub_1409F3EF0, sub_1409F3EF0, 58378);
|
|
|
|
hkEventType type(aType);
|
|
|
|
TiltedPhoques::ThisCall(sub_1409F3EF0, this, aContext, type);
|
|
}
|
|
if (byte12E || g_forceAnimation)
|
|
{
|
|
TP_THIS_FUNCTION(Tsub_140A4DFA0, void, hkbBehaviorGraph, hkEventContext&);
|
|
POINTER_SKYRIMSE(Tsub_140A4DFA0, sub_140A4DFA0, 60079);
|
|
|
|
TiltedPhoques::ThisCall(sub_140A4DFA0, this, aContext);
|
|
}
|
|
|
|
aContext.behaviorGraph = nullptr;
|
|
aContext.byte30 = aContext.byte30 || cbyte30;
|
|
}
|
|
|
|
hkEventContext::hkEventContext(hkbCharacter* apCharacter, ahkpWorld* apWorld)
|
|
{
|
|
character = apCharacter;
|
|
behaviorGraph = nullptr;
|
|
unk10 = nullptr;
|
|
characterContext = nullptr;
|
|
unk20 = nullptr;
|
|
unk28 = nullptr;
|
|
byte30 = 0;
|
|
hkpWorld = apWorld;
|
|
unk40 = nullptr;
|
|
unk48 = nullptr;
|
|
}
|
|
|
|
hkEventType::hkEventType(int32_t aType)
|
|
{
|
|
type = aType;
|
|
behaviorGraph = nullptr;
|
|
pointer10 = nullptr;
|
|
}
|
|
|
|
bool BShkbAnimationGraph::ReSendEvent(BSFixedString* apEventName)
|
|
{
|
|
if (behaviorGraph && behaviorGraph->byte12C)
|
|
{
|
|
if (hkxDB->ptr160)
|
|
{
|
|
using Thash_stub = uint32_t(uint32_t&, const char*);
|
|
POINTER_SKYRIMSE(Thash_stub, hash_stub, 68221);
|
|
|
|
uint32_t hash = 0;
|
|
hash_stub(hash, apEventName->data);
|
|
|
|
const auto pBuckets = hkxDB->hashTable.buckets;
|
|
if (pBuckets)
|
|
{
|
|
const auto mask = hkxDB->hashTable.bucketCount - 1;
|
|
|
|
auto pEntry = &pBuckets[hash & mask];
|
|
if (pEntry->next)
|
|
{
|
|
while (pEntry->key != apEventName->data)
|
|
{
|
|
pEntry = pEntry->next;
|
|
if (pEntry == hkxDB->hashTable.end)
|
|
return false;
|
|
}
|
|
|
|
ahkpWorld* pWorld = nullptr;
|
|
if (hkWorldM)
|
|
pWorld = hkWorldM->GetWorld();
|
|
|
|
auto* pCharacter = &character;
|
|
|
|
hkEventContext context(pCharacter, pWorld);
|
|
hkEventType type(pEntry->value);
|
|
|
|
// 1409f0360
|
|
behaviorGraph->ReSendEvent(context, type);
|
|
|
|
return context.byte30 != 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
/*
|
|
TP_THIS_FUNCTION(TBSSendEvent, bool, BShkbAnimationGraph, BSFixedString*);
|
|
POINTER_SKYRIMSE(TBSSendEvent, InternalSendEvent, 63591);
|
|
|
|
return TiltedPhoques::ThisCall(InternalSendEvent, this, apEventName);*/
|
|
}
|
|
|
|
uint32_t BSAnimationGraphManager::ReSendEvent(BSFixedString* apEventName)
|
|
{
|
|
BSScopedLock<BSRecursiveLock> _(lock);
|
|
|
|
uint32_t counter = 0;
|
|
|
|
for (decltype(animationGraphs.size) i = 0; i < animationGraphs.size; ++i)
|
|
{
|
|
auto pCurrentAnimationGraph = animationGraphs.Get(i);
|
|
if (pCurrentAnimationGraph->ReSendEvent(apEventName))
|
|
++counter;
|
|
}
|
|
|
|
// Not sure what this is, looks like it call this function on another graph manager, maybe to sync ridder/ridden ?
|
|
TP_THIS_FUNCTION(Tsub_140AE2DB0, uint8_t, BSAnimationGraphManager, BSFixedString*);
|
|
POINTER_SKYRIMSE(Tsub_140AE2DB0, sub_140AE2DB0, 63372);
|
|
|
|
TiltedPhoques::ThisCall(sub_140AE2DB0, this, apEventName);
|
|
|
|
return counter;
|
|
}
|
|
|
|
bool IAnimationGraphManagerHolder::ReSendAnimationEvent(BSFixedString* apAnimEvent)
|
|
{
|
|
BSAnimationGraphManager* pAnimationGraph = nullptr;
|
|
auto result = GetBSAnimationGraph(&pAnimationGraph);
|
|
|
|
TP_THIS_FUNCTION(TBSSendEvent, uint32_t, BSAnimationGraphManager, BSFixedString*);
|
|
POINTER_SKYRIMSE(TBSSendEvent, BSSendEvent, 63362);
|
|
|
|
if (pAnimationGraph)
|
|
{
|
|
result = pAnimationGraph->ReSendEvent(apAnimEvent) != 0;
|
|
|
|
pAnimationGraph->Release();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
uint8_t Class142F3A1E8::SendGraphAction(TESActionData* apAction)
|
|
{
|
|
TP_THIS_FUNCTION(TGetSomeIdleProperty, uint8_t, TESIdleForm);
|
|
POINTER_SKYRIMSE(TGetSomeIdleProperty, GetSomeIdleProperty, 24568);
|
|
|
|
if (!apAction->actor)
|
|
return 0;
|
|
|
|
if (apAction->idleForm)
|
|
{
|
|
auto& objectManager = DefaultObjectManager::Get();
|
|
BGSAction* pAction = nullptr;
|
|
if (objectManager.isSomeActionReady)
|
|
{
|
|
pAction = objectManager.someAction;
|
|
}
|
|
|
|
if (pAction == apAction->action)
|
|
{
|
|
const auto result = static_cast<float>(TiltedPhoques::ThisCall(GetSomeIdleProperty, apAction->idleForm));
|
|
|
|
auto& stringManager = DefaultStringManager::Get();
|
|
|
|
apAction->actor->animationGraphHolder.SetVariableFloat(&stringManager.fIdleTimer, result);
|
|
}
|
|
}
|
|
|
|
return apAction->actor->animationGraphHolder.ReSendAnimationEvent(&apAction->eventName);
|
|
}
|
|
|
|
bool ActorMediator::RePerformAction(TESActionData* apAction) noexcept
|
|
{
|
|
TP_THIS_FUNCTION(TAnimationStep, uint8_t, ActorMediator, TESActionData*);
|
|
|
|
POINTER_SKYRIMSE(TAnimationStep, PerformIdleAction, 38952);
|
|
POINTER_SKYRIMSE(TAnimationStep, PerformComplexAction, 38953);
|
|
|
|
uint8_t result = 0;
|
|
|
|
auto pActor = static_cast<Actor*>(apAction->actor);
|
|
if (!pActor || pActor->animationGraphHolder.IsReady())
|
|
{
|
|
// result = TiltedPhoques::ThisCall(PerformIdleAction, this, apAction);
|
|
|
|
// if (apAction->someFlag & BGSActionData::kTransitionNoAnimation)
|
|
// apAction->someFlag = BGSActionData::kSkip;
|
|
// else
|
|
{
|
|
result = TiltedPhoques::ThisCall(PerformComplexAction, this, apAction);
|
|
// result = RePerformComplexAction(apAction);
|
|
}
|
|
|
|
ApplyAnimationVariables(*qword_142F271B8.Get(), apAction);
|
|
|
|
/*if (result == 0)
|
|
g_animErrorCode = "PerformIdleAction failed";
|
|
|
|
if(result)
|
|
{
|
|
if (apAction->someFlag & BGSActionData::kTransitionNoAnimation)
|
|
apAction->someFlag = BGSActionData::kSkip;
|
|
else
|
|
{
|
|
result = TiltedPhoques::ThisCall(PerformComplexAction, this, apAction);
|
|
//result = RePerformComplexAction(apAction);
|
|
}
|
|
}
|
|
else if ((apAction->someFlag & BGSActionData::kTransitionNoAnimation) == 0)
|
|
{
|
|
ApplyAnimationVariables(*qword_142F271B8.Get(), apAction);
|
|
}*/
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool ActorMediator::RePerformIdleAction(TESActionData* apData) noexcept
|
|
{
|
|
using Tsub_14063CAA0 = bool(void*, TESActionData*);
|
|
using Tsub_14063CFB0 = bool(void*, TESActionData*);
|
|
using Tsub_1405CCB20 = bool(void*, TESActionData*);
|
|
using Tsub_1404ECF50 = bool(void*, TESActionData*);
|
|
|
|
POINTER_SKYRIMSE(Tsub_14063CAA0, sub_14063CAA0, 39002);
|
|
POINTER_SKYRIMSE(Tsub_14063CFB0, sub_14063CFB0, 38952);
|
|
POINTER_SKYRIMSE(Tsub_1405CCB20, sub_1405CCB20, 37147);
|
|
POINTER_SKYRIMSE(Tsub_1404ECF50, sub_1404ECF50, 32802);
|
|
|
|
POINTER_SKYRIMSE(void*, qword_142F271C8, 403568);
|
|
POINTER_SKYRIMSE(void*, qword_142EFF990, 401100);
|
|
|
|
bool result = true;
|
|
|
|
if (((apData->someFlag >> 1) & 1) == 0)
|
|
{
|
|
if (!sub_14063CAA0(*qword_142F271B8.Get(), apData))
|
|
{
|
|
result = false;
|
|
}
|
|
|
|
if (sub_1405CCB20(*qword_142F271C8.Get(), apData))
|
|
{
|
|
if (result && !sub_14063CFB0(*qword_142F271B8.Get(), apData))
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
result = false;
|
|
}
|
|
|
|
// Has something to do with the target refr
|
|
sub_1404ECF50(*qword_142EFF990.Get(), apData);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool ActorMediator::RePerformComplexAction(TESActionData* apData) noexcept
|
|
{
|
|
TP_THIS_FUNCTION(Tsub_1404ED090, uint8_t, void, TESActionData*);
|
|
|
|
using Tsub_1401A2220 = void(BSFixedString*);
|
|
|
|
POINTER_SKYRIMSE(Tsub_1404ED090, sub_1404ED090, 32803);
|
|
POINTER_SKYRIMSE(Tsub_1401A2220, sub_1401A2220, 15002);
|
|
|
|
POINTER_SKYRIMSE(void, qword_142EFF990, 401100);
|
|
POINTER_SKYRIMSE(Class142F3A1E8, qword_142F3A1E8, 403988);
|
|
|
|
auto v4 = false;
|
|
if (apData->ComputeResult())
|
|
v4 = apData->result == 2;
|
|
|
|
auto result = TiltedPhoques::ThisCall(sub_1404ED090, qword_142EFF990, apData);
|
|
if (result)
|
|
{
|
|
qword_142F3A1E8->SendGraphAction(apData);
|
|
}
|
|
|
|
ApplyAnimationVariables(*qword_142F271B8.Get(), apData);
|
|
|
|
if (!v4)
|
|
return result;
|
|
|
|
apData->someFlag &= 0xFFFFFFFC;
|
|
sub_1401A2220(&apData->eventName);
|
|
|
|
result = apData->Perform() & 0xFF;
|
|
|
|
return result;
|
|
}
|
|
|
|
bool TESActionData::ComputeResult()
|
|
{
|
|
using Tsub_1401A1D50 = char(void*, TESActionData*);
|
|
POINTER_SKYRIMSE(Tsub_1401A1D50, sub_1401A1D50, 15006);
|
|
|
|
result = 0;
|
|
if (targetIdleForm)
|
|
{
|
|
if (!_strnicmp(eventName, "NA_", 3))
|
|
{
|
|
result = 2;
|
|
return true;
|
|
}
|
|
|
|
auto v3 = sub_3();
|
|
if (v3)
|
|
{
|
|
result = 1;
|
|
sub_1401A1D50(v3, this);
|
|
}
|
|
}
|
|
|
|
return result > 0;
|
|
}
|
|
|
|
#pragma optimize("", on)
|