Campaign Index

Welcome to the homepage for campaign scripting in Total War. Here you can find resources and guidance for the creation of scripts that will run in campaigns.

Quick Links:

Episodic Scripting interface

Model Hierarchy

campaign_manager

If any of the links above are dead then launch a campaign in the game. The episodic scripting interface and model hierarchy documentation are generated by code when a campaign is run.

Relevant in Campaign loaded in campaign
Back to top

Script File Locations

The first script that is run when a particular campaign loads can be customised in the relevant record in the campaigns table, in the script_path field. By convention this is data\script\campaign\%campaign_name%\scripting.lua.

From Warhammer onwards, all campaign scripts can be found in data\script\campaign\ (as well as data\script\_lib\, for library scripts related to campaign). This data\script\campaign\ folder contains a number of subfolders, all of which may contain script files. Script files in those folders should contain functionality related to their location in the folder structure:

Folder PathComment
script\campaign\Scripts potentially related to all campaigns in this project.
script\campaign\%campaign_name%\Scripts related to a particular campaign.
script\campaign\%campaign_name%\factions\%faction_name%\Scripts related to a particular faction in a particular campaign.

For more information see the page about campaign_script_structure.

Back to top

Campaign Script Libraries

The campaign script libraries are built on top of the raw interface provided by campaign to script and offer extensive support and extended functionality for campaign scripting. The main script object through which campaign calls are made is the campaign_manager.

A campaign_manager object is created automatically when the script libraries are loaded in, but a name for the campaign must be set at an early stage with campaign_manager:set_campaign_name.

Other script objects exist in addition to the campaign manager, documentation for which can be found in the Script Pages list in the navigation bar on the left-hand side of this page. The main script objects related to campaign are listed below:

ObjectDescription
coreCentral object that provides functionality shared across both campaign and battle, such as ui querying and event listeners.
campaign_managerCentral interface object for campaign scripts. The main campaign game interface is accessed through this object.
campaign_ui_managerCentral campaign object providing functionality specifically related to the user interface.
mission_managerWrapper object provided functionality related to the declaring and management of missions.
campaign_cutsceneObject interface for creating scripted cutscenes in campaign.
interventionA mechanism for stopping progress in the game to allow one bit of script to play through to completion, such as some advice or a scripted tour.

Back to top

Scripts During Loading

Unlike in battle, campaign scripts begin to load near to the start of the loading sequence. This is to allow scripts to be present while the save file (or startpos file) are loaded - the scripts can save values into the savegame when the game is saved and it is during the loading sequence that these values are read back out. Being loaded at such an early stage presents some complications, however, as the game model is not initialised until much later in the load sequence. If the script attempts to access or interrogate the game model before it's created then the game will crash. Care must be taken to ensure that this doesn't happen.

The standard script architecture put in place for each campaign attempts to ameliorate this issue by providing loading sequence processes with which callbacks to be registered. These registered callbacks will then be called at key points during the loading sequence when certain new elements of functionality become available.

Use campaign_manager:add_loading_game_callback to register a function to be called when the LoadingGame event is triggered. This happens early in the load sequence, before the model is created. Scripts may load values in from the savegame at this point but may not access the model. Other methods of loading information from the savegame exist - see the Loading Game section in the campaign manager documentation.

Use campaign_manager:add_pre_first_tick_callback to register a function to be called when the game and ui have been created. The campaign model may be queried after this point in the loading sequence. It is only at this point that the local faction can be identified and any faction-specific scripts loaded in.

Use campaign_manager:add_first_tick_callback or a related function (see the list available in the First Tick section) to register a function to be called when time in the game first starts ticking. This event is triggered once loading is finished and the game becomes interactive.

The campaign model (and hence the campaign scripts) completely shut down when the game loads from campaign into battle. From the perspective of campaign script the load back into campaign after a battle is (nearly) indistinguishable from being loaded from a savegame.

Back to top

Campaign Model Interfaces

The campaign model provides an interface of functions that can be used to query and modify the campaign state, known for historic reasons as the episodic scripting interface. An auto-generated list of functions it provides can be found here: Episodic Scripting Interface.

These functions are provided through a game_interface object. The campaign_manager, when created, internally creates and stores a game_interface object and provides a pass-through interface to it. This means that functions on the episodic scripting interface may be called on the campaign manager e.g. cm:enable_ui(false). Scripters are encouraged to call functions on the episodic scripting interface in this way, rather than trying to get an interface to the underlying game_interface object, as in many cases the campaign_manager overrides the underlying call and adds additional functionality.

