Skip to content

Editor reference — every screen

The walkthrough builds one pack end to end. This page is the reference: what every screen holds, and why.

The title bar carries the open pack file and the build stamp of the editor itselfGalactic Heroes Editor — ewt32.ghpack.json [build 2026-09-18 17:15], and DEBUG when it is a debug build. Which build am I looking at should be a reading, not a deduction.

The toolbar is seven buttons:

ButtonWhat it does
New / Open… / Save / Save as…the .ghpack.json source file — your pack, not the extension
Checkrun the validator and go to the Check tab
Export…write the extension into the export folder
Export into the gamewrite it straight into extensions/<packid> — asks first, game must be closed

The status bar is two halves. On the left, what is in this pack and what the host already has: “1 fleet template(s), 1 hero(es) in this pack · 17 fleet(s) and 261 hero(es) already in the game, shown read only.” On the right, the harvest receipt: “6 archetypes · 28 perks · 390 ships · 17 host fleets · 261 host heroes · 1 PROBLEM(S).” Zeroes on the right mean the folders on the Pack tab are wrong.

TabAuthorsNotes
Packthe manifest, the text page number and the three folderscovered in the overview
Fleetsfleet templatesa ladder, one tier per hero star
Heroeshero templatescovered in the walkthrough
Missionscorporation missionssee below
Spend planswhat heroes buy, in ordercovered in the walkthrough
Corporationscompaniesnot a catalogue entry — see below
Checknothing — it reports104 rules, the full list; the same findings are shown on every other tab
What was readnothing — it reportssix screens proving the harvest

Fleets, Heroes and Corporations share a left-hand shape: a filter box, then In this pack above Already in Galactic Heroes — read only, then Add, Copy into this pack and Remove. Host objects are shown so you can read, filter and copy them; they can never be edited, because an edit to something the host owns would be silently discarded and the host may reshape it in any later version.

Missions and Spend plans list only what the pack itself defines, with Add, Copy and Delete. What the host already declares is on the What was read screens instead — Spend for its eleven plans.

A corporation mission is paid work a company offers you against a rival it is already fighting. The mod ships six; a pack can add more. See Corporation missions for what they are in game.

Galactic Heroes Editor, Missions tab. A left-hand panel explains that these are missions a corporation offers the player against a rival, and that the target is chosen at runtime: a station managed by a corporation the client is already paying to hurt. Below it an empty list with Add, Copy and Delete buttons. The right pane holds Mission id "test" and empty Title, Briefing and Objective boxes. A section headed "What the player does there" says the panel list is read from the game's own schema, so it is whatever your installed version declares, and that hack_* panels break something while access_* panels only look and are worth less; under it an empty Control panel dropdown. A second section, "When it is offered, and for how much", says a grudge counts campaigns one corporation has already run against another, that zero means the mission is offered without a feud and two means it waits for a real one; under it empty Reward, Minimum grudge and Mission level boxes

FieldWhat it decides
Mission idpermanent, prefixed, unique against the host’s own six
Titlewhat the player reads in the corporation’s offer list
Briefingthe longer text
Objectivethe one line the game shows while the mission is active
Control panelwhat the player actually walks up to and uses
Rewardbase payout in credits
Minimum grudgehow many campaigns one company must already have run against the other before this is offered. 0 means “offer it even without a feud.”
Mission leveldifficulty band

The control panel list is read out of the game’s own schemalibraries/common.xsd declares them as the controlpaneltypelookup enumeration — not typed into the editor. A patch that adds a panel gives it to the editor with no code change, and a panel that does not exist is an error rather than a mission nobody can finish.

One note rather than an error is worth knowing about: access_* panels only look at something, hack_* panels break it. An access panel with a sabotage-sized reward is a balance choice, not a defect, so the editor says it out loud and lets you keep it. For scale, the core reconnaissance mission pays 90,000.

