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
15 changes: 15 additions & 0 deletions include/RE/A/ATTACK_STATE_ENUM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

namespace RE
{
enum class ATTACK_STATE_ENUM : std::int32_t
{
kNone = 0x0,
kDraw = 0x1,
kSwing = 0x2,
kHit = 0x3,
kNextAttack = 0x4,
kFollowThrough = 0x5,
kBash = 0x6
};
}
7 changes: 7 additions & 0 deletions include/RE/A/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ namespace RE
return currentProcess ? currentProcess->GetCurrentAmmo(a_equipIndex) : nullptr;
}

[[nodiscard]] std::uint32_t GetCurrentAmmoCount(BGSEquipIndex a_equipIndex) const
{
using func_t = decltype(&Actor::GetCurrentAmmoCount);
static REL::Relocation<func_t> func{ ID::Actor::GetCurrentAmmoCount };
return func(this, a_equipIndex);
}

std::uint32_t GetCurrentCollisionGroup()
{
using func_t = decltype(&Actor::GetCurrentCollisionGroup);
Expand Down
16 changes: 16 additions & 0 deletions include/RE/A/ActorEquipManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ namespace RE
return *singleton;
}

// Whether the actor is allowed to equip the item the handle names, and
// what stops it when it is not. Equipping through the Pip-Boy, the
// favourites bar or a quick key asks this first and turns anything but
// kSuccess into the matching HUD message.
//
// kItemBroken is the one answer an unmodified game never gives. It comes
// from ExtraDataList::IsItemBroken, so it needs an item whose health has
// been written down as zero or less, and nothing in the base game writes
// an item's health at all.
[[nodiscard]] CanEquipResult CanEquip(Actor* a_actor, const std::uint32_t& a_handleID, std::uint32_t a_stackID)
{
using func_t = decltype(&ActorEquipManager::CanEquip);
static REL::Relocation<func_t> func{ ID::ActorEquipManager::CanEquip };
return func(this, a_actor, a_handleID, a_stackID);
}

