Skip to content

Commit

Permalink
Merge pull request Ryan-rsm-McKenzie#125 from zax-ftw/pr
Browse files Browse the repository at this point in the history
Add `bhkCharacterController` `MovementControllerNPC` and `Actor` related
  • Loading branch information
powerof3 authored Aug 15, 2024
2 parents b76137b + 2fb79fc commit 32ed704
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 48 deletions.
1 change: 1 addition & 0 deletions include/RE/A/AIProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ namespace RE
bool InLowProcess() const;
bool IsArrested() const;
bool IsGhost() const;
bool IsInCommandState() const;
void KnockExplosion(Actor* a_actor, const NiPoint3& a_location, float a_magnitude);
bool PlayIdle(Actor* a_actor, TESIdleForm* a_idle, TESObjectREFR* a_target);
void SetActorsDetectionEvent(Actor* a_actor, const NiPoint3& a_location, std::int32_t a_soundLevel, TESObjectREFR* a_ref);
Expand Down
8 changes: 8 additions & 0 deletions include/RE/A/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -548,13 +549,16 @@ namespace RE
bool GetMountedBy(NiPointer<Actor>& a_outRider);
double GetMoveDirectionRelativeToFacing();
ObjectRefHandle GetOccupiedFurniture() const;
bool GetPlayerControls() const;
TESRace* GetRace() const;
float GetRegenDelay(ActorValue a_actorValue) const;
bool GetRider(NiPointer<Actor>& 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();
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions include/RE/A/ActorState.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ namespace RE
}
}

[[nodiscard]] bool IsReanimated() const noexcept { return GetLifeState() == ACTOR_LIFE_STATE::kReanimate; }
[[nodiscard]] bool IsSneaking() const noexcept { return static_cast<bool>(actorState1.sneaking); }
[[nodiscard]] bool IsSprinting() const noexcept { return static_cast<bool>(actorState1.sprinting); }
[[nodiscard]] bool IsSwimming() const noexcept { return static_cast<bool>(actorState1.swimming); }
Expand Down
3 changes: 2 additions & 1 deletion include/RE/B/bhkCharacterController.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ namespace RE
hkRefPtr<hkpRigidBody> bumpedBody; // 2C0
hkRefPtr<hkpRigidBody> bumpedCharCollisionObject; // 2C8
BSTHashMap<NiPointer<bhkRigidBody>, DamageImpactData*> damageImpacts; // 2D0
std::uint64_t unk300; // 300
std::uint32_t unk300; // 300
MATERIAL_ID surfaceMaterial; // 304
std::uint64_t unk308; // 308
std::uint64_t unk310; // 310
std::uint64_t unk318; // 318
Expand Down
60 changes: 30 additions & 30 deletions include/RE/M/MovementControllerNPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,38 +26,38 @@ namespace RE
~MovementControllerNPC() override; // 00

// add
virtual void Unk_0A(void); // 0A
virtual void Unk_0B(void); // 0B
virtual void Unk_0C(void); // 0C
virtual void Unk_0D(void); // 0D
virtual void Unk_0E(void); // 0E - { return unk1C5 == 0; }
virtual void Unk_0F(void); // 0F - { return unk1C5; }
virtual void Unk_10(void); // 10
virtual void Unk_11(void); // 11
virtual void Unk_12(void); // 12
virtual void Unk_13(void); // 13
virtual void Unk_14(void); // 14
virtual void Unk_0A(void); // 0A
virtual void Unk_0B(void); // 0B
virtual void DisablePlayerControls(); // 0C
virtual void EnablePlayerControls(); // 0D
virtual bool IsPlayerControlsDisabled(); // 0E - { return unk1C5 == 0; }
virtual bool IsPlayerControlsEnabled(); // 0F - { return unk1C5; }
virtual void Unk_10(void); // 10
virtual void Unk_11(void); // 11
virtual void Unk_12(void); // 12
virtual void Unk_13(void); // 13
virtual void Unk_14(void); // 14

