Battle Hierarchy

References must be obtained to objects in battle - chiefly battle_unit objects - in order to query and direct the course of events in a scripted battle. These script references are obtained through a hierarchy, accessed from the battle/battle_manager objects.

Relevant in Campaign Loaded in Campaign
Relevant in Battle Loaded in Battle
Relevant in Frontend Loaded in Frontend
Back to top

A Note on Practical Use

In practise, the objects in the hierarchy described on this page are rarely created or used directly in battle scripts. Use of the frameworks provided by the script_unit and generated_battle libraries means that minimal direct references to the objects described on this page need to be created in battle scripts. Nevertheless, it is important to know about the battle object hierarchy and how it is laid out as it underpins all the script systems built on top of it.

Back to top

A First Look

The table below shows the list of object types found within the hierarchy, and how they are sourced from the battle object and then from one another:

ObjectSample ScriptComments
battle_alliancesalliances = bm:alliances()The battle_alliances object is a list of all the alliances present on the battlefield. An alliance is one or more armies on the battlefield that are fighting together. The battle_alliances object may be retrieved by calling battle:alliances.
battle_alliancealliance = alliances:item(1)Each battle_alliance object represents an alliance participating in the battle. Individual alliance objects are retrieved from an battle_alliances object with the alliances:item method. The index of an battle:alliances object is 1-based, so supplying 1 as an argument to alliances:item would return the first alliance, which is always the attacker in the battle.
In all circumstances (at time of writing) there are exactly two battle_alliance objects in the battle_alliances list.
battle_armiesarmies = alliance:armies()An battle_armies object is a list of individual battle_army objects that belong to a particular alliance.
battle_armyarmy = armies:item(1)An battle_army object represents a logical army on the battlefield, which is a collection of units of the same faction fighting together under the same controlling entity (either the player or the AI). A battle_army object is retrieved from an battle_armies list object by calling armies:item.
battle_unitsunits = army:units()A battle_units object is a list of individual battle_unit objects that belong to a specific army in the battle. It may be retrieved by calling army:units.
battle_unitunit = units:item(1)Each battle_unit object represents an individual unit on the battlefield. Unit objects may be retrieved from a battle_units list object by calling units:item.

This diagram shows the setup above in pictoral form:

battle hierarchy

Traditional scripted battles tend to be directed at the unit level, so the interfaces to each battle_unit object (and the associated battle_unitcontroller objects - see further down this page) are the most useful interfaces of those in the hierarchy given above.

Back to top

Example Scripts

The partial example given below shows script creating handles to battle objects in a battle with two armies in each alliance. The two alliances are named alliance_a and alliance_b:

bm = battle_manager:new() -- this is automatically called when the script libraries are loaded

alliances = bm:alliances()


-- set up alliance_a objects

alliance_a = alliances:item(1)

armies_a = alliance_a:armies()


-- set up alliance_b objects

alliance_b = alliances:item(2)

armies_b = alliance_b:armies()


-- set up alliance_a army objects

army_a1 = armies_a:item(1)

units_a1 = army_a1:units()

army_a2 = armies_a:item(2)

units_a2 = army_a2:units()


-- set up alliance b army objects

army_b1 = armies_b:item(1)

units_b1 = army_b1:units()

army_b2 = armies_b:item(2)

units_b2 = army_b2:units()


-- set up army a1 units

unit_a1_1 = units_a1:item(1)

unit_a1_2 = units_a1:item(2)

unit_a1_3 = units_a1:item(3)

-- etc


-- set up army a2 units

-- set up army b1 units

-- set up army b2 units

It is not often necessary to get and retain handles to all objects in the hierarchy. The partial example given below is the same as the first but without handles created to list objects:

bm = battle_manager:new() -- this is automatically called when the script libraries are loaded

alliances = bm:alliances()


-- set up alliance objects

alliance_a = bm:alliances():item(1)

alliance_b = bm:alliances():item(2)


-- set up army objects

army_a1 = alliance_a:armies():item(1)

army_a2 = alliance_a:armies():item(2)

army_b1 = alliance_b:armies():item(1)

