mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-12 08:40:53 +01:00
Git: Añadido .gitignore y limpieza de archivos de compilación
This commit is contained in:
parent
88dd258cd7
commit
38c2dc701d
42 changed files with 41 additions and 2612 deletions
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
# --- Visual Studio ---
|
||||||
|
.vs/
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
*.user
|
||||||
|
*.aps
|
||||||
|
*.pdb
|
||||||
|
*.obj
|
||||||
|
*.log
|
||||||
|
*.tlog
|
||||||
|
*.lastbuildstate
|
||||||
|
*.idb
|
||||||
|
*.iobj
|
||||||
|
*.ipdb
|
||||||
|
*.ipch
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.suo
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.orig
|
||||||
|
*.db
|
||||||
|
*.opendb
|
||||||
|
|
||||||
|
# --- Archivos de compilación ---
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.lib
|
||||||
|
*.exp
|
||||||
|
*.ilk
|
||||||
|
|
||||||
|
# --- Archivos de sistema ---
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# --- F4MP Específico ---
|
||||||
|
# Ignorar logs que genera el mod al testearlo
|
||||||
|
F4MP.log
|
||||||
|
F4MP_Client.log
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"Version": 1,
|
|
||||||
"WorkspaceRootPath": "C:\\Users\\Jous\\Documents\\GitHub\\F4MP\\Client\\F4MP\\",
|
|
||||||
"Documents": [],
|
|
||||||
"DocumentGroupContainers": [
|
|
||||||
{
|
|
||||||
"Orientation": 0,
|
|
||||||
"VerticalTabListWidth": 256,
|
|
||||||
"DocumentGroups": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"Version": 1,
|
|
||||||
"WorkspaceRootPath": "C:\\Users\\Jous\\Documents\\GitHub\\F4MP\\Client\\F4MP\\",
|
|
||||||
"Documents": [],
|
|
||||||
"DocumentGroupContainers": [
|
|
||||||
{
|
|
||||||
"Orientation": 0,
|
|
||||||
"VerticalTabListWidth": 256,
|
|
||||||
"DocumentGroups": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup />
|
|
||||||
</Project>
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,446 +0,0 @@
|
||||||
#include <BranchInfo.h>
|
|
||||||
|
|
||||||
#include <Havok/hkbStateMachine.h>
|
|
||||||
#include <Structs/AnimationGraphDescriptorManager.h>
|
|
||||||
|
|
||||||
#include <Havok/BShkbAnimationGraph.h>
|
|
||||||
#include <Havok/BShkbHkxDB.h>
|
|
||||||
#include <Havok/hkbBehaviorGraph.h>
|
|
||||||
|
|
||||||
#include <Services/ImguiService.h>
|
|
||||||
#include <Services/DebugService.h>
|
|
||||||
#include <Services/TransportService.h>
|
|
||||||
#include <Services/PapyrusService.h>
|
|
||||||
#include <Services/QuestService.h>
|
|
||||||
|
|
||||||
#include <Events/UpdateEvent.h>
|
|
||||||
#include <Events/DialogueEvent.h>
|
|
||||||
#include <Events/SubtitleEvent.h>
|
|
||||||
#include <Events/MoveActorEvent.h>
|
|
||||||
#include <Events/ConnectionErrorEvent.h>
|
|
||||||
|
|
||||||
#include <Games/References.h>
|
|
||||||
|
|
||||||
#include <BSAnimationGraphManager.h>
|
|
||||||
#include <Forms/TESFaction.h>
|
|
||||||
#include <Forms/TESQuest.h>
|
|
||||||
|
|
||||||
#include <Forms/BGSAction.h>
|
|
||||||
#include <Forms/TESIdleForm.h>
|
|
||||||
#include <Forms/TESNPC.h>
|
|
||||||
#include <Games/Animation/ActorMediator.h>
|
|
||||||
#include <Games/Animation/TESActionData.h>
|
|
||||||
#include <Magic/ActorMagicCaster.h>
|
|
||||||
#include <Misc/BSFixedString.h>
|
|
||||||
#include <Structs/ActionEvent.h>
|
|
||||||
|
|
||||||
#include <Components.h>
|
|
||||||
#include <World.h>
|
|
||||||
|
|
||||||
#include <Forms/TESObjectCELL.h>
|
|
||||||
#include <Forms/TESWorldSpace.h>
|
|
||||||
#include <Games/TES.h>
|
|
||||||
|
|
||||||
#include <AI/AIProcess.h>
|
|
||||||
|
|
||||||
#include <Messages/RequestRespawn.h>
|
|
||||||
#include <Messages/PartyCreateRequest.h>
|
|
||||||
#include <Messages/PartyLeaveRequest.h>
|
|
||||||
|
|
||||||
#include <Games/Misc/SubtitleManager.h>
|
|
||||||
#include <Games/Overrides.h>
|
|
||||||
#include <OverlayApp.hpp>
|
|
||||||
|
|
||||||
#include <EquipManager.h>
|
|
||||||
#include <Forms/TESAmmo.h>
|
|
||||||
#include <BSGraphics/BSGraphicsRenderer.h>
|
|
||||||
#include <Interface/UI.h>
|
|
||||||
|
|
||||||
#include <Combat/CombatController.h>
|
|
||||||
#include <Camera/PlayerCamera.h>
|
|
||||||
#include <AI/Movement/PlayerControls.h>
|
|
||||||
#include <Interface/IMenu.h>
|
|
||||||
#include <Camera/PlayerCamera.h>
|
|
||||||
#include <DefaultObjectManager.h>
|
|
||||||
#include <Misc/InventoryEntry.h>
|
|
||||||
#include <Misc/MiddleProcess.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
extern thread_local bool g_overrideFormId;
|
|
||||||
|
|
||||||
constexpr char kBuildTag[] = "Build: " BUILD_COMMIT " " BUILD_BRANCH " EVO\nBuilt: " __TIMESTAMP__;
|
|
||||||
static void DrawBuildTag()
|
|
||||||
{
|
|
||||||
auto* pWindow = BSGraphics::GetMainWindow();
|
|
||||||
const ImVec2 coord{50.f, static_cast<float>((pWindow->uiWindowHeight + 25) - 100)};
|
|
||||||
ImGui::GetBackgroundDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize(), coord, ImColor::ImColor(255.f, 0.f, 0.f), kBuildTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __declspec(noinline) DebugService::PlaceActorInWorld() noexcept
|
|
||||||
{
|
|
||||||
if (m_actors.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto pPlayerBaseForm = static_cast<TESNPC*>(PlayerCharacter::Get()->baseForm);
|
|
||||||
|
|
||||||
auto pActor = Actor::Create(pPlayerBaseForm);
|
|
||||||
|
|
||||||
const Inventory inventory = PlayerCharacter::Get()->GetActorInventory();
|
|
||||||
pActor->SetActorInventory(inventory);
|
|
||||||
|
|
||||||
pActor->GetExtension()->SetPlayer(true);
|
|
||||||
|
|
||||||
m_actors.emplace_back(pActor);
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugService::DebugService(entt::dispatcher& aDispatcher, World& aWorld, TransportService& aTransport, ImguiService& aImguiService)
|
|
||||||
: m_dispatcher(aDispatcher)
|
|
||||||
, m_transport(aTransport)
|
|
||||||
, m_world(aWorld)
|
|
||||||
{
|
|
||||||
m_updateConnection = m_dispatcher.sink<UpdateEvent>().connect<&DebugService::OnUpdate>(this);
|
|
||||||
m_drawImGuiConnection = aImguiService.OnDraw.connect<&DebugService::OnDraw>(this);
|
|
||||||
m_dialogueConnection = m_dispatcher.sink<DialogueEvent>().connect<&DebugService::OnDialogue>(this);
|
|
||||||
m_dispatcher.sink<SubtitleEvent>().connect<&DebugService::OnSubtitle>(this);
|
|
||||||
m_dispatcher.sink<MoveActorEvent>().connect<&DebugService::OnMoveActor>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::OnDialogue(const DialogueEvent& acEvent) noexcept
|
|
||||||
{
|
|
||||||
if (ActorID)
|
|
||||||
return;
|
|
||||||
ActorID = acEvent.ActorID;
|
|
||||||
VoiceFile = acEvent.VoiceFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::OnSubtitle(const SubtitleEvent& acEvent) noexcept
|
|
||||||
{
|
|
||||||
if (SubActorID)
|
|
||||||
return;
|
|
||||||
SubActorID = acEvent.SpeakerID;
|
|
||||||
SubtitleText = acEvent.Text;
|
|
||||||
TopicID = acEvent.TopicFormID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: yeah, i'm aware of how dumb this looks, but things crash if
|
|
||||||
// you do it directly by adding an event to the queue, no symbols for tiltedcore when debugging,
|
|
||||||
// so this'll do for now
|
|
||||||
struct MoveData
|
|
||||||
{
|
|
||||||
Actor* pActor = nullptr;
|
|
||||||
TESObjectCELL* pCell = nullptr;
|
|
||||||
NiPoint3 position;
|
|
||||||
} moveData;
|
|
||||||
|
|
||||||
void DebugService::OnMoveActor(const MoveActorEvent& acEvent) noexcept
|
|
||||||
{
|
|
||||||
Actor* pActor = Cast<Actor>(TESForm::GetById(acEvent.FormId));
|
|
||||||
TESObjectCELL* pCell = Cast<TESObjectCELL>(TESForm::GetById(acEvent.CellId));
|
|
||||||
|
|
||||||
if (!pActor || !pCell)
|
|
||||||
return;
|
|
||||||
|
|
||||||
moveData.pActor = pActor;
|
|
||||||
moveData.pCell = pCell;
|
|
||||||
moveData.position = acEvent.Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern thread_local bool g_forceAnimation;
|
|
||||||
|
|
||||||
void DebugService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept
|
|
||||||
{
|
|
||||||
if (!BSGraphics::GetMainWindow()->IsForeground())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (moveData.pActor)
|
|
||||||
{
|
|
||||||
moveData.pActor->MoveTo(moveData.pCell, moveData.position);
|
|
||||||
moveData.pActor = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::atomic<bool> s_f8Pressed = false;
|
|
||||||
static std::atomic<bool> s_f7Pressed = false;
|
|
||||||
static std::atomic<bool> s_f6Pressed = false;
|
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_F3) & 0x01)
|
|
||||||
{
|
|
||||||
m_showDebugStuff = !m_showDebugStuff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (!IS_MASTER)
|
|
||||||
if (GetAsyncKeyState(VK_F6))
|
|
||||||
{
|
|
||||||
if (!s_f6Pressed)
|
|
||||||
{
|
|
||||||
s_f6Pressed = true;
|
|
||||||
|
|
||||||
static char s_address[256] = "127.0.0.1:10578";
|
|
||||||
if (!m_transport.IsOnline())
|
|
||||||
m_transport.Connect(s_address);
|
|
||||||
else
|
|
||||||
m_transport.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s_f6Pressed = false;
|
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_F7))
|
|
||||||
{
|
|
||||||
if (!s_f7Pressed)
|
|
||||||
{
|
|
||||||
s_f7Pressed = true;
|
|
||||||
|
|
||||||
if (!m_world.GetPartyService().IsInParty())
|
|
||||||
m_transport.Send(PartyCreateRequest{});
|
|
||||||
else
|
|
||||||
m_transport.Send(PartyLeaveRequest{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s_f7Pressed = false;
|
|
||||||
|
|
||||||
if (GetAsyncKeyState(VK_F8) & 0x01)
|
|
||||||
{
|
|
||||||
if (!s_f8Pressed)
|
|
||||||
{
|
|
||||||
s_f8Pressed = true;
|
|
||||||
|
|
||||||
//PlaceActorInWorld();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s_f8Pressed = false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool g_enableServerWindow{false};
|
|
||||||
static bool g_enableAnimWindow{false};
|
|
||||||
static bool g_enableEntitiesWindow{false};
|
|
||||||
static bool g_enableInventoryWindow{false};
|
|
||||||
static bool g_enableNetworkWindow{false};
|
|
||||||
static bool g_enableFormsWindow{false};
|
|
||||||
static bool g_enablePlayerWindow{false};
|
|
||||||
static bool g_enableSkillsWindow{false};
|
|
||||||
static bool g_enablePartyWindow{false};
|
|
||||||
static bool g_enableActorValuesWindow{false};
|
|
||||||
static bool g_enableQuestWindow{false};
|
|
||||||
static bool g_enableCellWindow{false};
|
|
||||||
static bool g_enableProcessesWindow{false};
|
|
||||||
static bool g_enableWeatherWindow{false};
|
|
||||||
static bool g_enableCombatWindow{false};
|
|
||||||
static bool g_enableCalendarWindow{false};
|
|
||||||
static bool g_enableDragonSpawnerWindow{false};
|
|
||||||
|
|
||||||
void DebugService::DrawServerView() noexcept
|
|
||||||
{
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver);
|
|
||||||
ImGui::Begin("Server");
|
|
||||||
|
|
||||||
static char s_address[1024] = "127.0.0.1:10578";
|
|
||||||
static char s_password[1024] = "";
|
|
||||||
ImGui::InputText("Address", s_address, std::size(s_address));
|
|
||||||
ImGui::InputText("Password", s_password, std::size(s_password));
|
|
||||||
|
|
||||||
if (m_transport.IsOnline())
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Disconnect"))
|
|
||||||
m_transport.Close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Connect"))
|
|
||||||
{
|
|
||||||
m_transport.SetServerPassword(s_password);
|
|
||||||
m_transport.Connect(s_address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::OnDraw() noexcept
|
|
||||||
{
|
|
||||||
const auto view = m_world.view<FormIdComponent>();
|
|
||||||
if (view.empty() || !m_showDebugStuff)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::BeginMainMenuBar();
|
|
||||||
if (ImGui::BeginMenu("Helpers"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Unstuck player"))
|
|
||||||
{
|
|
||||||
auto* pPlayer = PlayerCharacter::Get();
|
|
||||||
pPlayer->currentProcess->KnockExplosion(pPlayer, &pPlayer->position, 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Stop all combat"))
|
|
||||||
{
|
|
||||||
auto* pPlayer = PlayerCharacter::Get();
|
|
||||||
pPlayer->PayCrimeGoldToAllFactions();
|
|
||||||
|
|
||||||
ProcessLists* const pProcessLists = ProcessLists::Get();
|
|
||||||
if (pProcessLists)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < pProcessLists->highActorHandleArray.length; ++i)
|
|
||||||
{
|
|
||||||
Actor* const pRefr = Cast<Actor>(TESObjectREFR::GetByHandle(pProcessLists->highActorHandleArray[i]));
|
|
||||||
if (pRefr && pRefr->GetNiNode())
|
|
||||||
pRefr->StopCombat();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
#if (!IS_MASTER)
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Components"))
|
|
||||||
{
|
|
||||||
ImGui::MenuItem("Show selected entity in world", nullptr, &m_drawComponentsInWorldSpace);
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginMenu("UI"))
|
|
||||||
{
|
|
||||||
ImGui::MenuItem("Show build tag", nullptr, &m_showBuildTag);
|
|
||||||
if (ImGui::Button("Log all open windows"))
|
|
||||||
{
|
|
||||||
UI* pUI = UI::Get();
|
|
||||||
for (const auto& it : pUI->menuMap)
|
|
||||||
{
|
|
||||||
if (pUI->GetMenuOpen(it.key))
|
|
||||||
spdlog::info("{}", it.key.AsAscii());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Close all menus"))
|
|
||||||
{
|
|
||||||
UI::Get()->CloseAllMenus();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ImGui::BeginMenu("Debuggers"))
|
|
||||||
{
|
|
||||||
ImGui::MenuItem("Quests", nullptr, &g_enableQuestWindow);
|
|
||||||
ImGui::MenuItem("Entities", nullptr, &g_enableEntitiesWindow);
|
|
||||||
ImGui::MenuItem("Server", nullptr, &g_enableServerWindow);
|
|
||||||
ImGui::MenuItem("Party", nullptr, &g_enablePartyWindow);
|
|
||||||
ImGui::MenuItem("Dragon spawner", nullptr, &g_enableDragonSpawnerWindow);
|
|
||||||
|
|
||||||
#if (!IS_MASTER)
|
|
||||||
ImGui::MenuItem("Network", nullptr, &g_enableNetworkWindow);
|
|
||||||
ImGui::MenuItem("Forms", nullptr, &g_enableFormsWindow);
|
|
||||||
ImGui::MenuItem("Inventory", nullptr, &g_enableInventoryWindow);
|
|
||||||
ImGui::MenuItem("Animations", nullptr, &g_enableAnimWindow);
|
|
||||||
ImGui::MenuItem("Player", nullptr, &g_enablePlayerWindow);
|
|
||||||
ImGui::MenuItem("Skills", nullptr, &g_enableSkillsWindow);
|
|
||||||
ImGui::MenuItem("Cell", nullptr, &g_enableCellWindow);
|
|
||||||
ImGui::MenuItem("Processes", nullptr, &g_enableProcessesWindow);
|
|
||||||
ImGui::MenuItem("Weather", nullptr, &g_enableWeatherWindow);
|
|
||||||
ImGui::MenuItem("Combat", nullptr, &g_enableCombatWindow);
|
|
||||||
ImGui::MenuItem("Calendar", nullptr, &g_enableCalendarWindow);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginMenu("Misc"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Crash Client"))
|
|
||||||
{
|
|
||||||
#if (!IS_MASTER)
|
|
||||||
spdlog::error("Crash client");
|
|
||||||
int* m = 0;
|
|
||||||
*m = 1338;
|
|
||||||
#else
|
|
||||||
ConnectionErrorEvent errorEvent{};
|
|
||||||
errorEvent.ErrorDetail = "Skyrim Together never crashes ;) With love, Yamashi, Force, Dragonisser, Cosideci.";
|
|
||||||
|
|
||||||
m_world.GetRunner().Trigger(errorEvent);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
ImGui::EndMainMenuBar();
|
|
||||||
|
|
||||||
if (g_enableQuestWindow)
|
|
||||||
DrawQuestDebugView();
|
|
||||||
if (g_enableEntitiesWindow)
|
|
||||||
DrawEntitiesView();
|
|
||||||
if (g_enableServerWindow)
|
|
||||||
DrawServerView();
|
|
||||||
if (g_enablePartyWindow)
|
|
||||||
DrawPartyView();
|
|
||||||
if (g_enableDragonSpawnerWindow)
|
|
||||||
DrawDragonSpawnerView();
|
|
||||||
|
|
||||||
#if (!IS_MASTER)
|
|
||||||
if (g_enableNetworkWindow)
|
|
||||||
DrawNetworkView();
|
|
||||||
if (g_enableFormsWindow)
|
|
||||||
DrawFormDebugView();
|
|
||||||
if (g_enableInventoryWindow)
|
|
||||||
DrawContainerDebugView();
|
|
||||||
if (g_enableAnimWindow)
|
|
||||||
DrawAnimDebugView();
|
|
||||||
if (g_enablePlayerWindow)
|
|
||||||
DrawPlayerDebugView();
|
|
||||||
if (g_enableSkillsWindow)
|
|
||||||
DrawSkillView();
|
|
||||||
if (g_enableActorValuesWindow)
|
|
||||||
DrawActorValuesView();
|
|
||||||
if (g_enableCellWindow)
|
|
||||||
DrawCellView();
|
|
||||||
if (g_enableProcessesWindow)
|
|
||||||
DrawProcessView();
|
|
||||||
if (g_enableWeatherWindow)
|
|
||||||
DrawWeatherView();
|
|
||||||
if (g_enableCombatWindow)
|
|
||||||
DrawCombatView();
|
|
||||||
if (g_enableCalendarWindow)
|
|
||||||
DrawCalendarView();
|
|
||||||
|
|
||||||
if (m_drawComponentsInWorldSpace)
|
|
||||||
DrawComponentDebugView();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_showBuildTag)
|
|
||||||
DrawBuildTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::ArrangeGameWindows(HWND aThisWindow) noexcept
|
|
||||||
{
|
|
||||||
// This function conveniently arranges multiple game windows (multi-monitor window rearrangement is
|
|
||||||
// not implemented)
|
|
||||||
#if (!IS_MASTER)
|
|
||||||
const uint32_t screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
||||||
const uint32_t screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
|
||||||
RECT rect{};
|
|
||||||
GetWindowRect(aThisWindow, &rect);
|
|
||||||
const uint32_t gameWindowWidth = rect.right - rect.left;
|
|
||||||
const uint32_t gameWindowHeight = rect.bottom - rect.top;
|
|
||||||
|
|
||||||
const bool shouldArrangeWindows = (static_cast<float>(gameWindowWidth) / screenWidth) < 0.76f;
|
|
||||||
if (!shouldArrangeWindows)
|
|
||||||
return; // Too little room for that
|
|
||||||
|
|
||||||
SetWindowPos(GetConsoleWindow(), nullptr, 0, gameWindowHeight, 0, 0, SWP_NOSIZE);
|
|
||||||
|
|
||||||
CreateMutexA(0, FALSE, "SkyrimTogetherWindowMutex");
|
|
||||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
|
||||||
{
|
|
||||||
// One game instance is already open, arrange secondary game window...
|
|
||||||
const bool arrangeSideBySide = (static_cast<float>(gameWindowWidth) / screenWidth) <= 0.51f;
|
|
||||||
|
|
||||||
RECT conRect{};
|
|
||||||
GetWindowRect(GetConsoleWindow(), &conRect);
|
|
||||||
const uint32_t conY = arrangeSideBySide ? gameWindowHeight : 0;
|
|
||||||
const uint32_t conX = arrangeSideBySide ? (gameWindowWidth - 16) : screenWidth - (conRect.right - conRect.left);
|
|
||||||
SetWindowPos(GetConsoleWindow(), nullptr, conX, conY, 0, 0, SWP_NOSIZE);
|
|
||||||
|
|
||||||
const uint32_t x = arrangeSideBySide ? (gameWindowWidth - 16) : (screenWidth - gameWindowWidth);
|
|
||||||
const uint32_t y = arrangeSideBySide ? 0 : (screenHeight - gameWindowHeight - 48);
|
|
||||||
SetWindowPos(aThisWindow, nullptr, x, y, 0, 0, SWP_NOSIZE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <Forms/ActorValueInfo.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
void DebugService::DrawActorValuesView()
|
|
||||||
{
|
|
||||||
Actor* pActor = Cast<Actor>(TESForm::GetById(m_formId));
|
|
||||||
if (!pActor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::Begin("Actor values");
|
|
||||||
|
|
||||||
// for (int i = 0; i < ActorValueInfo::kActorValueCount; i++)
|
|
||||||
{
|
|
||||||
ActorValueOwner& actorValueOwner = pActor->actorValueOwner;
|
|
||||||
float health[3]{actorValueOwner.GetValue(24), actorValueOwner.GetBaseValue(24), actorValueOwner.GetPermanentValue(24)};
|
|
||||||
ImGui::InputFloat3("Health (val/base/perm)", health, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,408 +0,0 @@
|
||||||
#include <imgui.h>
|
|
||||||
#include <EquipManager.h>
|
|
||||||
#include <services/DebugService.h>
|
|
||||||
|
|
||||||
#include <Games/Skyrim/Forms/TESForm.h>
|
|
||||||
#include <Games/Skyrim/BSGraphics/BSGraphicsRenderer.h>
|
|
||||||
#include <Games/Skyrim/DefaultObjectManager.h>
|
|
||||||
#include <Games/Skyrim/Forms/TESAmmo.h>
|
|
||||||
#include <Games/Skyrim/Misc/InventoryEntry.h>
|
|
||||||
#include <Games/Skyrim/Misc/MiddleProcess.h>
|
|
||||||
|
|
||||||
#include <Games/ActorExtension.h>
|
|
||||||
|
|
||||||
#include <Actor.h>
|
|
||||||
|
|
||||||
#include <BSAnimationGraphManager.h>
|
|
||||||
#include <Havok/hkbStateMachine.h>
|
|
||||||
#include <Havok/BShkbAnimationGraph.h>
|
|
||||||
#include <Havok/BShkbHkxDB.h>
|
|
||||||
#include <Havok/hkbBehaviorGraph.h>
|
|
||||||
|
|
||||||
#include <structs/AnimationGraphDescriptorManager.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include <ModCompat/BehaviorVar.h>
|
|
||||||
|
|
||||||
uint64_t DisplayGraphDescriptorKey(BSAnimationGraphManager* pManager) noexcept
|
|
||||||
{
|
|
||||||
auto hash = pManager->GetDescriptorKey();
|
|
||||||
auto pDescriptor = AnimationGraphDescriptorManager::Get().GetDescriptor(hash);
|
|
||||||
|
|
||||||
spdlog::info("Key: {}", hash);
|
|
||||||
std::cout << "uint64_t key = " << hash << ";" << std::endl;
|
|
||||||
if (!pDescriptor)
|
|
||||||
spdlog::error("Descriptor key not found");
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DrawAnimDebugView()
|
|
||||||
{
|
|
||||||
static uint32_t fetchFormId = 0;
|
|
||||||
static Actor* pActor = nullptr;
|
|
||||||
static Map<uint32_t, uint32_t> s_values;
|
|
||||||
static Map<uint32_t, uint32_t> s_reusedValues;
|
|
||||||
static Map<uint32_t, short> s_valueTypes; // 0 for bool, 1 for float, 2 for int
|
|
||||||
static Vector<uint32_t> s_blacklist{};
|
|
||||||
static SortedMap<uint32_t, String> s_varMap{};
|
|
||||||
static Map<uint64_t, uint32_t> s_cachedKeys{};
|
|
||||||
|
|
||||||
ImGui::Begin("Animation debugging");
|
|
||||||
|
|
||||||
ImGui::InputScalar("Form ID", ImGuiDataType_U32, &fetchFormId, 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
if (ImGui::Button("Look up"))
|
|
||||||
{
|
|
||||||
if (fetchFormId)
|
|
||||||
{
|
|
||||||
auto* pFetchForm = TESForm::GetById(fetchFormId);
|
|
||||||
if (pFetchForm)
|
|
||||||
pActor = Cast<Actor>(pFetchForm);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_values.clear();
|
|
||||||
s_reusedValues.clear();
|
|
||||||
s_valueTypes.clear();
|
|
||||||
s_blacklist.clear();
|
|
||||||
s_varMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pActor)
|
|
||||||
{
|
|
||||||
ImGui::End();
|
|
||||||
s_varMap.clear();
|
|
||||||
s_values.clear();
|
|
||||||
s_reusedValues.clear();
|
|
||||||
s_valueTypes.clear();
|
|
||||||
s_blacklist.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Show cached hash"))
|
|
||||||
{
|
|
||||||
spdlog::info("{}", pActor->GetExtension()->GraphDescriptorHash);
|
|
||||||
BehaviorVar::Get()->Debug();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Clear all"))
|
|
||||||
{
|
|
||||||
s_varMap.clear();
|
|
||||||
s_values.clear();
|
|
||||||
s_reusedValues.clear();
|
|
||||||
s_valueTypes.clear();
|
|
||||||
s_blacklist.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
BSAnimationGraphManager* pManager = nullptr;
|
|
||||||
pActor->animationGraphHolder.GetBSAnimationGraph(&pManager);
|
|
||||||
|
|
||||||
if (!pManager)
|
|
||||||
{
|
|
||||||
ImGui::End();
|
|
||||||
s_varMap.clear();
|
|
||||||
s_values.clear();
|
|
||||||
s_reusedValues.clear();
|
|
||||||
s_valueTypes.clear();
|
|
||||||
s_blacklist.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto pGraph = pManager->animationGraphs.Get(pManager->animationGraphIndex);
|
|
||||||
|
|
||||||
if (!pGraph)
|
|
||||||
{
|
|
||||||
ImGui::End();
|
|
||||||
s_varMap.clear();
|
|
||||||
s_values.clear();
|
|
||||||
s_reusedValues.clear();
|
|
||||||
s_valueTypes.clear();
|
|
||||||
s_blacklist.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_varMap.empty())
|
|
||||||
{
|
|
||||||
s_varMap = pManager->DumpAnimationVariables(true);
|
|
||||||
|
|
||||||
auto hash = DisplayGraphDescriptorKey(pManager);
|
|
||||||
|
|
||||||
if (s_cachedKeys.find(hash) != std::end(s_cachedKeys))
|
|
||||||
spdlog::warn("Key was detected before! Form ID of last detected actor: {:X}", s_cachedKeys[hash]);
|
|
||||||
s_cachedKeys[hash] = pActor->formID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Revert animation graph"))
|
|
||||||
{
|
|
||||||
spdlog::info("RevertAnimationGraphManager success? {}",
|
|
||||||
pActor->animationGraphHolder.RevertAnimationGraphManager());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
|
|
||||||
{
|
|
||||||
if (ImGui::BeginTabItem("Variables"))
|
|
||||||
{
|
|
||||||
auto hash = pManager->GetDescriptorKey();
|
|
||||||
auto pDescriptor = AnimationGraphDescriptorManager::Get().GetDescriptor(hash);
|
|
||||||
if (pDescriptor)
|
|
||||||
{
|
|
||||||
const auto* pVariableSet = pGraph->behaviorGraph->animationVariables;
|
|
||||||
|
|
||||||
Map<String, bool> bools{};
|
|
||||||
Map<String, float> floats{};
|
|
||||||
Map<String, int> ints{};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < pDescriptor->BooleanLookUpTable.size(); ++i)
|
|
||||||
{
|
|
||||||
const auto idx = pDescriptor->BooleanLookUpTable[i];
|
|
||||||
bools[s_varMap[idx]] = *reinterpret_cast<bool*>(&pVariableSet->data[idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < pDescriptor->FloatLookupTable.size(); ++i)
|
|
||||||
{
|
|
||||||
const auto idx = pDescriptor->FloatLookupTable[i];
|
|
||||||
floats[s_varMap[idx]] = *reinterpret_cast<float*>(&pVariableSet->data[idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < pDescriptor->IntegerLookupTable.size(); ++i)
|
|
||||||
{
|
|
||||||
const auto idx = pDescriptor->IntegerLookupTable[i];
|
|
||||||
ints[s_varMap[idx]] = *reinterpret_cast<int*>(&pVariableSet->data[idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Dump variable values"))
|
|
||||||
{
|
|
||||||
std::cout << "Bools: " << std::endl;
|
|
||||||
for (auto& [name, value] : bools)
|
|
||||||
{
|
|
||||||
std::cout << "\t" << name << ": " << value << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Floats: " << std::endl;
|
|
||||||
for (auto& [name, value] : floats)
|
|
||||||
{
|
|
||||||
std::cout << "\t" << name << ": " << value << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Integers: " << std::endl;
|
|
||||||
for (auto& [name, value] : ints)
|
|
||||||
{
|
|
||||||
std::cout << "\t" << name << ": " << value << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Bools", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
{
|
|
||||||
for (auto pair : bools)
|
|
||||||
{
|
|
||||||
auto name = pair.first;
|
|
||||||
auto value = pair.second;
|
|
||||||
int iValue = int(value);
|
|
||||||
ImGui::InputInt(name.c_str(), &iValue, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Floats", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
{
|
|
||||||
for (auto pair : floats)
|
|
||||||
{
|
|
||||||
auto name = pair.first;
|
|
||||||
auto value = pair.second;
|
|
||||||
ImGui::InputFloat(name.c_str(), &value, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Integers", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
{
|
|
||||||
for (auto pair : ints)
|
|
||||||
{
|
|
||||||
auto name = pair.first;
|
|
||||||
auto value = pair.second;
|
|
||||||
ImGui::InputInt(name.c_str(), &value, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginTabItem("Blacklist"))
|
|
||||||
{
|
|
||||||
static uint32_t s_selectedBlacklistVar = 0;
|
|
||||||
static uint32_t s_selected = 0;
|
|
||||||
|
|
||||||
ImGui::BeginChild("Blacklisted variables");
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto blacklistedVar : s_blacklist)
|
|
||||||
{
|
|
||||||
if (blacklistedVar >= pGraph->behaviorGraph->animationVariables->size)
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto varName = s_varMap[blacklistedVar];
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
sprintf_s(name, std::size(name), "k%s (%d)", varName.c_str(), blacklistedVar);
|
|
||||||
|
|
||||||
if (ImGui::Selectable(name, s_selectedBlacklistVar == blacklistedVar))
|
|
||||||
{
|
|
||||||
s_selectedBlacklistVar = blacklistedVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_selectedBlacklistVar == blacklistedVar)
|
|
||||||
{
|
|
||||||
s_selected = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndChild();
|
|
||||||
|
|
||||||
if (s_selected < s_blacklist.size())
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Delete"))
|
|
||||||
{
|
|
||||||
s_blacklist.erase(s_blacklist.begin() + s_selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t s_blacklistVar = 0;
|
|
||||||
ImGui::InputInt("New blacklist var:", (int*)&s_blacklistVar, 0, 0);
|
|
||||||
|
|
||||||
if (ImGui::Button("Add"))
|
|
||||||
{
|
|
||||||
s_blacklist.push_back(s_blacklistVar);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginTabItem("Control"))
|
|
||||||
{
|
|
||||||
ImGui::InputInt("Animation graph count", (int*)&pManager->animationGraphs.size, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputInt("Animation graph index", (int*)&pManager->animationGraphIndex, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
sprintf_s(name, std::size(name), "%s", pGraph->behaviorGraph->stateMachine->name);
|
|
||||||
ImGui::InputText("Graph state machine name", name, std::size(name), ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
const auto pVariableSet = pGraph->behaviorGraph->animationVariables;
|
|
||||||
|
|
||||||
auto pDescriptor = AnimationGraphDescriptorManager::Get().GetDescriptor(pManager->GetDescriptorKey());
|
|
||||||
|
|
||||||
static bool toggleVariableRecord = false;
|
|
||||||
if (ImGui::Button("Toggle variable recording"))
|
|
||||||
{
|
|
||||||
toggleVariableRecord = !toggleVariableRecord;
|
|
||||||
spdlog::info("Toggle variable recording: {}", toggleVariableRecord);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pVariableSet && toggleVariableRecord)
|
|
||||||
{
|
|
||||||
for (auto i = 0u; i < pVariableSet->size; ++i)
|
|
||||||
{
|
|
||||||
if (std::find(s_blacklist.begin(), s_blacklist.end(), i) != s_blacklist.end())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pDescriptor && pDescriptor->IsSynced(i))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto iter = s_values.find(i);
|
|
||||||
if (iter == std::end(s_values))
|
|
||||||
{
|
|
||||||
s_values[i] = pVariableSet->data[i];
|
|
||||||
|
|
||||||
const auto varName = s_varMap[i];
|
|
||||||
|
|
||||||
spdlog::info("Variable k{} ({}) initialized to f: {} i: {}", varName, i, *(float*)&pVariableSet->data[i], *(int32_t*)&pVariableSet->data[i]);
|
|
||||||
}
|
|
||||||
else if (iter->second != pVariableSet->data[i])
|
|
||||||
{
|
|
||||||
const auto varName = s_varMap[i];
|
|
||||||
|
|
||||||
float floatCast = *(float*)&pVariableSet->data[i];
|
|
||||||
int intCast = *(int32_t*)&pVariableSet->data[i];
|
|
||||||
spdlog::warn("Variable k{} ({}) changed to f: {} i: {}", varName, i, floatCast, intCast);
|
|
||||||
|
|
||||||
s_values[i] = pVariableSet->data[i];
|
|
||||||
s_reusedValues[i] = pVariableSet->data[i];
|
|
||||||
|
|
||||||
char varTypeChar = varName[0]; // for guessing type, to see if u can find type char (i, f, b)
|
|
||||||
if (varTypeChar == 'f')
|
|
||||||
{
|
|
||||||
s_valueTypes[i] = 1;
|
|
||||||
}
|
|
||||||
else if (varTypeChar == 'i' && varName[1] != 's')
|
|
||||||
{
|
|
||||||
s_valueTypes[i] = 2;
|
|
||||||
}
|
|
||||||
else if (varTypeChar != 'b' && s_valueTypes[i] != 1) // no char hint to go off of and not assuming float
|
|
||||||
{
|
|
||||||
if (intCast > 1000 || intCast < -1000) // arbitrary int threshold
|
|
||||||
{
|
|
||||||
s_valueTypes[i] = 1; // assume float
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (intCast > 1 || intCast < 0)
|
|
||||||
{
|
|
||||||
s_valueTypes[i] = 2; // assume int
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Dump variables") && pVariableSet)
|
|
||||||
{
|
|
||||||
// kinda ugly to iterate 3 times but idc cuz its just for debugging and its a small collection
|
|
||||||
// BOOLS
|
|
||||||
std::cout << "{" << std::endl;
|
|
||||||
for (auto& [key, value] : s_reusedValues)
|
|
||||||
{
|
|
||||||
if (s_valueTypes[key] == 0)
|
|
||||||
{
|
|
||||||
const auto varName = s_varMap[key];
|
|
||||||
std::cout << "k" << varName << "," << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// FLOATS
|
|
||||||
std::cout << "}," << std::endl << "{" << std::endl;
|
|
||||||
for (auto& [key, value] : s_reusedValues)
|
|
||||||
{
|
|
||||||
if (s_valueTypes[key] == 1)
|
|
||||||
{
|
|
||||||
const auto varName = s_varMap[key];
|
|
||||||
std::cout << "k" << varName << "," << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// INTS
|
|
||||||
std::cout << "}," << std::endl << "{" << std::endl;
|
|
||||||
for (auto& [key, value] : s_reusedValues)
|
|
||||||
{
|
|
||||||
if (s_valueTypes[key] == 2)
|
|
||||||
{
|
|
||||||
const auto varName = s_varMap[key];
|
|
||||||
std::cout << "k" << varName << "," << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "}" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Reset recording"))
|
|
||||||
{
|
|
||||||
s_values.clear();
|
|
||||||
s_reusedValues.clear();
|
|
||||||
spdlog::info("Variable recording has been reset");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include <TimeManager.h>
|
|
||||||
|
|
||||||
void DebugService::DrawCalendarView()
|
|
||||||
{
|
|
||||||
ImGui::Begin("Calendar");
|
|
||||||
|
|
||||||
auto* pGameTime = TimeData::Get();
|
|
||||||
|
|
||||||
auto year = pGameTime->GameYear->f;
|
|
||||||
ImGui::InputFloat("Year", &year, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
auto month = pGameTime->GameMonth->f;
|
|
||||||
ImGui::InputFloat("Month", &month, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
auto day = pGameTime->GameDay->f;
|
|
||||||
ImGui::InputFloat("Day", &day, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
auto hour = pGameTime->GameHour->f;
|
|
||||||
ImGui::InputFloat("Hour", &hour, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
auto passed = pGameTime->GameDaysPassed->f;
|
|
||||||
ImGui::InputFloat("Passed", &passed, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
auto scale = pGameTime->TimeScale->f;
|
|
||||||
ImGui::InputFloat("Scale", &scale, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <Games/TES.h>
|
|
||||||
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
|
|
||||||
#include <Forms/TESObjectCELL.h>
|
|
||||||
#include <Forms/TESWorldSpace.h>
|
|
||||||
|
|
||||||
void DebugService::DrawCellView()
|
|
||||||
{
|
|
||||||
ImGui::Begin("Cell");
|
|
||||||
|
|
||||||
PlayerCharacter* pPlayer = PlayerCharacter::Get();
|
|
||||||
|
|
||||||
if (auto* pWorldSpace = pPlayer->GetWorldSpace())
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("World space", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
{
|
|
||||||
const uint32_t worldFormId = pWorldSpace->formID;
|
|
||||||
ImGui::InputScalar("Id", ImGuiDataType_U32, (void*)&worldFormId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
char* pName = (char*)pWorldSpace->GetName();
|
|
||||||
size_t nameLen = strlen(pName);
|
|
||||||
ImGui::InputText("Name", pName, nameLen, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
char* pEditorId = (char*)pWorldSpace->GetFormEditorID();
|
|
||||||
size_t editorIdLen = strlen(pEditorId);
|
|
||||||
ImGui::InputText("Editor ID", pEditorId, editorIdLen, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pCell = pPlayer->parentCell)
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("Parent cell", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
{
|
|
||||||
const uint32_t cellId = pCell->formID;
|
|
||||||
ImGui::InputScalar("Id", ImGuiDataType_U32, (void*)&cellId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
char* pName = (char*)pCell->GetName();
|
|
||||||
size_t nameLen = strlen(pName);
|
|
||||||
ImGui::InputText("Name", pName, nameLen, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
char* pEditorId = (char*)pCell->GetFormEditorID();
|
|
||||||
size_t editorIdLen = strlen(pEditorId);
|
|
||||||
ImGui::InputText("Editor ID", pEditorId, editorIdLen, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,225 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include <Combat/CombatController.h>
|
|
||||||
#include <Combat/CombatGroup.h>
|
|
||||||
#include <Combat/CombatTargetSelector.h>
|
|
||||||
#include <Games/Misc/BGSWorldLocation.h>
|
|
||||||
#include <Combat/CombatInventory.h>
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct DetectionState : public NiRefObject
|
|
||||||
{
|
|
||||||
~DetectionState() override;
|
|
||||||
|
|
||||||
uint32_t level;
|
|
||||||
uint8_t unk14;
|
|
||||||
uint8_t unk15;
|
|
||||||
uint8_t unk16;
|
|
||||||
uint8_t pad17;
|
|
||||||
float unk18;
|
|
||||||
NiPoint3 unk1C;
|
|
||||||
float unk28;
|
|
||||||
NiPoint3 unk2C;
|
|
||||||
float unk38;
|
|
||||||
NiPoint3 unk3C;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(DetectionState) == 0x48);
|
|
||||||
|
|
||||||
BGSEncounterZone* GetLocationEncounterZone(Actor* apActor)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TGetLocationEncounterZone, BGSEncounterZone*, Actor);
|
|
||||||
POINTER_SKYRIMSE(TGetLocationEncounterZone, getLocationEncounterZone, 20203);
|
|
||||||
return TiltedPhoques::ThisCall(getLocationEncounterZone, apActor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidTarget(CombatTargetSelector* apThis, Actor* apAttacker, Actor* apTarget, BGSEncounterZone* apEncounterZone)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TIsValidTarget, bool, CombatTargetSelector, Actor* apAttacker, Actor* apTarget,
|
|
||||||
BGSEncounterZone* apEncounterZone);
|
|
||||||
POINTER_SKYRIMSE(TIsValidTarget, isValidTarget, 47196);
|
|
||||||
return TiltedPhoques::ThisCall(isValidTarget, apThis, apAttacker, apTarget, apEncounterZone);
|
|
||||||
}
|
|
||||||
|
|
||||||
DetectionState* GetDetectionState(Actor* apAttacker, Actor* apTarget)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TGetDetectionState, DetectionState*, Actor, Actor* apTarget);
|
|
||||||
POINTER_SKYRIMSE(TGetDetectionState, getDetectionState, 37757);
|
|
||||||
return TiltedPhoques::ThisCall(getDetectionState, apAttacker, apTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetCombatTargetSelectorDetectionTimeLimit()
|
|
||||||
{
|
|
||||||
POINTER_SKYRIMSE(float, s_value, 382393);
|
|
||||||
return *s_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetCombatTargetSelectorRecentLOSTimeLimit()
|
|
||||||
{
|
|
||||||
POINTER_SKYRIMSE(float, s_value, 382400);
|
|
||||||
return *s_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ActorHasEquippedRangedWeapon_m(Actor* apActor)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TActorHasEquippedRangedWeapon_m, bool, Actor);
|
|
||||||
POINTER_SKYRIMSE(TActorHasEquippedRangedWeapon_m, actorHasEquippedRangedWeapon_m, 47303);
|
|
||||||
return TiltedPhoques::ThisCall(actorHasEquippedRangedWeapon_m, apActor);
|
|
||||||
}
|
|
||||||
|
|
||||||
BGSWorldLocation* RefrGetWorldLocation(TESObjectREFR* apThis, BGSWorldLocation* apResult)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TRefrGetWorldLocation, BGSWorldLocation*, TESObjectREFR, BGSWorldLocation*);
|
|
||||||
POINTER_SKYRIMSE(TRefrGetWorldLocation, refrGetWorldLocation, 19784);
|
|
||||||
return TiltedPhoques::ThisCall(refrGetWorldLocation, apThis, apResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetModifiedDistance(BGSWorldLocation* apThis, BGSWorldLocation* apWorldLocation)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TGetModifiedDistance, float, BGSWorldLocation, BGSWorldLocation*);
|
|
||||||
POINTER_SKYRIMSE(TGetModifiedDistance, getModifiedDistance, 18518);
|
|
||||||
return TiltedPhoques::ThisCall(getModifiedDistance, apThis, apWorldLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetDword_142FE5B78()
|
|
||||||
{
|
|
||||||
POINTER_SKYRIMSE(float, s_value, 405282);
|
|
||||||
return *s_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckMovement(CombatController* apThis, BGSWorldLocation* apWorldLocation)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TCheckMovement, bool, CombatController, BGSWorldLocation*);
|
|
||||||
POINTER_SKYRIMSE(TCheckMovement, checkMovement, 33261);
|
|
||||||
return TiltedPhoques::ThisCall(checkMovement, apThis, apWorldLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sub_1407E7A40(Actor* apThis, BGSWorldLocation* apWorldLocation)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TFunc, bool, Actor, BGSWorldLocation*);
|
|
||||||
POINTER_SKYRIMSE(TFunc, func, 47307);
|
|
||||||
return TiltedPhoques::ThisCall(func, apThis, apWorldLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsFleeing(Actor* apThis)
|
|
||||||
{
|
|
||||||
TP_THIS_FUNCTION(TFunc, bool, Actor);
|
|
||||||
POINTER_SKYRIMSE(TFunc, func, 37577);
|
|
||||||
return TiltedPhoques::ThisCall(func, apThis);
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalculateTargetScore(CombatTargetSelector* apThis, CombatTarget* apCombatTarget, Actor* apAttacker, Actor* apTarget, BGSEncounterZone* apEncounterZone)
|
|
||||||
{
|
|
||||||
float score = 0.f;
|
|
||||||
|
|
||||||
CombatController* pCombatController = apThis->pCombatController;
|
|
||||||
Actor* pCachedAttacker = pCombatController->pCachedAttacker.object;
|
|
||||||
|
|
||||||
BGSWorldLocation pAttackerWorldLocation{};
|
|
||||||
RefrGetWorldLocation(apAttacker, &pAttackerWorldLocation);
|
|
||||||
BGSWorldLocation pTargetWorldLocation{};
|
|
||||||
RefrGetWorldLocation(apTarget, &pTargetWorldLocation);
|
|
||||||
|
|
||||||
float aiTime = AITimer::GetAITime();
|
|
||||||
|
|
||||||
auto* pDetectionState = GetDetectionState(apAttacker, apTarget);
|
|
||||||
if (pDetectionState && (aiTime - pDetectionState->unk38) <= GetCombatTargetSelectorDetectionTimeLimit())
|
|
||||||
{
|
|
||||||
if (pDetectionState->unk15)
|
|
||||||
score = 1000.f;
|
|
||||||
else if (pCachedAttacker == apTarget &&
|
|
||||||
(aiTime - pDetectionState->unk18) < GetCombatTargetSelectorRecentLOSTimeLimit())
|
|
||||||
score = 1000.f;
|
|
||||||
|
|
||||||
if (pDetectionState->unk14)
|
|
||||||
score += 100.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pCachedAttacker == apTarget)
|
|
||||||
score += 100.f;
|
|
||||||
|
|
||||||
if (ActorHasEquippedRangedWeapon_m(apAttacker) == ActorHasEquippedRangedWeapon_m(apTarget))
|
|
||||||
score += 100.f;
|
|
||||||
|
|
||||||
bool isSameWorldLocation = pTargetWorldLocation.pSpace == pAttackerWorldLocation.pSpace;
|
|
||||||
float distanceFactor = 0.f;
|
|
||||||
if (isSameWorldLocation)
|
|
||||||
distanceFactor = GetModifiedDistance(&pAttackerWorldLocation, &pTargetWorldLocation);
|
|
||||||
else if (apTarget != pCachedAttacker)
|
|
||||||
distanceFactor = 2048.f;
|
|
||||||
|
|
||||||
score += (float)((float)(1.0 - (float)(fminf(distanceFactor, 2048.f) * 0.00048828125f)) * 1000.f);
|
|
||||||
|
|
||||||
if (apCombatTarget->attackerCount > (pCachedAttacker == apTarget))
|
|
||||||
score += GetDword_142FE5B78();
|
|
||||||
|
|
||||||
if (pCombatController->pInventory->maximumRange < 1024.f || !isSameWorldLocation)
|
|
||||||
{
|
|
||||||
if (!CheckMovement(pCombatController, &pTargetWorldLocation))
|
|
||||||
score -= 2000.f;
|
|
||||||
if (!isSameWorldLocation && !sub_1407E7A40(apAttacker, &pTargetWorldLocation))
|
|
||||||
score -= 2500.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apTarget->VirtIsDead(false))
|
|
||||||
score -= 500.f;
|
|
||||||
|
|
||||||
if (IsFleeing(apTarget))
|
|
||||||
score -= 500.f;
|
|
||||||
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void DebugService::DrawCombatView()
|
|
||||||
{
|
|
||||||
if (!m_formId)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::Begin("Combat");
|
|
||||||
|
|
||||||
ImGui::InputScalar("Form ID", ImGuiDataType_U32, (void*)&m_formId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
Actor* pActor = Cast<Actor>(TESForm::GetById(m_formId));
|
|
||||||
|
|
||||||
if (pActor && pActor->pCombatController && pActor->pCombatController->pCombatGroup && pActor->pCombatController->pActiveTargetSelector)
|
|
||||||
{
|
|
||||||
Actor* pTarget = Cast<Actor>(TESObjectREFR::GetByHandle(pActor->pCombatController->targetHandle));
|
|
||||||
if (pTarget)
|
|
||||||
{
|
|
||||||
uint32_t targetFormID = pTarget->formID;
|
|
||||||
ImGui::InputScalar("Current target ID", ImGuiDataType_U32, (void*)&targetFormID, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
|
|
||||||
BGSEncounterZone* pZone = GetLocationEncounterZone(pActor);
|
|
||||||
|
|
||||||
ImGui::BeginChild("Potential targets", ImVec2(0, 200), true);
|
|
||||||
|
|
||||||
auto& targets = pActor->pCombatController->pCombatGroup->targets;
|
|
||||||
for (int i = 0; i < targets.length; i++)
|
|
||||||
{
|
|
||||||
auto& target = targets[i];
|
|
||||||
Actor* pTarget = Cast<Actor>(TESObjectREFR::GetByHandle(target.targetHandle));
|
|
||||||
if (pTarget)
|
|
||||||
{
|
|
||||||
const uint32_t formID = pTarget->formID;
|
|
||||||
ImGui::InputScalar("Form ID", ImGuiDataType_U32, (void*)&formID, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
float score =
|
|
||||||
CalculateTargetScore(pActor->pCombatController->pActiveTargetSelector, &target, pActor, pTarget, pZone);
|
|
||||||
|
|
||||||
ImGui::InputFloat("Score", &score, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,202 +0,0 @@
|
||||||
#include <Components.h>
|
|
||||||
#include <World.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <Services/DebugService.h>
|
|
||||||
#include <Systems/AnimationSystem.h>
|
|
||||||
|
|
||||||
#include <BSGraphics/BSGraphicsRenderer.h>
|
|
||||||
#include <Camera/PlayerCamera.h>
|
|
||||||
#include <Games/Skyrim/Forms/TESForm.h>
|
|
||||||
#include <Games/Skyrim/Interface/Menus/HUDMenuUtils.h>
|
|
||||||
#include <Games/Skyrim/NetImmerse/NiCamera.h>
|
|
||||||
#include <Games/Skyrim/TESObjectREFR.h>
|
|
||||||
#include <NetImmerse/NiCamera.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
constexpr float fFloatQuestMarkerMaxDistance = 2000.f;
|
|
||||||
constexpr float fFloatQuestMarkerMinDistance = 1000.f;
|
|
||||||
|
|
||||||
float CalculateFloatingQuestMarkerAlpha()
|
|
||||||
{
|
|
||||||
float v1 = fsqrt((__m128)LODWORD(this->fDistanceToPlayerSqr)).m128_f32[0] -
|
|
||||||
fFloatQuestMarkerMaxDistance) /
|
|
||||||
(fFloatQuestMarkerMinDistance - fFloatQuestMarkerMaxDistance)) * 100.0;
|
|
||||||
if (v1 > 100.0)
|
|
||||||
return FLOAT_100_0;
|
|
||||||
result = 0.0;
|
|
||||||
if (v1 >= 0.0)
|
|
||||||
return v1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __declspec(noinline) bool DrawInWorldSpace(TESObjectREFR* apRefr, ImVec2& outViewPos)
|
|
||||||
{
|
|
||||||
// Attach at the head ish.
|
|
||||||
auto pos = apRefr->position;
|
|
||||||
pos.z += apRefr->GetHeight();
|
|
||||||
|
|
||||||
NiPoint3 screenPoint{};
|
|
||||||
HUDMenuUtils::WorldPtToScreenPt3(pos, screenPoint);
|
|
||||||
// Calculate window collision bounds.
|
|
||||||
auto* pViewport = BSGraphics::GetMainWindow();
|
|
||||||
|
|
||||||
// Translate to screen
|
|
||||||
const ImVec2 screenPos = ImVec2{
|
|
||||||
(pViewport->uiWindowWidth * screenPoint.x),
|
|
||||||
(pViewport->uiWindowHeight * (1.0f - screenPoint.y)),
|
|
||||||
};
|
|
||||||
|
|
||||||
const ImVec2 windowSize = {
|
|
||||||
static_cast<float>(pViewport->uiWindowWidth),
|
|
||||||
static_cast<float>(pViewport->uiWindowHeight),
|
|
||||||
};
|
|
||||||
|
|
||||||
auto IsVisible = [](const ImVec2& acVec2, const ImVec2& acScreenSize, float z) {
|
|
||||||
return (acVec2.x > 0 && acVec2.x <= acScreenSize.x) &&
|
|
||||||
(acVec2.y > 0 && acVec2.y <= acScreenSize.y) && z >= 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (IsVisible(screenPos, windowSize, screenPoint.z))
|
|
||||||
{
|
|
||||||
outViewPos = screenPos;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
outViewPos = {};
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// TODO(Force): Net Histrogram (waves)
|
|
||||||
// Engine stuff.
|
|
||||||
// Fix cursor.
|
|
||||||
|
|
||||||
void DebugService::SetDebugId(const uint32_t aFormId) noexcept
|
|
||||||
{
|
|
||||||
m_formId = aFormId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DrawComponentDebugView()
|
|
||||||
{
|
|
||||||
auto view = m_world.view<FormIdComponent>();
|
|
||||||
|
|
||||||
if (!m_formId)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto entityIt = std::find_if(view.begin(), view.end(), [id = m_formId, view](auto entity) { return view.get<FormIdComponent>(entity).Id == id; });
|
|
||||||
|
|
||||||
if (entityIt == view.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto entity = *entityIt;
|
|
||||||
|
|
||||||
if (auto* pObject = Cast<TESObjectREFR>(TESForm::GetById(m_formId)))
|
|
||||||
{
|
|
||||||
ImVec2 screenPos{};
|
|
||||||
if (DrawInWorldSpace(pObject, screenPos))
|
|
||||||
{
|
|
||||||
ImGui::SetNextWindowPos(screenPos);
|
|
||||||
ImGui::Begin("Component debug");
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<ReplayedActionsDebugComponent>(entity))
|
|
||||||
{
|
|
||||||
DisplayListOfReplayedActions(*pComponent, m_world.try_get<RemoteAnimationComponent>(entity));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto serverIdRes = Utils::GetServerId(entity))
|
|
||||||
{
|
|
||||||
ImGui::InputScalar("Server ID", ImGuiDataType_U32, &(*serverIdRes), 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<LocalComponent>(entity))
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("LocalComponent"))
|
|
||||||
{
|
|
||||||
ImGui::InputScalar("Is dead?", ImGuiDataType_U8, &pComponent->IsDead, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<LocalAnimationComponent>(entity))
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("LocalAnimationComponent"))
|
|
||||||
{
|
|
||||||
int actions = int(pComponent->Actions.size());
|
|
||||||
ImGui::InputInt("Number of actions", &actions, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<RemoteComponent>(entity))
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("RemoteComponent"))
|
|
||||||
{
|
|
||||||
ImGui::InputScalar("Cached ref ID", ImGuiDataType_U32, &pComponent->CachedRefId, 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<InterpolationComponent>(entity))
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("InterpolationComponent"))
|
|
||||||
{
|
|
||||||
ImGui::Text("%f,%f,%f\n", pComponent->Position.x, pComponent->Position.y, pComponent->Position.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<FaceGenComponent>(entity))
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("FaceGenComponent"))
|
|
||||||
{
|
|
||||||
for (auto x : pComponent->FaceTints.Entries)
|
|
||||||
{
|
|
||||||
ImGui::Text("Alpha %f, Color %u, Type %u\n", x.Alpha, x.Color, x.Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pComponent = m_world.try_get<RemoteAnimationComponent>(entity))
|
|
||||||
{
|
|
||||||
if (ImGui::CollapsingHeader("RemoteAnimationComponent"))
|
|
||||||
{
|
|
||||||
ImGui::Text("EventName: %s\nTargetEventName: %s\nState1: %u\nState2: %u", pComponent->LastRanAction.EventName.c_str(), pComponent->LastRanAction.TargetEventName.c_str(), pComponent->LastRanAction.State1, pComponent->LastRanAction.State2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayListOfReplayedActions(const ReplayedActionsDebugComponent& aDebugComponent,
|
|
||||||
RemoteAnimationComponent* apAnimationComponent) const noexcept
|
|
||||||
{
|
|
||||||
const size_t total = aDebugComponent.ActionsReceivedForReplay.Actions.size();
|
|
||||||
const auto header = fmt::format("List of Replayed Actions ({})", total);
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
{
|
|
||||||
String replayedActionsText;
|
|
||||||
if (aDebugComponent.ActionsReceivedForReplay.ResetAnimationGraph)
|
|
||||||
replayedActionsText += "<Animation graph reset>, ";
|
|
||||||
|
|
||||||
for (size_t i = 0; i < total; ++i)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
replayedActionsText += ", ";
|
|
||||||
replayedActionsText += aDebugComponent.ActionsReceivedForReplay.Actions[i].EventName;
|
|
||||||
}
|
|
||||||
total == 0 ? replayedActionsText = "<None>" : replayedActionsText += '.';
|
|
||||||
ImGui::TextWrapped(replayedActionsText.c_str());
|
|
||||||
|
|
||||||
if (ImGui::IsItemHovered())
|
|
||||||
{
|
|
||||||
ImGui::SetTooltip("Actions that were run (replayed) after this remote Actor received\n"
|
|
||||||
"spawn data from the server. Right click to replay again.");
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemClicked(1) && apAnimationComponent && total > 0)
|
|
||||||
{
|
|
||||||
AnimationSystem::AddActionsForReplay(*apAnimationComponent, aDebugComponent.ActionsReceivedForReplay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
#include <EquipManager.h>
|
|
||||||
#include <World.h>
|
|
||||||
|
|
||||||
#include <DefaultObjectManager.h>
|
|
||||||
|
|
||||||
void DebugService::DrawContainerDebugView()
|
|
||||||
{
|
|
||||||
static TESForm* pFetchForm = nullptr;
|
|
||||||
static Actor* pActor = nullptr;
|
|
||||||
|
|
||||||
ImGui::Begin("Inventory");
|
|
||||||
|
|
||||||
ImGui::InputScalar("Form ID", ImGuiDataType_U32, &m_formId, 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
if (ImGui::Button("Look up"))
|
|
||||||
{
|
|
||||||
if (m_formId)
|
|
||||||
{
|
|
||||||
pFetchForm = TESForm::GetById(m_formId);
|
|
||||||
if (pFetchForm)
|
|
||||||
pActor = Cast<Actor>(pFetchForm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pActor)
|
|
||||||
{
|
|
||||||
static Inventory inventory{};
|
|
||||||
|
|
||||||
if (ImGui::Button("Fetch inventory"))
|
|
||||||
inventory = pActor->GetInventory();
|
|
||||||
|
|
||||||
int inventoryCount = inventory.Entries.size();
|
|
||||||
|
|
||||||
ImGui::InputInt("Inventory count", &inventoryCount, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::BeginChild("Items", ImVec2(0, 200), true);
|
|
||||||
|
|
||||||
for (Inventory::Entry& entry : inventory.Entries)
|
|
||||||
{
|
|
||||||
std::string itemLabel = fmt::format("{:X}", entry.BaseId.BaseId + entry.BaseId.ModId);
|
|
||||||
if (!ImGui::CollapsingHeader(itemLabel.c_str()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ImGui::Button("Equip"))
|
|
||||||
{
|
|
||||||
World::Get().GetRunner().Queue(
|
|
||||||
[entry, actorId = pActor->formID]()
|
|
||||||
{
|
|
||||||
auto& modSystem = World::Get().GetModSystem();
|
|
||||||
uint32_t itemId = modSystem.GetGameId(entry.BaseId);
|
|
||||||
TESForm* pItem = TESForm::GetById(itemId);
|
|
||||||
Actor* pActor = Cast<Actor>(TESForm::GetById(actorId));
|
|
||||||
EquipManager::Get()->Equip(pActor, pItem, nullptr, entry.Count, DefaultObjectManager::Get().rightEquipSlot, false, true, false, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Unequip"))
|
|
||||||
{
|
|
||||||
World::Get().GetRunner().Queue(
|
|
||||||
[entry, actorId = pActor->formID]()
|
|
||||||
{
|
|
||||||
auto& modSystem = World::Get().GetModSystem();
|
|
||||||
uint32_t itemId = modSystem.GetGameId(entry.BaseId);
|
|
||||||
TESForm* pItem = TESForm::GetById(itemId);
|
|
||||||
Actor* pActor = Cast<Actor>(TESForm::GetById(actorId));
|
|
||||||
EquipManager::Get()->UnEquip(pActor, pItem, nullptr, entry.Count, DefaultObjectManager::Get().rightEquipSlot, false, true, false, false, nullptr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int itemCount = entry.Count;
|
|
||||||
ImGui::InputInt("Item count", &itemCount, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
int isWorn = entry.ExtraWorn;
|
|
||||||
ImGui::InputInt("Is worn?", &isWorn, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
int isWornLeft = entry.ExtraWornLeft;
|
|
||||||
ImGui::InputInt("Is worn left?", &isWornLeft, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
int isWeapon = entry.EnchantData.IsWeapon;
|
|
||||||
ImGui::InputInt("Is weapon?", &isWeapon, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::InputFloat("Health", &entry.ExtraHealth, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
int poisonId = entry.ExtraPoisonId.BaseId + entry.ExtraPoisonId.ModId;
|
|
||||||
ImGui::InputInt("Poison ID", &poisonId, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
int poisonCount = entry.ExtraPoisonCount;
|
|
||||||
ImGui::InputInt("Poison count", &poisonCount, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
int soulLevel = entry.ExtraSoulLevel;
|
|
||||||
ImGui::InputInt("Soul level", &soulLevel, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::InputFloat("Charge", &entry.ExtraCharge, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
int enchantId = entry.ExtraEnchantId.BaseId + entry.ExtraEnchantId.ModId;
|
|
||||||
ImGui::InputInt("Enchant ID", &enchantId, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
int enchantCharge = entry.ExtraEnchantCharge;
|
|
||||||
ImGui::InputInt("Enchant charge", &enchantCharge, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
int isEnchantRemoveUnequip = entry.ExtraEnchantRemoveUnequip;
|
|
||||||
ImGui::InputInt("Remove enchant on unequip?", &isEnchantRemoveUnequip, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
if (ImGui::CollapsingHeader("Effects"))
|
|
||||||
{
|
|
||||||
for (Inventory::EffectItem& effect : entry.EnchantData.Effects)
|
|
||||||
{
|
|
||||||
std::string effectLabel = fmt::format("{:X}", effect.EffectId.BaseId + effect.EffectId.ModId);
|
|
||||||
if (!ImGui::CollapsingHeader(effectLabel.c_str()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ImGui::InputFloat("Magnitude", &effect.Magnitude, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
int area = effect.Area;
|
|
||||||
ImGui::InputInt("Area", &area, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
int duration = effect.Duration;
|
|
||||||
ImGui::InputInt("Duration", &duration, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Raw cost", &effect.RawCost, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
void DebugService::DrawDragonSpawnerView()
|
|
||||||
{
|
|
||||||
ImGui::Begin("Dragon spawner");
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Dragons (level 10)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Brown (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x1CA03);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Brown (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF80FA);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("White (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x8BC7F);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Bronze (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x8BC7E);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Blood dragons (level 20)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Blood (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF80FD);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Blood (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF77F8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Frost dragons (level 27-35)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Frost"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x351C3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Elder dragons (level 36-44)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Elder (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF811B);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Elder (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF811A);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Ancient dragons (level 45-54)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Ancient (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF811C);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Ancient (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0xF811E);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Serpentine dragons (level 55-58)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Serpentine (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x04036134);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Serpentine (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x04036133);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Revered dragons (level 62)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Revered (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x02008431);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Legendary dragons (level 75)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Legendary (fire)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x0200C5F5);
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Legendary (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x0200C5FD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Skeletal dragons (warning: very scary)"))
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Skeletal (frost)"))
|
|
||||||
{
|
|
||||||
Actor::Spawn(0x9192C);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,217 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <Services/CharacterService.h>
|
|
||||||
|
|
||||||
#include <AI/AIProcess.h>
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
#include <Games/ActorExtension.h>
|
|
||||||
#include <Forms/TESObjectCELL.h>
|
|
||||||
|
|
||||||
#include <Events/MoveActorEvent.h>
|
|
||||||
|
|
||||||
#include <World.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
void DebugService::DrawEntitiesView()
|
|
||||||
{
|
|
||||||
const auto view = m_world.view<FormIdComponent>();
|
|
||||||
if (view.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver);
|
|
||||||
ImGui::Begin("Entities");
|
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
|
|
||||||
{
|
|
||||||
if (ImGui::BeginTabItem("Actors"))
|
|
||||||
{
|
|
||||||
DisplayEntities();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginTabItem("Objects"))
|
|
||||||
{
|
|
||||||
DisplayObjects();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
ImGui::EndTabBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayEntities() noexcept
|
|
||||||
{
|
|
||||||
static uint32_t s_selected = 0;
|
|
||||||
|
|
||||||
StackAllocator<1 << 12> allocator;
|
|
||||||
ScopedAllocator _{allocator};
|
|
||||||
|
|
||||||
const auto view = m_world.view<FormIdComponent>(entt::exclude<ObjectComponent>);
|
|
||||||
|
|
||||||
Vector<entt::entity> entities(view.begin(), view.end());
|
|
||||||
|
|
||||||
ImGui::Text("Actor list (%d)", entities.size());
|
|
||||||
|
|
||||||
ImGui::BeginChild("Entities", ImVec2(0, 200), true);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto it : entities)
|
|
||||||
{
|
|
||||||
auto& formComponent = view.get<FormIdComponent>(it);
|
|
||||||
const auto pActor = Cast<Actor>(TESForm::GetById(formComponent.Id));
|
|
||||||
|
|
||||||
if (!pActor)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
|
|
||||||
if (!pActor->baseForm)
|
|
||||||
strncpy_s(name, "UNNAMED", sizeof(name));
|
|
||||||
|
|
||||||
sprintf_s(name, std::size(name), "%s (%x)", pActor->baseForm->GetName(), formComponent.Id);
|
|
||||||
|
|
||||||
if (ImGui::Selectable(name, m_formId == formComponent.Id))
|
|
||||||
m_formId = formComponent.Id;
|
|
||||||
|
|
||||||
if (m_formId == formComponent.Id)
|
|
||||||
s_selected = i;
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndChild();
|
|
||||||
|
|
||||||
if (s_selected < entities.size())
|
|
||||||
DisplayEntityPanel(entities[s_selected]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayObjects() noexcept
|
|
||||||
{
|
|
||||||
static uint32_t s_selected = 0;
|
|
||||||
|
|
||||||
StackAllocator<1 << 12> allocator;
|
|
||||||
ScopedAllocator _{allocator};
|
|
||||||
|
|
||||||
const auto view = m_world.view<FormIdComponent, ObjectComponent>();
|
|
||||||
|
|
||||||
Vector<entt::entity> entities(view.begin(), view.end());
|
|
||||||
|
|
||||||
ImGui::Text("Object list (%d)", entities.size());
|
|
||||||
|
|
||||||
ImGui::BeginChild("Entities", ImVec2(0, 200), true);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto it : entities)
|
|
||||||
{
|
|
||||||
auto& formComponent = view.get<FormIdComponent>(it);
|
|
||||||
const auto pRefr = Cast<TESObjectREFR>(TESForm::GetById(formComponent.Id));
|
|
||||||
|
|
||||||
if (!pRefr || !pRefr->baseForm)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
sprintf_s(name, std::size(name), "%s (%x)", pRefr->baseForm->GetName(), formComponent.Id);
|
|
||||||
|
|
||||||
if (ImGui::Selectable(name, m_formId == formComponent.Id))
|
|
||||||
m_formId = formComponent.Id;
|
|
||||||
|
|
||||||
if (m_formId == formComponent.Id)
|
|
||||||
s_selected = i;
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayEntityPanel(entt::entity aEntity) noexcept
|
|
||||||
{
|
|
||||||
const auto pFormIdComponent = m_world.try_get<FormIdComponent>(aEntity);
|
|
||||||
const auto pLocalComponent = m_world.try_get<LocalComponent>(aEntity);
|
|
||||||
const auto pRemoteComponent = m_world.try_get<RemoteComponent>(aEntity);
|
|
||||||
|
|
||||||
if (pFormIdComponent)
|
|
||||||
DisplayFormComponent(*pFormIdComponent);
|
|
||||||
if (pLocalComponent)
|
|
||||||
DisplayLocalComponent(*pLocalComponent, pFormIdComponent ? pFormIdComponent->Id : 0);
|
|
||||||
if (pRemoteComponent)
|
|
||||||
DisplayRemoteComponent(*pRemoteComponent, aEntity, pFormIdComponent ? pFormIdComponent->Id : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayFormComponent(FormIdComponent& aFormComponent) const noexcept
|
|
||||||
{
|
|
||||||
if (!ImGui::CollapsingHeader("Form Component", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto pActor = Cast<Actor>(TESForm::GetById(aFormComponent.Id));
|
|
||||||
|
|
||||||
if (!pActor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (ImGui::Button("Teleport away"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue([id = aFormComponent.Id]() {
|
|
||||||
Actor* pActor = Cast<Actor>(TESForm::GetById(id));
|
|
||||||
TESObjectCELL* pCell = Cast<TESObjectCELL>(TESForm::GetById(0x133C6));
|
|
||||||
NiPoint3 pos{};
|
|
||||||
pos.x = -313.f;
|
|
||||||
pos.y = 4.f;
|
|
||||||
pos.z = 13.f;
|
|
||||||
pActor->MoveTo(pCell, pos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ImGui::InputInt("Game Id", (int*)&aFormComponent.Id, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::InputFloat3("Position", pActor->position.AsArray(), "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat3("Rotation", pActor->rotation.AsArray(), "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
int isDead = int(pActor->IsDead());
|
|
||||||
ImGui::InputScalar("Is dead?", ImGuiDataType_U8, &isDead, 0, 0, "%" PRIx8, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
int isRemote = int(pActor->GetExtension()->IsRemote());
|
|
||||||
ImGui::InputScalar("Is remote?", ImGuiDataType_U8, &isRemote, 0, 0, "%" PRIx8, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
auto handle = pActor->GetHandle();
|
|
||||||
ImGui::InputInt("Handle", (int*)&handle.handle.iBits, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
auto owner = pActor->GetCommandingActor();
|
|
||||||
int commandingActorId = int(owner ? owner->formID : 0x0);
|
|
||||||
ImGui::InputScalar("Commanding Actor", ImGuiDataType_U8, &commandingActorId, 0, 0, "%" PRIx8, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
float attributes[3]{pActor->GetActorValue(24), pActor->GetActorValue(25), pActor->GetActorValue(26)};
|
|
||||||
ImGui::InputFloat3("Attributes (H/M/S)", attributes, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayLocalComponent(LocalComponent& aLocalComponent, const uint32_t acFormId) const noexcept
|
|
||||||
{
|
|
||||||
if (!ImGui::CollapsingHeader("Local Component", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ImGui::Button("Teleport to me"))
|
|
||||||
{
|
|
||||||
auto* pPlayer = PlayerCharacter::Get();
|
|
||||||
m_world.GetRunner().Trigger(MoveActorEvent(acFormId, pPlayer->parentCell->formID, pPlayer->position));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& action = aLocalComponent.CurrentAction;
|
|
||||||
ImGui::InputInt("Net Id", (int*)&aLocalComponent.Id, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::InputInt("Action Id", (int*)&action.ActionId, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::InputInt("Idle Id", (int*)&action.IdleId, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::InputScalarN("State", ImGuiDataType_U32, &action.State1, 2, nullptr, nullptr, "%x", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugService::DisplayRemoteComponent(RemoteComponent& aRemoteComponent, const entt::entity acEntity, const uint32_t acFormId) const noexcept
|
|
||||||
{
|
|
||||||
if (!ImGui::CollapsingHeader("Remote Component", ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::InputInt("Server Id", (int*)&aRemoteComponent.Id, 0, 0, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
if (ImGui::Button("Take ownership"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue(
|
|
||||||
[acEntity, acFormId]()
|
|
||||||
{
|
|
||||||
if (auto* pRemoteCompoment = World::Get().try_get<RemoteComponent>(acEntity))
|
|
||||||
World::Get().GetCharacterService().TakeOwnership(acFormId, pRemoteCompoment->Id, acEntity);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <Games/TES.h>
|
|
||||||
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
#include <Forms/TESObjectCELL.h>
|
|
||||||
#include <Forms/TESWorldSpace.h>
|
|
||||||
|
|
||||||
#include <Services/DebugService.h>
|
|
||||||
#include <AI/AIProcess.h>
|
|
||||||
#include <Misc/MiddleProcess.h>
|
|
||||||
#include <Effects/ActiveEffect.h>
|
|
||||||
|
|
||||||
void DebugService::DrawFormDebugView()
|
|
||||||
{
|
|
||||||
static TESForm* pFetchForm = nullptr;
|
|
||||||
static Actor* pRefr = nullptr;
|
|
||||||
|
|
||||||
ImGui::Begin("Form");
|
|
||||||
|
|
||||||
ImGui::InputScalar("Form ID", ImGuiDataType_U32, &m_formId, 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
if (ImGui::Button("Look up"))
|
|
||||||
{
|
|
||||||
if (m_formId)
|
|
||||||
{
|
|
||||||
pFetchForm = TESForm::GetById(m_formId);
|
|
||||||
if (pFetchForm)
|
|
||||||
pRefr = Cast<Actor>(pFetchForm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFetchForm)
|
|
||||||
{
|
|
||||||
ImGui::InputScalar("Memory address", ImGuiDataType_U64, (void*)&pFetchForm, 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pRefr)
|
|
||||||
{
|
|
||||||
if (auto* pParentCell = pRefr->GetParentCell())
|
|
||||||
{
|
|
||||||
const uint32_t cellId = pParentCell->formID;
|
|
||||||
ImGui::InputScalar("GetParentCell", ImGuiDataType_U32, (void*)&cellId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* pParentCell = pRefr->parentCell)
|
|
||||||
{
|
|
||||||
const uint32_t cellId = pParentCell->formID;
|
|
||||||
ImGui::InputScalar("parentCell", ImGuiDataType_U32, (void*)&cellId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
char name[256];
|
|
||||||
sprintf_s(name, std::size(name), "%s (%x)", pRefr->baseForm->GetName(), pRefr->formID);
|
|
||||||
ImGui::InputText("Name", name, std::size(name), ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
for (ActiveEffect* pEffect : *pRefr->currentProcess->middleProcess->ActiveEffects)
|
|
||||||
{
|
|
||||||
if (!pEffect)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!ImGui::CollapsingHeader(pEffect->pSpell->fullName.value, ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ImGui::InputFloat("Elapsed seconds", &pEffect->fElapsedSeconds, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Duration", &pEffect->fDuration, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Magnitude", &pEffect->fMagnitude, 0, 0, "%.1f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputInt("Flags", (int*)&pEffect->uiFlags, 0, 0, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
if (ImGui::Button("Elapse time"))
|
|
||||||
m_world.GetRunner().Queue([pEffect]() { pEffect->fElapsedSeconds = pEffect->fDuration - 3.f; });
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
#include <Services/TransportService.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
void DebugService::DrawNetworkView()
|
|
||||||
{
|
|
||||||
if (m_transport.IsConnected())
|
|
||||||
{
|
|
||||||
ImGui::Begin("Network");
|
|
||||||
|
|
||||||
auto stats = m_transport.GetStatistics();
|
|
||||||
float protocolSent = float(stats.SentBytes) / 1024.f;
|
|
||||||
float protocolReceived = float(stats.RecvBytes) / 1024.f;
|
|
||||||
float uncompressedSent = float(stats.UncompressedSentBytes) / 1024.f;
|
|
||||||
float uncompressedReceived = float(stats.UncompressedRecvBytes) / 1024.f;
|
|
||||||
|
|
||||||
// Fill an array of contiguous float values to plot
|
|
||||||
// Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
|
|
||||||
// and the sizeof() of your structure in the "stride" parameter.
|
|
||||||
static float values[90] = {};
|
|
||||||
static int values_offset = 0;
|
|
||||||
static double refresh_time = 0.0;
|
|
||||||
if (refresh_time == 0.0)
|
|
||||||
refresh_time = ImGui::GetTime();
|
|
||||||
while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
|
|
||||||
{
|
|
||||||
values[values_offset] = protocolSent;
|
|
||||||
values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
|
|
||||||
refresh_time += 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plots can display overlay texts
|
|
||||||
// (in this example, we will display an average value)
|
|
||||||
{
|
|
||||||
float average = 0.0f;
|
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(values); n++)
|
|
||||||
average += values[n];
|
|
||||||
average /= (float)IM_ARRAYSIZE(values);
|
|
||||||
ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, nullptr, 0.f, FLT_MAX, ImVec2(0, 160.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
float width = -ImGui::CalcItemWidth();
|
|
||||||
ImGui::PushItemWidth(width);
|
|
||||||
|
|
||||||
auto status = GetConnectionStatus();
|
|
||||||
status.m_flOutBytesPerSec /= 1024.f;
|
|
||||||
status.m_flInBytesPerSec /= 1024.f;
|
|
||||||
|
|
||||||
ImGui::InputFloat("Net Out kBps", (float*)&status.m_flOutBytesPerSec, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Net In kBps", (float*)&status.m_flInBytesPerSec, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::InputFloat("Protocol Out kBps", (float*)&protocolSent, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Protocol In kBps", (float*)&protocolReceived, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::InputFloat("User Out kBps", (float*)&uncompressedSent, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("User In kBps", (float*)&uncompressedReceived, 0.f, 0.f, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
*/
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
// online indicator
|
|
||||||
ImGui::GetBackgroundDrawList()->AddRectFilled(ImVec2(23.f, 23.f), ImVec2(50.f, 50.f), m_transport.IsConnected() ? ImColor(0, 230, 64) : ImColor(240, 52, 52));
|
|
||||||
}
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <Messages/PartyKickRequest.h>
|
|
||||||
#include <Messages/PartyChangeLeaderRequest.h>
|
|
||||||
#include <Messages/PartyInviteRequest.h>
|
|
||||||
#include <Messages/PartyAcceptInviteRequest.h>
|
|
||||||
#include <Messages/PartyLeaveRequest.h>
|
|
||||||
#include <Messages/PartyCreateRequest.h>
|
|
||||||
#include <Messages/TeleportCommandRequest.h>
|
|
||||||
|
|
||||||
#include <World.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
void DebugService::DrawPartyView()
|
|
||||||
{
|
|
||||||
if (!m_transport.IsConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::Begin("Party");
|
|
||||||
|
|
||||||
auto& partyService = m_world.GetPartyService();
|
|
||||||
auto& players = partyService.GetPlayers();
|
|
||||||
auto& members = partyService.GetPartyMembers();
|
|
||||||
auto& invitations = partyService.GetInvitations();
|
|
||||||
|
|
||||||
if (partyService.IsInParty())
|
|
||||||
{
|
|
||||||
ImGui::Text("Party Members");
|
|
||||||
String pName{"You"};
|
|
||||||
if (partyService.IsLeader())
|
|
||||||
{
|
|
||||||
pName += " (Leader)";
|
|
||||||
}
|
|
||||||
ImGui::BulletText(pName.c_str());
|
|
||||||
|
|
||||||
for (auto& playerId : members)
|
|
||||||
{
|
|
||||||
ImGui::PushID(playerId);
|
|
||||||
|
|
||||||
auto playerEntry = players.find(playerId);
|
|
||||||
if (playerEntry != players.end())
|
|
||||||
{
|
|
||||||
auto playerName = playerEntry.value();
|
|
||||||
if (playerId == partyService.GetLeaderPlayerId())
|
|
||||||
{
|
|
||||||
playerName += " (Leader)";
|
|
||||||
}
|
|
||||||
ImGui::BulletText(playerName.c_str());
|
|
||||||
|
|
||||||
ImGui::SameLine(200);
|
|
||||||
if (ImGui::Button("Teleport"))
|
|
||||||
{
|
|
||||||
TeleportCommandRequest request{};
|
|
||||||
request.TargetPlayer = playerEntry.value();
|
|
||||||
|
|
||||||
m_transport.Send(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partyService.IsLeader())
|
|
||||||
{
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Kick"))
|
|
||||||
{
|
|
||||||
PartyKickRequest kickMessage;
|
|
||||||
kickMessage.PartyMemberPlayerId = playerEntry.key();
|
|
||||||
m_transport.Send(kickMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Make Leader"))
|
|
||||||
{
|
|
||||||
PartyChangeLeaderRequest changeMessage;
|
|
||||||
changeMessage.PartyMemberPlayerId = playerEntry.key();
|
|
||||||
m_transport.Send(changeMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (partyService.IsLeader())
|
|
||||||
{
|
|
||||||
ImGui::NewLine();
|
|
||||||
ImGui::Text("Other Players");
|
|
||||||
auto playerCount = 0;
|
|
||||||
for (auto& player : partyService.GetPlayers())
|
|
||||||
{
|
|
||||||
if (std::find(std::begin(members), std::end(members), player.first) != std::end(members))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
playerCount++;
|
|
||||||
ImGui::BulletText(player.second.c_str());
|
|
||||||
ImGui::SameLine(100);
|
|
||||||
if (ImGui::Button("Invite"))
|
|
||||||
{
|
|
||||||
PartyInviteRequest request;
|
|
||||||
request.PlayerId = player.first;
|
|
||||||
m_transport.Send(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playerCount == 0)
|
|
||||||
{
|
|
||||||
ImGui::BulletText("<No one online>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& player : players)
|
|
||||||
{
|
|
||||||
auto itor = invitations.find(player.first);
|
|
||||||
if (itor != std::end(invitations))
|
|
||||||
{
|
|
||||||
if (std::find(std::begin(members), std::end(members), player.first) != std::end(members))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ImGui::Text(player.second.c_str());
|
|
||||||
ImGui::SameLine(100);
|
|
||||||
if (ImGui::Button("Accept"))
|
|
||||||
{
|
|
||||||
invitations.erase(itor);
|
|
||||||
|
|
||||||
PartyAcceptInviteRequest message;
|
|
||||||
message.InviterId = player.first;
|
|
||||||
m_transport.Send(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::NewLine();
|
|
||||||
if (partyService.IsInParty())
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Leave"))
|
|
||||||
{
|
|
||||||
PartyLeaveRequest request;
|
|
||||||
m_transport.Send(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Create Party"))
|
|
||||||
{
|
|
||||||
PartyCreateRequest request;
|
|
||||||
m_transport.Send(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <Games/TES.h>
|
|
||||||
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
#include <Forms/TESObjectCELL.h>
|
|
||||||
#include <Forms/TESWorldSpace.h>
|
|
||||||
|
|
||||||
void DebugService::DrawPlayerDebugView()
|
|
||||||
{
|
|
||||||
PlayerCharacter* pPlayer = PlayerCharacter::Get();
|
|
||||||
if (!pPlayer)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Begin("Player");
|
|
||||||
|
|
||||||
auto pLeftWeapon = pPlayer->GetEquippedWeapon(0);
|
|
||||||
auto pRightWeapon = pPlayer->GetEquippedWeapon(1);
|
|
||||||
|
|
||||||
uint32_t leftId = pLeftWeapon ? pLeftWeapon->formID : 0;
|
|
||||||
uint32_t rightId = pRightWeapon ? pRightWeapon->formID : 0;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Left Item", ImGuiDataType_U32, (void*)&leftId, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("Right Item", ImGuiDataType_U32, (void*)&rightId, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
leftId = pPlayer->magicItems[0] ? pPlayer->magicItems[0]->formID : 0;
|
|
||||||
rightId = pPlayer->magicItems[1] ? pPlayer->magicItems[1]->formID : 0;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Right Magic", ImGuiDataType_U32, (void*)&rightId, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("Left Magic", ImGuiDataType_U32, (void*)&leftId, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
auto* leftHandCaster = pPlayer->GetMagicCaster(MagicSystem::CastingSource::LEFT_HAND);
|
|
||||||
auto* rightHandCaster = pPlayer->GetMagicCaster(MagicSystem::CastingSource::RIGHT_HAND);
|
|
||||||
auto* otherHandCaster = pPlayer->GetMagicCaster(MagicSystem::CastingSource::OTHER);
|
|
||||||
auto* instantHandCaster = pPlayer->GetMagicCaster(MagicSystem::CastingSource::INSTANT);
|
|
||||||
|
|
||||||
ImGui::InputScalar("leftHandCaster", ImGuiDataType_U64, (void*)&leftHandCaster, 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("rightHandCaster", ImGuiDataType_U64, (void*)&rightHandCaster, 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("otherHandCaster", ImGuiDataType_U64, (void*)&otherHandCaster, 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("instantHandCaster", ImGuiDataType_U64, (void*)&instantHandCaster, 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
ImGui::InputScalar("leftHandCasterSpell", ImGuiDataType_U64, (void*)&(leftHandCaster->pCurrentSpell), 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("rightHandCasterSpell", ImGuiDataType_U64, (void*)&(rightHandCaster->pCurrentSpell), 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("otherHandCasterSpell", ImGuiDataType_U64, (void*)&(otherHandCaster->pCurrentSpell), 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputScalar("instantHandCasterSpell", ImGuiDataType_U64, (void*)&(instantHandCaster->pCurrentSpell), 0, 0, "%" PRIx64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
uint32_t shoutId = pPlayer->equippedShout ? pPlayer->equippedShout->formID : 0;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Shout", ImGuiDataType_U32, (void*)&shoutId, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
if (auto pWorldSpace = pPlayer->GetWorldSpace())
|
|
||||||
{
|
|
||||||
auto worldFormId = pWorldSpace->formID;
|
|
||||||
ImGui::InputScalar("Worldspace", ImGuiDataType_U32, (void*)&worldFormId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
if (auto pCell = pPlayer->GetParentCell())
|
|
||||||
{
|
|
||||||
auto cellFormId = pCell->formID;
|
|
||||||
ImGui::InputScalar("Cell Id", ImGuiDataType_U32, (void*)&cellFormId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
if (const auto playerParentCell = pPlayer->parentCell)
|
|
||||||
{
|
|
||||||
ImGui::InputScalar("Player parent cell", ImGuiDataType_U32, (void*)&playerParentCell->formID, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
if (auto* pTES = TES::Get())
|
|
||||||
{
|
|
||||||
int32_t playerGrid[2] = {pTES->currentGridX, pTES->currentGridY};
|
|
||||||
int32_t centerGrid[2] = {pTES->centerGridX, pTES->centerGridY};
|
|
||||||
|
|
||||||
ImGui::InputInt2("Player grid", playerGrid, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputInt2("Center grid", centerGrid, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& modSystem = m_world.GetModSystem();
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Worn armor"))
|
|
||||||
{
|
|
||||||
Inventory wornArmor{};
|
|
||||||
wornArmor = pPlayer->GetWornArmor();
|
|
||||||
for (const auto& armor : wornArmor.Entries)
|
|
||||||
{
|
|
||||||
const uint32_t armorId = armor.BaseId.BaseId;
|
|
||||||
ImGui::InputScalar("Item id", ImGuiDataType_U32, (void*)&armorId, nullptr, nullptr, "%" PRIx32, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <Games/TES.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
void DebugService::DrawProcessView()
|
|
||||||
{
|
|
||||||
ImGui::Begin("Processes");
|
|
||||||
|
|
||||||
ImGui::PushItemWidth(100.f);
|
|
||||||
|
|
||||||
int id = 0;
|
|
||||||
|
|
||||||
ProcessLists* pProcesses = ProcessLists::Get();
|
|
||||||
|
|
||||||
ImGui::InputScalar("Processing high?", ImGuiDataType_U8, &pProcesses->bProcessHigh, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::PushID(id);
|
|
||||||
if (ImGui::Button("Toggle"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue([pProcesses]() { pProcesses->bProcessHigh = !pProcesses->bProcessHigh; });
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
id++;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Processing Low?", ImGuiDataType_U8, &pProcesses->bProcessLow, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::PushID(id);
|
|
||||||
if (ImGui::Button("Toggle"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue([pProcesses]() { pProcesses->bProcessLow = !pProcesses->bProcessLow; });
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
id++;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Processing middle high?", ImGuiDataType_U8, &pProcesses->bProcessMHigh, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::PushID(id);
|
|
||||||
if (ImGui::Button("Toggle"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue([pProcesses]() { pProcesses->bProcessMHigh = !pProcesses->bProcessMHigh; });
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
id++;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Processing middle low?", ImGuiDataType_U8, &pProcesses->bProcessMLow, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::PushID(id);
|
|
||||||
if (ImGui::Button("Toggle"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue([pProcesses]() { pProcesses->bProcessMLow = !pProcesses->bProcessMLow; });
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
id++;
|
|
||||||
|
|
||||||
ImGui::InputScalar("Processing schedule?", ImGuiDataType_U8, &pProcesses->bProcessSchedule, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
ImGui::PushID(id);
|
|
||||||
if (ImGui::Button("Toggle"))
|
|
||||||
{
|
|
||||||
m_world.GetRunner().Queue([pProcesses]() { pProcesses->bProcessSchedule = !pProcesses->bProcessSchedule; });
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
id++;
|
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
#include <Services/QuestService.h>
|
|
||||||
#include <Services/PapyrusService.h>
|
|
||||||
#include <Services/PartyService.h>
|
|
||||||
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
#include <Forms/TESQuest.h>
|
|
||||||
#include <Forms/TESObjectCELL.h>
|
|
||||||
|
|
||||||
#include <Events/MoveActorEvent.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
void DebugService::DrawQuestDebugView()
|
|
||||||
{
|
|
||||||
auto* pPlayer = PlayerCharacter::Get();
|
|
||||||
if (!pPlayer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(250, 440), ImGuiCond_FirstUseEver);
|
|
||||||
ImGui::Begin("Quests");
|
|
||||||
|
|
||||||
// TODO(cosideci): yes I'll refactor this
|
|
||||||
if (!m_world.GetPartyService().IsLeader())
|
|
||||||
{
|
|
||||||
ImGui::Text("You need to be the quest leader to access the quest debugger.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Set<uint32_t> foundQuests{};
|
|
||||||
|
|
||||||
for (auto& objective : pPlayer->objectives)
|
|
||||||
{
|
|
||||||
TESQuest* pQuest = objective.instance->quest;
|
|
||||||
if (!pQuest)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (QuestService::IsNonSyncableQuest(pQuest))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (foundQuests.contains(pQuest->formID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foundQuests.insert(pQuest->formID);
|
|
||||||
|
|
||||||
if (!pQuest->IsActive())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char questName[256];
|
|
||||||
sprintf_s(questName, std::size(questName), "%s (%s)", pQuest->fullName.value.AsAscii(), pQuest->idName.AsAscii());
|
|
||||||
if (!ImGui::CollapsingHeader(questName))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Stages"))
|
|
||||||
{
|
|
||||||
for (auto* pStage : pQuest->stages)
|
|
||||||
{
|
|
||||||
ImGui::TextColored({0.f, 255.f, 255.f, 255.f}, "Stage: %d, is done? %s", pStage->stageIndex, pStage->IsDone() ? "true" : "false");
|
|
||||||
|
|
||||||
char setStage[64];
|
|
||||||
sprintf_s(setStage, std::size(setStage), "Set stage (%d)", pStage->stageIndex);
|
|
||||||
|
|
||||||
if (ImGui::Button(setStage))
|
|
||||||
pQuest->ScriptSetStage(pStage->stageIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Actors"))
|
|
||||||
{
|
|
||||||
Set<uint32_t> foundActors{};
|
|
||||||
|
|
||||||
for (BGSScene* pScene : pQuest->scenes)
|
|
||||||
{
|
|
||||||
for (uint32_t actorId : pScene->actorIds)
|
|
||||||
{
|
|
||||||
Actor* pActor = Cast<Actor>(pQuest->GetAliasedRef(actorId));
|
|
||||||
if (!pActor)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (foundActors.contains(pActor->formID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foundActors.insert(pActor->formID);
|
|
||||||
|
|
||||||
char name[256];
|
|
||||||
sprintf_s(name, std::size(name), "%s (%x)", pActor->baseForm->GetName(), pActor->formID);
|
|
||||||
ImGui::BulletText(name);
|
|
||||||
|
|
||||||
ImGui::PushID(pActor->formID);
|
|
||||||
if (ImGui::Button("Teleport to me"))
|
|
||||||
{
|
|
||||||
auto* pPlayer = PlayerCharacter::Get();
|
|
||||||
m_world.GetRunner().Trigger(MoveActorEvent(pActor->formID, pPlayer->parentCell->formID, pPlayer->position));
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
#include <PlayerCharacter.h>
|
|
||||||
|
|
||||||
void DebugService::DrawSkillView()
|
|
||||||
{
|
|
||||||
ImGui::Begin("Skills");
|
|
||||||
|
|
||||||
PlayerCharacter* pPlayer = PlayerCharacter::Get();
|
|
||||||
Skills* pSkills = *pPlayer->pSkills;
|
|
||||||
|
|
||||||
ImGui::InputFloat("Global XP", &pSkills->xp, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Global level threshold", &pSkills->levelThreshold, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
for (int i = 0; i < Skills::kTotal; i++)
|
|
||||||
{
|
|
||||||
const char* skillString = Skills::GetSkillString((Skills::Skill)i);
|
|
||||||
if (!ImGui::CollapsingHeader(skillString, ImGuiTreeNodeFlags_DefaultOpen))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Skills::SkillData pSkill = pSkills->skills[i];
|
|
||||||
ImGui::InputFloat("Level", &pSkill.level, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("XP", &pSkill.xp, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
ImGui::InputFloat("Level threshold", &pSkill.levelThreshold, 0, 0, "%.3f", ImGuiInputTextFlags_ReadOnly);
|
|
||||||
|
|
||||||
uint32_t legendaryLevel = pSkills->legendaryLevels[i];
|
|
||||||
ImGui::InputScalar("Legendary level", ImGuiDataType_U32, (void*)&legendaryLevel, nullptr, nullptr, nullptr, ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#include <Services/DebugService.h>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include <Sky/Sky.h>
|
|
||||||
#include <Forms/TESWeather.h>
|
|
||||||
|
|
||||||
void DebugService::DrawWeatherView()
|
|
||||||
{
|
|
||||||
ImGui::Begin("Weather");
|
|
||||||
|
|
||||||
Sky* pSky = Sky::Get();
|
|
||||||
|
|
||||||
TESWeather* pCurrentWeather = pSky->GetWeather();
|
|
||||||
if (pCurrentWeather)
|
|
||||||
{
|
|
||||||
ImGui::InputScalar("Current weather ID", ImGuiDataType_U32, &pCurrentWeather->formID, 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_ReadOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
ImGui::InputScalar("Weather updates enabled?", ImGuiDataType_U8, &Sky::s_shouldUpdateWeather, 0, 0, "%" PRIx8, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
if (ImGui::Button("Toggle weather updates"))
|
|
||||||
Sky::s_shouldUpdateWeather = !Sky::s_shouldUpdateWeather;
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
static uint32_t s_weatherId = 0;
|
|
||||||
ImGui::InputScalar("New weather ID", ImGuiDataType_U32, &s_weatherId, 0, 0, "%" PRIx32, ImGuiInputTextFlags_CharsHexadecimal);
|
|
||||||
|
|
||||||
if (ImGui::Button("Set weather"))
|
|
||||||
{
|
|
||||||
TESWeather* pWeather = Cast<TESWeather>(TESForm::GetById(s_weatherId));
|
|
||||||
if (pWeather)
|
|
||||||
pSky->SetWeather(pWeather);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Force weather"))
|
|
||||||
{
|
|
||||||
TESWeather* pWeather = Cast<TESWeather>(TESForm::GetById(s_weatherId));
|
|
||||||
if (pWeather)
|
|
||||||
pSky->ForceWeather(pWeather);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
if (ImGui::Button("Reset weather"))
|
|
||||||
{
|
|
||||||
pSky->ResetWeather();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,19 +0,0 @@
|
||||||
<div *ngIf="isShown$ | async" class="app-debug">
|
|
||||||
<div *ngIf="debugData$ | async as debugData">
|
|
||||||
<span>
|
|
||||||
<fa-icon [icon]="faWifi"></fa-icon>
|
|
||||||
<b>{{ debugData.RTT }}</b> ms,
|
|
||||||
<b>{{ debugData.packetLoss }}%</b> Loss
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<fa-icon [icon]="faArrowDown"></fa-icon>
|
|
||||||
<b>{{ debugData.receivedBandwidth / 1024 | number: '.0-2' }}</b> kB/s,
|
|
||||||
<b>{{ debugData.numPacketsReceived | number: '.0-2' }}</b> p/s
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<fa-icon [icon]="faArrowUp"></fa-icon>
|
|
||||||
<b>{{ debugData.sentBandwidth / 1024 | number: '.0-2' }}</b> kB/s,
|
|
||||||
<b>{{ debugData.numPacketsSent | number: '.0-2' }}</b> p/s
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
.app-debug {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
height: 1.6vw;
|
|
||||||
padding: 1px;
|
|
||||||
color: rgb(196, 196, 196);
|
|
||||||
|
|
||||||
b {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
fa-icon {
|
|
||||||
margin-right: 0.2vw;
|
|
||||||
margin-left: 0.15vw;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
padding-top: 0.2vw;
|
|
||||||
padding-bottom: 0.2vw;
|
|
||||||
border: solid grey 1px;
|
|
||||||
background-color: rgba($color: #000000, $alpha: 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
import {
|
|
||||||
faArrowDown,
|
|
||||||
faArrowUp,
|
|
||||||
faWifi,
|
|
||||||
IconDefinition,
|
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { Observable, startWith } from 'rxjs';
|
|
||||||
import { SettingService } from 'src/app/services/setting.service';
|
|
||||||
import { Debug } from '../../models/debug';
|
|
||||||
import { ClientService } from '../../services/client.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-debug',
|
|
||||||
templateUrl: './debug.component.html',
|
|
||||||
styleUrls: ['./debug.component.scss'],
|
|
||||||
})
|
|
||||||
export class DebugComponent {
|
|
||||||
/* ### ICONS ### */
|
|
||||||
faWifi: IconDefinition = faWifi;
|
|
||||||
faArrowDown: IconDefinition = faArrowDown;
|
|
||||||
faArrowUp: IconDefinition = faArrowUp;
|
|
||||||
|
|
||||||
isShown$: Observable<boolean>;
|
|
||||||
debugData$: Observable<Debug>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private readonly client: ClientService,
|
|
||||||
private readonly settingService: SettingService,
|
|
||||||
) {
|
|
||||||
this.isShown$ = this.settingService.settings.isDebugShown;
|
|
||||||
this.debugData$ = this.client.debugDataChange.pipe(startWith(new Debug()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Loading…
Reference in a new issue