Custom formations work using a callback function which sets up the formation data for a given unit's men. The callback function has the form:
this function will make use of the SetFormationRow function:
//Set the location of the nth man in the unit relative to the center of the tile. offset is [0, 32], angle is [0, 359]. Only relevant in FORMATION_CALLBACK SetFormationRow(n, offset, angle)
or, alternatively, the SetFormationRowXY function:
//Set the location of the nth man in the unit relative to the center of the tile, using offsets when facing 0. offset is [0, 32]. Only relevant in FORMATION_CALLBACK
SetFormationRowXY(n, x, y)
NOTE: What both these functions set is the points making up the formation. They do not assign a particular man to a particular formation point. A scoring algorithm determines which man moves to which formation point when the formation changes.
Unit Order Scripting
The ability to alter the behaviour of the units is one of the most powerful areas of the game scripting. Each unit type can have its own set of scripts and behaviour (although you don't have to do this). As you will see, you can get units to do almost anything with a well written script.
A unit will look for a script which is called <name>.BSF in the DATA\BATTLE\SCRIPTS directory, where <name> is the unit name as denoted by the Name entry in the squads.csv file. If the code cannot find a unique BSF file, it will load up a script called $DEFAULT.BSF to handle all the unit's behaviours.
The approach that the game itself uses is to have all units use a single set of scripts, but to use the unit attributes (as defined in the squads file) to determine what a unit can or cannot do. This has the advantage that abilities can be added or removed from a unit simply by altering data.
On the other hand, you might have units with very disparate abilities, in which case you might be best using individual scripts for each unit, bearing in mind you can always INCLUDE any shared functionality.
Unit Callback Functions
There are a variety of functions which a unit can have which are called at times by the code.
FUNCTION STARTTURN( me )
This function is called at the start of a unit's side's turn. This would be used to reset any per-turn counters or limits. Examples would be a unit's shots, or tick up its morale. STARTTURN is a required function for every unit.
FUNCTION CUSTOM_TRIGGER( me, a, b, c, d )
The custom trigger is a low level function used to trigger scripting from the unit animation files. It passes through any of the 4 parameters allowed in the animation file for a unit.
FUNCTION INIT_*( me )
Any function which is named with INIT_ as the first 5 characters will be called on unit creation. You can use this to set up attributes, initialised starting values, etc. Note that if there is more than one INIT_ function then the order they will be called in cannot be guaranteed.
Unit Ability Functions
To actually allow a unit to do anything, it needs to have scripted behaviours.
There are 3 types of ability, depending upon the contents of the tile you are attempting to action. These are TILE_, ALL_, and UNIT_. TILE_ can operate only on empty tiles, ALL_ will attempt to work on all tiles, and UNIT_ will only operate on a tile with a unit present on it.
The key functions which will allow you to begin creating unit behaviours are described below. Note we will show all examples using the ALL_ tag, but this can be replaced with the TILE_ or UNIT_ tag to simplify the scripting as desired.
Note that for all the functions described here, you can omit any of the parameters you don't use, and that the code will correctly assign them no matter where in the param list they are. Indeed, you can have extra parameters in a function header and they will be set to zero if they are called by the code rather than by you.
FUNCTION CHECK_ALL_<name>( me, unit, tilex, tiley [, reaction] )
This function is used to determine whether a unit can perform a task. The return value can be either the cost of the action in AP, or -2 if you with the task icon not to be shown, or -1 if you wish to show the icon in a disabled state. See below for details on the optional reaction parameter.
FUNCTION ALL_<name>(me, unit, tilex, tiley)
This is the function which is called when the user selects the action for the unit. Note this cannot happen if the check function returns -1 or -2 as the icon will not be selectable.
FUNCTION REACT_ALL_<name>(me, unit, tilex, tiley)
If you want a unit to be able to react to other units, then you make use of the reaction function. This works in concert with the CHECK_ function for a given command. The system first calls the CHECK_ function to determine whether an action is possible against the reacted-against unit. Note that when CHECK_ is called in this case, the optional reaction parameter is set to 1, rather than 0 as it normally is.
If the check function returns >=0 then this is taken as the AP cost of the action, and the system then calls the REACT_ function. The react function should return a 'score' for this unit using this action to react to the threat. Examples of how to calculate this score we be based on things like chance of success, range to target, etc - as dependent upon the game model. The system will go through all units on the reacting side and then sort the reactions by their scores, and execute them in the 'best' order. Note that returning -1 from a REACT_ function means that you do not want the unit to attempt to react with this action.
Other Unit Callbacks
Moving from Tile
This callback is called whenever a unit is about to move off from a tile during a movement (e.g. it is called once for each tile on the route). Returning -1 or -2 will cancel the movement (e.g. the whole route), the difference being that -1 does not refund any APs used for movement, while -2 does. Return zero for normal movement.
FUNCTION DEPLOYCHECK_ALL_MOVE(me, unit, tilex, tiley)
This works in the same way as the normal CHECK_ function, but is only called during a deployment phase - if it exists then it is called rather than the normal CHECK_ function during deployment.
FUNCTION UISETUP_ALL_<name>( x, y, width, height, me, tilex, tiley )
This optional function can be used to setup and draw the order icon. The x,y,width,height parameters are the onscreen positions of the button. Functions such as SetUITexture are used within this function, and any button tooltip is also set up here.
Custom Button Rendering
FUNCTION UIBUTTON_ALL_MOVE(me, x,y,width, height, tilex, tiley)
This function allows for custom rendering of the order button.
Banners are 3D meshes which can display over a squad. Any meshes and textures should live in the DATA/BATTLE/BANNERS folder in either the main or campaign folder. Campaign entries will generally over-ride main versions. You use a BANNER.TXT file to denote the banners which are used. This has the form:
[chunk_name_can_be_anything] BANNER <mesh name> // the name of the mesh, with type omitted INDEX <index> // the index for this banner. Must be [1,255] TEX <texture> // optional texture filename for a texture which will be applied to this mesh when rendered using this index
To give a unit a banner use the new script command SetUnitBanner
//set the banner index for a unit. A unit can have 2 banners (to allow for component-style banners). so index [0,1]. bannerIndex as defined in the BANNER.TXT file. zero for off. SetUnitBanner(me, index, bannerIndex)
Animation File Documentation
[Note this is incomplete] Unit animations are defined in a .txt file with the same name as the unit S4F file. The format of the chunks in the file is of the form:
[<animName><index>] FRM <start> <end>
[WAIT00] FRM 212 250
Animation numbering needs to start at 00 and increment one by one. All index values must be double digits, 00, 01, 02, etc.
Animations can also have various triggers attached. These are:
SFX <frame> <sfxIndex> [<sfxIndex> <sfxIndex> <sfxIndex>] // play a random one of the provided sfxs. FX <frame> <particleEffectIndex> // play a particle effect on the unit FREQ <value> // alter the frequency of a specific index of an animation. Default 100, less means the animation is seen less. DELAY <value> // Set a random delay at the start of the animation of [0,N] frames where N is [0,10]. Note that this means any triggers on the first frame will be triggered multiple times. CALL <frame> <param0> [<param1> <param2>] // call the CUSTOM_TRIGGER function in the unit script with the provided params - params default to zero if not provided. AMBIENT <sfxIndex> [<sfxIndex> <sfxIndex> <sfxIndex>] // play randomised ambient sfx while playing this animation