// members
std::uint64_t unk150; // 150
std::uint64_t unk158; // 158
std::uint64_t unk160; // 160
std::uint64_t unk168; // 168
std::uint64_t unk170; // 170
std::uint64_t unk178; // 178
std::uint64_t unk180; // 180
std::uint64_t unk188; // 188
std::uint64_t unk190; // 190
std::uint64_t unk198; // 198
std::uint64_t unk1A0; // 1A0
std::uint64_t unk1A8; // 1A8
std::uint64_t unk1B0; // 1B0
std::uint64_t unk1B8; // 1B8
std::uint32_t unk1C0; // 1C0
std::uint8_t unk1C4; // 1C4
std::uint8_t unk1C5; // 1C5
std::uint16_t unk1C6; // 1C6
std::uint64_t unk1C8; // 1C8
std::uint64_t unk150; // 150
std::uint64_t unk158; // 158
std::uint64_t unk160; // 160
std::uint64_t unk168; // 168
std::uint64_t unk170; // 170
std::uint64_t unk178; // 178
std::uint64_t unk180; // 180
std::uint64_t unk188; // 188
std::uint64_t unk190; // 190
std::uint64_t unk198; // 198
std::uint64_t unk1A0; // 1A0
std::uint64_t unk1A8; // 1A8
std::uint64_t unk1B0; // 1B0
std::uint64_t unk1B8; // 1B8
std::uint32_t unk1C0; // 1C0
std::uint8_t unk1C4; // 1C4
bool playerControls; // 1C5
std::uint16_t unk1C6; // 1C6
std::uint64_t unk1C8; // 1C8
};
static_assert(sizeof(MovementControllerNPC) == 0x1D0);
}
3 changes: 2 additions & 1 deletion include/RE/T/TESObjectREFR.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ namespace RE
TESContainer* GetContainer() const;
BGSLocation* GetCurrentLocation() const;
const char* GetDisplayFullName();
float GetDistance(TESObjectREFR* a_other, bool a_disabledRefs = false, bool a_ignoreWorldspace = false) const;
InventoryDropMap GetDroppedInventory();
InventoryDropMap GetDroppedInventory(std::function<bool(TESBoundObject&)> a_filter);
BGSEncounterZone* GetEncounterZone() const;
Expand Down Expand Up @@ -405,6 +406,7 @@ namespace RE
[[nodiscard]] float GetScale() const;
NiControllerSequence* GetSequence(stl::zstring a_name) const;
std::uint32_t GetStealValue(const InventoryEntryData* a_entryData, std::uint32_t a_numItems, bool a_useMult) const;
float GetSubmergeLevel(float a_zPos, TESObjectCELL* a_cell) const;
void GetTransform(NiTransform& a_transform) const;
float GetWaterHeight() const;
float GetWeight() const;
Expand Down Expand Up @@ -436,7 +438,6 @@ namespace RE
bool IsMarkedForDeletion() const;
bool IsOffLimits();
bool IsPersistent() const;
float IsPointDeepUnderWater(float a_zPos, TESObjectCELL* a_cell) const;
bool IsPointSubmergedMoreThan(const NiPoint3& a_pos, TESObjectCELL* a_cell, float a_waterLevel) const;
void MoveTo(TESObjectREFR* a_target);
bool MoveToNode(TESObjectREFR* a_target, const BSFixedString& a_nodeName);
Expand Down
5 changes: 5 additions & 0 deletions src/RE/A/AIProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ namespace RE
return cachedValues && cachedValues->flags.all(CachedValues::Flags::kActorIsGhost);
}

bool AIProcess::IsInCommandState() const
{
return high && high->inCommandState;
}

void AIProcess::KnockExplosion(Actor* a_actor, const NiPoint3& a_location, float a_magnitude)
{
using func_t = decltype(&AIProcess::KnockExplosion);
Expand Down
58 changes: 58 additions & 0 deletions src/RE/A/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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_t> 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 {
Expand Down Expand Up @@ -539,6 +548,14 @@ namespace RE
}
}

