Overview
Scar has a number of functions for spawning units via script. This allows you to create scripted events during scenarios where units spawn into a map at a certain time or when objective requirements are met, or simply creating units that roam around the map using pre-set movement patterns.
This guide covers what these unit spawning script commands are and how to use them.
Basic Unit Spawning
The most flexible system for spawning units is the Unit Entry function, shown below:
UnitEntry_DeploySquads(player, sgroup, units, spawn, [entryMethod], [stagger], [options]) |
The main parameters of this script are:
- player: a playerID, and all units spawned in this deployement will be owned by that player.
- sgroup: an SGroupID (or a table of SGroupIDs) that all units spawned in this deployment will be added to.
- units: a UnitTable (see below) describing the units that should be spawned.
- spawn: a MarkerID or ScarPosition where the units should be spawned. You can also pass in an SGroupID or EGroupID, and if that squad/entity can have units storedinside it, so the units will be spawned in the hold.
The parameters in square brackets are optional, and can usually be left off. They represent:
- entryMethod: specify one of the entry methods defined for your project if you want a fancy animated spawn.
- stagger: a number that indicates how many seconds it should wait between each individual squad is spawned.
- options: a table that contains keys for other spawn parameters.
Below is an example of this script in action:
local units = { {sbp = SBP.ENGLISH.UNIT_VILLAGER_1, numSquads = 10}, } UnitEntry_DeploySquads(player1, sg_villagers, units, mkr_villager_spawn) |
Unit Tables
The primary data structure for defining units is the UnitTable syntax.
This is a Lua table that follows the structure shown below:
units = { {sbp = SBP.ENGLISH.UNIT_VILLAGER_1, numSquads = 10}, {sbp = SBP.ENGLISH.UNIT_SPEARMAN_1, numSquads = 5}, {sbp = SBP.ENGLISH.UNIT_SCOUT, numSquads = 2}, } |
As shown in the example above, a unit table can describe a mix of units of different blueprints and can specify how many of each blueprint you wish to include.
There are a number of additional keys you can add to any line item in the unit table, all of which are optional, and the effects will apply just to the units in that line item.
These keys are included below:
Loadout
Type: Integer
Use this to specify how many units the squad should have. If omitted results in default squad size.
Sgroup
Type: SGroupID/Table
Specify one or more sgroups that this line item's units will be added to in addition to the group specified in the UnitEntry_DeploySquads() call.
Spawn
Type: Marker/Position
Spawn these units at this spawn location instead of the location specified in the UnitEntry_DeploySquads() call.
Facing
Type: Marker/Position
The facing of the unit when it spawns.
Destination
Type: Marker/Position
A move command given once a unit spawns.
DestinationFacing
Type: Marker/Position
The new facing a unit will take once it arrives at the destination.
Using Types Instead of Blueprints
In Age of Empires IV there is an extra feature where you can specify a unit by Squad Type rather than by SBP.
units = { {type = "scar_spearman", numSquads = 10}, {type = "scar_archer", numSquads = 5}, {type = "scar_scout", numSquads = 2}, } |
The approach show above makes it easier to specify units without worrying about what civilization the units are from or the tech level of those units.
The unit's type gets resolved to an SBP when the units are spawned, and since the system knows which player the units are being deployed for, it can figure out the appropriate SBP. This means, as a scripter, you don't have to worry about with these details.
This spawn function will take all groups of units that share the same spawn location and put them in formation with each other.
|
Entry Methods
The Unit Entry system is a framework for spawning units into the game in a dynamic manner.
The features of this method include:
- Can spawn a single unit or multiple units of mixed unit types at once.
- Can either spawn all units at once, or spawn them in a staggered fashion.
- The deployment can have a scripted entrance sequence.
- All of the units are created immediately (in a de-spawned state) and then spawned according to the entry method and stagger settings. This means you can use
SGroup_Count()
and you will see how many units are either (1) in the world, or (2) are incoming, so you don't have to worry about triggering kill conditions for units accidentally when they haven't arrived on map yet. - Most of the optional parameters are named items in a table, so the situation with
Util_CreateSquads()
does not occur, where there are many parameters and it becomes difficult to tell exactly which the "false" parameter is. - This framework is extensible in many ways, on a project-by-project or even a scenario-specific basis.
Entry Methods Usage
To use these entry methods within script, use the following examples as a guide:
UnitEntry_DeploySquads(player, sgroup, units, spawn, [entryMethod], [stagger], [options]) |
Player
Defines the player ID
Sgroup
All the squads in this deployment will be added to this SGroup.
Providing a table of SGroups will add these units to all of them.
Units
A list of units to spawn.
Spawn
The spawn location of the unit(s).
EntryMethod (optional)
Which entry method to use.Default: UNITENTRY.Default
Stagger (optional)
How much time (in seconds) to wait between the spawn of each unit. Default: 0
Options (optional)
An optional sub-table that can contain lesser-used parameters.
Unit Tables
The parameters of the spawned units is controlled by lists of individual unit tables, as displayed in the chart below.
If you only want a single unit, you can specify the one unit table. The system will do the rest of the work so you don't need to enter it as a single item in a units list.
SBP
Defines the blueprint.
Player
Can override the deployment's player owner on a per-squad basis.
Loadout
How many units in the squad (default is 0, meaning full squad).
NumSquads
How many of those squads should be spawned.
Spawn
Spawn location used instead of the deployment's spawn location.
BackupSpawn
Backup spawn location to use in the case that the spawn is an sgroup/egroup which is empty.
Facing
Spawn facing this other location.
Destination
Where to go after spawning.
AttackMove
Defines whether the unit should attack move to its destination.
SGroup
SGroup(s) for this specific unit.
Upgrade
Upgrade(s) for this specific unit.
Extending the System
There are two main blobs of data that get passed around by the system:
deployment
This is a data table that contains all of the parameters that were passed into the UnitEntry_DeploySquads() call (with the key names being the same as the variables above). This is often useful for access to the entire context for the deployment, but is also a good place to hold extra data.unit
When dealing with a specific unit, this is the table for the unit being dealt with. This is the same unit table that is somewhere in the deployment.units table, but this parameter gives you direct access to the one under consideration at that time. Again, you can store any unit-specific stuff in there.
Entry Methods
When a script requests a deployment, it can specify an "entry method" which will run different script sequences to deliver the units on the map. These are the built in methods:
UNITENTRY.Default
- Do nothing special, and units use their default spawn event if that's set upUNITENTRY.None
- As above, but units don't use their default spawn event
There is a delegate called during initialization where new entry methods can be defined:
[
module]_UnitEntry_RegisterEntryMethods(
)
- Note: Please just add new entry methods to the UNITENTRY table, rather than redeclaring the entire table!
Each entry method type is a table with the following elements, all of which are optional:
preprocessFunction
Function that is called before any units are created, so you can noodle with the unit list.
startFunction
Function that is called after all the units are created but before they are spawned.
onSpawnFunction
Function that is called as each unit is spawned.
endFunction
Function that is called after all the units in the deployment have spawned.
InitialSpawnDelay
Adds a delay (in seconds) before units start spawning. Used if your entry method wants to wait for something to happen first.
This value can be set to -1, which will disable the automatic starting of spawns, calling UnitEntry_StartSpawningUnits(deployment)
forceSpawnLocation
If set to True, the system overrides a unit's individual spawn location with the deployment's spawn location.
It will use the original spawn location as a destination, if the unit didn't already have a destination set.
spawnType
This is the same spawnType string that is passed to the motion tree as the units are spawned.
An empty string ("") uses a unit's default spawn type, which is set in the AE.
onSpawnAnimatorAction
Quick way to hook up an action that is triggered on an object when it was spawned.
Snap Deployment Completion
Occasionally, you may want to immediately complete all in-progress deployments, spawning all pending unit spawns.
To do this, the following commands can be used:
UnitEntry_CompleteAllImmediately()
UnitEntry_CompleteImmediately(
deployment)
When these are called, the following occurs:
- On the
deployment
table, thecompleteImmediately
key is set to true. - All remaining unspawned units in the deployment are spawned immediately.
- The
endFunction
of the entry method is called, as if the sequence had finished normally.
Depending on what your entry method is doing, you might want to check for the completeImmediately
flag in the end function if you wish to handle things a differently.
Alternate Spawn Methods
There are a number of alternative spawn methods you can use in a variety of scenarios. This section covers what these alternate methods are and how to use them.
CreateEntities
The CreateEntities function is an alternate spawn function that can be used when spawning ebp such as buildings or objects.
Examples of CreateEntities functions in use are given below:
Util_CreateEntities(player1, eg_temp, EBP.ENGLISH.BUILDING_RESOURCE_FARM_ENG, mkr_cheat_farm5, 1) Util_CreateEntities(player2, eg_scoutcamps, EBP.FRENCH.BUILDING_UNIT_CAVALRY_CONTROL_FRE, |
CreateSquads
The CreateSquads function is a high level method of creating swuads and giving them basic orders upon spawning, as shown below:
- Util_CreateSquads(player, sgroup, sbp, location, destination, numsquads, loadout, attackmove, dest_facing, upgrades, spawn_facing, spawntype, formationname, egroupignorelist, ignorepathfinding, useMarkerTransform)
Example of a CreateSquad function in use is given below:
Util_CreateSquads(player1, sg_monk, BP_GetSquadBlueprint(sbp_monk), position_spawn_monk, position_spawn_monk, 1) |
Spawning During Initialization
The GetRecipe() is available for a variety of functions.
The GetRecipe recipe function can let you:
- Set up the first event to start the mission.
- Define all the locations of the mission.
- Spawn units at locations and type of AI modules used.
- Present an aspect of the mission.
In the following example of a campaign mission, the following is set up: mission name, campaign, NIS, title card, locations, and a unit spawner module for units.
The units will spawn while the game is loading and will appear at the location specified.
There are a few Module type available, but the most used are UnitSpawner, Defend, Attack, and RovingArmy.
function GetRecipe() local recipe = { missionType = "Hold Off the French", campaign = "english", chapter = "chapter2", introNIS = EVENTS.Intro, outroNIS = EVENTS.Victory, onStart = { titleCard = { icon = "icons/campaign/campaign_angevin_rebellion", -- Brémule title = 11160636, -- 1119 date = 11160637, }, }, locations = { { descriptor = "Bremule", marker = mkr_village_bremule, player = player2, egroup = eg_village_bremule, }, }, modules = { -- Player units { type = "UnitSpawner", player = player1, spawnLocation = mkr_cine_playermove, zeroPopulation = true, sgroup = sg_player_flueryunits, units = { { type = "scar_manatarms", numSquads = 8, }, { type = "scar_archer", numSquads = 12, }, { type = "scar_horseman", numSquads = 18, }, { type = "scar_scout", numSquads = 1, }, }, }, }, |
Spawning into Modules
If no units were defined in the recipe modules, you can spawn units into empty modules. If you wish, you may also add new units into modules as the game progresses.
To spawn a unit into a module, you need to define:
- a unit structure detailing the unit
- the number of squad members
- their location
- other options such as tag or sgroup to add them to
After defining the structure, you can use the function SpawnUnitsToModule to add those units and spawn them at the location.
Example
The example below shows the process of spawning 1 knight in the module "moduleName" at location "mkr_location":
local unitsToSpawn = { { type = "scar_knight", numSquads = 1,spawn = mkr_location, tag = "tab_name", sgroup = sg_groupName}, } SpawnUnitsToModule( unitsToSpawn, "moduleName", mkr_location) |