#include "headers/includes.h" #include #include #include #include #include "Overlay/MenuBridge.h" // project header (src/ is on the include path) // ------------------------------------------------------------------------- // DayZ overlay integration // // This is the original Lumin demo `gui.cpp`, stripped of the login screen and // the placeholder "visual" feature panels. The window/sidebar/feature // scaffolding is preserved verbatim; only the tab list and per-tab content // were swapped to drive this project's real ESP state via `g_menu` // (see src/Overlay/MenuBridge.h). https://discord.gg/jxqVWub6Dk // ------------------------------------------------------------------------- static void sync_layout_preferences() { elements->padding = var->gui.compact_layout ? c_vec2(8, 8) : c_vec2(10, 10); elements->window.rounding = var->gui.window_rounding; } static constexpr float visual_window_width = 900.f; static constexpr float visual_window_height = 527.f; static constexpr float visual_sidebar_width = 162.5f; static constexpr float visual_outer_padding = 10.f; static constexpr float visual_column_gap = 14.f; static constexpr float visual_panel_scale = 1.0f; static constexpr float visual_section_width_scale = 0.98f; static constexpr float visual_feature_padding_x = 0.f; static constexpr float visual_feature_padding_y = 0.f; struct visual_panel_density_state { float dpi; float font_scale; }; static float unscale_visual(float value) { return value / ImMax(var->gui.dpi, 0.01f); } static float visual_section_height(int section_count) { const float content_height = unscale_visual(gui->content_avail().y); const float gaps = visual_column_gap * static_cast(ImMax(section_count - 1, 0)); return ImMax(220.f, (content_height - gaps) / static_cast(ImMax(section_count, 1))); } extern c_vec4 g_pill_selected_rect; extern c_vec4 g_sidebar_selected_rect; static int g_panel_number = 0; // ---- search filtering ----------------------------------------------------- static char visual_search_lower(char value) { return value >= 'A' && value <= 'Z' ? static_cast(value - 'A' + 'a') : value; } static std::string visual_search_query() { std::string query = var->gui.feature_search; size_t first = 0; while (first < query.size() && (query[first] == ' ' || query[first] == '\t')) first++; size_t last = query.size(); while (last > first && (query[last - 1] == ' ' || query[last - 1] == '\t')) last--; return query.substr(first, last - first); } static bool visual_contains_ci(std::string_view text, std::string_view query) { if (query.empty()) return true; if (query.size() > text.size()) return false; for (size_t i = 0; i <= text.size() - query.size(); i++) { size_t j = 0; while (j < query.size() && visual_search_lower(text[i + j]) == visual_search_lower(query[j])) j++; if (j == query.size()) return true; } return false; } static bool visual_search_matches(std::string_view name, std::string_view description = {}) { const std::string query = visual_search_query(); if (query.empty()) return true; return visual_contains_ci(name, query) || visual_contains_ci(description, query); } struct visual_widget_filter { bool checkbox(std::string name, std::string description, bool* callback, title_status_icon status = title_status_none) const { if (!visual_search_matches(name, description)) return false; return ::widgets->checkbox(name, description, callback, status); } bool slider(std::string name, std::string description, float* callback, float vmin, float vmax, std::string format = "%.1f") const { if (!visual_search_matches(name, description)) return false; return ::widgets->slider(name, description, callback, vmin, vmax, format); } }; // ---- section helpers ------------------------------------------------------ static void begin_visual_section(std::string_view name, float height) { const int panel_number = g_panel_number + 1; const float section_width = elements->child_width * visual_section_width_scale; const float content_padding_x = ImMax(0.f, section_width * 0.05f); gui->begin_content(name, c_vec2(section_width, s_(height)), c_vec2(content_padding_x, s_(5)), s_(0, 0), window_flags_no_move | window_flags_no_scrollbar, child_flags_none); c_window* window = gui->get_window(); draw->rect_filled(window->DrawList, window->Rect().Min, window->Rect().Max, draw->get_clr(clr->child), s_(14)); g_panel_number = panel_number; } static void end_visual_section() { gui->end_content(); } static visual_panel_density_state begin_visual_panel_density() { c_window* window = gui->get_window(); visual_panel_density_state state{ var->gui.dpi, window->FontWindowScale }; var->gui.dpi = ImMax(0.01f, state.dpi * visual_panel_scale); ImGui::SetWindowFontScale(state.font_scale * visual_panel_scale); return state; } static void end_visual_panel_density(visual_panel_density_state state) { ImGui::SetWindowFontScale(state.font_scale); var->gui.dpi = state.dpi; } static void draw_visual_sidebar_glass(const c_rect& rect) { ImDrawList* draw_list = gui->get_window()->DrawList; const float rounding = s_(14); draw->rect_filled(draw_list, rect.Min, rect.Max, draw->get_clr(clr->child), rounding); } // Full-width single-column panel (used by Info / Radar / Settings). static void begin_full_section(std::string_view name, float height, bool scroll = false) { const float section_width = gui->content_avail().x; const float content_padding_x = ImMax(0.f, section_width * 0.035f); const window_flags flags = window_flags_no_move | (scroll ? 0 : window_flags_no_scrollbar); gui->begin_content(name, c_vec2(section_width, s_(height)), c_vec2(content_padding_x, s_(10)), s_(0, 6), flags, child_flags_none); c_window* window = gui->get_window(); draw->rect_filled(window->DrawList, window->Rect().Min, window->Rect().Max, draw->get_clr(clr->child), s_(14)); } // Accent section heading. static void lumin_heading(const char* text) { c_window* w = gui->get_window(); const c_vec2 pos = w->DC.CursorPos; const c_vec2 size = c_vec2(gui->content_avail().x, s_(22)); const c_rect rect(pos, pos + size); gui->item_size(rect); if (!gui->item_add(rect, w->GetID(text))) return; draw->text_clipped(w->DrawList, font->get(inter_semibold, 13), rect.Min, rect.Max, draw->get_clr(clr->accent), text, 0, 0, { 0.f, 0.5f }); } // Muted single-line note. static void lumin_note(const char* text) { c_window* w = gui->get_window(); const c_vec2 pos = w->DC.CursorPos; const c_vec2 size = c_vec2(gui->content_avail().x, s_(16)); const c_rect rect(pos, pos + size); gui->item_size(rect); if (!gui->item_add(rect, w->GetID(text))) return; draw->text_clipped(w->DrawList, font->get(inter_medium, 11), rect.Min, rect.Max, draw->get_clr(clr->text), text, 0, 0, { 0.f, 0.5f }); } // Read-only "label .... value" row on a rounded widget background. static void lumin_kv(const char* label, const std::string& value, const c_vec4& value_clr) { c_window* w = gui->get_window(); const c_vec2 pos = w->DC.CursorPos; const c_vec2 size = c_vec2(gui->content_avail().x, s_(34)); const c_rect rect(pos, pos + size); gui->item_size(rect); if (!gui->item_add(rect, w->GetID(label))) return; draw->rect_filled(w->DrawList, rect.Min, rect.Max, draw->get_clr(clr->widget), s_(8)); draw->text_clipped(w->DrawList, font->get(inter_semibold, 12), rect.Min + s_(12, 0), rect.Max, draw->get_clr(clr->white), label, 0, 0, { 0.f, 0.5f }); draw->text_clipped(w->DrawList, font->get(inter_medium, 11), rect.Min, rect.Max - s_(12, 0), draw->get_clr(value_clr), value.data(), 0, 0, { 1.f, 0.5f }); } // ---- ESP / Items content -------------------------------------------------- static void render_esp_tab(const visual_widget_filter& w, float section_height) { if (!g_menu) return; gui->begin_group(); { begin_visual_section("Entities", section_height); w.checkbox("Players", "Show player ESP", g_menu->showPlayers); w.checkbox("Animals", "Show animal ESP", g_menu->showAnimals); w.checkbox("Zombies", "Show infected ESP", g_menu->showZombies); w.checkbox("Items", "Show loot ESP", g_menu->showItems); w.checkbox("Corpses", "Show dead bodies", g_menu->showCorpses); w.checkbox("Bounding Box", "Draw entity box", g_menu->showBox); w.checkbox("Skeleton", "Draw bone skeleton", g_menu->showSkeleton); w.checkbox("Head Circle", "Draw head highlight", g_menu->showHeadDot); w.checkbox("Weapon In Hand", "Show held weapon name", g_menu->showWeapon); w.checkbox("Health Bar", "Draw player health bar", g_menu->showHealthBar); w.checkbox("Health Number", "Draw numeric health", g_menu->showHealthNumber); w.checkbox("Skeleton Debug", "Label every named bone", g_menu->debugSkeleton); end_visual_section(); } gui->end_group(); gui->sameline(); gui->begin_group(); { begin_visual_section("Draw Distance", section_height); w.slider("Players", "Max player draw distance", g_menu->playerMaxDist, 50.f, 1000.f, "%.0f m"); w.slider("Animals", "Max animal draw distance", g_menu->animalMaxDist, 50.f, 1000.f, "%.0f m"); w.slider("Zombies", "Max zombie draw distance", g_menu->zombieMaxDist, 50.f, 500.f, "%.0f m"); w.slider("Items", "Max loot draw distance", g_menu->itemMaxDist, 20.f, 200.f, "%.0f m"); end_visual_section(); } gui->end_group(); } static void render_items_tab(const visual_widget_filter& w, float section_height) { if (!g_menu || !g_menu->itemCategories) return; struct cat_t { const char* key; const char* label; }; static const std::array kCats = { { { "isWeapon", "Weapons" }, { "isAmmo", "Ammo" }, { "isMelee", "Melee" }, { "isExplosives", "Explosives" }, { "isMedical", "Medical" }, { "isFood", "Food" }, { "isConsumables", "Consumables" }, { "isClothing", "Clothing" }, { "isBackpack", "Backpacks" }, { "isOptics", "Optics" }, { "isWeaponAttachments", "Weapon Attachments" }, { "isTool", "Tools" }, { "isCrafting", "Crafting" }, { "isVehiclePart", "Vehicle Parts" }, { "isForBuilding", "Building" }, { "isHouse", "House / Terrain" }, { "isOtherLoot", "Other" }, } }; auto& cats = *g_menu->itemCategories; auto draw_category = [&](const cat_t& c) { // Missing key defaults to enabled; widget mutates the map slot directly. auto it = cats.find(c.key); if (it == cats.end()) it = cats.emplace(c.key, true).first; w.checkbox(c.label, "Toggle loot category", &it->second); }; const size_t split = (kCats.size() + 1) / 2; gui->begin_group(); { begin_visual_section("Loot Categories", section_height); for (size_t i = 0; i < split; i++) draw_category(kCats[i]); end_visual_section(); } gui->end_group(); gui->sameline(); gui->begin_group(); { begin_visual_section("Loot Categories##2", section_height); for (size_t i = split; i < kCats.size(); i++) draw_category(kCats[i]); end_visual_section(); } gui->end_group(); } static void render_info_tab(float section_height) { const c_vec4 green = c_col(75, 225, 145).Value; const c_vec4 orange = c_col(255, 175, 75).Value; begin_full_section("Info", section_height); { lumin_heading("Server"); if (g_menu && g_menu->connected) { lumin_kv("Status", "Connected", green); if (!g_menu->serverName.empty()) lumin_kv("Server", g_menu->serverName, clr->white.Value); if (!g_menu->mapName.empty()) lumin_kv("Map", g_menu->mapName, clr->white.Value); if (g_menu->hasPos) { char pos[64]; ImFormatString(pos, IM_ARRAYSIZE(pos), "%.1f / %.1f / %.1f", g_menu->px, g_menu->py, g_menu->pz); lumin_kv("Position", pos, clr->accent.Value); } gui->dummy(c_vec2(0, s_(6))); lumin_heading("Entity Counts"); lumin_kv("Players", std::to_string(g_menu->nPlayers), clr->accent.Value); lumin_kv("Animals", std::to_string(g_menu->nAnimals), clr->accent.Value); lumin_kv("Zombies", std::to_string(g_menu->nZombies), clr->accent.Value); lumin_kv("Vehicles", std::to_string(g_menu->nVehicles), clr->accent.Value); lumin_kv("Items", std::to_string(g_menu->nItems), clr->accent.Value); lumin_kv("Bullets", std::to_string(g_menu->nBullets), clr->accent.Value); } else { lumin_kv("Status", (g_menu && !g_menu->status.empty()) ? g_menu->status : "Offline", orange); } } end_visual_section(); } static constexpr const char* kRadarDomain = "radar.charliecharliekirky.christmas"; static void render_radar_tab(float section_height) { begin_full_section("Radar", section_height, true); { lumin_heading("Web Radar"); lumin_note("Open this address in a browser:"); gui->dummy(c_vec2(0, s_(4))); if (widgets->action_button(kRadarDomain, "copy")) ImGui::SetClipboardText(kRadarDomain); if (g_menu) { gui->dummy(c_vec2(0, s_(6))); lumin_heading("Connection"); lumin_kv("Port", std::to_string(g_menu->webPort), clr->accent.Value); lumin_kv("Password", "Set in config.cfg", clr->text.Value); } } end_visual_section(); } static void render_exit_tab(float section_height) { begin_full_section("Exit", section_height); { lumin_heading("Exit Application"); lumin_note("This will close the overlay and exit the program."); gui->dummy(c_vec2(0, s_(10))); const c_col saved_accent = clr->accent; clr->accent = c_col(225, 70, 70); if (widgets->primary_button("Exit", "back") && g_menu && g_menu->onExit) g_menu->onExit(); clr->accent = saved_accent; } end_visual_section(); } static void render_settings_tab(float section_height) { if (!g_menu) return; // Persistent text buffers backing the four resolution fields. Seeded once // from the live values, then treated as the source of truth (parsed back // into the int pointers every frame). static char ovr_w[8], ovr_h[8], rnd_w[8], rnd_h[8]; static bool buffers_ready = false; if (!buffers_ready) { ImFormatString(ovr_w, IM_ARRAYSIZE(ovr_w), "%d", *g_menu->pendingW); ImFormatString(ovr_h, IM_ARRAYSIZE(ovr_h), "%d", *g_menu->pendingH); ImFormatString(rnd_w, IM_ARRAYSIZE(rnd_w), "%d", *g_menu->pendingRW); ImFormatString(rnd_h, IM_ARRAYSIZE(rnd_h), "%d", *g_menu->pendingRH); buffers_ready = true; } begin_full_section("Settings", section_height, true); { lumin_heading("Overlay (Monitor) Resolution"); lumin_note("Set to your MONITOR size. 0 x 0 = auto-detect."); gui->push_id("ovr_res"); widgets->text_field("Width", ovr_w, IM_ARRAYSIZE(ovr_w)); widgets->text_field("Height", ovr_h, IM_ARRAYSIZE(ovr_h)); gui->pop_id(); *g_menu->pendingW = ImMax(0, atoi(ovr_w)); *g_menu->pendingH = ImMax(0, atoi(ovr_h)); if (widgets->primary_button("Apply Monitor Resolution") && g_menu->onApplyDisplayRes) g_menu->onApplyDisplayRes(); gui->dummy(c_vec2(0, s_(8))); lumin_heading("Game Render Resolution"); lumin_note("Set to the in-game resolution when it differs from the"); lumin_note("monitor. 0 x 0 = no stretched-res correction."); gui->push_id("rnd_res"); widgets->text_field("Width", rnd_w, IM_ARRAYSIZE(rnd_w)); widgets->text_field("Height", rnd_h, IM_ARRAYSIZE(rnd_h)); gui->pop_id(); *g_menu->pendingRW = ImMax(0, atoi(rnd_w)); *g_menu->pendingRH = ImMax(0, atoi(rnd_h)); widgets->checkbox("Stretch to fill", "GPU stretches game to fill the monitor", g_menu->stretchToFill); if (widgets->primary_button("Apply Render Resolution") && g_menu->onApplyRenderRes) g_menu->onApplyRenderRes(); gui->dummy(c_vec2(0, s_(10))); lumin_heading("General"); lumin_note("Press INSERT to toggle this menu."); gui->dummy(c_vec2(0, s_(4))); if (widgets->primary_button("Save Config", "active") && g_menu->onSaveConfig) g_menu->onSaveConfig(); } end_visual_section(); } // --------------------------------------------------------------------------- void c_gui::render() { gui->initialize(); sync_layout_preferences(); gui->easing(var->gui.tab_alpha, var->gui.tab != var->gui.tab_stored ? 0.f : 1.f, 7.f, static_easing); if (var->gui.tab_alpha == 0) var->gui.tab = var->gui.tab_stored; const c_vec2 target(s_(visual_window_width), s_(visual_window_height)); gui->easing(elements->window.size.x, target.x, 24.f, dynamic_easing); gui->easing(elements->window.size.y, target.y, 24.f, dynamic_easing); const ImVec2 disp = ImGui::GetIO().DisplaySize; gui->set_next_window_size(elements->window.size); gui->set_next_window_pos(c_vec2(ImMax(0.f, (disp.x - elements->window.size.x) * 0.5f), ImMax(0.f, (disp.y - elements->window.size.y) * 0.5f))); gui->begin(elements->window.name, nullptr, window_flags_no_scrollbar | window_flags_no_scroll_with_mouse | window_flags_no_bring_to_front_on_focus | window_flags_no_focus_on_appearing | window_flags_no_background | window_flags_no_decoration | window_flags_no_move); { gui->set_style(); gui->draw_decorations(); const float top_row_y = visual_outer_padding; const float top_row_height = 50.f; const float top_row_gap = 2.f; const float bottom_row_y = top_row_y + top_row_height + top_row_gap; const float bottom_row_height = visual_window_height - bottom_row_y - visual_outer_padding; const float sidebar_tabs_y = top_row_y + top_row_height; const float sidebar_tabs_height = visual_window_height - sidebar_tabs_y - visual_outer_padding; draw_visual_sidebar_glass(c_rect(c_vec2(s_(visual_outer_padding), s_(top_row_y)), c_vec2(s_(visual_outer_padding + visual_sidebar_width), s_(visual_window_height - visual_outer_padding)))); gui->set_pos(c_vec2(s_(visual_outer_padding), s_(top_row_y)), pos_all); gui->begin_content("TopBrand", c_vec2(s_(visual_sidebar_width), s_(top_row_height)), s_(0, 0), s_(0, 0), window_flags_no_scrollbar | window_flags_no_background, child_flags_none); { widgets->brand_header("KarachiHook", var->gui.profile_name[0] != '\0' ? var->gui.profile_name : "DayZ Overlay"); } gui->end_content(); gui->set_pos(c_vec2(s_(visual_outer_padding), s_(sidebar_tabs_y)), pos_all); gui->begin_content("Tabs", c_vec2(s_(visual_sidebar_width), s_(sidebar_tabs_height)), s_(10, 10), s_(0, 4), window_flags_no_scrollbar | window_flags_no_background, child_flags_none); { var->gui.sidebar_glass = true; { c_window* tabs_inner_bg = gui->get_window(); static c_vec4 sidebar_overlay = c_vec4(0, 0, 0, 0); gui->easing(sidebar_overlay, g_sidebar_selected_rect, 18.f, dynamic_easing); if (sidebar_overlay.z > sidebar_overlay.x + 1.f) { draw->rect_filled(tabs_inner_bg->DrawList, c_vec2(sidebar_overlay.x, sidebar_overlay.y), c_vec2(sidebar_overlay.z, sidebar_overlay.w), draw->get_clr(clr->widget), s_(9.1f)); } } widgets->tab_button("ESP", "visuals", 1); widgets->tab_button("Items", "loot", 2); widgets->tab_button("Radar", "world", 3); widgets->tab_button("Settings", "polish", 4); widgets->tab_button("Exit", "back", 5); widgets->tab_button("Info", "stats", 6); { static c_vec4 sidebar_indicator = c_vec4(0, 0, 0, 0); gui->easing(sidebar_indicator, g_sidebar_selected_rect, 18.f, dynamic_easing); if (sidebar_indicator.w > sidebar_indicator.y + 1.f) { c_window* tabs_inner = gui->get_window(); const float bar_w = s_(2); const float bar_inset_y = s_(6); const float bar_x = sidebar_indicator.x + s_(2); const c_vec2 bar_min = c_vec2(bar_x, sidebar_indicator.y + bar_inset_y); const c_vec2 bar_max = c_vec2(bar_x + bar_w, sidebar_indicator.w - bar_inset_y); draw->rect_filled(tabs_inner->DrawList, bar_min, bar_max, draw->get_clr(clr->accent), bar_w * 0.5f); } } gui->easing(elements->tab_window_width, gui->get_window()->Size.x, 24.f, dynamic_easing); var->gui.sidebar_glass = false; } gui->end_content(); gui->push_var(style_var_alpha, var->gui.tab_alpha); const float feature_x = visual_outer_padding + visual_sidebar_width + visual_outer_padding; const float feature_width = visual_window_width - feature_x - visual_outer_padding; const float feature_header_height = top_row_height * 0.8f; const float feature_header_y = top_row_y; gui->set_pos(c_vec2(s_(feature_x), s_(feature_header_y) + s_(10) * (1.f - var->gui.tab_alpha)), pos_all); { const c_vec2 pill_pos = gui->get_window()->DC.CursorPos; draw->rect_filled(gui->get_window()->DrawList, pill_pos, pill_pos + c_vec2(s_(feature_width), s_(feature_header_height)), draw->get_clr(clr->child), s_(14)); gui->begin_content("FeatureHeader", c_vec2(s_(feature_width), s_(feature_header_height)), s_(8, 4), s_(8, 0), window_flags_no_scrollbar | window_flags_no_background, child_flags_none); { const float search_width = s_(178.f); widgets->search_field("Search", var->gui.feature_search, IM_ARRAYSIZE(var->gui.feature_search), c_vec2(search_width, s_(32.f))); } gui->end_content(); } gui->set_pos(c_vec2(s_(feature_x), s_(bottom_row_y) + s_(10) * (1.f - var->gui.tab_alpha)), pos_all); gui->begin_content("Features", c_vec2(s_(feature_width), s_(bottom_row_height)), s_(visual_feature_padding_x, visual_feature_padding_y), c_vec2(s_(visual_column_gap), 0.f), window_flags_no_scrollbar); { const visual_panel_density_state density_state = begin_visual_panel_density(); g_panel_number = 3; gui->easing(elements->child_width, (gui->content_avail().x - s_(visual_column_gap)) / 2, 24.f, dynamic_easing); const float section_height = visual_section_height(1); const visual_widget_filter visual_widgets; switch (var->gui.tab) { case 1: render_esp_tab(visual_widgets, section_height); break; case 2: render_items_tab(visual_widgets, section_height); break; case 3: render_radar_tab(section_height); break; case 4: render_settings_tab(section_height); break; case 5: render_exit_tab(section_height); break; case 6: render_info_tab(section_height); break; default: break; } end_visual_panel_density(density_state); } gui->end_content(); gui->pop_var(); } gui->end(); } // Shim called by GameOverlay (declared in src/Overlay/MenuBridge.h). void RenderLuminMenu() { gui->render(); }