army_b2 = alliance_b:armies():item(2)


-- set up army a1 units

unit_a1_1 = army_a1:units():item(1)

unit_a1_2 = army_a1:units():item(2)

unit_a1_3 = army_a1:units():item(3)

-- etc


-- set up army a2 units

-- set up army b1 units

-- set up army b2 units

Back to top

Container Interfaces

Each container object type provided by the battle hierarchy - battle_alliances, battle_armies and battle_units - provides the same interface and operates in the same way.

  1. Each contains a list of elements that belong to the parent object - battle_alliance, battle_army and battle_unit objects respectively.
  2. Elements may be retrieved in each case by calling the member function item() and supplying a numeric index value as a single argument. This index in each case is 1-based - the first element is retrieved with an index value of 1.

    second_army = armies:army(2)
  3. The number of elements in a container object is returned by the count() member function.

    num_units = units:count()

Back to top

Units and Unitcontrollers

battle_unit objects provide a variety of methods that may be called to determine information about the unit they represent. To modify the state of a unit, however - to give it orders - a battle_unitcontroller must be created that acts upon the unit.

The battle_army code interface provides the army:create_unit_controller for creating a unitcontroller and then attaching it to a unit:

uc_a1_1 = army_a1:create_unit_controller()
uc_a1_1:add_units(unit_a1_1)

The script libraries provide some helper functions for Unitcontroller Creation. Furthermore, use of the script_unit or generated_battle frameworks negate the need for explicit unitcontroller creation - it is strongly recommended that these are used.

Back to top

Using Scriptunits

In practice, the full battle hierarchy and the traditional method of creating a unitcontroller are seldom used in the forms given above. A shorthand method of creating battle_unit and battle_unitcontroller objects together is supplied by the script_unit library. In a full scripted battle it is highly recommended to set up handles to script_unit objects instead of manually creating battle_unit and battle_unitcontroller objects. The partial example script given below is the same as those shown above, but with script_unit objects declared in place of battle_unit objects.

bm = battle_manager:new()     -- this is automatically called when the script libraries are loaded

alliances = bm:alliances()


-- set up alliance objects

alliance_a = bm:alliances():item(1)

alliance_b = bm:alliances():item(2)


-- set up army objects

army_a1 = alliance_a:armies():item(1)

army_a2 = alliance_a:armies():item(2)

army_b1 = alliance_b:armies():item(1)

army_b2 = alliance_b:armies():item(2)


-- set up army a1 units

sunit_a1_1 = scriptunit:new(army_a1, 1)

sunit_a1_2 = scriptunit:new(army_a1, 2)

sunit_a1_3 = scriptunit:new(army_a1, 3)

-- etc


-- set up army a2 units

-- set up army b1 units

-- set up army b2 units

Each script_unit object contains a reference to a battle_unit object, as well as a battle_unitcontroller object set up to act upon that unit. These may be accessed at the unit and uc elements within the scriptunit (which is a lua table) as follows:

unit_a1_1 = sunit_a1_1.unit
uc_a1_1 = sunit_a1_1.uc

The script_unit packages a battle_unit and battle_unitcontroller together, as well as providing a suite of other functionality - see the script_unit page for more information.

Back to top

Setting Up a Generated Battle

The generated_battle system, if used, automatically sets up handles for armies and units in a battle. The partial example given below is the same as those shown above but set up using the generated_battle system. No handles to individual battle_unit or script_unit objects are explicitly created in this case as battles are co-ordinated and orders are given at the army level. This makes generated battle scripts easier to create and work with, at the expense of the fine unit-level control offered when creating a fully-scripted battle.

bm = battle_manager:new()     -- this is automatically called when the script libraries are loaded


-- set up generated battle object

gb = generated_battle:new()

ga_a1 = gb:get_army(1, 1)

ga_a2 = gb:get_army(1, 2)

ga_b1 = gb:get_army(2, 1)

ga_b2 = gb:get_army(2, 2)

Note that it is still possible to get handles to individual units in the generated battle system, but if this is necessary it may be worth considering creating a full scripted battle instead.

Last updated 12/08/2022 11:56:58