Dev Diary #4: The scripting system

Open the file. Read the rule. Change it.

In the first diary we said the rules of The Long Century should be something you can read, not a black box. This diary is about what that means in practice today: which parts of the game live in scripts, how those scripts are kept honest, and where the road to full mod support stands.

Write content, not code around content

Define a decision in one file. A decision is a short script with a name, a description, a tooltip, and four questions it answers: who can see it, who can take it, what the requirements read like, and what happens when it is taken. The example decision that ships with the game lets India move its capital to Delhi. It is visible to the right country, is available only while that country owns the province and has not already moved, and when taken it sets the capital and grants five prestige. That is the whole decision.

Events, casus belli, state foci, and state buildings follow the same pattern. Each is a small script that describes itself and answers the questions the game asks of it. Casus belli carry their infamy, prestige, validity, war score cost, and justification time as properties on the script. State foci react to being added, being removed, and to each passing day. Casus belli and state buildings remember things about themselves while they are in play, and decisions and foci do not. More on why in the next diary.

Draw the game with scripts too

Build the interface in the same language. The top bar, the Outliner, the map mode buttons, the province panel, the production, market, population, politics, research, diplomacy, military, and naval screens are all scripts. Each panel declares where it lives, when it is visible, and what it draws. The game owns the window and the frame loop, and the scripts own everything you see inside it.

This is the biggest practical win so far. A layout fix is a text edit followed by one console command that reloads the interface scripts, with no rebuild and no restart. When an edit is wrong, the script checker catches it before the game ever shows a window.

Keep the interface read-only

Let the interface look at everything and change nothing directly. A panel can read the state of the world: countries, provinces, markets, armies, research. It cannot reach in and modify any of it. That is not a convention we ask scripters to follow. Calling a function that writes to the game from an interface script fails when the scripts load, with an error that names the offending call. There is no mode where it quietly half works.

So how does a button actually do something? It asks. A panel can queue one of the game's built-in actions, or name a scripted effect to run. Either way the request travels through the same ordered stream as every other action in the game, and every player's game applies it on the same day. If it comes back invalid, stale, or aimed at something that no longer exists, it does nothing, rather than doing something surprising.

That is what keeps multiplayer honest. A script that decides what happens runs the same way for everyone, and a script that only decides what to show is free to differ on your screen.

Split scripts by what they are allowed to do

Give each kind of script only the permissions its job needs. There are four, from most restricted to least:

  • Interface scripts read the world, draw panels, and submit actions. They cannot write to the simulation.
  • Scripted effects have full access to change the world, but only run when called through the shared action stream.
  • On-actions are called on daily, monthly, and yearly ticks and on military events. They also have full access.
  • Setup scripts register content and build the opening state of the world while a scenario loads.

When a script reaches for something outside its permissions, the game refuses to load it. Failure arrives early and loudly, on your machine, with a line number.

Say what is not finished

Package-based mod support is a plan, not a feature. Today the base game's scripts and any mod that overrides them by path are what load. The design we have settled on lets a mod be a single folder with a script file that describes it and a logo, with its own scripts, data, and scenarios, kept separate from the base game's files so mods never edit them. It has clear rules for what happens when two mods want to change the same thing: they are told about it, and you choose, rather than the last mod loaded silently winning. None of that is running yet. The next diary covers the decisions behind the scripting interface itself, which is the part you can already use.

Open the files

Read a decision. Read a casus belli. Read how the top bar works out when your research will finish. Then change one and watch the game respond. The forum is open for questions, and we would like to hear which parts of the game you want to reach next.

← All dev diaries