Add campaign editor script runtime and debug overlays

This commit is contained in:
Richard Zink committed 2026-11-05 12:22:59 +01:00
1 parent cd35ca8e3d
commit b06c48172b
13 files changed
+2211 -66

No files matched your search

+49 -3
View File
@@ -29,7 +29,7 @@ pub struct FortDef {
}
pub struct MissionDef {
pub key: &'static str,
pub key: String,
pub size: (usize, usize),
pub seed: u32,
pub gold: f32,
@@ -145,9 +145,9 @@ impl FortDef {
}
}
fn base(key: &'static str, size: (usize, usize), seed: u32, goals: Vec<Goal>) -> MissionDef {
fn base(key: &str, size: (usize, usize), seed: u32, goals: Vec<Goal>) -> MissionDef {
MissionDef {
key,
key: key.to_string(),
size,
seed,
gold: 3000.0,
@@ -169,6 +169,21 @@ fn base(key: &'static str, size: (usize, usize), seed: u32, goals: Vec<Goal>) ->
}
}
// Converts one campaign editor mission into the same shape the campaign generator uses.
pub fn mission_def_from_doc(d: &crate::campaign_doc::MissionDoc) -> MissionDef {
let mut out = base(&d.key, d.size, d.seed, crate::campaign_doc::parse_goals(&d.goals));
out.gold = d.gold;
out.portals = d.portals;
out.treasures = d.treasures;
out.waves = d.waves;
out.wave_limit = d.wave_limit;
out.first_wave = d.first_wave;
out.gate = d.waves;
out.gate_defenders = d.waves;
out.time_limit = d.time_limit;
out
}
// Rivers are at least four tiles wide: a ranged attack just reaches across.
pub fn missions() -> Vec<MissionDef> {
let mut v = Vec::new();
@@ -487,6 +502,16 @@ pub fn start_coop_mission(i: usize, carry: Option<&Carry>) -> Game {
fn start_mission_mode(i: usize, carry: Option<&Carry>, coop: bool) -> Game {
let all = missions();
let d = &all[i.min(all.len() - 1)];
start_mission_def(d, i, carry, coop)
}
// A mission generated from the campaign editor file: same start pipeline, but without the
// built-in campaign table and without language-file story keys for the title.
pub fn start_mission_doc(d: &MissionDef, i: usize, carry: Option<&Carry>) -> Game {
start_mission_def(d, i, carry, false)
}
fn start_mission_def(d: &MissionDef, i: usize, carry: Option<&Carry>, coop: bool) -> Game {
let (w, h) = d.size;
let opts = GenOpts { portals: Some(d.portals), treasures: Some(d.treasures), gate: d.gate, core_y: None };
let map = Map::generate_with(d.seed, w, h, &opts);
@@ -600,6 +625,27 @@ pub fn carry_from(g: &Game) -> Carry {
mod tests {
use super::*;
#[test]
fn a_custom_editor_mission_can_be_started() {
let doc = crate::campaign_doc::MissionDoc {
key: "custom01".into(),
title: "Custom".into(),
size: (72, 72),
seed: 9991,
gold: 3500.0,
goals: vec!["KillAll".into()],
..Default::default()
};
let def = mission_def_from_doc(&doc);
assert_eq!(def.key, "custom01");
assert_eq!(def.goals, vec![Goal::KillAll]);
let g = start_mission_doc(&def, 0, None);
let m = g.mission.as_ref().expect("the custom mission has mission state");
assert_eq!(m.goals, vec![Goal::KillAll]);
assert_eq!(g.gold, 3500.0);
}
#[test]
fn all_missions_build() {
for (i, d) in missions().iter().enumerate() {