#pragma once #include #include #include #include #include #include #include #include #include #include #include struct TESNPC; struct TESRace; struct ExActor; struct ExPlayerCharacter; struct ActorExtension; struct AIProcess; struct CombatController; struct TESIdleForm; struct Actor : TESObjectREFR { static constexpr FormType Type = FormType::Character; // Allocs and calls constructor static GamePtr New() noexcept; // Places a brand new actor in the world static GamePtr Create(TESNPC* apBaseForm) noexcept; static GamePtr Spawn(uint32_t aBaseFormId) noexcept; virtual void sub_9C(); virtual void sub_9D(); virtual void sub_9E(); virtual void sub_9F(); virtual void sub_A0(); virtual void UnequipObject(void* apUnk1, TESBoundObject* apObject, int32_t aUnk2, void* aUnk3); virtual void sub_A2(); virtual void sub_A3(); virtual void sub_A4(); virtual void sub_A5(); virtual void SetWeaponDrawn(bool aDraw); virtual void sub_A7(); virtual void sub_A8(); virtual void SetPosition(const NiPoint3& acPoint, bool aSyncHavok = true); virtual void sub_AA(); virtual void Resurrect(bool aResetInventory); virtual void sub_AC(); virtual void sub_AD(); virtual void sub_AE(); virtual void sub_AF(); virtual void sub_B0(); virtual void sub_B1(); virtual void sub_B2(); virtual void sub_B3(); virtual void sub_B4(); virtual void sub_B5(); virtual void sub_B6(); virtual void sub_B7(); virtual void sub_B8(); virtual void sub_B9(); virtual void sub_BA(); virtual void PayFine(TESFaction* apFaction, bool aGoToJail, bool aRemoveStolenItems); virtual void sub_BC(); virtual void sub_BD(); virtual void sub_BE(); virtual void sub_BF(); virtual void sub_C0(); virtual void sub_C1(); virtual void sub_C2(); virtual void SetRefraction(bool aEnable, float aRefraction); virtual void sub_C4(); virtual void sub_C5(); virtual void sub_C6(); virtual void sub_C7(); virtual void sub_C8(); virtual void sub_C9(); virtual void sub_CA(); virtual void sub_CB(); virtual void sub_CC(); virtual void AttachArrow(); virtual void sub_CE(); virtual void sub_CF(); virtual void sub_D0(); virtual void sub_D1(); virtual bool sub_D2() const; virtual void sub_D3(); virtual void sub_D4(); virtual void sub_D5(); virtual void sub_D6(); virtual void sub_D7(); virtual void sub_D8(); virtual void sub_D9(); virtual void sub_DA(); virtual void sub_DB(); virtual void sub_DC(); virtual void sub_DD(); virtual void sub_DE(); virtual void PutCreatedPackage(struct TESPackage*, bool = false, bool = true, bool = true); // 14069BBF0 virtual void UpdateAlpha(); virtual void sub_E1(); virtual void sub_E2(); virtual void sub_E3(); virtual void sub_E4(); virtual void sub_E5(); virtual void sub_E6(); virtual void sub_E7(); virtual void sub_E8(); virtual void sub_E9(); virtual void sub_EA(); virtual void sub_EB(); virtual void sub_EC(); virtual void sub_ED(); virtual void sub_EE(); virtual void sub_EF(); // these 4 are not virtual funcs in fallout 4 virtual bool MoveToHigh(); virtual bool MoveToLow(); virtual bool MoveToMiddleLow(); virtual bool MoveToMiddleHigh(); virtual bool sub_F4(); virtual void sub_F5(); virtual void sub_F6(); virtual void sub_F7(); virtual void sub_F8(); virtual void sub_F9(); virtual void sub_FA(); virtual void sub_FB(); virtual void sub_FC(); virtual void sub_FD(); virtual void sub_FE(); virtual void sub_FF(); virtual void sub_100(); virtual void sub_101(); virtual void sub_102(); virtual void sub_103(); virtual void sub_104(); virtual void sub_105(); virtual void sub_106(); virtual void sub_107(); virtual void sub_108(); virtual void InitializeMovementControllerNPC(); virtual void sub_10A(); virtual void sub_10B(); virtual void sub_10C(); virtual void sub_10D(); virtual void KillImpl(Actor* apAttacker, float aDamage, bool aSendEvent, bool aRagdollInstant); virtual void DrinkPotion(TESBoundObject* apItem, ExtraDataList* apExtraDataList); // 90% sure about this virtual void sub_110(); virtual void sub_111(); virtual void sub_112(); virtual void sub_113(); virtual void sub_114(); virtual bool sub_115(); virtual bool sub_116(); virtual void sub_117(); virtual void sub_118(); virtual void sub_119(); virtual void sub_11A(); virtual void sub_11B(); virtual void sub_11C(); virtual void sub_11D(); virtual void sub_11E(); virtual void sub_11F(); virtual void sub_120(); virtual void sub_121(); virtual void sub_122(); virtual void sub_123(); virtual void sub_124(); virtual void sub_125(); virtual void sub_126(); virtual void sub_127(); // Real functions void DualCastSpell(TESObjectREFR* apDesiredTarget) noexcept; void InterruptCast(bool abRefund) noexcept; // Casting ActorExtension* GetExtension() noexcept; ExActor* AsExActor() noexcept; ExPlayerCharacter* AsExPlayerCharacter() noexcept; // Getters float GetSpeed() noexcept; TESForm* GetEquippedWeapon(uint32_t aSlotId) const noexcept; TESForm* GetEquippedAmmo() const noexcept; Actor* GetCommandingActor() const noexcept; // in reality this is a BGSLocation TESForm* GetCurrentLocation(); float GetActorValue(uint32_t aId) const noexcept; float GetActorPermanentValue(uint32_t aId) const noexcept; Inventory GetActorInventory() const noexcept; MagicEquipment GetMagicEquipment() const noexcept; Inventory GetEquipment() const noexcept; int32_t GetGoldAmount() const noexcept; uint16_t GetLevel() const noexcept; Factions GetFactions() const noexcept; ActorValues GetEssentialActorValues() const noexcept; [[nodiscard]] bool IsDead() const noexcept; [[nodiscard]] bool IsDragon() const noexcept; [[nodiscard]] bool IsPlayerSummon() const noexcept; [[nodiscard]] bool IsInCombat() const noexcept; [[nodiscard]] Actor* GetCombatTarget() const noexcept; [[nodiscard]] bool HasPerk(uint32_t aPerkFormId) const noexcept; [[nodiscard]] uint8_t GetPerkRank(uint32_t aPerkFormId) const noexcept; [[nodiscard]] bool IsWearingBodyPiece() const noexcept; [[nodiscard]] bool ShouldWearBodyPiece() const noexcept; [[nodiscard]] bool IsVampireLord() const noexcept; // Setters void SetSpeed(float aSpeed) noexcept; void SetLevelMod(uint32_t aLevel) noexcept; void SetActorValue(uint32_t aId, float aValue) noexcept; void ForceActorValue(ActorValueOwner::ForceMode aMode, uint32_t aId, float aValue) noexcept; void SetActorValues(const ActorValues& acActorValues) noexcept; void SetCommandingActor(BSPointerHandle aCommandingActor) noexcept; void SetFactions(const Factions& acFactions) noexcept; void SetFactionRank(const TESFaction* apFaction, int8_t aRank) noexcept; void ForcePosition(const NiPoint3& acPosition) noexcept; void SetWeaponDrawnEx(bool aDraw) noexcept; void SetPackage(TESPackage* apPackage) noexcept; void SetActorInventory(const Inventory& aInventory) noexcept; void SetMagicEquipment(const MagicEquipment& acEquipment) noexcept; void SetEssentialEx(bool aSet) noexcept; void SetNoBleedoutRecovery(bool aSet) noexcept; void SetPlayerRespawnMode(bool aSet = true) noexcept; void SetPlayerTeammate(bool aSet) noexcept; // Actions void UnEquipAll() noexcept; void RemoveFromAllFactions() noexcept; void QueueUpdate() noexcept; bool InitiateMountPackage(Actor* apMount) noexcept; void GenerateMagicCasters() noexcept; void DispelAllSpells(bool aNow = false) noexcept; void Reset() noexcept; void Kill() noexcept; void Respawn() noexcept; void PickUpObject(TESObjectREFR* apObject, int32_t aCount, bool aUnk1, float aUnk2) noexcept; void DropObject(TESBoundObject* apObject, ExtraDataList* apExtraData, int32_t aCount, NiPoint3* apLocation, NiPoint3* apRotation) noexcept; void DropOrPickUpObject(const Inventory::Entry& arEntry, NiPoint3* apPoint, NiPoint3* apRotate) noexcept; void SpeakSound(const char* pFile); void StartCombatEx(Actor* apTarget) noexcept; void SetCombatTargetEx(Actor* apTarget) noexcept; void StartCombat(Actor* apTarget) noexcept; void StopCombat() noexcept; bool PlayIdle(TESIdleForm* apIdle) noexcept; void FixVampireLordModel() noexcept; bool RemoveSpell(MagicItem* apSpell) noexcept; enum ActorFlags { IS_A_MOUNT = 1 << 1, IS_COMMANDED_ACTOR = 1 << 16, IS_ESSENTIAL = 1 << 18, }; bool IsMount() const noexcept { return flags2 & ActorFlags::IS_A_MOUNT; } bool IsEssential() const noexcept { return flags2 & ActorFlags::IS_ESSENTIAL; } void SetEssential(bool aSetEssential) noexcept { if (aSetEssential) flags2 |= ActorFlags::IS_ESSENTIAL; else flags2 &= ~ActorFlags::IS_ESSENTIAL; } bool IsCommandedActor() const noexcept { return flags2 & ActorFlags::IS_COMMANDED_ACTOR; } public: enum ChangeFlags : uint32_t { CHANGE_ACTOR_LIFESTATE = 1 << 10, CHANGE_ACTOR_EXTRA_PACKAGE_DATA = 1 << 11, CHANGE_ACTOR_EXTRA_MERCHANT_CONTAINER = 1 << 12, CHANGE_ACTOR_EXTRA_DISMEMBERED_LIMBS = 1 << 17, CHANGE_ACTOR_LEVELED_ACTOR = 1 << 18, CHANGE_ACTOR_DISPOSITION_MODIFIERS = 1 << 19, CHANGE_ACTOR_TEMP_MODIFIERS = 1 << 20, CHANGE_ACTOR_DAMAGE_MODIFIERS = 1 << 21, CHANGE_ACTOR_OVERRIDE_MODIFIERS = 1 << 22, CHANGE_ACTOR_PERMANENT_MODIFIERS = 1 << 23, }; struct ActorValueModifiers { float permanentModifier; float temporaryModifier; float damageModifier; }; struct SpellItemEntry { SpellItem* pItem; float unk8; SpellItemEntry* pNext; }; MagicTarget magicTarget; ActorValueOwner actorValueOwner; ActorState actorState; BSTEventSink tdEvent; BSTEventSink cmfEvent; IPostAnimationChannelUpdateFunctor unk78; uint32_t flags1; float headTrackingUpdateDelay; uint32_t unk84; AIProcess* currentProcess; uint32_t dialogueHandle; uint32_t combatHandle; uint32_t killerHandle; uint32_t unk98; float fVoiceTimer; uint32_t unkA0; uint32_t unkA4; int32_t iThiefCrimeStamp; int32_t iActionValue; float fTimerOnAction; uint32_t unkB4[5]; void* pad138[2]; struct IMovementDrivenControl* movementDrivenControl; // MovementControllerNPC uint32_t unk0D4; CombatController* pCombatController; void* unkDC; uint32_t unkE0; uint32_t unkE4; uint32_t unkE8; uint32_t unkEC; uint32_t unk178; // F0 uint32_t unk17C; // F4 SpellItemEntry* spellItemHead; // F8 BSTSmallArray addedSpells; ActorMagicCaster* casters[4]; MagicItem* magicItems[4]; TESForm* equippedShout; uint32_t someRefrHandle; TESRace* race; float weight; // set to -1.0 by extra container changes data ctor, asuming it's the weight uint32_t flags2; void* unk200[4]; struct BGSDialogueBranch* dialogueBranch; ActorValueModifiers healthModifiers; ActorValueModifiers staminaModifiers; ActorValueModifiers magickaModifiers; ActorValueModifiers voiceModifiers; float fLastUpdate; uint32_t iLastSeenTime; void* actorWeightData; float fArmorRating; float fArmorBaseFactorSum; uint8_t unk194; uint8_t unk195; uint8_t unk196; uint8_t flag197; uint8_t pad198[8]; BSRecursiveLock actorLock; uint8_t padActorEnd[0x2B0 - 0x284]; // void Save_Reversed(uint32_t aChangeFlags, Buffer::Writer& aWriter); }; static_assert(offsetof(Actor, currentProcess) == 0xF8); static_assert(offsetof(Actor, flags1) == 0xE8); static_assert(offsetof(Actor, actorValueOwner) == 0xB8); static_assert(offsetof(Actor, actorState) == 0xC0); static_assert(offsetof(Actor, flags2) == 0x204); static_assert(offsetof(Actor, unk194) == 0x278); static_assert(offsetof(Actor, fVoiceTimer) == 0x110); static_assert(offsetof(Actor, unk84) == 0xF0); static_assert(offsetof(Actor, unk17C) == 0x184); static_assert(offsetof(Actor, pCombatController) == 0x160); static_assert(offsetof(Actor, magicItems) == 0x1C8); static_assert(offsetof(Actor, equippedShout) == 0x1E8); static_assert(offsetof(Actor, actorLock) == 0x284); static_assert(sizeof(Actor) == 0x2B8); static_assert(sizeof(Actor::SpellItemEntry) == 0x18);