| 267 | } |
| 268 | |
| 269 | void DrawCheatsTab() |
| 270 | { |
| 271 | ImGui::TextUnformatted("Mission"); |
| 272 | ImGui::Separator(); |
| 273 | |
| 274 | // One-button End Mission, matching the original OFP ENDMISSION word |
| 275 | // cheat shape — no outcome picker; the cheat just wins the mission. |
| 276 | // Power users who want a specific outcome use the `triEndMission |
| 277 | // "lose"` / `endmission end3` / etc. paths through tri or the |
| 278 | // console; Cmd_EndMission::Invoke keeps all the outcome strings. |
| 279 | // |
| 280 | // Re-queried every frame so the button greys instantly when there's |
| 281 | // no mission running or the mission has already entered teardown. |
| 282 | const bool canEnd = DebugCheats::Cmd_EndMission::Available(); |
| 283 | CheatButton("End Mission (win)", canEnd, |
| 284 | canEnd ? "Force the active mission to win (sets EndMode=EMEnd1).\n" |
| 285 | "Matches the 1999 ENDMISSION word-cheat semantics.\n" |
| 286 | "Closes the dev panel afterwards — the engine starts\n" |
| 287 | "tearing down the world over the next several frames\n" |
| 288 | "and keeping any in-mission UI alive during that\n" |
| 289 | "transition risks crashes (textures get evicted while\n" |
| 290 | "we'd still be querying them).\n" |
| 291 | "Other outcomes still available via `triEndMission` /\n" |
| 292 | "the dev console (lose, killed, end1..end6)." |
| 293 | : "Requires an active mission that has not already ended.", |
| 294 | [] |
| 295 | { |
| 296 | // Hide first (cheap, just sets a bool) — the deferred |
| 297 | // Invoke can then run after ImGui::Render with no |
| 298 | // panel-render side effects to worry about. |
| 299 | SetVisible(false); |
| 300 | Defer([] { DebugCheats::Cmd_EndMission::Invoke("win", s_cheatsStatus); }); |
| 301 | }); |
| 302 | |
| 303 | ImGui::Spacing(); |
| 304 | ImGui::TextUnformatted("System"); |
| 305 | ImGui::Separator(); |
| 306 | |
| 307 | // Full in-process reload — re-mounts all banks/addons/config and rebuilds |
| 308 | // the world on the same window (the mod "Apply" path). Gated to outside a |
| 309 | // mission: re-mounting mid-mission would evict assets the simulation still |
| 310 | // references. Hide the panel first, then run after ImGui::Render — the |
| 311 | // reload tears down the very world/UI we'd otherwise be drawing this frame. |
| 312 | const bool canReload = Poseidon::GApp != nullptr && Poseidon::GApp->m_canRender && GWorld != nullptr && |
| 313 | GWorld->GetMode() == GModeIntro; |
| 314 | CheatButton("Reload game", canReload, |
| 315 | canReload ? "Reload all game content (mods + config) in place.\n" |
| 316 | "Keeps the window, shows the loading screen, and lands\n" |
| 317 | "back on a fresh main menu." |
| 318 | : "Available from the main menu (not during a mission).", |
| 319 | [] |
| 320 | { |
| 321 | SetVisible(false); |
| 322 | // Queue the reload for the next AppIdle (before simulate/draw) rather than |
| 323 | // running it inside the swap — see RequestRemount / RequestDeferredReload. |
| 324 | if (Poseidon::GApp != nullptr) |
| 325 | Poseidon::GApp->RequestRemount(); |
| 326 | }); |
no test coverage detected