Skip to content

Commit

Permalink
feat: ExtraLock, LockPickedEvent and related RE (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
powerof3 authored Oct 21, 2023
1 parent 206ebb3 commit 687f2ef
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 1 deletion.
57 changes: 57 additions & 0 deletions CommonLibSF/include/RE/E/ExtraLock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include "RE/B/BSExtraData.h"

namespace RE
{
class TESKey;
class TESObjectREFR;

enum class LOCK_LEVEL
{
kUnlocked = static_cast<std::underlying_type_t<LOCK_LEVEL>>(-1),
kEasy = 0,
kAverage = 1,
kHard = 2,
kVeryHard = 3,
kRequiresKey = 4,
kInaccessible = 5,
kTerminal = 6,
kBarred = 7,
kChained = 8,
};

struct REFR_LOCK
{
enum class Flag
{
kNone = 0,
kLocked = 1 << 0,
kLeveled = 1 << 2
};

[[nodiscard]] LOCK_LEVEL GetLockLevel(const TESObjectREFR* a_owner) const;
[[nodiscard]] constexpr bool IsLocked() const noexcept { return flags.all(Flag::kLocked); }
void SetLocked(bool a_locked);

// members
TESKey* key; // 00
std::uint32_t numTries; // 08
stl::enumeration<Flag, std::uint8_t> flags; // 0C
std::int8_t baseLevel; // 0D
};
static_assert(sizeof(REFR_LOCK) == 0x10);

class ExtraLock : public BSExtraData
{
public:
SF_RTTI_VTABLE(ExtraLock);
SF_EXTRADATATYPE(Lock);

~ExtraLock() override; // 00

// members
REFR_LOCK* lock; // 18
};
static_assert(sizeof(ExtraLock) == 0x20);
}
15 changes: 14 additions & 1 deletion CommonLibSF/include/RE/IDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ namespace RE::ID
inline constexpr REL::ID HasType{ 83208 };
}

namespace LockPickedEvent
{
inline constexpr REL::ID GetEventSource{ 107115 };
inline constexpr REL::ID Notify{ 107339 };
}

namespace MemoryManager
{
inline constexpr REL::ID GetSingleton{ 33961 };
Expand Down Expand Up @@ -174,6 +180,11 @@ namespace RE::ID
inline constexpr REL::ID singleton{ 865059 };
}

namespace REFR_LOCK
{
inline constexpr REL::ID GetLockLevel{ 84103 };
}