Galactic Heroes Editor, Corporations tab. The left panel explains that companies this pack founds are listed beside the host's, so you can see which faction and which niche are already taken. "In this pack" holds ewt32_corp_001 with no name; "Already in Galactic Heroes - read only" lists the seventeen host companies by id and name - cinderhaul Cinderhaul Reclamation, greenlane Greenlane Holdings, blackgate Blackgate Freeport Capital, quietwater Quietwater Intelligence, amaranth Amaranth Health Trust, halcyon Halcyon Arms Concord, rahar Rahar Ascendant Capital, bellwright Bellwright Capital, ascension Ascension Reach Trust, axiom Axiom Claytronics, harborlight Harborlight Commerce Trust, deeptide Deeptide Stewardship Fund, covenant Covenant Trust, sable Sable Ledger Assurance, amitra Amitra Concord Capital, throughline Throughline Capital and verdant Verdant Accord Trust. The right pane holds Id, an empty Name, an empty Origin faction with a note that it is not decoration because favour accrual, relation gates and market access all key off it, and Bucket A. A "How it behaves" section holds Founding capital 100000000, Aggression 100 and Defence reserve -1, each with a sentence explaining it. A "Who they are" section holds Field, Dirty side and Backstory. At the bottom, "What this company will be" reads: this company joins a market of 17; at 100M it is an even match for the companies already there, neither predator nor prey; it goes after rivals as readily as anybody else on the board; it has no origin faction yet, and the host refuses a corporation without one

Everything else the editor writes is a catalogue entry. The mod wipes its fleet and hero tables on every load and each extension registers into the empty table, so exporting again simply replaces what was there.

A corporation is not that. It owns money, contracts, favours, liabilities, a chronicle and a share register, and all of it lives in the player’s save. So the host’s registration is ensure-exists, and the split matters:

FieldOn a save that already has the company
name, bucket, lore, aggression, defence reservere-read on every load, so an edit does take effect
founding capitalread once, at founding — an edit never tops it up

There is no way to remove one, either. Uninstalling a pack leaves its corporations in the save, inert but intact, because every contract, grudge, share register and chronicle entry that ever named them would otherwise dangle. The Remove button says so before it does anything.

That permanence is why an id collision is an error here rather than a warning. A colliding fleet id produces a refused registration and a missing fleet, which is annoying. A colliding corporation id produces two packs both believing they own a company that holds money and shares in a live save, and that cannot be repaired afterwards.

Each defaults to what every corporation in the mod does today, so a company written without touching them behaves exactly like one written before the fields existed.

  • Founding capital — the host’s own companies start with 100,000,000. This is the number that decides a takeover: a raider roughly 1.6× richer than its target reaches control, so this field is what says whether a company is predator or prey.
  • Aggression (percent, 100 = ordinary) — scales the two budgets that gate whether the company commissions raids and assaults against rivals. 0 is a company that trades, bids and defends but never moves against anybody. It changes nothing else.
  • Defence reserve % (-1 = follow the mod’s global) — the share of its own money it refuses to spend buying back shares when somebody is taking it over.

The What this company will be line at the bottom says what the three add up to in sentences, because three integers do not tell an author that they have just founded somebody’s lunch.

Origin faction is not decoration. Favour accrual, relation gates and market access all key off it, and the host refuses a corporation without one.

104 rules: 68 errors, 28 warnings, 8 notes. Errors block export; warnings and notes do not. Every issue says what to do about it, and double-clicking a row on the Check tab jumps to the field it is about.

The check runs by itself about a third of a second after any edit, and every finding carries an address — the object, the nested object (a tier, a perk row, a plan step) and the field. That address is used in four places at once:

WhereWhat you see
the tab headerHeroes ✖ 2 or Fleets ⚠ 1 — the worst kind and the count, so a problem two tabs away is visible
the object’s row in the listthe same mark; a perk row, a plan step or a tier is tinted, with the findings as its tool tip
above the formone line per error or warning, message and fix together, five at a time and then a scroll bar; notes are counted underneath and listed on the Check tab
the field itselfa red or amber outline on the box that sets it, with the message and the fix as its tool tip

Fix the field and every mark goes. The Check tab remains the full list, notes included, and its double-click lands on the tab, selects the object and the row, and focuses the field.

One finding is not a rule about the pack but about the screen: text typed into a number box (GH140). WPF keeps the previous number and says nothing; the editor shows the box outlined, names the value the field still holds, and refuses to export until the box holds a number again.

The rules fall into three kinds, and keeping them apart is the point:

1. What the host also enforces — no id, no tiers, a tier with no flagship, no archetype, no faction, a duplicate id. Checking here is not redundant: the host can only refuse, hours later, into a log file the author may never open.

2. What the host cannot enforce. Namespacing above all. Once a save has seen an id it is permanent, and a collision between two guest packs cannot be repaired. The host cannot tell an unprefixed guest id from a core one — the editor knows which pack it is writing.

