Co-op campaign "League against the Lightwatch": 20 missions, selectable on the Match page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
405f8f60b2
commit
4e49c2fdc9
9 files changed
+240
-13
No files matched your search
+45
-11
@@ -421,7 +421,9 @@ pub struct Menu {
|
||||
pub error: Option<String>, // message on the login and account pages
|
||||
pub match_ui: MatchUi, // copied state of the multiplayer relay, shown on the Match page
|
||||
pub coop_mission: usize, // co-op campaign mission selected on the Match page
|
||||
pub coop_editor: bool, // the Match page offers the editor campaign instead of the built-in one
|
||||
pub coop_editor: bool, // the Match page offers a campaign document instead of the built-in missions
|
||||
pub coop_league: bool, // ... and that document is the co-op campaign "League against the Lightwatch"
|
||||
league_doc: Option<CampaignDoc>, // the co-op campaign, built the first time it is chosen
|
||||
pub coop_editor_mission: usize, // mission of `campaign_doc` selected for co-op
|
||||
pub in_match: bool, // a match is being played; the pause menu changes its shape
|
||||
pub gold_allies: Vec<u8>, // allies of the local master that can get gold (pause menu)
|
||||
@@ -463,6 +465,8 @@ impl Menu {
|
||||
match_ui: MatchUi::default(),
|
||||
coop_mission: crate::campaign::coop_mission_indexes().first().copied().unwrap_or(0),
|
||||
coop_editor: false,
|
||||
coop_league: false,
|
||||
league_doc: None,
|
||||
coop_editor_mission: 0,
|
||||
in_match: false,
|
||||
gold_allies: Vec::new(),
|
||||
@@ -764,7 +768,7 @@ impl Menu {
|
||||
Some(b @ (Btn::MatchCoopPrev | Btn::MatchCoopNext)) => {
|
||||
let dir = if b == Btn::MatchCoopPrev { -1 } else { 1 };
|
||||
if self.coop_editor {
|
||||
self.coop_editor_mission = crate::campaign::next_editor_coop_mission(&self.campaign_doc, self.coop_editor_mission, dir);
|
||||
self.coop_editor_mission = crate::campaign::next_editor_coop_mission(self.coop_doc(), self.coop_editor_mission, dir);
|
||||
} else {
|
||||
self.coop_mission = crate::campaign::next_coop_mission(self.coop_mission, dir);
|
||||
}
|
||||
@@ -772,8 +776,25 @@ impl Menu {
|
||||
MenuAction::Consumed
|
||||
}
|
||||
Some(Btn::MatchCoopSource) => {
|
||||
self.coop_editor = !self.coop_editor && !self.campaign_doc.missions.is_empty();
|
||||
self.coop_editor_mission = crate::campaign::next_editor_coop_mission(&self.campaign_doc, self.coop_editor_mission, 0);
|
||||
// built-in missions -> the league -> the editor's campaign (if it has missions) -> ...
|
||||
match (self.coop_editor, self.coop_league) {
|
||||
(false, _) => {
|
||||
if self.league_doc.is_none() {
|
||||
self.league_doc = Some(crate::editor::coop_campaign::coop_campaign());
|
||||
}
|
||||
self.coop_editor = true;
|
||||
self.coop_league = true;
|
||||
}
|
||||
(true, true) if !self.campaign_doc.missions.is_empty() => self.coop_league = false,
|
||||
_ => {
|
||||
self.coop_editor = false;
|
||||
self.coop_league = false;
|
||||
}
|
||||
}
|
||||
self.coop_editor_mission = 0;
|
||||
if self.coop_editor {
|
||||
self.coop_editor_mission = crate::campaign::next_editor_coop_mission(self.coop_doc(), 0, 0);
|
||||
}
|
||||
self.confirm = None;
|
||||
MenuAction::Consumed
|
||||
}
|
||||
@@ -1717,6 +1738,14 @@ impl Menu {
|
||||
self.column(gfx, x + (cols as f32 * CW() - w) * 0.5, y + (rows - 4) as f32 * CH(), w, &[(Btn::Resume, label)]);
|
||||
}
|
||||
|
||||
// the campaign document the co-op create offers: the league or the editor's campaign
|
||||
pub fn coop_doc(&self) -> &CampaignDoc {
|
||||
match (&self.league_doc, self.coop_league) {
|
||||
(Some(d), true) => d,
|
||||
_ => &self.campaign_doc,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scrollable(&self) -> bool {
|
||||
matches!(
|
||||
self.page,
|
||||
@@ -1920,15 +1949,16 @@ impl Menu {
|
||||
}
|
||||
|
||||
// the editor campaign can only be offered while it has missions (it may have been replaced)
|
||||
let editor_coop = self.coop_editor && !self.campaign_doc.missions.is_empty();
|
||||
let editor_list = if editor_coop { crate::campaign::editor_coop_indexes(&self.campaign_doc) } else { Vec::new() };
|
||||
let doc = self.coop_doc().clone();
|
||||
let editor_coop = self.coop_editor && !doc.missions.is_empty();
|
||||
let editor_list = if editor_coop { crate::campaign::editor_coop_indexes(&doc) } else { Vec::new() };
|
||||
if editor_coop && !editor_list.contains(&self.coop_editor_mission) {
|
||||
self.coop_editor_mission = editor_list.first().copied().unwrap_or(0);
|
||||
}
|
||||
if !ui.started && !ui.room_open() && editor_coop {
|
||||
let line = match self.campaign_doc.missions.get(self.coop_editor_mission).filter(|_| !editor_list.is_empty()) {
|
||||
let line = match doc.missions.get(self.coop_editor_mission).filter(|_| !editor_list.is_empty()) {
|
||||
Some(m) => {
|
||||
let name = if self.campaign_doc.name.trim().is_empty() { "?".to_string() } else { self.campaign_doc.name.clone() };
|
||||
let name = if doc.name.trim().is_empty() { "?".to_string() } else { doc.name.clone() };
|
||||
let title = if m.title.trim().is_empty() { m.key.clone() } else { m.title.clone() };
|
||||
trf("net.coop_editor_mission", &[name, (self.coop_editor_mission + 1).to_string(), title])
|
||||
}
|
||||
@@ -1963,9 +1993,13 @@ impl Menu {
|
||||
items.push((Btn::MatchCoopCreate, tr("net.coop_create")));
|
||||
items.push((Btn::MatchCoopNext, ">".to_string()));
|
||||
}
|
||||
if !self.campaign_doc.missions.is_empty() {
|
||||
items.push((Btn::MatchCoopSource, tr(if editor_coop { "net.coop_builtin" } else { "net.coop_editor" })));
|
||||
}
|
||||
// the button names what comes next
|
||||
let next = match (editor_coop, self.coop_league) {
|
||||
(false, _) => "net.coop_league",
|
||||
(true, true) if !self.campaign_doc.missions.is_empty() => "net.coop_editor",
|
||||
_ => "net.coop_builtin",
|
||||
};
|
||||
items.push((Btn::MatchCoopSource, tr(next)));
|
||||
}
|
||||
if ui.room_open() {
|
||||
items.push((Btn::MatchReady, tr(if ui.ready { "net.unready" } else { "net.ready" })));
|
||||
|
||||
Reference in new issue
Block a user