Skip to content

Commit

Permalink
Merge pull request #674 from tiltedphoques/dev
Browse files Browse the repository at this point in the history
V1.6.5
  • Loading branch information
RobbeBryssinck authored May 9, 2024
2 parents bd9a756 + df47981 commit 6bc8861
Show file tree
Hide file tree
Showing 36 changed files with 884 additions and 33 deletions.
4 changes: 3 additions & 1 deletion Code/client/CrashHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ std::string SerializeTimePoint(const time_point& time, const std::string& format

LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
if (pExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005)
static int alreadycrashed = 0;

if (pExceptionInfo->ExceptionRecord->ExceptionCode == 0xC0000005 && alreadycrashed++ == 0)
{
spdlog::error("Crash occurred!");
MINIDUMP_EXCEPTION_INFORMATION M;
Expand Down
11 changes: 11 additions & 0 deletions Code/client/Games/Primitives.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ template <class T> struct GameList
Entry entry;

inline bool Empty() const noexcept { return entry.data == nullptr; }
inline size_t Size() const noexcept
{
if (entry.data == nullptr)
return 0ULL;

size_t size = 0;
for (const Entry* current = &entry; current; current = current->next)
size++;

return size;
}

// Range for loop compatibility
struct Iterator
Expand Down
47 changes: 46 additions & 1 deletion Code/client/Games/Skyrim/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <Components/TESActorBaseData.h>
#include <ExtraData/ExtraFactionChanges.h>
#include <Games/Memory.h>
#include <Forms/TESLevItem.h>

#include <Events/HealthChangeEvent.h>
#include <Events/InventoryChangeEvent.h>
Expand Down Expand Up @@ -44,6 +45,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 @@ -191,6 +194,48 @@ TESForm* Actor::GetEquippedAmmo() const noexcept
return nullptr;
}

bool Actor::IsWearingBodyPiece() const noexcept
{
return GetContainerChanges()->GetArmor(32) != nullptr;
}

bool Actor::ShouldWearBodyPiece() const noexcept
{
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)
{
TESLevItem* pLevItem = Cast<TESLevItem>(pItem);
if (!pLevItem || !pLevItem->pLeveledListA || !pLevItem->pLeveledListA->pForm)
continue;

pArmor = Cast<TESObjectARMO>(pLevItem->pLeveledListA->pForm);
}
else
continue;

if (!pArmor)
continue;

if (pArmor->IsBodyPiece())
return true;
}

return false;
}

