Co-op matches of editor campaigns
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0966e3318f
commit
abe01ff23e
13 files changed
+394
-44
No files matched your search
+46
-8
@@ -278,6 +278,7 @@ enum Btn {
|
||||
MatchCoopPrev,
|
||||
MatchCoopNext,
|
||||
MatchCoopCreate,
|
||||
MatchCoopSource, // switch between the built-in campaign and the editor campaign
|
||||
MatchTake(usize),
|
||||
MatchAi(usize),
|
||||
MatchReady,
|
||||
@@ -392,6 +393,7 @@ pub enum MenuAction {
|
||||
MatchJoin(String),
|
||||
MatchCreate,
|
||||
MatchCoopCreate(usize),
|
||||
MatchCoopEditorCreate(usize), // co-op match of a mission of `campaign_doc`
|
||||
MatchTakeSide(u8),
|
||||
MatchSetAi(u8, bool),
|
||||
MatchReady(bool),
|
||||
@@ -414,6 +416,8 @@ 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_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 editor_test: bool, // a mission of the editor is being tested: back to the editor
|
||||
pub custom_briefing: (String, String), // title and text of an editor mission's briefing
|
||||
@@ -451,6 +455,8 @@ impl Menu {
|
||||
error: None,
|
||||
match_ui: MatchUi::default(),
|
||||
coop_mission: crate::campaign::coop_mission_indexes().first().copied().unwrap_or(0),
|
||||
coop_editor: false,
|
||||
coop_editor_mission: 0,
|
||||
in_match: false,
|
||||
editor_test: false,
|
||||
custom_briefing: (String::new(), String::new()),
|
||||
@@ -746,16 +752,23 @@ impl Menu {
|
||||
None => MenuAction::Consumed,
|
||||
},
|
||||
Some(Btn::MatchCreate) => MenuAction::MatchCreate,
|
||||
Some(Btn::MatchCoopPrev) => {
|
||||
self.coop_mission = crate::campaign::next_coop_mission(self.coop_mission, -1);
|
||||
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);
|
||||
} else {
|
||||
self.coop_mission = crate::campaign::next_coop_mission(self.coop_mission, dir);
|
||||
}
|
||||
self.confirm = None;
|
||||
MenuAction::Consumed
|
||||
}
|
||||
Some(Btn::MatchCoopNext) => {
|
||||
self.coop_mission = crate::campaign::next_coop_mission(self.coop_mission, 1);
|
||||
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);
|
||||
self.confirm = None;
|
||||
MenuAction::Consumed
|
||||
}
|
||||
Some(Btn::MatchCoopCreate) if self.coop_editor => MenuAction::MatchCoopEditorCreate(self.coop_editor_mission),
|
||||
Some(Btn::MatchCoopCreate) => MenuAction::MatchCoopCreate(self.coop_mission),
|
||||
Some(Btn::MatchReady) => MenuAction::MatchReady(!self.match_ui.ready),
|
||||
Some(Btn::MatchStart) => MenuAction::MatchStart,
|
||||
@@ -1866,7 +1879,27 @@ impl Menu {
|
||||
yy += CH() * 1.6;
|
||||
}
|
||||
|
||||
if !ui.started && !ui.room_open() {
|
||||
// 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() };
|
||||
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()) {
|
||||
Some(m) => {
|
||||
let name = if self.campaign_doc.name.trim().is_empty() { "?".to_string() } else { self.campaign_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])
|
||||
}
|
||||
None => tr("net.coop_editor_none"),
|
||||
};
|
||||
let maxc = ((cols - 6) as f32 * CW() / (GW * SMALL())) as usize;
|
||||
for text in wrap(&line, maxc).iter().take(2) {
|
||||
gfx.text(text, ix, yy, SMALL(), GOLD);
|
||||
yy += GH * SMALL() * 1.35;
|
||||
}
|
||||
} else if !ui.started && !ui.room_open() {
|
||||
if let Some(d) = missions().get(self.coop_mission) {
|
||||
let line = trf("net.coop_mission", &[(self.coop_mission + 1).to_string(), tr(&format!("camp.{}.title", d.key))]);
|
||||
let maxc = ((cols - 6) as f32 * CW() / (GW * SMALL())) as usize;
|
||||
@@ -1885,9 +1918,14 @@ impl Menu {
|
||||
items.push((Btn::MatchCreate, tr("net.create")));
|
||||
items.push((Btn::MatchJoin, tr("net.join")));
|
||||
if !ui.room_open() {
|
||||
items.push((Btn::MatchCoopPrev, "<".to_string()));
|
||||
items.push((Btn::MatchCoopCreate, tr("net.coop_create")));
|
||||
items.push((Btn::MatchCoopNext, ">".to_string()));
|
||||
if !editor_coop || !editor_list.is_empty() {
|
||||
items.push((Btn::MatchCoopPrev, "<".to_string()));
|
||||
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" })));
|
||||
}
|
||||
}
|
||||
if ui.room_open() {
|
||||
items.push((Btn::MatchReady, tr(if ui.ready { "net.unready" } else { "net.ready" })));
|
||||
|
||||
Reference in new issue
Block a user