The campaign model also provides a model hierarchy that may be navigated around and queried by script. This is of most use when a campaign event is triggered - from the context provided by event, the script may navigate amongst objects querying their state. For example, the FactionTurnStart event provides a context object from which the faction starting its turn may be derived. This faction object may be further queried to get a list of region objects that the faction owns, military force objects that the faction controls, a character object representing the faction leader, and so on. These objects in turn may be asked for further related objects (e.g. get the settlement of the region of the faction leader character of the faction starting its turn) allowing scripts to perform tests of any feasible complexity on the current state of the game. This model hierarchy is read-only, however - all function calls that modify objects are found on the episodic scripting interface.

The campaign automatically generates documentation on this model hierarchy which can be found here: Model Hierarchy.

More information about events and the model hierarchy can be found in the Events and Model Hierarchy sections below.

Back to top

Events

Read more about events in the dedicated page here: scripted_events

Campaign scripts rely heavily on the script event system. While processing, the game triggers script events when particular changes in the state of the model (or the UI) take place. Scripts may register functions as listeners for script events in order to be notified of these changes. Should a function be registered as a listener for an event then it will be called when the event is triggered by the game. Furthermore, the game provides a context object to the function being called which can then be queried to determine more information about the change taking place. Script events are triggered in all game environments, but they are used most extensively by campaign scripts.

Examples of campaign events include when a faction starts a turn (FactionTurnStart) or when a character is created (CharacterCreated). In the former case the context would contain information about the faction involved, in the latter the context would contain information about the character. A list of all events triggered across the game can be seen on the autogenerated model hierarchy documentation. For more information about context interrogation see the section below about the Model Hierarchy.

The events system also allows scripts to request functions to be called after an interval e.g. "call this function one second from now". The underlying functionality that supports this is repackaged by the campaign manager - see the Timer Callbacks section for information on usage.

Example - PendingBankruptcy listener:

Listen for a PendingBankruptcy event for a particular faction
core:add_listener(
    "faction_turn_start_listener",                                    -- name for listener
    "PendingBankruptcy",                                            -- event to listen for
    function(context)                                                -- test to perform prior to triggering callback
        return context:faction():name() == "wh_main_emp_empire"
    end,
    function()                                                        -- callback to trigger
        empire_pending_bankruptcy()
    end,
    false                                                            -- continue listening after trigger
);
Back to top

Model Hierarchy

When an event is triggered by the campaign model it provides a context object to any listener scripts that gets called. This context object provides links to one or more objects within the model hierarchy, each of which represent objects in the game such as a faction, a settlement, or a character. For example, the context of the FactionTurnStart event provides a faction object representing the faction that is starting its turn, whereas the CharacterLootedSettlement object provides both a character and settlement object.

Each object in the model hierarchy provides a range of functions that may be called by script to determine the state of the object and also to retrieve related objects. For example each faction object provides a faction_leader method which can be called to return a character object representing the faction leader character of that faction. This character object can then be queried like any other character object, including being asked for other related objects such as the military force commanded by the character or the region the character is stood in.

A list of events, what objects they provide, and what methods each of the objects in the model hierarchy support can be found in the model hierarchy documentation that is generated by the game when a campaign is loaded.

The following image illustrates many of the main objects provided by the model hierarchy and how they link together. It is by no means authoritative! See the model hierarchy documentation for a complete list.

loaded in campaign

Back to top

Script Output

See the section on Output for more information about how to print debug information to the console.

Back to top

Campaign Co-ordinates

The campaign contains two co-ordinate systems that are overlaid on top of one another: logical and display. Logical co-ordinates define the position of a hex in the logical data, and are used to position logical game objects that can only occupy a hex, such as a military force or a settlement. Display co-ordinates define the position of objects that don't exist in the logical game data, such as visual props or the camera.

The logical and display positions of the cursor may be shown in campaign by selecting controllers -> Campaign Debug and then UIs -> Cursor position from the debug dropdown menus. The hexmap map may also be drawn over the campaign map by selecting UIs -> Pathfinding Debug and also Warscape -> Debug Line Renderer. This hexmap and the co-ordinates of each hex should conform to the source hexmap in the Twitch tool.

The game can be instructed to output the display co-ordinates of the camera by entering the command camera_position on the console. The co-ordinates then printed to the command tab.

Example:

camera_position
Camera target: 201.634811, 520.228577; distance: 18.334259, bearing: 0.0, height: 9.76396 (201.634811 520.228577 18.334259 0.0 9.76396)
Last updated 25/08/2021 12:07:49