Skip to content
Open
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
12 changes: 12 additions & 0 deletions Code/client/Games/Skyrim/Forms/TESRace.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@

struct TESRace : TESForm, TESFullName
{
// RACE_DATA::Flag
enum : uint32_t
{
kPlayable = 1 << 0,
};

[[nodiscard]] bool IsPlayable() const noexcept { return (raceFlags & kPlayable) != 0; }

uint8_t unk30[0x108 - 0x30];
uint32_t raceFlags; // RACE_DATA (DATA) at 0xE8, its flags at +0x20
};

static_assert(offsetof(TESRace, raceFlags) == 0x108);
13 changes: 10 additions & 3 deletions Code/client/Services/Generic/PlayerService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,16 @@ void PlayerService::RunBeastFormDetection() const noexcept
static uint32_t lastRaceFormID = 0;
static std::chrono::steady_clock::time_point lastSendTimePoint;
constexpr auto cDelayBetweenUpdates = 250ms;
// Werewolf (0xCDD84) and Vampire Lord (0x200283A)
constexpr auto isBeastRace = [](uint32_t aFormId) noexcept {
return aFormId == 0xCDD84 || aFormId == 0x200283A;
// Werewolf (0xCDD84) and Vampire Lord (0x200283A), and any other non-playable race: mods transform the
// player with SetRace into their own beast races (e.g. Enderal's Theriantrophist wolf form), and without
// the respawn the remote puppet keeps its old body on the new race's skeleton and behavior. Playable races
// are excluded so race changes in the RaceSex menu don't respawn the puppet.
const auto isBeastRace = [](uint32_t aFormId) noexcept {
if (aFormId == 0xCDD84 || aFormId == 0x200283A)
return true;

const TESRace* pRace = Cast<TESRace>(TESForm::GetById(aFormId));
return pRace && !pRace->IsPlayable();
};

const auto now = std::chrono::steady_clock::now();
Expand Down