diff --git a/docs/CAMPAIGN_EDITOR.md b/docs/CAMPAIGN_EDITOR.md index c445493..94e67d3 100644 --- a/docs/CAMPAIGN_EDITOR.md +++ b/docs/CAMPAIGN_EDITOR.md @@ -117,8 +117,12 @@ Ctrl+Z/Y undo/redo, Ctrl+C/V copy/paste the selected block, Delete removes it, C save; *Published* adds the campaign to the list every logged-in player sees and can open (as a copy) and play. Server API: `/api/campaigns`, `/api/public/campaigns` (see `server/src/main.rs`). - **Co-op**: the campaign last opened in the editor can be played in a co-op match (Multiplayer, - *Editor campaign*), one mission per match; missions need a map of at least 72x72 and a goal besides - rival masters. See `docs/MULTIPLAYER.md`. + *Editor campaign*); missions need a map of at least 72x72 and a goal besides rival masters. The run + goes on over several missions: after a win the host starts the next mission (the branch of the reached + goal, or *next mission*) for everybody, after a defeat the same one again. Every player takes his five + strongest creatures and a fifth of his gold along; the host keeps the progress (missions done, chosen + branches, run seed). The room list shows the campaign's name and the current mission. See + `docs/MULTIPLAYER.md`. ## File format (`src/campaign_doc.rs`) diff --git a/docs/MULTIPLAYER.md b/docs/MULTIPLAYER.md index a3cd1f4..9201e76 100644 --- a/docs/MULTIPLAYER.md +++ b/docs/MULTIPLAYER.md @@ -76,8 +76,37 @@ per turn. Fog of war, particles and the camera are local and not part of the sha message); the relay keeps it in the room and adds it to the `start` message (room updates only show `"editor": true`). Every client builds the mission with `campaign::start_editor_coop_mission(doc, i, seed)` from the room's shared seed (rival masters of the map and the Rivals goal are left out, like in built-in co-op), - then the usual co-op setup. Block scripts run from side 0 in the fixed step. When the mission ends, the match - ends and the players go back to the lobby; there is no branching to a next mission and no progress is stored. + then the usual co-op setup. Block scripts run from side 0 in the fixed step. +- **Editor campaign runs over several missions**: when a mission ends, the host's end dialog offers *Next mission* + (won: the branch of the reached goal, `CampaignDoc::next_mission_choice` with `Game::match_goal_done`) or *Try + again* (lost: the same mission); the others see "waiting for the host" and may leave. The host sends + `{"t":"next","mission":i,"seed":run_seed,"carry":[[side,Carry],..]}`; the relay checks that he is side 0 and that + the mission exists, resets the turn clock, drops pending orders and sends `next` (seed, sides, teams, AI seats, + carry, no campaign) to every client. The clients keep the campaign of the `start`, drop turns of the old mission + and build the new one with `start_editor_coop_mission(doc, i, run_seed)`, then `campaign::apply_coop_carry`. + The carry (`campaign::coop_carry_from`, computed by the host from the shared final world) is per master: his + five strongest creatures and 20% of his gold, like the single-player `Carry`. The host stores the progress + (missions done, chosen branches, run seed) in local storage under `dc.coop_editor_progress` (campaign name -> + `CampaignProgress`). A run ends when no next mission fits co-op. +- **Teams in versus**: on the Match page every seat has a team A-D (default: a team of its own), set with + `{"t":"set_team","team":n}` for the own seat; the host may add `"side"` for a free or AI seat. Only before the + start. Room updates carry `team` per seat, the room list `teams`, and `start` a `teams` list in the order of + `sides` (`Game::set_teams`). Masters of one team are allies exactly like co-op partners (`Game::allied`: no + attacks, their creatures help each other, a tower spares them, the fog shows the team mates' ground, creatures + and towers). AI seats take part in teams as well. +- **Fallen hearts**: a master whose soul core falls is out (`Game::out_sides`, shared state, in the checksum). His + creatures fight on without a heart (no economy: no mana, no new creatures, no payday), the creatures in his hand + are put down, the core tiles become floor and his orders are ignored. The player watches: no fog, free camera, + chat; the match goes on for the others (`Game::spectating`, local only). +- **End of a match**: decided only from shared state (`Game::check_match_end`), so every client stops in the same + step: a versus match is over when only one team has masters (or AI seats) left - that team wins, the others lose; + if all seats are one team, the humans' gate is the enemy. A mission (co-op) is lost when every heart fell, and + won by its goals (mana springs count for any master). The checksum only mixes in *whether* the world still runs. +- **Gold for allies**: `Act::SendGold { to, amount }` (100, 500, 1000 or all), in the creature overview and the + pause menu (the ally button switches between allies). It runs in the fixed step on every client, never sends + more than the sender has nor more than the receiver's treasury takes; the receiver gets a message and a sound. +- **Room list**: rooms show what they play - versus, the built-in co-op mission, or the editor campaign's name and + the title of its current mission (`campaign`, `title` in `rooms` and `room`). - **Shared simulation side**: the shared part of a step (waves, units, towers, rivals, dwarves) runs with the first master switched in on every client; only the end check and the fog use the local master. @@ -89,12 +118,12 @@ per turn. Fog of war, particles and the camera are local and not part of the sha | B | All player actions as commands (`Command` + `Game::apply`), single player uses the same path; fixed time step | built | | C | Server: lobby and match relay over WebSocket (axum), turns, pause on disconnect, AI takeover on leave, chat, ping | built | | D | Client: *Multiplayer* menu (lobby, create, join, seats, ready), WebSocket bridge in `dc_plugin.js`, chat, ping | built | -| E | Alliances and co-op rules, AI masters for free and abandoned seats | partly built: co-op alliance and AI seats work; free teams in versus and sending gold are missing | +| E | Alliances and co-op rules, AI masters for free and abandoned seats | built: co-op alliance, teams A-D in versus, sending gold, fallen hearts as spectators, AI seats | | F | Co-op campaign: 20 missions with story (EN/DE) | partly built: co-op matches reuse the single player missions that fit the master areas (`coop_mission_indexes`); no own co-op missions or story yet | -Still open: teams/alliances in versus, sending gold to allies, own co-op campaign missions with story; still to be -checked against the decisions above: a fallen heart only knocking out that player (who may keep watching), and how -savegames treat a running match. +| G | Editor campaigns in co-op over several missions (branches, carry, host progress), campaign names in the room list | built | + +Still open: own co-op campaign missions with story; how savegames treat a running match. ## Masters and sides