bool Actor::GetPlayerControls() const
{
if (movementController) {
return movementController->IsPlayerControlsEnabled();
}
return false;
}

TESRace* Actor::GetRace() const
{
if (race) {
Expand Down Expand Up @@ -589,13 +606,27 @@ namespace RE
return func(this);
}

TESNPC* Actor::GetTemplateBase()
{
auto leveledCreature = extraList.GetByType<ExtraLeveledCreature>();
if (leveledCreature) {
return static_cast<TESNPC*>(leveledCreature->templateBase);
}
return GetActorBase();
}

float Actor::GetTotalCarryWeight()
{
using func_t = decltype(&Actor::GetTotalCarryWeight);
static REL::Relocation<func_t> func{ RELOCATION_ID(36456, 37452) };
return func(this);
}

float Actor::GetTrackedDamage() const
{
return currentProcess ? currentProcess->trackedDamage : 0.0f;
}

TESFaction* Actor::GetVendorFaction()
{
if (!vendorFaction) {
Expand Down Expand Up @@ -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_t> func{ RELOCATION_ID(37618, 38571) };
return func(this, a_other);
}

bool Actor::IsCommandedActor() const
{
return boolFlags.all(BOOL_FLAGS::kIsCommandedActor);
Expand All @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down
39 changes: 23 additions & 16 deletions src/RE/T/TESObjectREFR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ namespace RE
return func(this);
}

float TESObjectREFR::GetDistance(TESObjectREFR* a_other, bool a_disabledRefs, bool a_ignoreWorldspace) const
{
using func_t = decltype(&GetDistance);
REL::Relocation<func_t> func{ RELOCATION_ID(19396, 19823) };
return func(this, a_other, a_disabledRefs, a_ignoreWorldspace);
}

auto TESObjectREFR::GetDroppedInventory()
-> InventoryDropMap
{
Expand Down Expand Up @@ -507,6 +514,21 @@ namespace RE
return func(this, a_entryData, a_numItems, a_useMult);
}

float TESObjectREFR::GetSubmergeLevel(float a_zPos, TESObjectCELL* a_cell) const
{
auto waterHeight = !a_cell || a_cell == parentCell ? GetWaterHeight() : a_cell->GetExteriorWaterHeight();

if (waterHeight == -NI_INFINITY && a_cell) {
waterHeight = a_cell->GetExteriorWaterHeight();
}

if (waterHeight <= a_zPos) {
return 0.0f;
}

return std::fminf((waterHeight - a_zPos) / GetHeight(), 1.0f);
}

void TESObjectREFR::GetTransform(NiTransform& a_transform) const
{
using func_t = decltype(&TESObjectREFR::GetTransform);
Expand Down Expand Up @@ -739,24 +761,9 @@ namespace RE
return (GetFormFlags() & RecordFlags::kPersistent) != 0;
}

float TESObjectREFR::IsPointDeepUnderWater(float a_zPos, TESObjectCELL* a_cell) const
{
auto waterHeight = !a_cell || a_cell == parentCell ? GetWaterHeight() : a_cell->GetExteriorWaterHeight();

if (waterHeight == -NI_INFINITY && a_cell) {
waterHeight = a_cell->GetExteriorWaterHeight();
}

if (waterHeight <= a_zPos) {
return 0.0f;
}

return std::fminf((waterHeight - a_zPos) / GetHeight(), 1.0f);
}

bool TESObjectREFR::IsPointSubmergedMoreThan(const NiPoint3& a_pos, TESObjectCELL* a_cell, const float a_waterLevel) const
{
return IsPointDeepUnderWater(a_pos.z, a_cell) >= a_waterLevel;
return GetSubmergeLevel(a_pos.z, a_cell) >= a_waterLevel;
}

void TESObjectREFR::MoveTo(TESObjectREFR* a_target)
Expand Down

0 comments on commit 32ed704

Please sign in to comment.