Editor texts (EN/DE), whole-campaign play and briefings for editor missions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-05 17:15:20 +01:00
1 parent 30dd8441b9
commit 985c34759d
6 files changed
+705 -14

No files matched your search

+31 -4
View File
@@ -196,6 +196,12 @@ fn sanitize_campaign_key(value: &str) -> String {
value.trim().chars().filter(|c| c.is_ascii_alphanumeric() || *c == '_' || *c == '-').take(48).collect()
}
// the briefing of an editor mission (None: it has no text)
fn briefing_of(doc: &campaign_doc::CampaignDoc, i: usize) -> Option<(String, String)> {
let m = doc.missions.get(i)?;
(!m.story.trim().is_empty()).then(|| (m.title.clone(), m.story.clone()))
}
// a mission of an editor campaign (its map is painted, or rolled from the run's seed)
fn custom_mission_game(doc: &campaign_doc::CampaignDoc, i: usize, run_seed: u32) -> (Game, Cam) {
let g = campaign::start_editor_mission(&doc.missions[i], i, run_seed);
@@ -438,9 +444,11 @@ struct App {
frame_hist: [f32; FRAME_HIST],
frame_hist_pos: usize,
editor: Option<editor::Editor>, // the campaign editor (takes the whole frame while open)
editor_testing: bool, // a mission of the editor is being played
editor_testing: bool, // the editor waits while one of its missions is played
editor_test_only: bool, // only that mission (test play); else the campaign goes on
editor_public_pending: bool, // the public campaign list still has to be fetched
editor_loading: Option<String>, // server id of the own campaign being loaded
pending_briefing: Option<(String, String)>, // an editor mission began: show its briefing
custom_campaign: Option<campaign_doc::CampaignDoc>,
custom_progress: Option<campaign_doc::CampaignProgress>,
custom_mission_index: Option<usize>,
@@ -652,7 +660,7 @@ async fn main() {
let seed = (miniquad::date::now() * 1000.0) as u32 | 1;
// behind the title menu: the endless bridge battle
let (game, cam) = Game::new_demo(seed);
let mut app = App { game, cam, settings, seed, status: None, recorded: false, client: MatchClient::new(), ws_id: 0, match_mode: false, coop: false, fps: 0.0, renderer: platform::renderer(), frame_ms: 0.0, frame_hist: [0.0; FRAME_HIST], frame_hist_pos: 0, custom_campaign: None, custom_progress: None, custom_mission_index: None, custom_next_index: None, editor: None, editor_testing: false, editor_public_pending: false, editor_loading: None };
let mut app = App { game, cam, settings, seed, status: None, recorded: false, client: MatchClient::new(), ws_id: 0, match_mode: false, coop: false, fps: 0.0, renderer: platform::renderer(), frame_ms: 0.0, frame_hist: [0.0; FRAME_HIST], frame_hist_pos: 0, custom_campaign: None, custom_progress: None, custom_mission_index: None, custom_next_index: None, editor: None, editor_testing: false, editor_test_only: false, editor_public_pending: false, editor_loading: None, pending_briefing: None };
menu.progress = platform::storage_get(PROGRESS_KEY).and_then(|s| serde_json::from_str(&s).ok()).unwrap_or_default();
apply_game_settings(&mut app.game, &app.settings);
let mut inp = Input { ldown: None, rdown: None, rlast: (0.0, 0.0), rdrag: false, mlast: None, minimap_drag: false, tlast: None, touch_world: false, inspect: None };
@@ -684,6 +692,16 @@ async fn main() {
app.editor = Some(editor::Editor::new(menu.campaign_doc.clone()));
menu.page = Some(Page::Title);
}
// an editor mission began: its briefing first
if let Some(b) = app.pending_briefing.take() {
menu.custom_briefing = b;
menu.page = Some(Page::CustomBriefing);
menu.scroll_lines(-1000);
}
// a played editor campaign is over: back into the editor
if menu.page == Some(Page::CampaignEditor) && app.editor_testing {
back_to_editor(&mut app, &mut menu, &mut r3d);
}
if app.editor.is_some() && !app.editor_testing {
editor_frame(&mut app, &mut menu, &mut cloud, &mut r3d, &gfx, &mut ui, dt, now);
next_frame().await;
@@ -1311,6 +1329,7 @@ async fn main() {
let _ = mission_doc;
let progress = campaign_doc::CampaignProgress::for_doc(&menu.campaign_doc);
(app.game, app.cam) = custom_mission_game(&menu.campaign_doc, i, progress.run_seed);
app.pending_briefing = briefing_of(&menu.campaign_doc, i);
apply_game_settings(&mut app.game, &app.settings);
app.game.coop = false;
app.coop = false;
@@ -1391,7 +1410,7 @@ async fn main() {
app.coop = false;
}
// end of a mission: next mission (won) or try again (lost)
UiAction::EndNext | UiAction::EndCampaign if app.editor_testing => back_to_editor(&mut app, &mut menu, &mut r3d),
UiAction::EndNext | UiAction::EndCampaign if app.editor_testing && app.editor_test_only => back_to_editor(&mut app, &mut menu, &mut r3d),
UiAction::EndNext => {
if app.custom_campaign.is_some() {
let campaign = app.custom_campaign.clone();
@@ -1401,6 +1420,7 @@ async fn main() {
if let Some(campaign) = campaign {
if next < campaign.missions.len() {
(app.game, app.cam) = custom_mission_game(&campaign, next, progress.as_ref().map_or(1, |p| p.run_seed));
app.pending_briefing = briefing_of(&campaign, next);
apply_game_settings(&mut app.game, &app.settings);
app.game.coop = false;
app.coop = false;
@@ -1424,6 +1444,7 @@ async fn main() {
} else if let (Some(campaign), Some(i)) = (campaign, app.custom_mission_index) {
if i < campaign.missions.len() {
(app.game, app.cam) = custom_mission_game(&campaign, i, progress.as_ref().map_or(1, |p| p.run_seed));
app.pending_briefing = briefing_of(&campaign, i);
apply_game_settings(&mut app.game, &app.settings);
app.game.coop = false;
app.coop = false;
@@ -1841,9 +1862,14 @@ fn editor_frame(app: &mut App, menu: &mut Menu, cloud: &mut Cloud, r3d: &mut R3d
menu.page = Some(Page::Title);
return; // the editor is gone
}
editor::EdAction::Test(i) => {
editor::EdAction::Test(_) | editor::EdAction::Play => {
let (i, only) = match act {
editor::EdAction::Test(i) => (i, true),
_ => (0, false),
};
let progress = campaign_doc::CampaignProgress::for_doc(&ed.doc);
(app.game, app.cam) = custom_mission_game(&ed.doc, i, progress.run_seed);
app.pending_briefing = briefing_of(&ed.doc, i);
apply_game_settings(&mut app.game, &app.settings);
app.game.coop = false;
app.coop = false;
@@ -1853,6 +1879,7 @@ fn editor_frame(app: &mut App, menu: &mut Menu, cloud: &mut Cloud, r3d: &mut R3d
app.custom_mission_index = Some(i);
app.custom_next_index = None;
app.editor_testing = true;
app.editor_test_only = only;
menu.editor_test = true;
menu.page = None;
ui.log.clear();