3. What makes a template good rather than valid — a perk the archetype cannot use, a fleet hung on a station-bound hero that will never upgrade it, a founder name that repeats its own rank. None of these break anything, and all three are defects the core roster itself contains.

CodesAbout
GH001GH009the pack itself: id, prefix length, display name, registering nothing, version, the text page
GH010GH023fleet templates: tiers, flagships, escort counts, ship sources
GH030GH057heroes: ids, group, rank, faction, archetype, fleet, biography, the spend plan it names
GH060GH069perks on a hero: unknown, duplicated, unreachable, wrong archetype
GH080GH096corporations: collisions, origin faction, capital, aggression, reserve
GH100GH111corporation missions: ids, title, objective, panel, reward, grudge
GH120GH131spend plans: ids, label, steps, a perk step naming nothing or a perk twice, a shares target
GH140text typed into a number box
GH150a brace in a name or a story — X4 reads {…} on a text page as a reference to another entry

The generator also handles what an author cannot see coming: an apostrophe in a biography would end an MD string literal, a " would end the XML attribute, and -- is illegal inside an XML comment. All three are neutralised at the one place they are written.

Pointing the editor’s rules at the mod that taught it those rules costs nothing, and the self-test writes the result to host-audit.txt. Zero errors, and four kinds of warning:

GH047 ×200a founder name that repeats its own rank — the game prints “Commodore Commodore Falo”
GH063 ×16a perk whose applies_to does not include the hero’s archetype, so nothing reads its effects
GH042 ×14a coordinator carrying a $fleet_template_id, which fleet_upgrades=false means is never used
GH021 ×9a tier with an escort ship chosen and a count of zero

The audit also found one thing in the editor rather than the mod: GH017 fired five times on the Xenon fleets, which declare XL_I and XL_K for the I and the K. Those are the host’s own class labels, not typos, and the rule now compares only the size.

Six screens, and the reason they exist is that an empty list somewhere else in the editor is always a harvest failure, never an empty world. If a dropdown has nothing in it, the answer is here.

Reading — did it read, from where, and how much

Section titled “Reading — did it read, from where, and how much”

Galactic Heroes Editor, What was read, Reading screen. A "Problems while reading" box holds one red line: "ignored extensions_disabled_backup_20260820: it holds extensions in a folder the game does not load from, so nothing in it is really installed". Below, "Where the game loads data from" lists the sources in load order with their entry counts - base 461598 packed and 383 loose, ego_dlc_boron 9039 packed, ego_dlc_mini_01 591, ego_dlc_mini_02 1418, ego_dlc_pirate 7206, ego_dlc_split 11290, ego_dlc_terran 15111, ego_dlc_timelines 7021 - each with 2 or 4 loose files. A Counts block follows, opening with "text read from the mod 1438 string(s) (0001.xml, 0001-l007.xml; the first is the one shown)", then archetypes 6 with admin retired, perks 28, task kinds 26, decision kinds 19, decision sets 6, host fleet templates 17, host hero templates 261 in 53 groups, factions in the game 32 of which 0 from mods, 19 claim space and 6 tagged pirate, factions used by the host 22, ranks used by the host 133, ship macros 390 broken down by source, and the default decision set for each archetype

Three blocks:

  • Problems while reading — anything skipped and why. The line in the shot is a good example of the class: a folder named extensions_disabled_backup_20260820 holds extensions the game does not load from, so reading it would have offered ships that are not really installed.
  • Where the game loads data from — every archive and folder X4 will read, in load order, with its entry count.
  • Counts — the harvest in one block. This is the fastest way to answer “did it see my mod?”

Galactic Heroes Editor, What was read, Game screen. A note says a faction listed here is one a hero can belong to, read from libraries/factions.xml in every source, and that "claims space" is the game's own tag for a faction that owns territory - without it the mod cannot resolve a home sector and the hero never spawns. A table with columns id, from, claims space, pirate and tags lists alliance from base with no claim space, antigone, argon, boron from ego_dlc_boron, buccaneers which is both claimspace and pirate, civilian which is hidden, court from ego_dlc_split, criminal hidden, fallensplit which is pirate but claims no space, freesplit, and hatikvah which is claimspace and pirate

