F4MP/tiltedcode/Code/client/Games/Forms.cpp
Jous99 37b16f1547 code upload
codigo original de f4mp y tilted para referencias
2026-01-06 18:45:00 +01:00

141 lines
3.4 KiB
C++

#include <TiltedOnlinePCH.h>
#include <PlayerCharacter.h>
#include <Forms/BGSHeadPart.h>
#include <Forms/TESNPC.h>
#include <Games/IFormFactory.h>
#include <SaveLoad.h>
#include <Games/Overrides.h>
TESForm* TESForm::GetById(const uint32_t aId)
{
using TGetFormById = TESForm*(uint32_t);
POINTER_SKYRIMSE(TGetFormById, getFormById, 14617);
return getFormById.Get()(aId);
}
void TESNPC::Serialize(String* apSaveBuffer) const noexcept
{
ScopedSaveLoadOverride saveLoadOverride;
char buffer[1 << 15];
BGSSaveFormBuffer saveBuffer;
saveBuffer.buffer = buffer;
saveBuffer.capacity = 1 << 15;
saveBuffer.changeFlags = GetChangeFlags();
Save(&saveBuffer);
apSaveBuffer->assign(saveBuffer.buffer, saveBuffer.position);
saveBuffer.buffer = nullptr;
}
void TESNPC::Deserialize(const String& acBuffer, uint32_t aChangeFlags) noexcept
{
ScopedSaveLoadOverride saveLoadOverride;
BGSLoadFormBuffer loadBuffer(aChangeFlags);
loadBuffer.SetSize(acBuffer.size() & 0xFFFFFFFF);
loadBuffer.buffer = acBuffer.data();
loadBuffer.formId = formID;
loadBuffer.form = this;
Load(&loadBuffer);
loadBuffer.buffer = nullptr;
}
void TESNPC::Initialize() noexcept
{
auto pPlayerBaseForm = Cast<TESNPC>(PlayerCharacter::Get()->baseForm);
// These values are all defaulted, if the other actor did not modify them they won't be loaded, therefore we need to force them before load
attackDataForm.attackDataMap = pPlayerBaseForm->attackDataForm.attackDataMap;
npcClass = pPlayerBaseForm->npcClass;
combatStyle = pPlayerBaseForm->combatStyle;
raceForm.race = pPlayerBaseForm->raceForm.race;
outfits[0] = pPlayerBaseForm->outfits[0];
spellList.Initialize();
// End defaults
flags |= 0x200000;
}
void TESForm::Save_Reversed(const uint32_t aChangeFlags, Buffer::Writer& aWriter)
{
if (aChangeFlags & 1)
{
aWriter.WriteBytes(reinterpret_cast<uint8_t*>(&flags), 4);
aWriter.WriteBytes(reinterpret_cast<uint8_t*>(&unk10), 2);
}
}
void TESForm::SetSkipSaveFlag(bool aSet) noexcept
{
if (aSet)
{
unk10 = 0xFFFF;
}
/*const uint32_t flag = 1 << 14;
if (aSet)
flags |= flag;
else
flags &= ~flag;*/
}
uint32_t TESForm::GetChangeFlags() const noexcept
{
struct Unk
{
uint8_t unk0[0x330];
void* unk330;
};
TP_THIS_FUNCTION(InternalGetChangeFlags, bool, void, uint32_t formId, ChangeFlags& changeFlags);
POINTER_SKYRIMSE(InternalGetChangeFlags, internalGetChangeFlags, 35503);
POINTER_SKYRIMSE(Unk*, s_singleton, 403330);
const auto pUnk = *(s_singleton.Get());
ChangeFlags changeFlags;
const auto cResult = TiltedPhoques::ThisCall(internalGetChangeFlags, pUnk->unk330, formID, changeFlags);
if (!cResult)
return 0;
return changeFlags.flags;
}
TESNPC* TESNPC::Create(const String& acBuffer, const uint32_t aChangeFlags) noexcept
{
auto pNpc = IFormFactory::Create<TESNPC>();
pNpc->Initialize();
pNpc->Deserialize(acBuffer, aChangeFlags);
// This forces facegen for some reason
pNpc->overlayRace = nullptr;
return pNpc;
}
BGSHeadPart* TESNPC::GetHeadPart(uint32_t aType)
{
if (headparts)
{
for (auto i = 0; i < headpartsCount; ++i)
{
if (headparts[i] && headparts[i]->type == aType)
return headparts[i];
}
}
return nullptr;
}