docs: add plugin setup guide
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WARNING_TYPES : std::int32_t
|
||||
{
|
||||
kDefault = 0x0,
|
||||
kSystem = 0x1,
|
||||
kCombat = 0x2,
|
||||
kAnimation = 0x3,
|
||||
kAI = 0x4,
|
||||
kScripts = 0x5,
|
||||
kSaveLoad = 0x6,
|
||||
kDialogue = 0x7,
|
||||
kQuests = 0x8,
|
||||
kPackages = 0x9,
|
||||
kEditor = 0xA,
|
||||
kModels = 0xB,
|
||||
kTextures = 0xC,
|
||||
kPlugins = 0xD,
|
||||
kMasterFile = 0xE,
|
||||
kForms = 0xF,
|
||||
kMagic = 0x10,
|
||||
kShaders = 0x11,
|
||||
kRendering = 0x12,
|
||||
kPathfinding = 0x13,
|
||||
kMenus = 0x14,
|
||||
kAudio = 0x15,
|
||||
kCells = 0x16,
|
||||
kHavok = 0x17,
|
||||
kFaceGen = 0x18,
|
||||
kWater = 0x19,
|
||||
kInGameMessage = 0x1A,
|
||||
kMemory = 0x1B,
|
||||
kPerformance = 0x1C,
|
||||
kLootJoy = 0x1D,
|
||||
kVATS = 0x1E,
|
||||
kDismember = 0x1F,
|
||||
kCompanion = 0x20,
|
||||
kWorkshop = 0x21,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WEAPONHITBEHAVIOR : std::int32_t
|
||||
{
|
||||
kNormal = 0x0,
|
||||
kDismemberOnly = 0x1,
|
||||
kExplodeOnly = 0x2,
|
||||
kNoDismemberOrExplode = 0x3
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WEAPON_CULL_TYPE : std::int32_t
|
||||
{
|
||||
kGeneral = 0x0,
|
||||
kAnimation = 0x1,
|
||||
kWeaponSwitch = 0x2,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WEAPON_FLAGS : std::int32_t
|
||||
{
|
||||
kPlayerOnly = 0x00000001,
|
||||
kNPCsUseAmmo = 0x00000002,
|
||||
kNoJamAfterReload = 0x00000004,
|
||||
kChargingReload = 0x00000008,
|
||||
kMinorCrime = 0x00000010,
|
||||
kFixedRange = 0x00000020,
|
||||
kNotUsedInNormalCombat = 0x00000040,
|
||||
kCritEffectOnDeath = 0x00000100,
|
||||
kChargingAttack = 0x00000200,
|
||||
kHoldInputToPower = 0x00000800,
|
||||
kNonHostile = 0x00001000,
|
||||
kBoundWeapon = 0x00002000,
|
||||
kIgnoresNormalWeaponResistance = 0x00004000,
|
||||
kAutomatic = 0x00008000,
|
||||
kRepeatableSingleFire = 0x00010000,
|
||||
kCantDrop = 0x00020000,
|
||||
kHideBackpack = 0x00040000,
|
||||
kEmbeddedWeapon = 0x00080000,
|
||||
kNotPlayable = 0x00100000,
|
||||
kHasScope = 0x00200000,
|
||||
kBoltAction = 0x00400000,
|
||||
kSecondaryWeapon = 0x00800000,
|
||||
kDisableShells = 0x01000000,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WEAPON_RUMBLE_PATTERN : std::int32_t
|
||||
{
|
||||
kConstant = 0x0,
|
||||
kPeriodicSquare = 0x1,
|
||||
kPeriodicTriangle = 0x2,
|
||||
kPeriodicSawtooth = 0x3,
|
||||
kPatternCount = 0x4
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WEAPON_STATE : std::int32_t
|
||||
{
|
||||
kSheathed = 0x0,
|
||||
kWantToDraw = 0x1,
|
||||
kDrawing = 0x2,
|
||||
kDrawn = 0x3,
|
||||
kWantToSheathe = 0x4,
|
||||
kSheathing = 0x5
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
enum class WEAPON_TYPE : std::int32_t
|
||||
{
|
||||
kNone = 0xFF,
|
||||
kHandToHand = 0x0,
|
||||
kOneHandSword = 0x1,
|
||||
kOneHandDagger = 0x2,
|
||||
kOneHandAxe = 0x3,
|
||||
kOneHandMace = 0x4,
|
||||
kTwoHandSword = 0x5,
|
||||
kTwoHandAxe = 0x6,
|
||||
kBow = 0x7,
|
||||
kStaff = 0x8,
|
||||
kGun = 0x9,
|
||||
kGrenade = 0xA,
|
||||
kMine = 0xB,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "RE/N/NiPoint3.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class TESForm;
|
||||
|
||||
class WORLD_LOCATION
|
||||
{
|
||||
public:
|
||||
// members
|
||||
TESForm* locationForm; // 00
|
||||
NiPoint3 locPt; // 08
|
||||
float zRot; // 14
|
||||
};
|
||||
static_assert(sizeof(WORLD_LOCATION) == 0x18);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class WORLD_MAP_DATA
|
||||
{
|
||||
public:
|
||||
// members
|
||||
std::uint32_t usableWidth; // 00
|
||||
std::uint32_t usableHeight; // 04
|
||||
std::int16_t nwCellX; // 08
|
||||
std::int16_t nwCellY; // 0A
|
||||
std::int16_t seCellX; // 0C
|
||||
std::int16_t seCellY; // 0E
|
||||
};
|
||||
static_assert(sizeof(WORLD_MAP_DATA) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class WORLD_MAP_OFFSET_DATA
|
||||
{
|
||||
public:
|
||||
// members
|
||||
float mapScale; // 00
|
||||
float mapOffsetX; // 04
|
||||
float mapOffsetY; // 08
|
||||
float mapOffsetZ; // 0C
|
||||
};
|
||||
static_assert(sizeof(WORLD_MAP_OFFSET_DATA) == 0x10);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class WadingWaterData
|
||||
{
|
||||
public:
|
||||
// members
|
||||
NiPoint2 lastPlaceOffset;
|
||||
NiPoint2 lastDisplaceOffset;
|
||||
NiPoint3 lastPosition;
|
||||
};
|
||||
static_assert(sizeof(WadingWaterData) == 0x1C);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class WaterShaderData
|
||||
{
|
||||
public:
|
||||
// members
|
||||
float maxDepth; // 00
|
||||
std::uint32_t shallowWaterColor; // 04
|
||||
std::uint32_t deepWaterColor; // 08
|
||||
float shallowFogColorRange; // 0C
|
||||
float deepFogColorRange; // 10
|
||||
float shallowAlpha; // 14
|
||||
float deepAlpha; // 18
|
||||
float shallowFogAlphaRange; // 1C
|
||||
float deepFogAlphaRange; // 20
|
||||
std::uint32_t underwaterFogColor; // 24
|
||||
float underwaterFogAmount; // 28
|
||||
float underwaterFogDistNear; // 2C
|
||||
float underwaterFogDistFar; // 30
|
||||
float normalMagnitude; // 34
|
||||
float normalFalloffShallow; // 38
|
||||
float normalFalloffDeep; // 3C
|
||||
float reflectionAmount; // 40
|
||||
float fresnelAmount; // 44
|
||||
float surfaceEffectFalloff; // 48
|
||||
float displacementForce; // 4C
|
||||
float displacementVelocity; // 50
|
||||
float displacementFalloff; // 54
|
||||
float displacementDampener; // 58
|
||||
float displacementSize; // 5C
|
||||
std::uint32_t reflectionWaterColor; // 60
|
||||
float sunSpecularPower; // 64
|
||||
float sunSpecularMagnitude; // 68
|
||||
float sunSparklePower; // 6C
|
||||
float sunSparkleMagnitude; // 70
|
||||
float lightRadius; // 74
|
||||
float lightBrightness; // 78
|
||||
float shininess; // 7C
|
||||
float noiseWindDirections[3]; // 80
|
||||
float noiseWindSpeeds[3]; // 8C
|
||||
float amplitude[3]; // 98
|
||||
float uvScales[3]; // A4
|
||||
float noiseFalloff[3]; // B0
|
||||
float siltAmount; // BC
|
||||
std::uint32_t lightSiltColor; // C0
|
||||
std::uint32_t darkSiltColor; // C4
|
||||
bool ssrEnabled; // C8
|
||||
};
|
||||
static_assert(sizeof(WaterShaderData) == 0xCC);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "RE/B/BSIntrusiveRefCounted.h"
|
||||
#include "RE/B/BSPointerHandle.h"
|
||||
#include "RE/B/BSTEvent.h"
|
||||
#include "RE/B/BSTSmartPointer.h"
|
||||
#include "RE/I/IAnimationGraphManagerHolder.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class BSAnimationGraphEvent;
|
||||
class BSAnimationGraphManager;
|
||||
|
||||
class __declspec(novtable) WeaponAnimationGraphManagerHolder :
|
||||
public IAnimationGraphManagerHolder,
|
||||
public BSTEventSink<BSAnimationGraphEvent>,
|
||||
public BSIntrusiveRefCounted
|
||||
{
|
||||
public:
|
||||
static constexpr auto RTTI{ RTTI::WeaponAnimationGraphManagerHolder };
|
||||
static constexpr auto VTABLE{ VTABLE::WeaponAnimationGraphManagerHolder };
|
||||
|
||||
virtual ~WeaponAnimationGraphManagerHolder() = default; // 00
|
||||
|
||||
// override (BSTEventSink<BSAnimationGraphEvent>)
|
||||
BSEventNotifyControl ProcessEvent(const BSAnimationGraphEvent& a_event, BSTEventSource<BSAnimationGraphEvent>* a_eventSource) override;
|
||||
|
||||
// members
|
||||
BSTSmartPointer<BSAnimationGraphManager> animationGraphManager; // 08
|
||||
ObjectRefHandle owner; // 10
|
||||
};
|
||||
static_assert(sizeof(WeaponAnimationGraphManagerHolder) == 0x28);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class WeatherEntry
|
||||
{
|
||||
public:
|
||||
// members
|
||||
TESWeather* weather; // 00
|
||||
std::uint32_t chance; // 08
|
||||
TESGlobal* chanceVar; // 10
|
||||
};
|
||||
static_assert(sizeof(WeatherEntry) == 0x18);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class WorkbenchData
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
kNone = 0x0,
|
||||
kCreateObject = 0x1,
|
||||
kWeapons = 0x2,
|
||||
kEnchanting = 0x3,
|
||||
kEnchantingExperiment = 0x4,
|
||||
kAlchemy = 0x5,
|
||||
kAlchemyExperiment = 0x6,
|
||||
kArmor = 0x7,
|
||||
kPowerArmor = 0x8,
|
||||
kRobotMod = 0x9
|
||||
};
|
||||
|
||||
// members
|
||||
REX::TEnumSet<Type, std::int8_t> type; // 00
|
||||
};
|
||||
static_assert(sizeof(WorkbenchData) == 0x01);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
#include "RE/B/BGSInventoryList.h"
|
||||
#include "RE/B/BGSTypedFormValuePair.h"
|
||||
#include "RE/B/BSPointerHandle.h"
|
||||
#include "RE/B/BSTSmartPointer.h"
|
||||
#include "RE/B/BSTTuple.h"
|
||||
#include "RE/G/GameMenuBase.h"
|
||||
#include "RE/I/Inventory3DManager.h"
|
||||
#include "RE/I/InventoryInterface.h"
|
||||
#include "RE/N/NiPointer.h"
|
||||
#include "RE/R/Rumble.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class ExtraDataList;
|
||||
class NiNode;
|
||||
|
||||
class __declspec(novtable) WorkbenchMenuBase :
|
||||
public GameMenuBase // 00
|
||||
{
|
||||
public:
|
||||
static constexpr auto RTTI{ RTTI::WorkbenchMenuBase };
|
||||
static constexpr auto VTABLE{ VTABLE::WorkbenchMenuBase };
|
||||
|
||||
enum class HighlightMode
|
||||
{
|
||||
kModMenu,
|
||||
kAll,
|
||||
kWorld
|
||||
};
|
||||
|
||||
class InitParams
|
||||
{
|
||||
public:
|
||||
InitParams();
|
||||
|
||||
// members
|
||||
ObjectRefHandle workbenchFurniture; // 00
|
||||
ObjectRefHandle inventorySource; // 04
|
||||
InventoryInterface::Handle item{ 0xFFFFFFFF }; // 08
|
||||
NiPointer<Actor> actor{ nullptr }; // 10
|
||||
std::uint32_t stack{ 0 }; // 18
|
||||
bool inspectMode{ true }; // 1C
|
||||
bool inspectingSingleItem{ false }; // 1D
|
||||
bool inspectingFeaturedItem{ false }; // 1E
|
||||
bool showFeaturedItemMessage{ false }; // 1F
|
||||
bool botCompanion{ false }; // 20
|
||||
};
|
||||
static_assert(sizeof(InitParams) == 0x28);
|
||||
|
||||
class ModChoiceData
|
||||
{
|
||||
public:
|
||||
// members
|
||||
union
|
||||
{
|
||||
BGSMod::Attachment::Mod* mod;
|
||||
TESBoundObject* object;
|
||||
}; // 00
|
||||
const BGSConstructibleObject* recipe; // 08
|
||||
BSTArray<BSTTuple<TESForm*, BGSTypedFormValuePair::SharedVal>>* requiredItems; // 10
|
||||
BSTArray<BSTTuple<BGSPerk*, std::uint32_t>> requiredPerks; // 18
|
||||
std::uint8_t rank; // 30
|
||||
std::uint8_t index; // 31
|
||||
};
|
||||
static_assert(sizeof(ModChoiceData) == 0x38);
|
||||
|
||||
virtual ~WorkbenchMenuBase(); // 00
|
||||
|
||||
// override (GameMenuBase)
|
||||
virtual void Call(const Params&) override; // 01
|
||||
virtual void MapCodeObjectFunctions() override; // 02
|
||||
virtual void PreDisplay() override; // 05
|
||||
virtual void OnMenuStackChanged(const BSFixedString& a_topMenuName, bool a_passesTopMenuTest) override; // 09
|
||||
|
||||
// override (BSInputEventUser)
|
||||
virtual bool ShouldHandleEvent(const InputEvent*) override; // 01
|
||||
virtual void OnThumbstickEvent(const ThumbstickEvent*) override; // 04
|
||||
virtual void OnCursorMoveEvent(const CursorMoveEvent*) override; // 05
|
||||
virtual void OnButtonEvent(const ButtonEvent*) override; // 08
|
||||
|
||||
// add
|
||||
virtual void OnHideMenu(); // 14
|
||||
virtual void UpdateMenu(); // 15
|
||||
virtual void BuildCanceled(); // 16
|
||||
virtual void BuildConfirmed(bool a_ownerIsWorkbench) = 0; // 17
|
||||
virtual bool GetWorkbenchHasInventory(); // 18
|
||||
virtual const ModChoiceData* QCurrentModChoiceData(); // 19
|
||||
virtual void ShowBuildFailureMessage(); // 1A
|
||||
virtual bool TryCreate() = 0; // 1B
|
||||
|
||||
void UpdateOptimizedAutoBuildInv()
|
||||
{
|
||||
using func_t = decltype(&WorkbenchMenuBase::UpdateOptimizedAutoBuildInv);
|
||||
static REL::Relocation<func_t> func{ ID::WorkbenchMenuBase::UpdateOptimizedAutoBuildInv };
|
||||
return func(this);
|
||||
}
|
||||
|
||||
// members
|
||||
NiPointer<TESObjectREFR> sharedContainerRef; // 0E0
|
||||
NiPointer<TESObjectREFR> workbenchContainerRef; // 0E8
|
||||
BSTArray<NiPointer<TESObjectREFR>> sharedContainers; // 0F0
|
||||
Inventory3DManager inv3DModelManager; // 110
|
||||
BGSInventoryList optimizedAutoBuildInv; // 250
|
||||
BSTArray<ModChoiceData> modChoiceArray; // 2D0
|
||||
std::uint32_t modChoiceIndex; // 2E8
|
||||
std::uint32_t lastModChoiceIndex; // 2EC
|
||||
bool repairing; // 2F0
|
||||
bool queueHide; // 2F1
|
||||
bool hiding; // 2F2
|
||||
bool VATSWasEnabled; // 2F3
|
||||
NiPointer<TESObjectREFR> workbenchRef; // 2F8
|
||||
BSTSmartPointer<ExtraDataList> recipeExtraDataList; // 300
|
||||
NiPointer<NiNode> item3DGeometry; // 308
|
||||
BSTArray<TESForm*> queuedCraftingComponents; // 310
|
||||
std::uint64_t soundTimer; // 328
|
||||
REX::TEnumSet<HighlightMode, std::uint32_t> highlightMode; // 330
|
||||
Rumble::AutoRumblePause autoRumblePause; // 334
|
||||
bool initialized; // 335
|
||||
bool soundsQueued; // 336
|
||||
};
|
||||
static_assert(sizeof(WorkbenchMenuBase) == 0x340);
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
#pragma once
|
||||
|
||||
#include "RE/A/Actor.h"
|
||||
#include "RE/B/BSExtraData.h"
|
||||
#include "RE/B/BSPointerHandle.h"
|
||||
#include "RE/B/BSTArray.h"
|
||||
#include "RE/B/BSTTuple.h"
|
||||
#include "RE/N/NiPoint3.h"
|
||||
#include "RE/N/NiPointer.h"
|
||||
#include "RE/P/PowerUtils.h"
|
||||
#include "RE/T/TESObjectCELL.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
template <class>
|
||||
class BSPointerHandleSmartPointer;
|
||||
|
||||
class bhkNPCollisionObject;
|
||||
class hknpShape;
|
||||
|
||||
namespace Workshop
|
||||
{
|
||||
enum class PlacementStatusValue : std::int8_t
|
||||
{
|
||||
kNoEditItem = 0x0,
|
||||
kValidPlacement = 0x1,
|
||||
kFloating = 0x2,
|
||||
kIntersecting = 0x3,
|
||||
kTerrainOnly = 0x4,
|
||||
kWaterRestriction = 0x5,
|
||||
kSplineTooLong = 0x6,
|
||||
kOutsideBuildArea = 0x7,
|
||||
kRedundantSpline = 0x8,
|
||||
kAttachedSplineInvalid = 0x9,
|
||||
kUnsupported = 0xA,
|
||||
kMustSnap = 0xB,
|
||||
kRadiusOverlap = 0xC,
|
||||
kTimer = 0xD,
|
||||
kReasonCount = 0xE
|
||||
};
|
||||
|
||||
enum class StartWorkshopStatus
|
||||
{
|
||||
kOk = 0x0,
|
||||
kNoNearbyWorkshop = 0x1,
|
||||
kAlreadyInWorkshopMode = 0x2,
|
||||
kActivationBlocked = 0x3
|
||||
};
|
||||
|
||||
class BuildableAreaEvent
|
||||
{
|
||||
public:
|
||||
// members
|
||||
bool exit; // 00
|
||||
};
|
||||
static_assert(sizeof(BuildableAreaEvent) == 0x1);
|
||||
|
||||
class ContextData
|
||||
{
|
||||
public:
|
||||
ContextData(Actor* a_actor)
|
||||
{
|
||||
// lookDir.y = 1.0f;
|
||||
zAngle = a_actor->data.angle.z;
|
||||
parentCell = a_actor->parentCell;
|
||||
worldSpace = a_actor->parentCell->worldSpace;
|
||||
a_actor->GetEyeVector(lookPos, lookDir, false);
|
||||
}
|
||||
|
||||
// members
|
||||
NiPoint3 lookPos; // 00
|
||||
NiPoint3 lookDir; // 0C
|
||||
float zAngle; // 18
|
||||
TESObjectCELL* parentCell; // 20
|
||||
TESWorldSpace* worldSpace; // 28
|
||||
};
|
||||
static_assert(sizeof(ContextData) == 0x30);
|
||||
|
||||
class DeletedItemInfo
|
||||
{
|
||||
public:
|
||||
~DeletedItemInfo() noexcept {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
// members
|
||||
TESFormID formID; // 0
|
||||
std::uint32_t count; // 4
|
||||
};
|
||||
static_assert(sizeof(DeletedItemInfo) == 0x8);
|
||||
|
||||
class __declspec(novtable) ExtraData :
|
||||
public BSExtraData // 00
|
||||
{
|
||||
public:
|
||||
static constexpr auto RTTI{ RTTI::Workshop__ExtraData };
|
||||
static constexpr auto VTABLE{ VTABLE::Workshop__ExtraData };
|
||||
static constexpr auto TYPE{ EXTRA_DATA_TYPE::kWorkshop };
|
||||
|
||||
// members
|
||||
PowerUtils::PowerGrid* currentPowerGrid; // 18
|
||||
BSTArray<PowerUtils::PowerGrid*> powerGrid; // 20
|
||||
BSTArray<DeletedItemInfo*> deletedItems; // 38
|
||||
std::int32_t powerRating; // 50
|
||||
bool offGridItems; // 54
|
||||
};
|
||||
static_assert(sizeof(ExtraData) == 0x58);
|
||||
|
||||
class ItemDestroyedEvent
|
||||
{
|
||||
public:
|
||||
// members
|
||||
NiPointer<TESObjectREFR> workshop; // 00
|
||||
NiPointer<TESObjectREFR> objectDestroyed; // 08
|
||||
};
|
||||
static_assert(sizeof(ItemDestroyedEvent) == 0x10);
|
||||
|
||||
class ItemMovedEvent
|
||||
{
|
||||
public:
|
||||
// members
|
||||
NiPointer<TESObjectREFR> workshop; // 00
|
||||
NiPointer<TESObjectREFR> movedItem; // 08
|
||||
};
|
||||
static_assert(sizeof(ItemMovedEvent) == 0x10);
|
||||
|
||||
class ItemPlacedEvent
|
||||
{
|
||||
public:
|
||||
// members
|
||||
NiPointer<TESObjectREFR> workshop; // 00
|
||||
NiPointer<TESObjectREFR> placedItem; // 08
|
||||
};
|
||||
static_assert(sizeof(ItemPlacedEvent) == 0x10);
|
||||
|
||||
class alignas(0x10) PlacementItemData
|
||||
{
|
||||
public:
|
||||
void Set(TESObjectREFR& a_refr)
|
||||
{
|
||||
using func_t = decltype(&PlacementItemData::Set);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::PlacementItemData::Set };
|
||||
return func(this, a_refr);
|
||||
}
|
||||
|
||||
// members
|
||||
ObjectRefHandle placementItem; // 00
|
||||
BSTArray<hknpShape*> dropProxy; // 08
|
||||
BSTArray<bhkNPCollisionObject*> body; // 20
|
||||
std::byte pad38[0x80 - 0x38]; // 38 - TODO
|
||||
float sinkDepth; // 80
|
||||
float zOffset; // 84
|
||||
float intersectTolerance; // 88
|
||||
float snapPointQueryRadius; // 8C
|
||||
float forwardCastZRot; // 90
|
||||
float xyBoundOverride; // 94
|
||||
float xBoundMinOverride; // 98
|
||||
float xBoundMaxOverride; // 9C
|
||||
float yBoundMinOverride; // A0
|
||||
float yBoundMaxOverride; // A4
|
||||
float zBoundMinOverride; // A8
|
||||
float zBoundMaxOverride; // AC
|
||||
std::uint32_t dropProxyIndex; // B0
|
||||
bool anythingIsGround; // B4
|
||||
bool clampUp; // B5
|
||||
bool forwardCast; // B6
|
||||
bool recenter; // B7
|
||||
bool ignoreSimpleIntersection; // B8
|
||||
bool allowUnsupportedStacking; // B9
|
||||
bool isSet; // BA
|
||||
bool mustSnap; // BB
|
||||
bool stacksWhenSnapped; // BC
|
||||
};
|
||||
static_assert(sizeof(PlacementItemData) == 0xC0);
|
||||
|
||||
class PlacementStatusEvent
|
||||
{
|
||||
public:
|
||||
// members
|
||||
PlacementStatusValue value; // 00
|
||||
};
|
||||
static_assert(sizeof(PlacementStatusEvent) == 0x1);
|
||||
|
||||
class WorkshopMenuNode
|
||||
{
|
||||
public:
|
||||
~WorkshopMenuNode() { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
filterKeyword = nullptr;
|
||||
parent = nullptr;
|
||||
recipe = nullptr;
|
||||
row = 0;
|
||||
column = 0;
|
||||
selected = false;
|
||||
children.clear();
|
||||
}
|
||||
|
||||
bool FindAndSetSelectedNode(std::uint16_t a_row, std::uint32_t a_crc, std::uint16_t& a_outRow)
|
||||
{
|
||||
using func_t = decltype(&WorkshopMenuNode::FindAndSetSelectedNode);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::WorkshopMenuNode::FindAndSetSelectedNode };
|
||||
return func(this, a_row, a_crc, a_outRow);
|
||||
}
|
||||
|
||||
F4_HEAP_REDEFINE_NEW(WorkshopMenuNode);
|
||||
|
||||
// members
|
||||
BGSKeyword* filterKeyword{ nullptr }; // 00
|
||||
WorkshopMenuNode* parent{ nullptr }; // 08
|
||||
BSTArray<std::unique_ptr<WorkshopMenuNode>> children; // 10
|
||||
BGSConstructibleObject* recipe{ nullptr }; // 28
|
||||
BGSConstructibleObject* sourceFormListRecipe{ nullptr }; // 30
|
||||
TESForm* form{ nullptr }; // 38
|
||||
std::uint32_t uniqueID{ static_cast<std::uint32_t>(-1) }; // 40
|
||||
std::uint16_t row{ 0 }; // 44
|
||||
std::uint16_t column{ 0 }; // 46
|
||||
bool selected{ false }; // 48
|
||||
};
|
||||
static_assert(sizeof(WorkshopMenuNode) == 0x50);
|
||||
|
||||
class WorkshopModeEvent
|
||||
{
|
||||
public:
|
||||
// members
|
||||
NiPointer<TESObjectREFR> workshop; // 00
|
||||
bool start; // 08
|
||||
};
|
||||
static_assert(sizeof(WorkshopModeEvent) == 0x10);
|
||||
|
||||
[[nodiscard]] inline TESObjectREFR* FindNearestValidWorkshop(const TESObjectREFR& a_refr)
|
||||
{
|
||||
using func_t = decltype(&Workshop::FindNearestValidWorkshop);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::FindNearestValidWorkshop };
|
||||
return func(a_refr);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool FreeBuild()
|
||||
{
|
||||
using func_t = decltype(&Workshop::FreeBuild);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::FreeBuild };
|
||||
return func();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline WorkshopMenuNode* GetSelectedWorkshopMenuNode(std::uint32_t a_row, std::uint32_t& a_column)
|
||||
{
|
||||
using func_t = decltype(&Workshop::GetSelectedWorkshopMenuNode);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::GetSelectedWorkshopMenuNode };
|
||||
return func(a_row, a_column);
|
||||
}
|
||||
|
||||
inline void InitializePlacementReference(const ContextData& a_context, TESBoundObject& a_object)
|
||||
{
|
||||
using func_t = decltype(&Workshop::InitializePlacementReference);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::InitializePlacementReference };
|
||||
return func(a_context, a_object);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool IsLocationWithinBuildableArea(const TESObjectREFR& a_workshop, const NiPoint3& a_location)
|
||||
{
|
||||
using func_t = decltype(&Workshop::IsLocationWithinBuildableArea);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::IsLocationWithinBuildableArea };
|
||||
return func(a_workshop, a_location);
|
||||
}
|
||||
|
||||
inline bool PlaceCurrentReference(const ContextData& a_context)
|
||||
{
|
||||
using func_t = decltype(&Workshop::PlaceCurrentReference);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::PlaceCurrentReference };
|
||||
return func(a_context);
|
||||
}
|
||||
|
||||
inline void RegisterForItemDestroyed(BSTEventSink<ItemDestroyedEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::RegisterForItemDestroyed);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::RegisterForItemDestroyed };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void RegisterForItemMoved(BSTEventSink<ItemMovedEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::RegisterForItemMoved);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::RegisterForItemMoved };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void RegisterForItemPlaced(BSTEventSink<ItemPlacedEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::RegisterForItemPlaced);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::RegisterForItemPlaced };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void RegisterForWorkshopModeEvent(BSTEventSink<WorkshopModeEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::RegisterForWorkshopModeEvent);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::RegisterForWorkshopModeEvent };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void RequestExitWorkshop(bool a_allowReEntry)
|
||||
{
|
||||
using func_t = decltype(&Workshop::RequestExitWorkshop);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::RequestExitWorkshop };
|
||||
return func(a_allowReEntry);
|
||||
}
|
||||
|
||||
inline void ScrapReference(const ContextData& a_context, BSPointerHandleSmartPointer<BSPointerHandleManagerInterface<TESObjectREFR, HandleManager>>& a_scrapRef, BSTArray<BSTTuple<TESBoundObject*, std::uint32_t>>* a_rewards)
|
||||
{
|
||||
using func_t = decltype(&Workshop::ScrapReference);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::ScrapReference };
|
||||
return func(a_context, a_scrapRef, a_rewards);
|
||||
}
|
||||
|
||||
inline void SetSelectedEditItem(ObjectRefHandle a_refr)
|
||||
{
|
||||
using func_t = decltype(&Workshop::SetSelectedEditItem);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::SetSelectedEditItem };
|
||||
return func(a_refr);
|
||||
}
|
||||
|
||||
inline void StartWorkshop(TESObjectREFR* a_workshopRef)
|
||||
{
|
||||
using func_t = decltype(&Workshop::StartWorkshop);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::StartWorkshop };
|
||||
return func(a_workshopRef);
|
||||
}
|
||||
|
||||
inline void ToggleEditMode(const ContextData& a_context)
|
||||
{
|
||||
using func_t = decltype(&Workshop::ToggleEditMode);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::ToggleEditMode };
|
||||
return func(a_context);
|
||||
}
|
||||
|
||||
inline void UnregisterForItemDestroyed(BSTEventSink<ItemDestroyedEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::UnregisterForItemDestroyed);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::UnregisterForItemDestroyed };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void UnregisterForItemMoved(BSTEventSink<ItemMovedEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::UnregisterForItemMoved);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::UnregisterForItemMoved };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void UnregisterForItemPlaced(BSTEventSink<ItemPlacedEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::UnregisterForItemPlaced);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::UnregisterForItemPlaced };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void UnregisterForWorkshopModeEvent(BSTEventSink<WorkshopModeEvent>* a_sink)
|
||||
{
|
||||
using func_t = decltype(&Workshop::UnregisterForWorkshopModeEvent);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::UnregisterForWorkshopModeEvent };
|
||||
return func(a_sink);
|
||||
}
|
||||
|
||||
inline void UpdateActiveEdit(const ContextData& a_context, bool a_multiselect = false)
|
||||
{
|
||||
using func_t = decltype(&Workshop::UpdateActiveEdit);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::UpdateActiveEdit };
|
||||
return func(a_context, a_multiselect);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool WorkshopCanShowRecipe(BGSConstructibleObject* a_recipe, BGSKeyword* a_filter)
|
||||
{
|
||||
using func_t = decltype(&Workshop::WorkshopCanShowRecipe);
|
||||
static REL::Relocation<func_t> func{ ID::Workshop::WorkshopCanShowRecipe };
|
||||
return func(a_recipe, a_filter);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline PlacementItemData* GetCurrentPlacementItemData()
|
||||
{
|
||||
static REL::Relocation<PlacementItemData*> value{ ID::Workshop::CurrentPlacementItemData };
|
||||
return value.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::uint16_t* GetCurrentRow()
|
||||
{
|
||||
static REL::Relocation<std::uint16_t*> value{ ID::Workshop::CurrentRow };
|
||||
return value.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline ObjectRefHandle* GetPlacementItem()
|
||||
{
|
||||
static REL::Relocation<ObjectRefHandle*> value{ ID::Workshop::PlacementItem };
|
||||
return value.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
|
||||
#include "RE/B/BGSListForm.h"
|
||||
#include "RE/B/BSSpinLock.h"
|
||||
#include "RE/B/BSTEvent.h"
|
||||
#include "RE/B/BSTInterpolator.h"
|
||||
#include "RE/B/BSTSmartPointer.h"
|
||||
#include "RE/B/BSTTuple.h"
|
||||
#include "RE/D/DisplayItemModel.h"
|
||||
#include "RE/G/GameMenuBase.h"
|
||||
#include "RE/I/Inventory3DManager.h"
|
||||
#include "RE/N/NiPoint3.h"
|
||||
#include "RE/N/NiPointer.h"
|
||||
|
||||
namespace RE
|
||||
{
|
||||
class PickRefUpdateEvent;
|
||||
class UserEventEnabledEvent;
|
||||
class WorkshopMenuGeometry;
|
||||
|
||||
namespace Workshop
|
||||
{
|
||||
class BuildableAreaEvent;
|
||||
class PlacementStatusEvent;
|
||||
}
|
||||
|
||||
class __declspec(novtable) WorkshopMenu :
|
||||
public GameMenuBase, // 000
|
||||
public BSTEventSink<UserEventEnabledEvent>, // 0E0
|
||||
public BSTEventSink<Workshop::BuildableAreaEvent>, // 0E8
|
||||
public BSTEventSink<PickRefUpdateEvent>, // 0F0
|
||||
public BSTEventSink<Workshop::PlacementStatusEvent> // 0F8
|
||||
{
|
||||
public:
|
||||
static constexpr auto RTTI{ RTTI::WorkshopMenu };
|
||||
static constexpr auto VTABLE{ VTABLE::WorkshopMenu };
|
||||
static constexpr auto MENU_NAME{ "WorkshopMenu"sv };
|
||||
|
||||
enum class TAG_FOR_SEARCH_RESULT
|
||||
{
|
||||
kNone = 0x0,
|
||||
kTaggedComponents = 0x1,
|
||||
kUntaggedComponents = 0x2
|
||||
};
|
||||
|
||||
class FXWorkshopMenu :
|
||||
public BSGFxShaderFXTarget // 000
|
||||
{
|
||||
public:
|
||||
// members
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground1; // 0B0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground2; // 0B8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground3; // 0C0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground4; // 0C8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground5; // 0D0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground6; // 0D8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground7; // 0E0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happyBackground8; // 0E8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> buttonBackground; // 0F0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> iconCardBackground; // 0F8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> requirementsListBackground; // 100
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessPeopleBase; // 108
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessFoodBase; // 110
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessWaterBase; // 118
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessPowerBase; // 120
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessSafetyBase; // 128
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessBedsBase; // 130
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessHappyValue; // 138
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessHappyLabel; // 140
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessHappyIcon; // 148
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessHappyArrow; // 150
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessSizeBase; // 158
|
||||
std::unique_ptr<BSGFxShaderFXTarget> happinessBarBrackets; // 160
|
||||
std::unique_ptr<BSGFxShaderFXTarget> requirementsBase; // 168
|
||||
std::unique_ptr<BSGFxShaderFXTarget> itemName; // 170
|
||||
std::unique_ptr<BSGFxShaderFXTarget> selectionBracket; // 178
|
||||
std::unique_ptr<BSGFxShaderFXTarget> itemCounts; // 180
|
||||
std::unique_ptr<BSGFxShaderFXTarget> newRecipeIcon; // 188
|
||||
std::unique_ptr<BSGFxShaderFXTarget> iconCardBracketsAndText; // 190
|
||||
std::unique_ptr<BSGFxShaderFXTarget> producesIcons; // 198
|
||||
std::unique_ptr<BSGFxShaderFXTarget> requiresIcon1; // 1A0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> requiresIcon2; // 1A8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> assignmentIcon; // 1B0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> rowBrackets; // 1B8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> displayPath; // 1C0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> perkPanel1; // 1C8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> perkPanel2; // 1D0
|
||||
std::unique_ptr<BSGFxShaderFXTarget> descriptionBase; // 1D8
|
||||
std::unique_ptr<BSGFxShaderFXTarget> iconBackground; // 1E0
|
||||
};
|
||||
static_assert(sizeof(FXWorkshopMenu) == 0x1E8);
|
||||
|
||||
class IconBG
|
||||
{
|
||||
public:
|
||||
BSTAlignedArray<UIShaderFXInfo> cachedColorFXInfos; // 00
|
||||
BSTAlignedArray<UIShaderFXInfo> cachedBackgroundFXInfos; // 18
|
||||
BSReadWriteLock cachedQuadsLock; // 30
|
||||
};
|
||||
static_assert(sizeof(IconBG) == 0x38);
|
||||
|
||||
void CheckAndSetItemForPlacement()
|
||||
{
|
||||
using func_t = decltype(&WorkshopMenu::CheckAndSetItemForPlacement);
|
||||
static REL::Relocation<func_t> func{ ID::WorkshopMenu::CheckAndSetItemForPlacement };
|
||||
return func(this);
|
||||
}
|
||||
|
||||
void UpdateButtonText()
|
||||
{
|
||||
using func_t = decltype(&WorkshopMenu::UpdateButtonText);
|
||||
static REL::Relocation<func_t> func{ ID::WorkshopMenu::UpdateButtonText };
|
||||
return func(this);
|
||||
}
|
||||
|
||||
// members
|
||||
BSTArray<NiPoint3> item3DPositions[4]; // 100
|
||||
BSTArray<BSTTuple<DisplayItemModel, TESObjectREFR*>> displayItemModels; // 160
|
||||
IconBG iconBG; // 178
|
||||
Inventory3DManager inv3DModelManager; // 1B0
|
||||
BSTArray<BSTTuple<NiPointer<nsInventory3DManager::NewInventoryMenuItemLoadTask>, NiPoint3>> loadTasks; // 2F0
|
||||
BSTInterpolator<float, EaseOutInterpolator, GetCurrentPositionFunctor> upDownGlassAnimationInterpolator; // 308
|
||||
BSTInterpolator<float, EaseOutInterpolator, GetCurrentPositionFunctor> leftRightGlassAnimationInterpolator[4]; // 320
|
||||
BSTSmartPointer<WorkshopMenuGeometry> displayGeometry; // 380
|
||||
BSFixedString dpadInput; // 388
|
||||
BGSListForm includeList; // 390
|
||||
BGSListForm excludeList; // 3D8
|
||||
long double lastBudget; // 420
|
||||
std::uint16_t topMenuCount; // 428
|
||||
bool inputAdjustMode; // 42A
|
||||
bool verticalAdjustment; // 42B
|
||||
bool disableAdjustOnThumbEvent; // 42C
|
||||
bool initialized; // 42D
|
||||
bool inEditMode; // 42E
|
||||
bool electricalDevice; // 42F
|
||||
bool useMovementAsDirectional; // 430
|
||||
bool motionBlurActive; // 431
|
||||
bool exitDebounce; // 432
|
||||
std::unique_ptr<FXWorkshopMenu> workshopMenuBase; // 438
|
||||
};
|
||||
static_assert(sizeof(WorkshopMenu) == 0x440);
|
||||
}
|
||||
Reference in New Issue
Block a user