enhanced husk spawning logic, seperate device pointer for imgui

This commit is contained in:
ApfelTeeSaft
2026-01-07 19:19:27 +01:00
parent cd697085ff
commit 8a7d2aef7e
4 changed files with 81 additions and 36 deletions
+51 -10
View File
@@ -295,11 +295,43 @@ void Features::RefreshActorCache() {
void Features::RenderSpawningTab() {
ImGui::Text("Husk Spawning:");
if (ImGui::Button("Spawn Husk (No AI / T-Pose)")) {
SpawnHusk(false);
}
if (ImGui::Button("Spawn Husk (With AI)")) {
SpawnHusk(true);
static const char* kHuskOptions[] = {
"WerewolfPawn_C",
"FlingerPawn_C",
"TakerPawn_C",
"TrollPawn_C",
"BlasterPawn_C",
"HuskPawn_Beehive_C",
"HuskPawn_Bombshell_Poison_C",
"HuskPawn_Bombshell_C",
"HuskPawn_Dwarf_Fire_C",
"HuskPawn_Dwarf_Ice_C",
"HuskPawn_Dwarf_Lightning_C",
"HuskPawn_Dwarf_C",
"HuskPawn_Fire_C",
"HuskPawn_Husky_Fire_C",
"HuskPawn_Husky_Ice_C",
"HuskPawn_Husky_Lightning_C",
"HuskPawn_Husky_C",
"HuskPawn_Ice_C",
"HuskPawn_Lightning_C",
"HuskPawn_Pitcher_C",
"HuskPawn_Sploder_C",
"HuskPawn_Trashman_C",
"HuskPawn_C",
"SmasherPawn_Boss_C",
"SmasherPawn_Fire_C",
"SmasherPawn_Ice_C",
"SmasherPawn_Lightning_C",
"SmasherPawn_C",
"SmasherPawn_BossRampage_C",
};
static int selectedHusk = 0;
ImGui::Combo("Husk Type", &selectedHusk, kHuskOptions, static_cast<int>(std::size(kHuskOptions)));
static bool withAI = true;
ImGui::Checkbox("With AI", &withAI);
if (ImGui::Button("Spawn Husk")) {
SpawnHusk(kHuskOptions[selectedHusk], withAI);
}
}
@@ -462,14 +494,19 @@ void Features::ProcessPendingCommands() {
lastCommandRun_ = now;
}
void Features::SpawnHusk(bool withAI) {
void Features::SpawnHusk(const std::string& huskClassName, bool withAI) {
auto controller = GetLocalPlayerController();
if (!controller) {
return;
}
SDK::UObject* huskClass = FindObjectByName(L"Class FortniteGame.FortAIPawn_Husk");
if (huskClassName.empty()) {
return;
}
std::wstring className(huskClassName.begin(), huskClassName.end());
std::wstring fullClassName = L"Class FortniteGame." + className;
SDK::UObject* huskClass = FindObjectByName(fullClassName);
if (!huskClass) {
huskClass = FindObjectByName(L"Husk");
huskClass = FindObjectByName(className);
}
if (!huskClass) {
return;
@@ -484,8 +521,12 @@ void Features::SpawnHusk(bool withAI) {
}
SDK::FVector spawnLoc{0.0f, 0.0f, 300.0f};
if (controller->AcknowledgedPawn) {
spawnLoc = controller->AcknowledgedPawn->K2_GetActorLocation();
spawnLoc.X += 200.0f;
auto pawn = reinterpret_cast<SDK::AActor*>(controller->AcknowledgedPawn);
spawnLoc = pawn->K2_GetActorLocation();
SDK::FVector forward = pawn->GetActorForwardVector();
spawnLoc.X += forward.X * 10.0f;
spawnLoc.Y += forward.Y * 10.0f;
spawnLoc.Z += forward.Z * 10.0f;
}
struct SpawnParams {
SDK::UClass* Class;
+1 -1
View File
@@ -39,7 +39,7 @@ private:
void ReloadMap();
void ApplyMovementCheats();
void SpawnHusk(bool withAI);
void SpawnHusk(const std::string& huskClassName, bool withAI);
void SetupGameplay();
void StartContentScan();
void ProcessScanResults();
+24 -22
View File
@@ -19,21 +19,21 @@ bool ImGuiLayer::Initialize(IDirect3DDevice9* device) {
LogMessage("ImGuiLayer::Initialize: device null");
return false;
}
device_ = device;
gameDevice_ = device;
D3DDEVICE_CREATION_PARAMETERS params{};
if (FAILED(device_->GetCreationParameters(&params))) {
if (FAILED(gameDevice_->GetCreationParameters(&params))) {
return false;
}
hwnd_ = params.hFocusWindow;
gameHwnd_ = params.hFocusWindow;
if (!contextInitialized_) {
ImGui::CreateContext();
contextInitialized_ = true;
}
if (!backendInitialized_) {
ImGui_ImplWin32_Init(hwnd_);
ImGui_ImplDX9_Init(device_);
ImGui_ImplWin32_Init(gameHwnd_);
ImGui_ImplDX9_Init(gameDevice_);
backendInitialized_ = true;
LogMessage("ImGuiLayer::Initialize: backend initialized hwnd=%p device=%p", hwnd_, device_);
LogMessage("ImGuiLayer::Initialize: backend initialized hwnd=%p device=%p", gameHwnd_, gameDevice_);
}
threadedRender_ = false;
return true;
@@ -44,7 +44,7 @@ bool ImGuiLayer::InitializeStandalone(HWND hwnd) {
LogMessage("ImGuiLayer::InitializeStandalone: hwnd null");
return false;
}
hwnd_ = hwnd;
standaloneHwnd_ = hwnd;
if (!contextInitialized_) {
ImGui::CreateContext();
contextInitialized_ = true;
@@ -57,17 +57,17 @@ bool ImGuiLayer::InitializeStandaloneDevice(HWND hwnd, IDirect3DDevice9* device)
LogMessage("ImGuiLayer::InitializeStandaloneDevice: invalid hwnd/device hwnd=%p device=%p", hwnd, device);
return false;
}
hwnd_ = hwnd;
device_ = device;
standaloneHwnd_ = hwnd;
standaloneDevice_ = device;
if (!contextInitialized_) {
ImGui::CreateContext();
contextInitialized_ = true;
}
if (!backendInitialized_) {
ImGui_ImplWin32_Init(hwnd_);
ImGui_ImplDX9_Init(device_);
ImGui_ImplWin32_Init(standaloneHwnd_);
ImGui_ImplDX9_Init(standaloneDevice_);
backendInitialized_ = true;
LogMessage("ImGuiLayer::InitializeStandaloneDevice: backend initialized hwnd=%p device=%p", hwnd_, device_);
LogMessage("ImGuiLayer::InitializeStandaloneDevice: backend initialized hwnd=%p device=%p", standaloneHwnd_, standaloneDevice_);
}
threadedRender_ = false;
return true;
@@ -87,8 +87,10 @@ void ImGuiLayer::Shutdown() {
contextInitialized_ = false;
LogMessage("ImGuiLayer::Shutdown: context destroyed");
}
device_ = nullptr;
hwnd_ = nullptr;
gameDevice_ = nullptr;
gameHwnd_ = nullptr;
standaloneDevice_ = nullptr;
standaloneHwnd_ = nullptr;
}
void ImGuiLayer::RenderForPresent() {
@@ -100,7 +102,7 @@ void ImGuiLayer::RenderForEndScene() {
}
void ImGuiLayer::RenderStandalone() {
RenderInternal(false);
RenderInternal(standaloneDevice_, standaloneHwnd_, false);
}
void ImGuiLayer::StartRenderThread() {
@@ -123,7 +125,7 @@ void ImGuiLayer::StartRenderThread() {
frameRequested_ = false;
beginScene = nextBeginScene_;
}
RenderInternal(beginScene);
RenderInternal(gameDevice_, gameHwnd_, beginScene);
}
LogMessage("ImGuiLayer::RenderThread: exiting");
});
@@ -144,7 +146,7 @@ void ImGuiLayer::StopRenderThread() {
void ImGuiLayer::RequestFrame(bool beginScene) {
if (!threadedRender_) {
RenderInternal(beginScene);
RenderInternal(gameDevice_, gameHwnd_, beginScene);
return;
}
if (!renderThreadRunning_.load()) {
@@ -158,14 +160,14 @@ void ImGuiLayer::RequestFrame(bool beginScene) {
frameCv_.notify_one();
}
void ImGuiLayer::RenderInternal(bool beginScene) {
if (!device_ || !hwnd_) {
LogMessage("ImGuiLayer::RenderInternal: device/hwnd missing device=%p hwnd=%p", device_, hwnd_);
void ImGuiLayer::RenderInternal(IDirect3DDevice9* device, HWND hwnd, bool beginScene) {
if (!device || !hwnd) {
LogMessage("ImGuiLayer::RenderInternal: device/hwnd missing device=%p hwnd=%p", device, hwnd);
return;
}
const auto start = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> lock(renderMutex_);
if (beginScene && FAILED(device_->BeginScene())) {
if (beginScene && FAILED(device->BeginScene())) {
LogMessage("ImGuiLayer::RenderInternal: BeginScene failed");
return;
}
@@ -176,7 +178,7 @@ void ImGuiLayer::RenderInternal(bool beginScene) {
ImGui::Render();
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
if (beginScene) {
device_->EndScene();
device->EndScene();
}
const auto end = std::chrono::steady_clock::now();
if (lastRenderLog_ == std::chrono::steady_clock::time_point{}
+5 -3
View File
@@ -22,10 +22,12 @@ private:
void StartRenderThread();
void StopRenderThread();
void RequestFrame(bool beginScene);
void RenderInternal(bool beginScene);
void RenderInternal(IDirect3DDevice9* device, HWND hwnd, bool beginScene);
IDirect3DDevice9* device_ = nullptr;
HWND hwnd_ = nullptr;
IDirect3DDevice9* gameDevice_ = nullptr;
HWND gameHwnd_ = nullptr;
IDirect3DDevice9* standaloneDevice_ = nullptr;
HWND standaloneHwnd_ = nullptr;
bool contextInitialized_ = false;
bool backendInitialized_ = false;
bool threadedRender_ = false;