Every faction the game has, with its source and its tags. claims space is the one to read: it is the game’s own tag for a faction that owns territory. Without it the mod cannot resolve a home sector, and a hero of that faction never spawns. The from column tells you whether a faction came from the base game, a DLC or a mod.

Galactic Heroes Editor, What was read, Heroes screen. An Archetypes table with columns id, label, commands, fleet upgrades, station bound, Kha'ak only and subordinate cap lists six rows: admiral labelled Admiral commands fleet with fleet upgrades on, cap 0; engineer labelled Engineer the same; raider labelled Raider the same; seeder labelled Seeder commands summon_pool with fleet upgrades on and Kha'ak only ticked, cap 0; coordinator labelled Coordinator commands fleet_leaders with fleet upgrades off, station bound ticked and a subordinate cap of 5; hive_lord labelled Hive Lord commands subordinates with fleet upgrades off, station bound and Kha'ak only ticked, and a cap of 8. A Perks table below gives each perk its name and what it does: Veteran, common, +200 XP at spawn - promoted to second star immediately; Logistic, +50% Recovery Points accrual rate; Attentive, +50% XP gain from combat; Quick Learner, rare, -25% XP needed to reach next star; Lucky, rare, -10% chance of KIA in death roll; Volunteer, spawn weight ten times more likely to be picked when a slot opens; Second in Line and Third in Line, which cannot spawn until the faction already has one or two active heroes; Khaak Seed, which adds RP to a shared grief pool on each three-minute cycle; Squad Commander, +2 S-class fighters in escort from first star; Master Technician, rare, engineer station buff potency relative +20%; and Quartermaster, -25% RP cost when rebuilding escorts

The archetype table is the most useful thing on this screen, because it is where the differences between the six live:

ColumnWhy it matters to a pack
commandsfleet, summon_pool, fleet_leaders, subordinates — what the hero actually directs
fleet upgradesoff for coordinators and hive lords. Giving one a fleet template is a warning: nothing will ever build it.
station boundthe hero does not fly. It also means the hero cannot be hired.
Kha’ak onlyseeder and hive lord
subordinate capcoordinator 5, hive lord 8; zero for the rest

Galactic Heroes Editor, What was read, Decisions screen. A note explains that two lists describe decisions - the catalogue says what a decision can BE, the sets say what a template offers - and that they live in different files and neither knows about the other, so they are compared here. "Decision kinds the host declares" lists each kind with its label and the archetypes that may take it: idle, replenish and retreat name all six - admiral, engineer, raider, seeder, coordinator, hive_lord - while guard names admiral, engineer, raider and coordinator, guard_hive names seeder and hive_lord, hunting names admiral and raider, urgent_defense names admiral and coordinator, station_strike names admiral and raider, fishing and recon name admiral, raider and coordinator, and raid and lurk name the raider alone. A declared-by column reads core throughout. A line notes that 5 declared kinds are offered by no set - fishing, hunting, player_contract, recon, station_strike - because the decision worker reaches for some of these on its own, so it is a note and not a fault. "Task kinds the host declares" lists fishing, recon and satellite worked by admiral, coordinator and raider, then station, expansion, hunting, urgent_defense, fleet_defense, gate_defense, call_for_help, hive_development and swarm_summon all listed against the admiral alone, with a declared-by column reading core. A Decision sets block spells out the six sets - adm, rdr, eng, coord, hive and seeder - with their decisions and priorities

Two lists describe decisions, they live in different files, and neither one knows about the other — so the editor compares them here.

  • Decision kinds — the catalogue: what a decision can be, and which archetypes may take it. A kind is a name and its holders, never behaviour; the behaviour lives in the mod’s decision worker.
  • Task kinds — what a faction’s board can ask for, and which archetype works it. A decision is what a hero chooses; a task is what the board offers. An archetype is composed from both.
  • Decision sets — what a template offers, with priorities. These are the six the host keeps private, and the ones your exported pack carries as literals.

Two columns repay attention. declared by reads core, or core-no-page for a task type that exists on the board and has no drill-down page in the mod’s Order Board. And the line under the first table — “5 declared kind(s) are set by no set” — is a note, not a fault: the decision worker reaches for some kinds on its own without any set offering them.

