Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions include/RE/B/BSInputEventUser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include "RE/B/BSFixedString.h"
#include "RE/M/MemoryManager.h"

#include <type_traits>
#include <utility>

namespace RE
{
class ButtonEvent;
Expand Down Expand Up @@ -51,8 +54,13 @@ namespace RE
virtual ~InputEvent() = default; // 00

// add
virtual bool HasIDCode() const { return false; }
virtual const BSFixedString QUserEvent() const { return ""; }
virtual bool HasIDCode() const { return false; }

virtual const BSFixedString& QUserEvent() const
{
static const BSFixedString empty;
return empty;
}

// members
DeviceType deviceType{ DeviceType::kNone }; // 08
Expand All @@ -64,6 +72,7 @@ namespace RE
Status status{ Status::kUnhandled }; // 24
};
static_assert(sizeof(InputEvent) == 0x28);
static_assert(std::is_same_v<decltype(std::declval<const InputEvent&>().QUserEvent()), const BSFixedString&>);

class IDEvent :
public InputEvent
Expand All @@ -76,9 +85,10 @@ namespace RE
// override (InputEvent)
virtual bool HasIDCode() const override { return true; }

virtual const BSFixedString QUserEvent() const override
virtual const BSFixedString& QUserEvent() const override
{
return disabled ? "DISABLED" : strUserEvent;
static const BSFixedString disabledEvent{ "DISABLED" };
return disabled ? disabledEvent : strUserEvent;
}

// members
Expand All @@ -87,6 +97,7 @@ namespace RE
bool disabled{ false }; // 34
};
static_assert(sizeof(IDEvent) == 0x38);
static_assert(std::is_same_v<decltype(std::declval<const IDEvent&>().QUserEvent()), const BSFixedString&>);

