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:
model_hierarchy
(internal documentation) and Model Hierarchy (direct link to external documentation)
old episodic scripting interface - now obselete
If any of the links above are dead then launch a campaign in the game. The old-style episodic scripting interface and model hierarchy documentation are generated by code when a campaign is run.
Relevant in Campaign | |
Relevant in Battle | |
Relevant in Frontend |
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 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. This is the main interface through which scripts can modify the state of the game in campaign. Documentation for it can be found here: episodic_scripting
These functions are provided through a game_interface
object. The object is stored internally by the campaign_manager
, which also 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.
Read more about the Model Hierarchy in the dedicated page here: model_hierarchy
Quick link to the external model hierarchy documentation: Model Hierarchy
The campaign model also provides a model hierarchy that may be navigated around and queried by script. The model hierarchy represents the main way that scripts can read the state of the game in campaign.
The model hierarchy is mostly used when a campaign event is triggered - see documentation on scripted_events
. 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
that is starting its turn may be derived. The interface of 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.
For the most part, this model hierarchy is read-only - (nearly) all function calls that modify objects are found on the episodic_scripting
interface.
The campaign script libraries are built on top of the episodic_scripting
and model_hierarchy
interfaces provided by the campaign model, and offer extensive additional support and extended functionality for campaign scripting. The main script object through which campaign calls are made is the campaign_manager
.
Other script objects exist in addition to the campaign manager, documentation for which can be found in the Script Interfaces
list in the navigation bar on the right-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 episodic_scripting 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. |
Other script library interfaces are listed under the Script Interfaces
section of the bar on the right of this page.
Read more about events in the dedicated page here: scripted_events
Campaign scripts rely on the script event system to receive notifications about events happening in the game. While running, 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 lua function be registered as a listener for an event then that function will be called when the event is triggered by the game. Furthermore, the game provides a userdata
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. For a list of events in the game and more information about context interrogation see the external model hierarchy documentation: Model Hierarchy
The recommended method for scripts to listen for an event is by using the core:add_listener
function. See an example of this below.
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
);
See the section on Output
for more information about how to print debug output.
Script functions can be registered to be called in the future using the campaign_manager:callback
command. Other commands are available with which to register functions to be called later - see the Timer Callbacks
section.
Example:
-- call function one second from now
cm:callback(function() example_function() end, 1);
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)