Galactic Heroes Editor, What was read, Spend screen. A note says a plan is an ORDERED build order, not a set of priorities: step 1 is bought before step 2 whatever the perk's tier says, and the screen is read-only so a pack author can point a hero at one. "Plans the host registers" reads 11 plans, 98 steps in total of which 21 buy shares, and 6 of 6 archetypes name a default. A table lists line "Career Officer" with 11 steps, 8 perks and 3 shares, then survivor, hunter, squad, logistician, scholar, capital, legend, technician, staff and swarm, each opening with veteran. "The selected plan, step by step" lists eleven rows for the Career Officer plan: veteran, logistic, 10,000,000 cr of shares most_expensive, quartermaster, squad_commander, 40,000,000 cr of shares, quick_learner, lucky, 120,000,000 cr of shares, legendary_veteran and tactical_genius. A closing block says a hero resolves its plan the way it resolves its fleet - the template's own spend_plan_id first, the archetype default second, nothing third - and that 66 templates name this plan directly, it being also the default for admiral and raider

Read-only, and here so a pack author can point a hero at an existing plan instead of writing one.

The closing block is the part worth reading: a hero resolves its plan the way it resolves its fleet — the template’s own spend_plan_id first, the archetype’s default second, nothing third. A hero that resolves to nothing keeps the tier ladder, so a plan is an override, never a requirement.

Live — what the running game is actually deciding

Section titled “Live — what the running game is actually deciding”

Galactic Heroes Editor, What was read, Live screen. A note explains that this shows what the running game is deciding right now, read from its own dump, while the other screens show what a decision CAN be - and that either can look healthy while the other is wrong. "The snapshot" says the log has no finished MLOG_DECISIONS dump, and to ask the game for one through the dev bridge signal cue mlog_heroes_decisions and then reopen the screen; it names the debug.log path it is reading. A "Re-read the log" button sits below. Headings for "Kinds the game holds that the catalogue does not declare" and "Decisions held" follow, with an empty table having columns faction, hero, archetype, slot, kind, target and sector

The other five screens show what a decision can be. This one shows what is being decided, read out of the running game’s own dump in debug.log. Either can look healthy while the other is wrong, which is the whole reason it is a separate screen.

It needs the game to have written a dump — asked for through the mod’s dev bridge — and the screen says so when there is none, along with the exact log path it is reading. Kinds the game holds that the catalogue does not declare is the row that catches a decision the mod produces and never documented.

Both must pass before a build is worth shipping, and tools/build.ps1 runs both from the Release binary:

GalacticHeroesEditor.exe --selftest <dir> # headless: harvest, validate, generate, read back; every rule made to fire
GalacticHeroesEditor.exe --uitest <file> # opens the real window: 8 tabs, 34 behaviour checks

The self-test walks the validator’s own table of codes and refuses to finish green while a code exists that no case has ever made fire. Measured before that check was written: 86 codes, 23 ever exercised. It also feeds the editor pack files it did not write — nulls, unknown fields, not JSON at all — and the generated text page back through the editor’s own reader.

--uitest exists because a XAML binding is not checked at compile time. A misspelled binding path builds cleanly and shows an empty combo box to someone with no way to know four hundred ships were meant to be in it. WPF reports every one of those, but only to a trace listener nobody attaches. This one attaches, and fails the run. It caught a real crash — RowHeight="Auto", where RowHeight is a double — on its first run.

It has since earned its keep twice more. A reported bug — a group name typed into a hero, gone the moment you left the tab — was reproduced in it before anything was changed, one step per dispatcher tick, so the step that destroyed the value named itself: not typing, not the list rebuild, not saving. Leaving the tab and coming back.

The cause is a trap in WPF rather than in this program, and it is worth knowing if you write WPF: the group box is an editable ComboBox whose Text is bound TwoWay, and whose ItemsSource is a list of suggestions. Clearing that list makes the box reset its Text — and a TwoWay Text writes the empty string straight back over the model. Two rules came out of it: a suggestion list feeding an editable control is append-only, and nothing may be selected while the whole vocabulary is replaced.

A second WPF trap, found on 2026-09-21 and worth knowing for the same reason: the UI lane could not fail the build. It ended with Application.Shutdown(1), and a WPF app’s generated Main is void — it discards what Run() returns — so the process exited 0 whatever the lane found, and the build script read every UI failure as a pass. It exits through Environment.Exit now, the script also reads the verdict the lane prints, and --uitest-fail provokes a red on demand to prove the path carries one. Nothing green before that date was evidence about the UI lane.