150 lines
8.6 KiB
Markdown
150 lines
8.6 KiB
Markdown
# Campaign editor
|
||
|
||
The campaign editor is part of the game: *Campaign editor* in the title menu. It works with the
|
||
game's own graphics and needs a mouse and a keyboard (desktop). It has three levels:
|
||
|
||
1. the **campaign graph** – all missions as cards, linked by arrows,
|
||
2. the **mission** – settings, goals and branches, map, scripts,
|
||
3. the **map editor** and the **block editor** for one mission.
|
||
|
||
Code: `src/editor/` (`mod.rs` graph and mission pages, `map.rs` map editor, `blocks_ui.rs` block
|
||
editor, `widgets.rs` the small interface toolkit, `templates.rs` demo campaign and templates),
|
||
the file format in `src/campaign_doc.rs`, the scripts in `src/blocks.rs` and `src/mscript.rs`
|
||
(see [MISSION_SCRIPTING.md](MISSION_SCRIPTING.md)).
|
||
|
||
## Campaign graph
|
||
|
||
- Top bar: campaign name, author, the campaign's language (one language per campaign), and the
|
||
buttons *Play*, *New*, *Open*, *Save file*, *Save online*, *Close*; *+ Mission* adds a card.
|
||
*Published* (after saving online) puts the campaign into the public list.
|
||
- A card shows the title, random or painted map and its size, the goals, the number of triggers
|
||
and, in red, the number of problems in its scripts.
|
||
- Click a card to open the mission. Drag a card to move it; drag with the right (or middle) mouse
|
||
button to move the view.
|
||
- Links: drag from the **gold dot** of a card onto another card – that is the *next mission*.
|
||
The **blue dots** are branches; the empty blue ring makes a new branch. Dropping a link on empty
|
||
space removes it. The `x` on a card deletes the mission (click twice).
|
||
- *Play* plays the whole campaign from the first mission, following next missions and branches; at
|
||
the end (or via the pause menu) the editor comes back.
|
||
|
||
## Opening
|
||
|
||
*Open* offers:
|
||
|
||
- a `.dccamp` file (or drop the file onto the window),
|
||
- **Open the demo** – the demo campaign, which uses every trigger kind and every special script,
|
||
- **League against the Lightwatch** – the built-in 20-mission co-op campaign, as a copy to change or learn from,
|
||
- **a mission of the built-in campaign as a copy** – its map as it starts, its texts and goals,
|
||
added to the current campaign (the original stays untouched),
|
||
- **my campaigns (online)** and **published campaigns** of all players (needs a login on a server
|
||
with the savegame service).
|
||
|
||
## A mission
|
||
|
||
The mission page has four tabs and a **Test play** button. Test play starts the mission with the
|
||
script debug view (trigger zones on the map, the variables and a log of which trigger fired when);
|
||
*Back to the editor* in the pause menu – or the end of the mission – returns to the editor.
|
||
|
||
### General
|
||
|
||
Title, briefing (shown when the mission begins; Enter starts a new paragraph), starting gold, time
|
||
limit, and hero waves (number of waves, time to the first wave).
|
||
|
||
### Goals
|
||
|
||
- The goals of the mission; it is won when all are reached. Goals the map cannot have (shards on a
|
||
map without shards, the gate without a gate, ...) are left out when the mission starts, so they
|
||
can never be won by accident. A mission without goals is won only by a script (*Win*).
|
||
- *Next mission*.
|
||
- *Branches*: another goal (with its number) leads to another mission if it is reached first;
|
||
the higher priority wins when several are reached.
|
||
|
||
Goal kinds: defeat all heroes, take the shards, destroy the gate, raze the knight towers, defeat
|
||
the rivals, loot gold (amount), survive waves (count), claim mana springs (count), free creatures
|
||
(count).
|
||
|
||
### Map
|
||
|
||
A mission has a **random map** or a **painted map**:
|
||
|
||
- **Random map**: size, seed, water rivers (0–3), lava rivers (0–2), knight fortresses (0–3),
|
||
rival masters (0–2), difficulty and portals. It is rolled **once per run of the campaign** (the
|
||
run's seed is kept, so a restarted mission has the same map) – its scripts should use triggers
|
||
without fixed places (timers, events, values) or zones that are sure to fit.
|
||
- **Generate and paint the map** makes a map from these settings and opens the map editor; when it
|
||
is done the mission has a **painted map**: the whole game state is stored in the campaign file,
|
||
so it never changes. *Make it a random map* goes back.
|
||
|
||
### Scripts
|
||
|
||
- **Special scripts**: *Start* (once), *Victory check*, *Defeat check* and *Clock* (every second).
|
||
- **Triggers**: name, kind, *once* (fires only the first time) and *active* (switched on from the
|
||
start). The second line holds the condition: zone, side, unit kind, comparison, number, time, ...
|
||
*Blocks* opens the trigger's script. A red frame means a problem (missing zone, script problems).
|
||
|
||
## Map editor
|
||
|
||
The map in the game's 3D view; tool bar on the left, options on top.
|
||
|
||
| Tool | What it does |
|
||
|---|---|
|
||
| Ground | floor, earth, reinforced wall, rock, water, lava, bridges, gold/silver/ruby/diamond veins, steel; with an owner for floor and walls |
|
||
| Rooms | the 14 rooms (and plain floor), with an owner |
|
||
| Places | soul core (moves it), portal, hero gate (moves it), mana spring, core shard, rune chest, chained creature (kind, level) |
|
||
| Units | creatures and heroes: kind, side (player, heroes, Mossgrim, Lady Nightwell, rival 3), level |
|
||
| Towers | arrow, cannon, magic, rune forge tower; the dungeon's or the knights', level 1–3 |
|
||
| Traps | the seven traps and three doors, armed |
|
||
| Forts | a knight fortress (with or without a shard), rival masters (Mossgrim, Lady Nightwell, rival 3); level = strength |
|
||
| Zones | trigger zones: rectangle, circle (drag from the middle), painted tiles (paint onto the selected tiles zone; *Remove tiles* takes them out again), line (drag from start to end); name, rename, delete (the "x"); the list scrolls with the wheel |
|
||
| Erase | removes units, towers, traps and doors on a tile |
|
||
|
||
Options: brush size 1–5, rectangle, fill (connected area of the same ground), mirror (left/right,
|
||
top/bottom, both – for fair maps), undo/redo (Ctrl+Z / Ctrl+Y). Camera: right button moves, middle
|
||
button turns, wheel zooms, WASD/arrows and Q/E. *Done* stores the map in the mission.
|
||
|
||
## Block editor
|
||
|
||
See [MISSION_SCRIPTING.md](MISSION_SCRIPTING.md). In short: the palette on the left (categories
|
||
Speak, Units, World, Logic, Variables, Mission) – drag a block into the script; move blocks by their
|
||
grip `≡`, drop them on the palette to delete them; the fields inside a block are set right there;
|
||
the small switch in front of a value changes its kind (number, variable, gold, comparison, ...).
|
||
Problems are marked red with a tooltip; the help line explains the block under the pointer.
|
||
Ctrl+Z/Y undo/redo, Ctrl+C/V copy/paste the selected block, Delete removes it, Ctrl+F searches.
|
||
|
||
## Saving and sharing
|
||
|
||
- **File**: `.dccamp` (JSON). A campaign with painted maps can be a few MB.
|
||
- **Online** (server with the savegame service): own campaigns per user, overwrite on the next
|
||
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*); 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`)
|
||
|
||
```json
|
||
{
|
||
"format": "dungeoncraft.campaign", "version": 2,
|
||
"name": "...", "author": "...", "language": "de",
|
||
"missions": [{
|
||
"key": "m01", "title": "...", "story": "...", "size": [96, 80], "seed": 101,
|
||
"gold": 3000, "portals": 1, "goals": ["KillAll", "Loot(3000)"],
|
||
"waves": false, "wave_limit": 0, "first_wave": 300, "time_limit": 0,
|
||
"next": "m02", "branches": [{ "id": "b1", "goal": "Loot(5000)", "next": "m03", "priority": 1 }],
|
||
"zones": [{ "name": "gate", "shape": "rect", "from": [40, 20], "to": [44, 24] }],
|
||
"map": { "kind": "Random" }, // or { "kind": "Fixed", "game": "<game JSON>" }
|
||
"gen": { "rivers": 1, "lava": 0, "forts": 1, "rivals": 0, "difficulty": 1 },
|
||
"scripts": { "start": [...], "victory": [...], "defeat": [...], "tick": [...], "triggers": [...] },
|
||
"pos": [40, 40] // the card in the graph
|
||
}]
|
||
}
|
||
```
|
||
|
||
Zone coordinates are tiles. Shapes: `rect` (`from`/`to`, inclusive), `circle` (`at`, `radius`),
|
||
`tiles` (list), `line` (`from`/`to`). Version 1 files still load; their text scripts are not run.
|