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:
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 |
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 Path | Comment |
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
.
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:
Object | Description |
core | Central object that provides functionality shared across both campaign and battle, such as ui querying and event listeners. |
campaign_manager | Central interface object for campaign scripts. The main campaign game interface is accessed through this object. |
campaign_ui_manager | Central campaign object providing functionality specifically related to the user interface. |
mission_manager | Wrapper object provided functionality related to the declaring and management of missions. |
campaign_cutscene | Object interface for creating scripted cutscenes in campaign. |
intervention | A 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. |
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.
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.
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
);
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.
See the section on Output
for more information about how to print debug information to the console.
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)