feat: add ballistic overlay and improve DMA stability
- Add ballistic aim dot and bullet trail rendering with menu toggles - Read local weapon ammo data for prediction inputs - Rework bone scatter reads to per-bone pages with cached skeleton fallback - Add DMA throughput stats to the overlay info panel - Improve signature scanning with page-based scatter reads - Cache encoded map tiles and support cross-origin/static web radar hosting - Add Caddy config for serving the web radar UI
This commit is contained in:
Vendored
+146
-76
@@ -220,47 +220,86 @@ static void lumin_kv(const char* label, const std::string& value, const c_vec4&
|
||||
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 --------------------------------------------------
|
||||
// ---- Tab content ----------------------------------------------------------
|
||||
|
||||
static void render_esp_tab(const visual_widget_filter& w, float section_height)
|
||||
static void render_aim_tab(const visual_widget_filter& w, float section_height)
|
||||
{
|
||||
if (!g_menu)
|
||||
return;
|
||||
|
||||
gui->begin_group();
|
||||
begin_full_section("Aim Assistance", section_height);
|
||||
{
|
||||
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();
|
||||
lumin_heading("Prediction");
|
||||
w.checkbox("Ballistic Dot", "Cyan dot showing where to aim to hit centre mass (accounts for gravity + drag)", g_menu->showBallisticDot);
|
||||
gui->dummy(c_vec2(0, s_(6)));
|
||||
lumin_heading("Trails");
|
||||
w.checkbox("Bullet Trails", "Draw flight path of each bullet from origin to impact or despawn", g_menu->showBulletTrails);
|
||||
}
|
||||
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();
|
||||
end_visual_section();
|
||||
}
|
||||
|
||||
static void render_items_tab(const visual_widget_filter& w, float section_height)
|
||||
static void render_visuals_tab(const visual_widget_filter& w, float section_height)
|
||||
{
|
||||
if (!g_menu)
|
||||
return;
|
||||
|
||||
if (var->gui.sub_tab_stored == 1)
|
||||
{
|
||||
// ---- Players sub-tab ----
|
||||
gui->begin_group();
|
||||
{
|
||||
begin_visual_section("Players", section_height);
|
||||
w.checkbox("Show Players", "Show player ESP", g_menu->showPlayers);
|
||||
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("Corpses", "Show dead bodies", g_menu->showCorpses);
|
||||
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");
|
||||
end_visual_section();
|
||||
}
|
||||
gui->end_group();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ---- World sub-tab ----
|
||||
gui->begin_group();
|
||||
{
|
||||
begin_visual_section("Entities", section_height);
|
||||
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);
|
||||
end_visual_section();
|
||||
}
|
||||
gui->end_group();
|
||||
|
||||
gui->sameline();
|
||||
|
||||
gui->begin_group();
|
||||
{
|
||||
begin_visual_section("Draw Distance", section_height);
|
||||
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_loot_tab(const visual_widget_filter& w, float section_height)
|
||||
{
|
||||
if (!g_menu || !g_menu->itemCategories)
|
||||
return;
|
||||
@@ -320,13 +359,17 @@ static void render_items_tab(const visual_widget_filter& w, float section_height
|
||||
gui->end_group();
|
||||
}
|
||||
|
||||
static constexpr const char* kRadarDomain = "radar.charliecharliekirky.christmas";
|
||||
|
||||
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;
|
||||
const c_vec4 red = c_col(225, 70, 70).Value;
|
||||
|
||||
begin_full_section("Info", section_height);
|
||||
begin_full_section("Info", section_height, true);
|
||||
{
|
||||
// ---- Server ----
|
||||
lumin_heading("Server");
|
||||
if (g_menu && g_menu->connected)
|
||||
{
|
||||
@@ -353,26 +396,39 @@ static void render_info_tab(float section_height)
|
||||
{
|
||||
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";
|
||||
// ---- DMA Handle ----
|
||||
gui->dummy(c_vec2(0, s_(6)));
|
||||
lumin_heading("DMA Handle");
|
||||
if (g_menu)
|
||||
{
|
||||
lumin_kv("Handle", g_menu->dmaAttached ? "Attached" : "Detached",
|
||||
g_menu->dmaAttached ? green : red);
|
||||
|
||||
static void render_radar_tab(float section_height)
|
||||
{
|
||||
begin_full_section("Radar", section_height, true);
|
||||
{
|
||||
char buf[64];
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.2f MB/s", g_menu->dmaReadMBps);
|
||||
lumin_kv("Read Speed", buf, clr->accent.Value);
|
||||
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f /s", g_menu->dmaScatterOps);
|
||||
lumin_kv("Scatter Calls", buf, clr->accent.Value);
|
||||
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.3f GB", g_menu->dmaTotalGB);
|
||||
lumin_kv("Total Read", buf, clr->text.Value);
|
||||
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%llu", static_cast<unsigned long long>(g_menu->dmaTotalOps));
|
||||
lumin_kv("Total Ops", buf, clr->text.Value);
|
||||
}
|
||||
|
||||
// ---- Web Radar ----
|
||||
gui->dummy(c_vec2(0, s_(6)));
|
||||
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");
|
||||
gui->dummy(c_vec2(0, s_(4)));
|
||||
lumin_kv("Port", std::to_string(g_menu->webPort), clr->accent.Value);
|
||||
lumin_kv("Password", "Set in config.cfg", clr->text.Value);
|
||||
}
|
||||
@@ -380,24 +436,7 @@ static void render_radar_tab(float section_height)
|
||||
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)
|
||||
static void render_config_tab(float section_height)
|
||||
{
|
||||
if (!g_menu)
|
||||
return;
|
||||
@@ -416,7 +455,7 @@ static void render_settings_tab(float section_height)
|
||||
buffers_ready = true;
|
||||
}
|
||||
|
||||
begin_full_section("Settings", section_height, true);
|
||||
begin_full_section("Config", section_height, true);
|
||||
{
|
||||
lumin_heading("Overlay (Monitor) Resolution");
|
||||
lumin_note("Set to your MONITOR size. 0 x 0 = auto-detect.");
|
||||
@@ -449,6 +488,16 @@ static void render_settings_tab(float section_height)
|
||||
gui->dummy(c_vec2(0, s_(4)));
|
||||
if (widgets->primary_button("Save Config", "active") && g_menu->onSaveConfig)
|
||||
g_menu->onSaveConfig();
|
||||
|
||||
gui->dummy(c_vec2(0, s_(10)));
|
||||
lumin_heading("Exit");
|
||||
lumin_note("This will close the overlay and exit the program.");
|
||||
gui->dummy(c_vec2(0, s_(4)));
|
||||
const c_col saved_accent = clr->accent;
|
||||
clr->accent = c_col(225, 70, 70);
|
||||
if (widgets->primary_button("Exit", "back") && g_menu->onExit)
|
||||
g_menu->onExit();
|
||||
clr->accent = saved_accent;
|
||||
}
|
||||
end_visual_section();
|
||||
}
|
||||
@@ -491,7 +540,7 @@ void c_gui::render()
|
||||
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");
|
||||
widgets->brand_header("DayZ DMA", var->gui.profile_name[0] != '\0' ? var->gui.profile_name : "DayZ Overlay");
|
||||
}
|
||||
gui->end_content();
|
||||
|
||||
@@ -512,12 +561,11 @@ void c_gui::render()
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
widgets->tab_button("Aim", "aim", 1);
|
||||
widgets->tab_button("Visuals", "visuals", 2);
|
||||
widgets->tab_button("Loot", "loot", 3);
|
||||
widgets->tab_button("Info", "stats", 4);
|
||||
widgets->tab_button("Config", "polish", 5);
|
||||
|
||||
{
|
||||
static c_vec4 sidebar_indicator = c_vec4(0, 0, 0, 0);
|
||||
@@ -555,6 +603,29 @@ void c_gui::render()
|
||||
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);
|
||||
|
||||
if (var->gui.tab == 2) // Visuals — show sub-tab row
|
||||
{
|
||||
// Animated pill highlight behind the selected sub_tab_button.
|
||||
static c_vec4 pill_anim = c_vec4(0, 0, 0, 0);
|
||||
c_window* pill_win = gui->get_window();
|
||||
gui->easing(pill_anim, g_pill_selected_rect, 18.f, dynamic_easing);
|
||||
if (pill_anim.z > pill_anim.x + 1.f)
|
||||
draw->rect_filled(pill_win->DrawList,
|
||||
c_vec2(pill_anim.x, pill_anim.y), c_vec2(pill_anim.z, pill_anim.w),
|
||||
draw->get_clr(clr->widget), s_(9.1f));
|
||||
|
||||
widgets->sub_tab_button("Players", "player", 1);
|
||||
gui->sameline(0.f, s_(4.f));
|
||||
widgets->sub_tab_button("World", "world", 2);
|
||||
// Keep on the same row; jump cursor to right edge for search.
|
||||
ImGui::SameLine(ImGui::GetContentRegionMax().x - search_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SetCursorPosX(ImGui::GetContentRegionMax().x - search_width);
|
||||
}
|
||||
|
||||
widgets->search_field("Search", var->gui.feature_search, IM_ARRAYSIZE(var->gui.feature_search), c_vec2(search_width, s_(32.f)));
|
||||
}
|
||||
gui->end_content();
|
||||
@@ -572,12 +643,11 @@ void c_gui::render()
|
||||
|
||||
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;
|
||||
case 1: render_aim_tab(visual_widgets, section_height); break;
|
||||
case 2: render_visuals_tab(visual_widgets, section_height); break;
|
||||
case 3: render_loot_tab(visual_widgets, section_height); break;
|
||||
case 4: render_info_tab(section_height); break;
|
||||
case 5: render_config_tab(section_height); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user