class ICanBeChorded
{
Expand Down
6 changes: 6 additions & 0 deletions include/RE/B/BSTHeapSTLVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ namespace RE
[[nodiscard]] constexpr pointer data() noexcept { return _begin; }
[[nodiscard]] constexpr const_pointer data() const noexcept { return _begin; }

// Raw capacity sentinel for validating engine-owned vectors before using
// size() or capacity(). Those helpers subtract pointers and therefore require
// an already-valid vector representation.
[[nodiscard]] constexpr pointer capacity_end() noexcept { return _capacityEnd; }
[[nodiscard]] constexpr const_pointer capacity_end() const noexcept { return _capacityEnd; }

[[nodiscard]] constexpr size_type size() const noexcept
{
return static_cast<size_type>(_end - _begin);
Expand Down
14 changes: 1 addition & 13 deletions include/RE/E/Events.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "RE/B/BSPointerHandle.h"
#include "RE/B/BSTEvent.h"
#include "RE/N/NiSmartPointer.h"
#include "RE/S/StarMap.h"

namespace RE
{
Expand Down Expand Up @@ -3374,19 +3375,6 @@ namespace RE
static_assert(sizeof(SpellsLearned::Event) == 0x8);
};

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

struct StarMapMenu_LandingInputInProgress
{
[[nodiscard]] static BSTEventSource<StarMapMenu_LandingInputInProgress>* GetEventSource()
Expand Down
19 changes: 17 additions & 2 deletions include/RE/IDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ namespace RE::ID
inline constexpr REL::ID dtor{ 0 }; // 187216
inline constexpr REL::ID ShouldHandleEvent{ 0 }; // 187262
inline constexpr REL::ID OnThumbstickEvent{ 0 }; // 187235
inline constexpr REL::ID OnButtonEvent{ 0 }; // 187234
inline constexpr REL::ID OnButtonEvent{ 130632 };
inline constexpr REL::ID LoadMovie{ 0 }; // 187240
inline constexpr REL::ID ProcessMessage{ 0 }; // 187247
inline constexpr REL::ID Unk09{ 0 }; // 80440
Expand Down Expand Up @@ -2156,6 +2156,20 @@ namespace RE::ID
{
inline constexpr REL::ID RefreshPanelData{ 93988 };
inline constexpr REL::ID ScanHandler{ 94011 };
inline constexpr REL::ID ComposeSurfaceQuestTarget{ 95013 };
}

namespace StarMap::StarMapMenu
{
inline constexpr REL::ID OnButtonEvent{ 94684 };
inline constexpr REL::ID GetSurfaceMapState{ 94755 };
}

namespace StarMap::SurfaceMapState
{
inline constexpr REL::ID RebuildSurfaceMarkers{ 95000 };
inline constexpr REL::ID Refresh{ 95003 };
inline constexpr REL::ID GatherSurfaceQuestTargets{ 95012 };
}

namespace StarMap::PlanetTraitKnownEvent
Expand Down Expand Up @@ -2506,7 +2520,8 @@ namespace RE::ID

namespace TESQuest
{
inline constexpr REL::ID IsStageDone{ 0 }; // 112585
inline constexpr REL::ID IsStageDone{ 0 }; // 112585
inline constexpr REL::ID ToggleTracking{ 91440 };
}

namespace TESQuestRewardEvent
Expand Down
120 changes: 120 additions & 0 deletions include/RE/S/StarMap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#pragma once

#include "RE/B/BSCoreTypes.h"
#include "RE/B/BSFixedString.h"
#include "RE/B/BSTEvent.h"
#include "RE/B/BSTHeapSTLVector.h"
#include "RE/G/GameMenuBase.h"

namespace RE
{
struct StarMap
{
enum class SurfaceMarkerType : std::uint16_t
{
kQuest = 0x48
};

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

struct SurfaceMarkerStaticData
{
[[nodiscard]] constexpr bool IsLocation() const noexcept { return isLocation == 1; }
[[nodiscard]] constexpr bool HasQuestTarget() const noexcept { return hasQuestTarget == 1; }
[[nodiscard]] constexpr bool IsQuestActive() const noexcept { return questActive == 1; }

// members
std::byte pad000[0x28]; // 00
BSFixedString nameText; // 28
BSFixedString extraText; // 30
BSFixedString questTargetText; // 38
std::uint32_t markerHandleBits; // 40
std::uint32_t pad044; // 44
BSTHeapSTLVector<TESFormID> questOwners; // 48
SurfaceMarkerType markerType; // 60
std::byte pad062[0x6]; // 62
std::uint8_t isLocation; // 68
std::uint8_t hasQuestTarget; // 69
std::uint8_t questActive; // 6A
std::byte pad06B[0x15]; // 6B
};
static_assert(offsetof(SurfaceMarkerStaticData, nameText) == 0x28);
static_assert(offsetof(SurfaceMarkerStaticData, extraText) == 0x30);
static_assert(offsetof(SurfaceMarkerStaticData, questTargetText) == 0x38);
static_assert(offsetof(SurfaceMarkerStaticData, markerHandleBits) == 0x40);
static_assert(offsetof(SurfaceMarkerStaticData, questOwners) == 0x48);
static_assert(offsetof(SurfaceMarkerStaticData, markerType) == 0x60);
static_assert(offsetof(SurfaceMarkerStaticData, isLocation) == 0x68);
static_assert(offsetof(SurfaceMarkerStaticData, hasQuestTarget) == 0x69);
static_assert(offsetof(SurfaceMarkerStaticData, questActive) == 0x6A);
static_assert(sizeof(SurfaceMarkerStaticData) == 0x80);

class SurfaceMapState
{
public:
SF_RTTI_VTABLE(StarMap__SurfaceMapState);

inline static constexpr REL::ID PRIMARY_VTABLE = RE::VTABLE::StarMap__SurfaceMapState[0];

// Surface Map state is owned by the Star Map UI thread. These operations
// are not thread-safe or reentrant.

void RebuildSurfaceMarkers()
{
using func_t = void (*)(SurfaceMapState*);
static REL::Relocation<func_t> func{ ID::StarMap::SurfaceMapState::RebuildSurfaceMarkers };
func(this);
}

void Refresh()
{
using func_t = void (*)(SurfaceMapState*);
static REL::Relocation<func_t> func{ ID::StarMap::SurfaceMapState::Refresh };
func(this);
}

// members
// Engine-owned storage. External callers must treat it as read-only.
// Elements and their nested storage are invalidated by rebuild, refresh,
// state transition, and destruction. Do not retain pointers or views.
std::byte pad000[0x8B8]; // 000
BSTHeapSTLVector<SurfaceMarkerStaticData> surfaceMarkers; // 8B8
};
static_assert(offsetof(SurfaceMapState, surfaceMarkers) == 0x8B8);

class StarMapMenu :
public GameMenuBase
{
public:
SF_RTTI_VTABLE(StarMap__StarMapMenu);
SF_MENU_NAME("GalaxyStarMapMenu");

inline static constexpr REL::ID PRIMARY_VTABLE = RE::VTABLE::StarMap__StarMapMenu[12];
inline static constexpr REL::ID BSINPUTEVENTUSER_VTABLE = RE::VTABLE::StarMap__StarMapMenu[13];

void OnButtonEvent(const ButtonEvent* a_event) override
{
using func_t = void (*)(BSInputEventUser*, const ButtonEvent*);
static REL::Relocation<func_t> func{ ID::StarMap::StarMapMenu::OnButtonEvent };
func(this, a_event);
}

// Returns a non-owning owner-thread pointer. It is invalidated by Star Map
// state transition and menu destruction; do not retain it.
[[nodiscard]] SurfaceMapState* GetSurfaceMapState()
{
using func_t = SurfaceMapState* (*)(StarMapMenu*);
static REL::Relocation<func_t> func{ ID::StarMap::StarMapMenu::GetSurfaceMapState };
return func(this);
}
};
};
}
1 change: 1 addition & 0 deletions include/RE/Starfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@
#include "RE/S/SpellItem.h"
#include "RE/S/Stack.h"
#include "RE/S/StackFrame.h"
#include "RE/S/StarMap.h"
#include "RE/S/Store.h"
#include "RE/S/Stream.h"
#include "RE/S/StreamBase.h"
Expand Down
55 changes: 51 additions & 4 deletions include/RE/T/TESQuest.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include "RE/B/BGSStoryManagerTreeForm.h"

#include <memory>
#include <type_traits>

namespace RE
{
class BGSStoryEvent;
Expand All @@ -16,13 +19,30 @@ namespace RE
};
static_assert(sizeof(QUEST_DATA) == 0x8);

struct QuestInstanceKey
{
TESFormID formID; // 0
std::uint32_t instanceID; // 4

[[nodiscard]] constexpr bool operator==(const QuestInstanceKey&) const noexcept = default;
};
static_assert(sizeof(QuestInstanceKey) == 0x8);
static_assert(std::is_trivially_copyable_v<QuestInstanceKey>);

class __declspec(novtable) TESQuest :
public BGSStoryManagerTreeForm
{
public:
SF_RTTI_VTABLE(TESQuest);
SF_FORMTYPE(QUST);

enum class RuntimeFlag : std::uint32_t
{
kRunning = 1 << 0,
kStopped = 1 << 1,
kTracked = 1 << 11
};

~TESQuest() override; // 00

[[nodiscard]] bool IsStageDone(std::uint16_t a_stage) const
Expand All @@ -32,11 +52,38 @@ namespace RE
return func(this, a_stage);
}

[[nodiscard]] constexpr std::uint32_t GetInstanceID() const noexcept { return instanceID; }

[[nodiscard]] QuestInstanceKey GetInstanceKey() const noexcept
{
return { GetFormID(), GetInstanceID() };
}

[[nodiscard]] constexpr bool IsRunning() const noexcept { return runtimeFlags.all(RuntimeFlag::kRunning); }
[[nodiscard]] constexpr bool IsStopped() const noexcept { return runtimeFlags.all(RuntimeFlag::kStopped); }
[[nodiscard]] constexpr bool IsTracked() const noexcept { return runtimeFlags.all(RuntimeFlag::kTracked); }

// This is the engine's toggle operation. Callers that need set semantics
// must compare IsTracked() with the desired state before invoking it.
void ToggleTracking()
{
const auto key = GetInstanceKey();
using func_t = void (*)(const QuestInstanceKey*);
static REL::Relocation<func_t> func{ ID::TESQuest::ToggleTracking };
func(std::addressof(key));
}

// members
std::byte pad038[0xD0]; // 038
QUEST_DATA data; // 108
std::byte pad110[0x220]; // 110
BGSStoryEvent* startEventData; // 330
std::byte pad038[0x38]; // 038
std::uint32_t instanceID; // 070
std::byte pad074[0x94]; // 074
QUEST_DATA data; // 108
std::byte pad110[0x4]; // 110
REX::TEnumSet<RuntimeFlag, std::uint32_t> runtimeFlags; // 114
std::byte pad118[0x218]; // 118
BGSStoryEvent* startEventData; // 330
};
static_assert(offsetof(TESQuest, instanceID) == 0x70);
static_assert(offsetof(TESQuest, runtimeFlags) == 0x114);
static_assert(offsetof(TESQuest, startEventData) == 0x330);
}