mirror of
https://github.com/Jous99/F4MP.git
synced 2026-01-12 17:10:54 +01:00
218 lines
7.3 KiB
C++
218 lines
7.3 KiB
C++
|
|
#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);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|