Skip to content

Commit

Permalink
Better humanoid npc detection
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbeBryssinck committed Mar 29, 2024
1 parent 6aa97ed commit 61488e6
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 6 deletions.
41 changes: 39 additions & 2 deletions Code/client/Games/Skyrim/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include <Games/Skyrim/BSAnimationGraphManager.h>
#include <Havok/hkbStateMachine.h>
#include <Havok/hkbBehaviorGraph.h>
#include <Forms/BGSOutfit.h>
#include <Forms/TESObjectARMO.h>

#ifdef SAVE_STUFF

Expand Down Expand Up @@ -196,9 +198,44 @@ bool Actor::IsWearingBodyPiece() const noexcept
return GetContainerChanges()->GetArmor(32) != nullptr;
}

bool Actor::IsHumanoidNPC() const noexcept
bool Actor::ShouldWearBodyPiece() const noexcept
{
return Cast<TESNPC>(baseForm)->outfits[0] != nullptr;
TESNPC* pBase = Cast<TESNPC>(baseForm);
if (!pBase)
return false;

BGSOutfit* pDefaultOutfit = pBase->outfits[0];
if (!pDefaultOutfit)
return false;

for (auto* pItem : pDefaultOutfit->outfitItems)
{
TESObjectARMO* pArmor = nullptr;

if (pItem->formType == FormType::Armor)
pArmor = Cast<TESObjectARMO>(pItem);
else if (pItem->formType == FormType::LeveledItem)
{
// TODO: leveled items can probably also be handled but afaik,
// the naked npc bug mostly occurs to town NPCs.
// Since this is a bit more complex and possibly error prone, leave out for now.
#if 0
TESLevItem* pLevItem = Cast<TESLevItem>(pItem);
if (!pLevItem)
continue;
#endif
}
else
continue;

if (!pArmor)
continue;

if (pArmor->slotType & 0x4) // 0x4 is flag for body piece
return true;
}

return false;
}

// Get owner of a summon or raised corpse
Expand Down
2 changes: 1 addition & 1 deletion Code/client/Games/Skyrim/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ struct Actor : TESObjectREFR
[[nodiscard]] bool HasPerk(uint32_t aPerkFormId) const noexcept;
[[nodiscard]] uint8_t GetPerkRank(uint32_t aPerkFormId) const noexcept;
[[nodiscard]] bool IsWearingBodyPiece() const noexcept;
[[nodiscard]] bool IsHumanoidNPC() const noexcept;
[[nodiscard]] bool ShouldWearBodyPiece() const noexcept;

// Setters
void SetSpeed(float aSpeed) noexcept;
Expand Down
1 change: 1 addition & 0 deletions Code/client/Games/Skyrim/Forms/BGSOutfit.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

struct BGSOutfit : TESForm
{
GameArray<TESForm*> outfitItems;
};
1 change: 1 addition & 0 deletions Code/client/Games/Skyrim/Forms/TESForm.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum class FormType : uint8_t
Npc = 43,
LeveledCharacter = 44,
Alchemy = 46,
LeveledItem = 53,
Character = 62,
QuestItem = 77,
Count = 0x87
Expand Down
6 changes: 6 additions & 0 deletions Code/client/Games/Skyrim/Forms/TESLevItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

struct TESLevItem : BaseFormComponent
{

};
2 changes: 2 additions & 0 deletions Code/client/Games/Skyrim/Forms/TESObjectARMO.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@

struct TESObjectARMO : TESForm
{
uint8_t unk20[0x1B8 - sizeof(TESForm)];
uint32_t slotType;
};
10 changes: 9 additions & 1 deletion Code/client/Services/Debug/DebugService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,15 @@ void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
{
s_f8Pressed = true;

PlaceActorInWorld();
//PlaceActorInWorld();
Actor* pActor = Cast<Actor>(TESForm::GetById(m_formId));
if (pActor)
{
if (pActor->ShouldWearBodyPiece())
spdlog::warn("Actor has body piece");
else
spdlog::error("Actor does not have body piece");
}
}
}
else
Expand Down
5 changes: 3 additions & 2 deletions Code/client/Services/Generic/InventoryService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <Games/Overrides.h>
#include <EquipManager.h>
#include <Games/ActorExtension.h>
#include <Forms/TESNPC.h>

#if TP_FALLOUT4
#include <Forms/BGSObjectInstance.h>
Expand Down Expand Up @@ -324,10 +325,10 @@ void InventoryService::RunNakedNPCBugChecks() noexcept
if (pActor->IsDead())
continue;

if (!pActor->IsHumanoidNPC())
if (pActor->IsWearingBodyPiece())
continue;

if (pActor->IsWearingBodyPiece())
if (!pActor->ShouldWearBodyPiece())
continue;

// Don't broadcast changes if a remote actor needs fixing
Expand Down

0 comments on commit 61488e6

Please sign in to comment.