bool EquipObject(
Actor* a_actor,
const BGSObjectInstance& a_object,
Expand Down
10 changes: 10 additions & 0 deletions include/RE/B/BGSConstructibleObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ namespace RE
[[nodiscard]] TESForm* GetCreatedItem() const noexcept { return createdItem; }
[[nodiscard]] std::uint16_t GetWorkshopPriority() const noexcept { return data.workshopPriority; }

// The recipe that builds a form, or null when nothing builds it. Matches
// a recipe that creates the form itself, and one that creates a form list
// the form belongs to.
[[nodiscard]] static BGSConstructibleObject* FindRecipeForCreatedForm(const TESForm* a_form)
{
using func_t = decltype(&BGSConstructibleObject::FindRecipeForCreatedForm);
static REL::Relocation<func_t> func{ ID::BGSConstructibleObject::FindRecipeForCreatedForm };
return func(a_form);
}

bool PlayerPassesConditions()
{
using func_t = decltype(&BGSConstructibleObject::PlayerPassesConditions);
Expand Down
14 changes: 14 additions & 0 deletions include/RE/C/CombatFormulas.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ namespace RE
return func(a_target, a_bodyPart, a_physicalDamage, a_damageTypes);
}

// The damage one attack deals before the target's armour. Combat and the
// damage an item card shows both work it out through this.
//
// a_avOwner is the actor the damage belongs to, and a TESNPC record is
// taken as well, with the actor values read off that instead. a_condition
// is the weapon's item health, and a_rangeMult the falloff for a target
// past the weapon's range, 1.0 within it.
[[nodiscard]] inline float CalcWeaponDamage(const TESForm* a_avOwner, const TESObjectWEAP::InstanceData* a_data, const TESAmmo* a_ammo, float a_condition, float a_rangeMult)
{
using func_t = decltype(&CombatFormulas::CalcWeaponDamage);
static REL::Relocation<func_t> func{ ID::CombatFormulas::CalcWeaponDamage };
return func(a_avOwner, a_data, a_ammo, a_condition, a_rangeMult);
}

[[nodiscard]] inline std::int64_t GetNumCrippledAttackConditions(Actor* a_actor)
{
using func_t = decltype(&CombatFormulas::GetNumCrippledAttackConditions);
Expand Down
2 changes: 1 addition & 1 deletion include/RE/E/EquippedWeaponData.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "RE/A/ATTACK_STATE_ENUM.h"
#include "RE/B/BGSObjectInstance.h"
#include "RE/B/BSSoundHandle.h"
#include "RE/B/BSTArray.h"
Expand All @@ -9,7 +10,6 @@

namespace RE
{
enum class ATTACK_STATE_ENUM;
class AimModel;
class BSCloneReserver;
class MuzzleFlash;
Expand Down
28 changes: 28 additions & 0 deletions include/RE/E/Explosion.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace RE
{
class Actor;
class ActorCause;
class NiLight;
class NonActorMagicCaster;
Expand Down Expand Up @@ -74,6 +75,33 @@ namespace RE
virtual void Update(float a_delta); // C7
virtual void FindTargets(); // C8

// Whoever set the blast off, or null when the owner has gone away or is
// not an actor. This is the aggressor the engine credits an explosion's
// blows to.
[[nodiscard]] Actor* GetActorOwner()
{
using func_t = decltype(&Explosion::GetActorOwner);
static REL::Relocation<func_t> func{ ID::Explosion::GetActorOwner };
return func(this);
}

// What the blast is worth. Worked out from the explosion record's damage
// and this explosion's damageMult the first time anything asks, then kept
// in calculatedDamage and handed back unchanged after that.
//
// Every question the engine asks about a live blast is answered from
// here, from whether it is worth looking for targets at all to what each
// of them loses. The item card is the one thing that does not come
// through it, because a weapon being looked at has set nothing off, so
// CombatFormulas::GetWeaponDisplayDamage reads the explosion record
// instead and the two arrive at the same number by different routes.
[[nodiscard]] float GetDamage()
{
using func_t = decltype(&Explosion::GetDamage);
static REL::Relocation<func_t> func{ ID::Explosion::GetDamage };
return func(this);
}

// members
hknpClosestUniqueBodyIdHitCollector collector; // 110
void* explosionDBHandle; // 520 - TODO
Expand Down
11 changes: 11 additions & 0 deletions include/RE/E/ExtraDataList.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,17 @@ namespace RE
return func(this);
}

// Whether the health in this list is zero or less, which is what the game
// calls a broken item. The counterpart of IsDamaged above, which asks the
// weaker question of whether the health is anything below full. Both
// answer false for a list carrying no health at all.
inline bool IsItemBroken()
{
using func_t = decltype(&ExtraDataList::IsItemBroken);
static REL::Relocation<func_t> func{ ID::ExtraDataList::IsItemBroken };
return func(this);
}

inline bool CompareList(const ExtraDataList* a_compare, ComparisonQualifier a_qualifier)
{
using func_t = decltype(&ExtraDataList::CompareList);
Expand Down
26 changes: 26 additions & 0 deletions include/RE/E/ExtraLeveledItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "RE/B/BSExtraData.h"

namespace RE
{
class __declspec(novtable) ExtraLeveledItem :
public BSExtraData // 00
{
public:
static constexpr auto RTTI{ RTTI::ExtraLeveledItem };
static constexpr auto VTABLE{ VTABLE::ExtraLeveledItem };
static constexpr auto TYPE{ EXTRA_DATA_TYPE::kLevelItem };

ExtraLeveledItem(std::uint32_t a_levItem) :
BSExtraData(TYPE),
levItem(a_levItem)
{
REX::EMPLACE_VTABLE(this);
}

// members
std::uint32_t levItem; // 18
};
static_assert(sizeof(ExtraLeveledItem) == 0x20);
}
26 changes: 26 additions & 0 deletions include/RE/E/ExtraOutfitItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "RE/B/BSExtraData.h"

namespace RE
{
class __declspec(novtable) ExtraOutfitItem :
public BSExtraData // 00
{
public:
static constexpr auto RTTI{ RTTI::ExtraOutfitItem };
static constexpr auto VTABLE{ VTABLE::ExtraOutfitItem };
static constexpr auto TYPE{ EXTRA_DATA_TYPE::kOutfitItem };

ExtraOutfitItem(std::uint32_t a_outfit) :
BSExtraData(TYPE),
outfit(a_outfit)
{
REX::EMPLACE_VTABLE(this);
}

// members
std::uint32_t outfit; // 18
};
static_assert(sizeof(ExtraOutfitItem) == 0x20);
}
3 changes: 3 additions & 0 deletions include/RE/Fallout.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "RE/A/AITimeStamp.h"
#include "RE/A/AITimer.h"
#include "RE/A/AMMO_DATA.h"
#include "RE/A/ATTACK_STATE_ENUM.h"
#include "RE/A/ActionInput.h"
#include "RE/A/ActionOutput.h"
#include "RE/A/ActionPoints.h"
Expand Down Expand Up @@ -691,13 +692,15 @@
#include "RE/E/ExtraHealth.h"
#include "RE/E/ExtraInstanceData.h"
#include "RE/E/ExtraLeveledCreature.h"
#include "RE/E/ExtraLeveledItem.h"
#include "RE/E/ExtraLight.h"
#include "RE/E/ExtraLinkedRef.h"
#include "RE/E/ExtraLinkedRefChildren.h"
#include "RE/E/ExtraLocation.h"
#include "RE/E/ExtraLock.h"
#include "RE/E/ExtraMapMarker.h"
#include "RE/E/ExtraMaterialSwap.h"
#include "RE/E/ExtraOutfitItem.h"
#include "RE/E/ExtraPoison.h"
#include "RE/E/ExtraPowerLinks.h"
#include "RE/E/ExtraRadioData.h"
Expand Down
11 changes: 11 additions & 0 deletions include/RE/IDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace RE::ID
inline constexpr REL::ID GetClosestBone{ 2230051 };
inline constexpr REL::ID GetCollisionFilter{ 2277949 };
inline constexpr REL::ID GetCombatStyle{ 2231053 };
inline constexpr REL::ID GetCurrentAmmoCount{ 2229950 };
inline constexpr REL::ID SetCurrentAmmoCount{ 2229952 };
inline constexpr REL::ID GetCurrentCollisionGroup{ 2229993 };
inline constexpr REL::ID GetCurrentFireLocation{ 2231167 };
Expand Down Expand Up @@ -77,6 +78,7 @@ namespace RE::ID
inline constexpr REL::ID EquipObject{ 2231392 };
inline constexpr REL::ID UnequipObject{ 2231395 };
inline constexpr REL::ID UnequipItem{ 2231399 };
inline constexpr REL::ID CanEquip{ 2231405 };
}

namespace ActorUtils
Expand Down Expand Up @@ -170,6 +172,7 @@ namespace RE::ID

namespace BGSConstructibleObject
{
inline constexpr REL::ID FindRecipeForCreatedForm{ 2197324 };
inline constexpr REL::ID PlayerPassesConditions{ 2197318 };
}

Expand Down Expand Up @@ -1033,6 +1036,12 @@ namespace RE::ID
inline constexpr REL::ID GetBuildConfirmQuestion{ 2223057 };
}

namespace Explosion
{
inline constexpr REL::ID GetActorOwner{ 2236659 };
inline constexpr REL::ID GetDamage{ 2236658 };
}

namespace ExteriorCellSingleton
{
inline constexpr REL::ID Singleton{ 4796370 };
Expand All @@ -1054,6 +1063,7 @@ namespace RE::ID
inline constexpr REL::ID ClearFavorite{ 2190191 };
inline constexpr REL::ID IsFavorite{ 2190189 };
inline constexpr REL::ID IsDamaged{ 2190224 };
inline constexpr REL::ID IsItemBroken{ 2190223 };
inline constexpr REL::ID CompareList{ 2190098 };
inline constexpr REL::ID SetFavorite{ 2190188 };
inline constexpr REL::ID GetPrimitive{ 2190427 };
Expand Down Expand Up @@ -2318,6 +2328,7 @@ namespace RE::ID

namespace TESObjectWEAP
{
inline constexpr REL::ID GetProjectile{ 2198934 };
inline constexpr REL::ID GetMeleeAttackSpeed{ 2198957 };
inline constexpr REL::ID GetMeleeAttackSpeedLabel{ 2198959 };
inline constexpr REL::ID Fire{ 2198960 };
Expand Down
16 changes: 16 additions & 0 deletions include/RE/T/TESObjectWEAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@ namespace RE
};
static_assert(sizeof(Data) == 0x138);

// What this weapon fires, or null for one that fires nothing.
//
// The instance data's own override is preferred, then the base form's,
// and the ammunition's projectile stands in when neither names one. A
// muzzle or a barrel that swaps the projectile is therefore followed,
// and so is a change of ammunition.
//
// a_instanceData may be null, in which case only the base form and the
// ammunition are consulted.
[[nodiscard]] static BGSProjectile* GetProjectile(const TESObjectWEAP* a_weapon, const TESAmmo* a_ammo, const InstanceData* a_instanceData)
{
using func_t = decltype(&TESObjectWEAP::GetProjectile);
static REL::Relocation<func_t> func{ ID::TESObjectWEAP::GetProjectile };
return func(a_weapon, a_ammo, a_instanceData);
}

[[nodiscard]] MELEE_ATTACK_SPEED GetMeleeAttackSpeed()
{
using func_t = decltype(&TESObjectWEAP::GetMeleeAttackSpeed);
Expand Down