How an edit works
Reading is a plain call. Changing has two shapes, both the editor's.
Read, change, apply. The settings and the trigger list come out as a value and go back
with an apply. The apply marks the sections it touched so the next write includes them;
changing scenario.triggers by hand does not.
const triggers = readTriggers(scn);
triggers.push(newTrigger()); // owned by All Players unless told otherwise
applyTriggers(scn, triggers);
Change lists. Units and locations produce a list of changes, which applyUnitChanges
or applyLocationChanges carries out — or undoes, with "undo". That is the editor's
undo history, and it is what makes a script's edit cheap to reverse.
const serial = nextSerial(scn);
const changes = addUnits(scn, [makeUnit(null, START_LOCATION, 0, 10 * 32, 10 * 32, serial)]);
applyUnitChanges(scn, changes);
Positions are in pixels (a tile is 32). The null passed to makeUnit is the unit table
from the game data; without it a unit gets no default resources or hit points, which is
what a start location needs anyway.
By hand. A field of the scenario can also be set directly, as long as the section it
is written to is marked with markDirty(scn, "SIDE"); an unmarked change is not saved.
The unit, upgrade and technology tables are each written to one or both of a pair (UNIS
and UNIx, …) depending on the map's revision and what the file has already, and
unitSettingsSections(scn), upgradeSettingsSections, upgradeRestrictionSections,
techSettingsSections and techRestrictionSections name the ones to mark.
scn.playerRaces[0] = PlayerRace.Protoss;
markDirty(scn, "SIDE");
// after a change to scn.unitSettings:
markDirty(scn, ...unitSettingsSections(scn));