F4MP/codigos originales/tiltedcode/Code/client/Services/Debug/Views/EntitiesView.cpp
2026-01-06 18:53:59 +01:00

217 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);
});
}
}