namespace RegSettingCollection
{
inline constexpr REL::ID singleton{ 885510 };
Expand Down Expand Up @@ -248,8 +259,10 @@ namespace RE::ID

namespace TESObjectREFR
{
inline constexpr REL::ID GetCurrentLocation{ 106554 };
inline constexpr REL::ID AddLockChange{ 106386 };
inline constexpr REL::ID GetCurrentLocation{ 106554 };
inline constexpr REL::ID GetLinkedRef{ 107578 };
inline constexpr REL::ID GetLock{ 107581 };
inline constexpr REL::ID GetParentWorldSpace{ 106696 };
inline constexpr REL::ID GetSpaceship{ 173851 };
inline constexpr REL::ID GetSpaceshipParentDock{ 174134 };
Expand Down
42 changes: 42 additions & 0 deletions CommonLibSF/include/RE/L/LockPickedEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "RE/B/BSTEvent.h"
#include "RE/E/ExtraLock.h"
#include "RE/N/NiSmartPointer.h"

namespace RE
{
class TESObjectREFR;
class BGSTerminalMenu;

struct LockPickedEvent
{
public:
[[nodiscard]] static BSTEventSource<LockPickedEvent>* GetEventSource()
{
using func_t = decltype(&LockPickedEvent::GetEventSource);
REL::Relocation<func_t> func{ ID::LockPickedEvent::GetEventSource };
return func();
}

static void Notify(const NiPointer<TESObjectREFR>& a_actionRef, const NiPointer<TESObjectREFR>& a_lock, bool a_succeeded, bool a_isOffLimits, LOCK_LEVEL lockLevel, std::uint32_t a_numDigiPicksUsed, float a_arg7 = 0.0f, float a_arg8 = 0.0f, BGSTerminalMenu* a_terminalMenu = nullptr, std::int32_t a_arg10 = -1)
{
using func_t = decltype(&LockPickedEvent::Notify);
REL::Relocation<func_t> func{ ID::LockPickedEvent::Notify };
return func(a_actionRef, a_lock, a_succeeded, a_isOffLimits, lockLevel, a_numDigiPicksUsed, a_arg7, a_arg8, a_terminalMenu, a_arg10);
}

// members
NiPointer<TESObjectREFR> actionRef; // 00
NiPointer<TESObjectREFR> lock; // 08
BGSTerminalMenu* terminalMenu; // 10
std::int32_t unk18; // 14 - terminalMenu related
std::uint32_t numDigiPicksUsed; // 18
float unk20; // 20 - 0.0f
float unk24; // 24 - 0.0f
stl::enumeration<LOCK_LEVEL, std::uint32_t> lockLevel; // 28
bool succeeded; // 2C
bool isOffLimits; // 2D
};
static_assert(sizeof(LockPickedEvent) == 0x30);
}
10 changes: 10 additions & 0 deletions CommonLibSF/include/RE/T/TESObjectREFR.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace RE
{
enum class LOCK_LEVEL;
class TESContainer;
class Actor;
class BGSEquipSlot;
Expand All @@ -33,6 +34,7 @@ namespace RE
class TESTopicInfo;
class TESWorldSpace;
class TESWaterForm;
struct REFR_LOCK;

namespace ActorValueEvents
{
Expand Down Expand Up @@ -361,6 +363,8 @@ namespace RE
[[nodiscard]] const TESBoundObject* GetBaseObject() const { return data.objectReference.get(); }
[[nodiscard]] BGSLocation* GetCurrentLocation();
[[nodiscard]] TESObjectREFR* GetLinkedRef(BGSKeyword* a_keyword);
[[nodiscard]] REFR_LOCK* GetLock() const;
[[nodiscard]] LOCK_LEVEL GetLockLevel() const;
[[nodiscard]] TESWorldSpace* GetParentWorldSpace();
[[nodiscard]] constexpr NiPoint3A GetPosition() const noexcept { return data.location; }
[[nodiscard]] constexpr float GetPositionX() const noexcept { return data.location.x; }
Expand All @@ -373,9 +377,12 @@ namespace RE
[[nodiscard]] bool HasKeyword(BGSKeyword* a_keyword);
[[nodiscard]] bool IsCrimeToActivate();
[[nodiscard]] bool IsInSpace(bool a_arg1);
[[nodiscard]] bool IsLocked() const;
[[nodiscard]] bool IsObjectEquipped(TESBoundObject* a_object);
[[nodiscard]] bool IsSpaceshipDocked();
[[nodiscard]] bool IsSpaceshipLanded();
void Lock();
void Unlock();

// members
OBJ_REFR data; // 0A0
Expand All @@ -389,6 +396,9 @@ namespace RE
std::uint16_t scale; // 108
bool unk10A; // 10A
std::uint8_t flags; // 10B

private:
void AddLockChange();
};
static_assert(sizeof(TESObjectREFR) == 0x110);
}
25 changes: 25 additions & 0 deletions CommonLibSF/src/RE/E/ExtraLock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "RE/E/ExtraLock.h"

namespace RE
{
LOCK_LEVEL REFR_LOCK::GetLockLevel(const TESObjectREFR* a_owner) const
{
if (IsLocked()) {
using func_t = decltype(&REFR_LOCK::GetLockLevel);
REL::Relocation<func_t> func{ ID::REFR_LOCK::GetLockLevel };
return func(this, a_owner);
} else {
return LOCK_LEVEL::kUnlocked;
}
}

void REFR_LOCK::SetLocked(bool a_locked)
{
if (a_locked) {
flags.set(Flag::kLocked);
} else {
flags.reset(Flag::kLocked);
numTries = 0;
}
}
}
41 changes: 41 additions & 0 deletions CommonLibSF/src/RE/T/TESObjectREFR.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#include "RE/T/TESObjectREFR.h"
#include "RE/B/BGSInventoryItem.h"
#include "RE/E/ExtraLock.h"

namespace RE
{
void TESObjectREFR::AddLockChange()
{
using func_t = decltype(&TESObjectREFR::AddLockChange);
REL::Relocation<func_t> func{ ID::TESObjectREFR::AddLockChange };
return func(this);
}

void TESObjectREFR::ForEachEquippedItem(std::function<BSContainer::ForEachResult(const BGSInventoryItem&)> a_callback) const
{
ForEachInventoryItem([&](const BGSInventoryItem& a_invItem) {
Expand Down Expand Up @@ -36,6 +44,19 @@ namespace RE
return func(this, a_keyword);
}

REFR_LOCK* TESObjectREFR::GetLock() const
{
using func_t = decltype(&TESObjectREFR::GetLock);
REL::Relocation<func_t> func{ ID::TESObjectREFR::GetLock };
return func(this);
}

LOCK_LEVEL TESObjectREFR::GetLockLevel() const
{
const auto state = GetLock();
return state ? state->GetLockLevel(this) : LOCK_LEVEL::kUnlocked;
}

TESWorldSpace* TESObjectREFR::GetParentWorldSpace()
{
using func_t = decltype(&TESObjectREFR::GetParentWorldSpace);
Expand Down Expand Up @@ -92,6 +113,11 @@ namespace RE
return func(this, a_arg1);
}

bool TESObjectREFR::IsLocked() const
{
return GetLockLevel() != LOCK_LEVEL::kUnlocked;
}

bool TESObjectREFR::IsObjectEquipped(TESBoundObject* a_object)
{
using func_t = decltype(&TESObjectREFR::IsObjectEquipped);
Expand All @@ -113,4 +139,19 @@ namespace RE
return func(this);
}

void TESObjectREFR::Lock()
{
if (const auto lock = GetLock()) {
lock->SetLocked(true);
AddLockChange();
}
}

void TESObjectREFR::Unlock()
{
if (const auto lock = GetLock()) {
lock->SetLocked(false);
AddLockChange();
}
}
}

0 comments on commit 687f2ef

Please sign in to comment.