diff --git a/include/RE/A/Actor.h b/include/RE/A/Actor.h index 5e79f3792..09b47219b 100644 --- a/include/RE/A/Actor.h +++ b/include/RE/A/Actor.h @@ -536,6 +536,7 @@ namespace RE TESForm* GetEquippedObjectInSlot(const BGSEquipSlot* slot) const; float GetEquippedWeight(); std::int32_t GetFactionRank(TESFaction* a_faction, bool a_isPlayer); + FIGHT_REACTION GetFactionReaction(Actor* a_other) const; std::int32_t GetGoldAmount(bool a_noInit = false); ActorHandle GetHandle(); [[nodiscard]] NiAVObject* GetHeadPartObject(BGSHeadPart::HeadPartType a_type); @@ -548,13 +549,16 @@ namespace RE bool GetMountedBy(NiPointer& a_outRider); double GetMoveDirectionRelativeToFacing(); ObjectRefHandle GetOccupiedFurniture() const; + bool GetPlayerControls() const; TESRace* GetRace() const; float GetRegenDelay(ActorValue a_actorValue) const; bool GetRider(NiPointer& a_outRider); [[nodiscard]] TESObjectARMO* GetSkin() const; [[nodiscard]] TESObjectARMO* GetSkin(BGSBipedObjectForm::BipedObjectSlot a_slot, bool a_noInit = false); [[nodiscard]] SOUL_LEVEL GetSoulSize() const; + TESNPC* GetTemplateBase(); float GetTotalCarryWeight(); + float GetTrackedDamage() const; TESFaction* GetVendorFaction(); const TESFaction* GetVendorFaction() const; float GetVoiceRecoveryTime(); @@ -573,12 +577,15 @@ namespace RE bool IsAIEnabled() const; bool IsAlarmed() const; bool IsAMount() const; + bool IsAngryWithPlayer() const { return boolFlags.all(BOOL_FLAGS::kAngryWithPlayer); }; bool IsAnimationDriven() const; bool IsBeingRidden() const; bool IsBlocking() const; bool IsCasting(MagicItem* a_spell) const; + bool IsCombatTarget(Actor* a_other) const; bool IsCommandedActor() const; bool IsCurrentShout(SpellItem* a_power); + bool IsDoingFavor() const; bool IsDualCasting() const; bool IsEssential() const; bool IsFactionInCrimeGroup(const TESFaction* a_faction) const; @@ -614,6 +621,7 @@ namespace RE void SetHeading(float a_angle); // SetRotationZ void SetLifeState(ACTOR_LIFE_STATE a_lifeState); void SetLooking(float a_angle); // SetRotationX + void SetPlayerControls(bool a_enable); bool SetSleepOutfit(BGSOutfit* a_outfit, bool a_update3D); void StealAlarm(TESObjectREFR* a_ref, TESForm* a_object, std::int32_t a_num, std::int32_t a_total, TESForm* a_owner, bool a_allowWarning); void StopAlarmOnActor(); diff --git a/src/RE/A/Actor.cpp b/src/RE/A/Actor.cpp index f3eed92e4..0b430e181 100644 --- a/src/RE/A/Actor.cpp +++ b/src/RE/A/Actor.cpp @@ -12,11 +12,13 @@ #include "RE/B/bhkCharacterController.h" #include "RE/E/ExtraCanTalkToPlayer.h" #include "RE/E/ExtraFactionChanges.h" +#include "RE/E/ExtraLeveledCreature.h" #include "RE/F/FixedStrings.h" #include "RE/F/FormTraits.h" #include "RE/H/HighProcessData.h" #include "RE/I/InventoryEntryData.h" #include "RE/M/MiddleHighProcessData.h" +#include "RE/M/MovementControllerNPC.h" #include "RE/M/Misc.h" #include "RE/N/NiColor.h" #include "RE/N/NiMath.h" @@ -433,6 +435,13 @@ namespace RE return func(this, a_faction, a_isPlayer); } + FIGHT_REACTION Actor::GetFactionReaction(Actor* a_other) const + { + using func_t = decltype(&GetFactionReaction); + REL::Relocation func{ RELOCATION_ID(36658, 37666) }; + return func(this, a_other); + } + std::int32_t Actor::GetGoldAmount(bool a_noInit) { const auto inv = GetInventory([](TESBoundObject& a_object) -> bool { @@ -539,6 +548,14 @@ namespace RE } } + bool Actor::GetPlayerControls() const + { + if (movementController) { + return movementController->IsPlayerControlsEnabled(); + } + return false; + } + TESRace* Actor::GetRace() const { if (race) { @@ -589,6 +606,15 @@ namespace RE return func(this); } + TESNPC* Actor::GetTemplateBase() + { + auto leveledCreature = extraList.GetByType(); + if (leveledCreature) { + return static_cast(leveledCreature->templateBase); + } + return GetActorBase(); + } + float Actor::GetTotalCarryWeight() { using func_t = decltype(&Actor::GetTotalCarryWeight); @@ -596,6 +622,11 @@ namespace RE return func(this); } + float Actor::GetTrackedDamage() const + { + return currentProcess ? currentProcess->trackedDamage : 0.0f; + } + TESFaction* Actor::GetVendorFaction() { if (!vendorFaction) { @@ -766,6 +797,13 @@ namespace RE return func(this, a_spell); } + bool Actor::IsCombatTarget(Actor* a_other) const + { + using func_t = decltype(&IsCombatTarget); + REL::Relocation func{ RELOCATION_ID(37618, 38571) }; + return func(this, a_other); + } + bool Actor::IsCommandedActor() const { return boolFlags.all(BOOL_FLAGS::kIsCommandedActor); @@ -778,6 +816,14 @@ namespace RE return func(this, a_power); } + bool Actor::IsDoingFavor() const + { + if (currentProcess) { + return currentProcess->IsInCommandState(); + } + return false; + } + bool Actor::IsDualCasting() const { if (!currentProcess) { @@ -1036,6 +1082,18 @@ namespace RE return func(this, a_angle); } + void Actor::SetPlayerControls(bool a_enable) + { + if (movementController) { + EnableAI(!a_enable); + if (a_enable) { + movementController->EnablePlayerControls(); + } else { + movementController->DisablePlayerControls(); + } + } + } + bool Actor::SetSleepOutfit(BGSOutfit* a_outfit, bool a_update3D) { const auto npc = GetActorBase();