// Get owner of a summon or raised corpse
Actor* Actor::GetCommandingActor() const noexcept
{
Expand All @@ -207,7 +252,7 @@ Actor* Actor::GetCommandingActor() const noexcept
// Get owner of a summon or raised corpse
void Actor::SetCommandingActor(BSPointerHandle<TESObjectREFR> aCommandingActor) noexcept
{
if (currentProcess && currentProcess->middleProcess && currentProcess->middleProcess)
if (currentProcess && currentProcess->middleProcess)
{
currentProcess->middleProcess->commandingActor = aCommandingActor;
flags2 |= ActorFlags::IS_COMMANDED_ACTOR;
Expand Down
2 changes: 2 additions & 0 deletions Code/client/Games/Skyrim/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ struct Actor : TESObjectREFR
[[nodiscard]] Actor* GetCombatTarget() const noexcept;
[[nodiscard]] bool HasPerk(uint32_t aPerkFormId) const noexcept;
[[nodiscard]] uint8_t GetPerkRank(uint32_t aPerkFormId) const noexcept;
[[nodiscard]] bool IsWearingBodyPiece() const noexcept;
[[nodiscard]] bool ShouldWearBodyPiece() const noexcept;

// Setters
void SetSpeed(float aSpeed) noexcept;
Expand Down
10 changes: 6 additions & 4 deletions Code/client/Games/Skyrim/EquipManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void* TP_MAKE_THISCALL(EquipHook, EquipManager, Actor* apActor, TESForm* apItem,
// Consumables are "equipped" as well. We don't want this to sync, for several reasons.
// The right hand item on the server would be overridden by the consumable.
// Furthermore, the equip action on the other clients would doubly subtract the consumables.
if (pExtension->IsLocal() && !apItem->IsConsumable())
if (pExtension->IsLocal() && !apItem->IsConsumable() && !apData->bQueueEquip)
{
EquipmentChangeEvent evt{};
evt.ActorId = apActor->formID;
Expand Down Expand Up @@ -189,7 +189,7 @@ void* TP_MAKE_THISCALL(UnEquipHook, EquipManager, Actor* apActor, TESForm* apIte
return nullptr;
}

if (pExtension->IsLocal() && !ScopedUnequipOverride::IsOverriden())
if (pExtension->IsLocal() && !ScopedUnequipOverride::IsOverriden() && !apData->bQueueEquip)
{
EquipmentChangeEvent evt{};
evt.ActorId = apActor->formID;
Expand All @@ -216,7 +216,7 @@ void* TP_MAKE_THISCALL(EquipSpellHook, EquipManager, Actor* apActor, TESForm* ap
if (pExtension->IsRemote() && !ScopedEquipOverride::IsOverriden())
return nullptr;

if (pExtension->IsLocal())
if (pExtension->IsLocal() && !apData->bQueueEquip)
{
EquipmentChangeEvent evt{};
evt.ActorId = apActor->formID;
Expand All @@ -241,7 +241,7 @@ void* TP_MAKE_THISCALL(UnEquipSpellHook, EquipManager, Actor* apActor, TESForm*
if (pExtension->IsRemote() && !ScopedEquipOverride::IsOverriden())
return nullptr;

if (pExtension->IsLocal() && !ScopedUnequipOverride::IsOverriden())
if (pExtension->IsLocal() && !ScopedUnequipOverride::IsOverriden() && !apData->bQueueEquip)
{
EquipmentChangeEvent evt{};
evt.ActorId = apActor->formID;
Expand All @@ -265,6 +265,7 @@ void* TP_MAKE_THISCALL(EquipShoutHook, EquipManager, Actor* apActor, TESForm* ap
if (pExtension->IsRemote() && !ScopedEquipOverride::IsOverriden())
return nullptr;

// TODO: queue check?
if (pExtension->IsLocal())
{
EquipmentChangeEvent evt{};
Expand All @@ -289,6 +290,7 @@ void* TP_MAKE_THISCALL(UnEquipShoutHook, EquipManager, Actor* apActor, TESForm*
if (pExtension->IsRemote() && !ScopedEquipOverride::IsOverriden())
return nullptr;

// TODO: queue check?
if (pExtension->IsLocal() && !ScopedUnequipOverride::IsOverriden())
{
EquipmentChangeEvent evt{};
Expand Down
9 changes: 9 additions & 0 deletions Code/client/Games/Skyrim/ExtraData/ExtraContainerChanges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,12 @@ bool ExtraContainerChanges::Entry::IsQuestObject() noexcept

return TiltedPhoques::ThisCall(s_isQuestObject, this);
}

TESObjectARMO* ExtraContainerChanges::Data::GetArmor(uint32_t aSlotId) noexcept
{
TP_THIS_FUNCTION(TGetArmor, TESObjectARMO*, ExtraContainerChanges::Data, uint32_t);

POINTER_SKYRIMSE(TGetArmor, s_getArmor, 16113);

return TiltedPhoques::ThisCall(s_getArmor, this, aSlotId);
}
2 changes: 2 additions & 0 deletions Code/client/Games/Skyrim/ExtraData/ExtraContainerChanges.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct BGSLoadFormBuffer;
struct BGSSaveFormBuffer;
struct TESObjectREFR;
struct TESForm;
struct TESObjectARMO;

struct ExtraContainerChanges : BSExtraData
{
Expand All @@ -25,6 +26,7 @@ struct ExtraContainerChanges : BSExtraData
{
void Save(BGSSaveFormBuffer* apBuffer);
void Load(BGSLoadFormBuffer* apBuffer);
TESObjectARMO* GetArmor(uint32_t aSlotId) noexcept;

GameList<Entry>* entries;
TESObjectREFR* parent;
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
9 changes: 9 additions & 0 deletions Code/client/Games/Skyrim/Forms/TESLevItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "TESLeveledList.h"

struct TESLevItem : TESBoundObject, TESLeveledList
{
};

static_assert(sizeof(TESLevItem) == 0x58);
18 changes: 18 additions & 0 deletions Code/client/Games/Skyrim/Forms/TESLeveledList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

struct TESLeveledList : BaseFormComponent
{
struct LEVELED_OBJECT
{
TESForm* pForm;
uint16_t count;
uint16_t level;
uint32_t padC;
void* pItemExtra;
};

LEVELED_OBJECT* pLeveledListA; // this array has count at offset -8
uint8_t unk10[0x28 - 0x10];
};

static_assert(sizeof(TESLeveledList) == 0x28);
7 changes: 7 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,11 @@

struct TESObjectARMO : TESForm
{
[[nodiscard]] bool IsBodyPiece() const noexcept
{
return (slotType & 0x4) != 0; // 0x4 is flag for body piece
}

uint8_t unk20[0x1B8 - sizeof(TESForm)];
uint32_t slotType;
};
2 changes: 1 addition & 1 deletion Code/client/Games/Skyrim/TESObjectREFR.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct TESObjectREFR : TESForm
virtual void sub_87();
virtual void sub_88();
virtual void DisableImpl();
virtual void sub_8A();
virtual void ResetInventory(bool abLeveledOnly);
virtual void sub_8B();
virtual void sub_8C();
virtual void sub_8D();
Expand Down
1 change: 1 addition & 0 deletions Code/client/Games/TES.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ struct INISettingCollection
Entry* next;
};

// TODO(FT): Setting a setting should be followed by SettingHandlerMap::SettingUpdated() call
Setting* GetSetting(const char* acpName) noexcept;

uint8_t unk0[0x118];
Expand Down
43 changes: 43 additions & 0 deletions Code/client/Services/Generic/DiscoveryService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <Events/CellChangeEvent.h>
#include <Events/LocationChangeEvent.h>
#include <Events/ConnectedEvent.h>
#include <Events/ConnectionErrorEvent.h>

#include <World.h>

Expand Down Expand Up @@ -250,12 +251,54 @@ void DiscoveryService::OnUpdate(const PreUpdateEvent& acUpdateEvent) noexcept

void DiscoveryService::OnConnected(const ConnectedEvent& acEvent) noexcept
{
// uGridsToLoad should always be 5, as this is what the server enforces
auto* pSetting = INISettingCollection::Get()->GetSetting("uGridsToLoad:General");
if (pSetting && pSetting->data != 5)
{
ConnectionErrorEvent errorEvent{};
errorEvent.ErrorDetail = "{\"error\": \"bad_uGridsToLoad\"}";

m_world.GetRunner().Trigger(errorEvent);
}

VisitCell(true);
}

BSTEventResult DiscoveryService::OnEvent(const TESLoadGameEvent*, const EventDispatcher<TESLoadGameEvent>*)
{
spdlog::info("Finished loading, triggering visit cell");

const TiltedPhoques::String defaultModlist[7] = {"Skyrim.esm", "Update.esm", "Dawnguard.esm",
"HearthFires.esm", "Dragonborn.esm", "_ResourcePack.esl",
"SkyrimTogether.esp"};

auto& currentModlist = ModManager::Get()->mods;

bool isModlistEqual = currentModlist.Size() == 7;

if (isModlistEqual)
{
int i = 0;
for (const auto& currentMod : currentModlist)
{
if (currentMod->filename != defaultModlist[i])
{
isModlistEqual = false;
break;
}

i++;
}
}

if (!isModlistEqual)
{
ConnectionErrorEvent errorEvent{};
errorEvent.ErrorDetail = "{\"error\": \"non_default_install\"}";

m_world.GetRunner().Trigger(errorEvent);
}

VisitCell(true);

return BSTEventResult::kOk;
Expand Down
Loading

0 comments on commit 6bc8861

Please sign in to comment.