F4MP/tiltedcode/Code/client/Games/Skyrim/AnimationExperiments.cpp

430 lines
12 KiB
C++
Raw Normal View History

#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)