Skip to content

Types

CONTROL gives Lua math types, a color type, game object types and strategic helper classes.

GetCurrentGameOptions() and the pre-game setup types are on the GameOptions page.

Arguments

On this page, optional arguments end in ?; every other argument is required. Whole-number parameters (ids, counts, enums) also accept a float with a whole value such as 10.0, but not 10.5.

Math Types

Create a vector with .new(...) or with the short form: Vector3.new(1, 2, 0) and Vector3(1, 2, 0) are the same. Static-style calls such as Vector3.Dot(a, b) work on the type table.

Vector2

Constructors: Vector2.new() (all zero), Vector2.new(x, y), Vector2.new(value) (every component set to value)

Member Returns Description
x, y number Components.
LengthSqr() number Squared length.
Length() number Length.
Normalize() nil Scales the vector to length 1 in place. A vector shorter than 0.00001 is left unchanged.
Normalized() Vector2 Returns a copy scaled to length 1.
Dot(other) number Dot product. Vector2.Dot(a, b) also works.
Cross(other) number 2D cross product (x * other.y - y * other.x). Vector2.Cross(a, b) also works.
IsNearlyZero() boolean true when every component is closer to 0 than 0.000001.
Lerp(target, alpha) Vector2 Interpolates linearly toward target; alpha 0 returns this vector, 1 returns target.
Distance(other) number Distance to another Vector2.

Operators: + and - with another Vector2; * with a Vector2 (per component) or a number on either side; / with a Vector2 (per component) or a number on the right; unary -; ==.

Vector3

Constructors: Vector3.new() (all zero), Vector3.new(x, y, z), Vector3.new(value) (every component set to value)

Member Returns Description
x, y, z number Components.
LengthSqr() number Squared length.
Length() number Length.
Normalize() nil Scales the vector to length 1 in place. A vector shorter than 0.00001 is left unchanged.
Normalized() Vector3 Returns a copy scaled to length 1.
Dot(other) number Dot product. Vector3.Dot(a, b) also works.
Cross(other) Vector3 Cross product. Vector3.Cross(a, b) also works.
IsNearlyZero() boolean true when every component is closer to 0 than 0.000001.
Lerp(target, alpha) Vector3 Interpolates linearly toward target; alpha 0 returns this vector, 1 returns target.
Distance(other) number Distance to another Vector3.

Operators: +, -, * and / with another Vector3 (per component) or a number on either side; unary -; ==.

Vector4

Constructors: Vector4.new() (all zero), Vector4.new(x, y, z, w), Vector4.new(value) (every component set to value)

Member Returns Description
x, y, z, w number Components.
LengthSqr() number Squared length.
Length() number Length.
Normalize() nil Scales the vector to length 1 in place. A vector shorter than 0.00001 is left unchanged.
Normalized() Vector4 Returns a copy scaled to length 1.
Dot(other) number Dot product. Vector4.Dot(a, b) also works.
IsNearlyZero() boolean true when every component is closer to 0 than 0.000001.
Lerp(target, alpha) Vector4 Interpolates linearly toward target; alpha 0 returns this vector, 1 returns target.
Distance(other) number Distance to another Vector4.

Operators: +, -, * and / with another Vector4 (per component); or a number on either side; unary -; ==.

Color

Constructors (Color(...) is the same as Color.new(...))

Constructor Result
Color.new() Transparent black (all components 0).
Color.new(r, g, b, a?) with integers Every argument an integer such as 255: components from 0 to 255. a defaults to 255 (opaque).
Color.new(r, g, b, a?) with floats Any argument written as a float such as 1.0 or 0.5: components from 0 to 1. a defaults to 1.
Color.new(hex) A string "#RRGGBB" or "#RRGGBBAA"; the # is optional. Any other string gives opaque white.

Lua decides the scale by how the numbers are written: Color(255, 255, 255) and Color(1.0, 1.0, 1.0) are both white, and Color(1, 1, 1) is almost black. A computed value such as x / 2 is always a float.

Static methods

Method Returns Description
Color.Parse(hex) Color Same as Color.new(hex).
Color.HSV(h, s, v, a?) Color Creates a color from hue, saturation and value, each from 0 to 1. a defaults to 1.
local green = Color(0, 255, 0)
local translucent = Color(0, 255, 0, 128)
local orange = Color("#FF8000")

Game Types

Object

A unit, building, resource or other map object. Returned by the object lookups on the Facts page (GetObjectById, GetObjectsByType, GetObjectsInArea and others), by the Player object lists and by MapTile:GetObjects().

Method Returns Description
GetId() number Returns the object's id.
GetName() string Returns the name of the object's current graphic, such as Villager Male (Idle). It changes with the object's activity. Returns "" when the object has no graphic.
GetGraphicFileName() string Returns the file name of the object's current graphic, such as u_vil_male_villager_idleA_x1. Returns "" when the object has no graphic.
GetTypeName() string Returns the name the game shows for the object's type, such as Villager or Town Center, in the game's language. Returns "" for types without one.
GetObjectType() ObjectType Returns the object's category: resource, building, projectile and so on.
GetOwningPlayer() Player Returns the player who owns the object.
GetGarrisonObject() Object or nil Returns the object this one is garrisoned in.
GetTargetPosition() Vector3 Returns the target position of the object's unit AI, with z = 0. Returns (0, 0, 0) for objects without a unit AI.
GetTargetObject() Object or nil Returns the object the unit AI targets.
GetActionTargetPosition() Vector3 or nil Returns the target position of the object's current action, for example where a projectile will land. Returns nil when the object has no current action.
GetDirection() Vector3 Returns the direction the object faces, with z = 0.
IsVisible() boolean Returns whether the object's tile is visible to the assigned player. Always true with Modules See Everything on. Returns false for an object that no longer exists and never raises an error.
IsExplored() boolean Returns whether the object's tile is explored or visible for the assigned player. Never raises an error.
IsAlive() boolean Returns whether the object is finished and alive. Foundations and dead units return false.
IsFoundation() boolean Returns whether the object is a building that is not finished yet (ObjectData.STATUS 0).
GetUnitObjectType() UnitObjectType Returns the object's type id.
GetClass() UnitClass Returns the object's class id.
GetAttribute(attribute, damageType?) number Returns the object's current value of an ObjectAttribute. damageType defaults to 0.
GetObjectData(objectData) number Returns an ObjectData field.
IsIdle() boolean Returns whether the game marks the object as idle (ObjectData.IDLING).
IsMoving() boolean Returns whether the unit is following a path. false for buildings and objects that cannot move.
GetSprite() table or nil Returns the object's current graphic: name, fileName, facet, facetCount, frameCount and frameDuration. See Sprites. Returns nil when the object has no graphic.
IsScouting() boolean Returns whether the unit is auto-scouting.
GetHitpoints() number Returns the current hit points.
GetMaxHitpoints() number Returns the maximum hit points.
GetPosition() Vector3 Returns the world position.
GetCurrentMapTile() MapTile or nil Returns the map tile the object stands on.
GetPath() Vector3[] Returns the waypoints of the path the unit follows. Empty when the unit is not moving.
CalculatePath(targetPos) Vector3[] Asks the game's pathfinder for a path from the object's position to the Vector3 targetPos, sized for the object. Returns the waypoints.

Resources and other objects that cannot move (GetObjectType() is ObjectType.RESOURCE_OR_EYE_CANDY or ObjectType.ANIMATED_MAP_OBJECT: trees, mines, bushes, decorations) have no direction, path or action. For them GetDirection() returns (0, 0, 0), GetPath() returns an empty list and GetActionTargetPosition() returns nil.

With Multithreading on, or while the Agent Bridge is on, modules read objects from a copy of the game state (see Limits). In that copy GetAttribute() returns nil for every attribute except HITPOINTS, RADIUS_X and RADIUS_Y, and GetObjectData() returns nil for fields the copy does not record.

Fog of war and stale objects

Unless Modules See Everything is on (Perspective And Visibility), object lookups return only objects the assigned player can see, plus animals and resources on explored tiles.

An Object you keep from an earlier frame can go into the fog or stop existing. Calling a method on it then raises a Lua error. Check IsVisible() before you use a kept object, or fetch objects again in the current frame.

Animals and resources on explored tiles that are not visible allow only IsVisible(), IsExplored(), GetId(), GetPosition(), GetClass() and GetUnitObjectType(). Other methods raise an error until the object is visible again.

Sprites

Object:GetSprite() describes the graphic the game draws for the object now. The graphic changes with the object's activity: a villager switches between idle, walking and work graphics.

Field Type Description
name string The graphic's name, such as Villager Male (Walk). Same as GetName().
fileName string The graphic's file name, such as u_vil_male_villager_walkA_x1. Same as GetGraphicFileName().
facet number The direction the object faces, from 0. Walking villagers use 0 to 15. Ignore it when facetCount is 1.
facetCount number How many directions the graphic has: 16 for a villager, 1 for a town center.
frameCount number Frames in one animation cycle of one direction.
frameDuration number Seconds per frame at normal game speed. 0 for graphics without animation.

The current animation frame is not available.

MapTile

Returned by GetMapTile, GetAllMapTiles, Object:GetCurrentMapTile() and ConstructionPlacement:GetValidFarmPlacementTile().

Method Returns Description
GetPosition() Vector2 Returns the tile coordinates as Vector2(x, y).
GetTerrain() Terrain Returns the tile's terrain id. Returns Terrain.UNKNOWN for unexplored tiles.
GetElevation() number Returns the tile's elevation. Returns 0 for unexplored tiles.
GetTileVisibility() TileVisibility Returns the assigned player's visibility of the tile.
IsBuildable() boolean Returns whether the game would let the assigned player place a 1x1 building (an outpost) on the tile now: terrain, slope and objects, including units, are checked. Unexplored tiles return false. With Multithreading on, returns nil. For a real building type, use CheckPlacement.
IsWalkable() boolean Returns whether land units can be on the tile: its terrain is navigatable and the game marks no blocking object on it (buildings, trees, mines). Units standing there do not count. A town center blocks only the tiles under its centre, so the rest of its footprint is walkable; IsBuildable() is false on the whole footprint. Unexplored tiles return false.
IsNavigatable() boolean Returns whether the tile's terrain lets land units move, whatever stands on it. Water returns false. Unexplored tiles return false.
GetObjectCount() number Returns how many objects are on the tile. Returns 0 unless the tile is TileVisibility.VISIBLE.
GetObjects() Object[] Returns the objects on the tile. Returns an empty list unless the tile is TileVisibility.VISIBLE.

Player

Returned by GetAssignedPlayer, GetPlayerById, GetVictoryPlayer and Object:GetOwningPlayer().

Method Returns Description
GetId() number Returns the player id.
GetPlayerType() PlayerType Returns the player type.
GetPlayerObjects() Object[] Returns the player's objects.
GetCameraPosition() Vector2 Returns the player's camera position.
GetMouseHoveredObject() Object or nil Returns the object under the player's mouse cursor.
GetSelectedObject() Object or nil Returns the object the player selected last.
GetSelectedObjectCount() number Returns how many objects the player has selected.
GetPlayerName() string Returns the player name.
GetCivilizationId() number Returns the civilization id, or 0 when unknown.
GetCivilizationName() string Returns the civilization name, or "" when unknown.
HasWon() boolean Returns whether the game (or replay) has ended and this player won.
IsAlliedWith(player) boolean Returns whether this player is allied with another Player.
IsEnemyTo(player) boolean Returns whether this player is an enemy of another Player.
GetColor() Color Returns the player's color.
GetAttribute(attribute) number Returns a PlayerAttribute value.
GetUnitTypeCount(id) number Returns how many units of a type id the player has.
GetFact(fact, parameter?) number Returns a Fact value for this player; see Facts. parameter defaults to 0. With Multithreading on, or while the Agent Bridge is on, returns nil for facts the game-state copy does not record.
IsObjectTypeAvailable(unitObjectType) boolean Returns whether the player can currently get a unit or building type.
CanAfford(id, isBuilding?) boolean Returns whether the player has the resources for object type id and, unless isBuilding is true, the population room. Does not check whether the type is available.
GetResearchState(technology) ResearchState Returns the research state of a technology.
GetTechCost(technology) cost list Returns the player's current cost of a technology.
GetObjectCost(unitObjectType, costMultiplier?) cost list Returns the player's current cost of a unit or building type, multiplied by costMultiplier (default 1.0).
CanAffordResearch(technology) boolean Returns whether the player can pay for a technology.
CanResearch(technology) boolean Returns whether the technology is researchable now and the player can pay for it.
IsTechnologyResearched(technology) boolean Returns whether the player has researched a technology.
GetObjectsByTypes(unitTypes) Object[] Returns the player's objects of any type in the array unitTypes.
GetObjectsByMostCommonType(unitTypes) Object[] Returns the player's objects of the type in unitTypes that the player has most of.
GetObjectsByClass(unitClass) Object[] Returns the player's objects of a UnitClass.
GetObjectsByClassDeadInclusive(unitClass) Object[] Same as GetObjectsByClass, plus objects of the class that are not alive, such as dead livestock.
GetFoundations() Object[] Returns the player's buildings that are not finished yet. The other object lists leave them out.
CountObjectsByTypes(unitTypes) number Returns how many objects GetObjectsByTypes(unitTypes) returns, without building the list.
CountObjectsByClass(unitClass) number Returns how many objects GetObjectsByClass(unitClass) returns, without building the list.
GetTownCenters() Object[] Returns the player's town centers.

A cost list has one entry per resource: { resourceId = ResourceType, amount = number }.

With Modules See Everything off, the attribute, fact, count, cost, research and availability methods return data only for the assigned player. For other players they return 0, false, an empty list or ResearchState.NOT_AVAILABLE. The object lists of every player follow the rules in Fog of war and stale objects.

Visibility Example

function Render()
    local player = GetAssignedPlayer()
    if not player then
        return
    end

    local selected = player:GetSelectedObject()
    if not selected or not selected:IsVisible() then
        return
    end

    local tile = selected:GetCurrentMapTile()
    if not tile then
        return
    end

    local tilePos = tile:GetPosition()
    local label = "Tile " .. tostring(tilePos.x) .. "," .. tostring(tilePos.y)
        .. " terrain=" .. tostring(tile:GetTerrain())
        .. " nav=" .. tostring(tile:IsNavigatable())
    RenderWorldText(label, selected:GetPosition(), 14.0, Color(255, 255, 255), true, true)
end

Strategic Component Types

These classes run a simple economy for the assigned player. Create them in Init(), not at file scope, and call their Update() methods from your Update(). ResourceTracker.new() and ResourceTracker:new() both work. The classes read the live game, so their Update() methods raise an error with Multithreading on.

ResourceTracker

Constructor: ResourceTracker.new()

Method Returns Description
Update() nil Rebuilds the lists below. The lists do not change between calls.
GetConvertibleLivestock(position, radius) Object[] Returns visible, living livestock owned by Gaia within radius tiles of the Vector3 position.
GetOwnedLivestock() Object[] Returns the assigned player's livestock, dead or alive.
GetDeadLivestock(position, radius) Object[] Returns the assigned player's dead livestock within radius tiles of position.
GetForage() Object[] Returns forage bushes.
GetFarms() Object[] Returns the assigned player's farms.
GetTrees() Object[] Returns trees.
GetGold() Object[] Returns gold mines.
GetStone() Object[] Returns stone mines.

Forage, trees and mines follow the rules in Fog of war and stale objects.

VillagerOccupation

Constructor: VillagerOccupation.new(resourceTracker)

Assigns the assigned player's villagers to wood, food, gold and stone. Each profession has a weight; its target share is its weight divided by the sum of the weights. All four weights start at 1 (25% each).

Method Returns Description
Update() nil Sends idle villagers to the profession furthest below its target share. With Sequential Actions on (the default), sends one villager per call. Call the ResourceTracker's Update() first.
GetVillagerCount() number Returns the player's villager count.
GetVillagerCount(profession) number Returns how many villagers work in a VillagerProfession.
GetIdleVillagerCount() number Returns how many villagers GetIdleVillagers() returns.
GetAllVillagers() Object[] Returns the player's villagers.
GetIdleVillagers() Object[] Returns idle villagers, leaving out villagers kept for construction.
RequestVillagers(amount, position, urgency) Object[] Picks up to amount villagers for a job at the Vector3 position and returns them; it gives them no order. UrgencyLevel.HIGH takes the closest villagers. MEDIUM prefers villagers from professions above their target share. LOW takes only villagers from professions above their target share. Villagers kept for construction are skipped.
SetPriorities(wood, food, gold, stone) nil Sets the four weights. Whole numbers from 0 to 1000000.
GetPriorityPercentage(profession) number Returns a profession's target share as a whole number from 0 to 100.
SetPriorityPercentage(profession, share) nil Sets one profession's target share as a fraction from 0 to 0.99 (larger values count as 0.99). The other professions keep their ratio to each other.
ResetPriorities() nil Sets all four weights back to 1.
RebalanceVillagers() nil Moves working villagers between professions to match the target shares. Update() assigns idle villagers only.
SetLivestockVillagerLimit(limit) nil Sets how many villagers food assignment sends to livestock before it uses forage and farms. Default 6.
SetForageVillagerLimit(limit) nil Sets how many villagers food assignment sends to forage before it uses farms. Default 8.
SetFarmMaxTownCenterDistance(distance) nil Sets how far, in tiles from a town center's edge, a new farm may be placed. Default 1.0.
SetFarmMaxMillDistance(distance) nil Sets how far, in tiles from a mill's edge, a new farm may be placed. Default 1.0.
SetProfessionBuildingRange(profession, range) nil Sets the drop-off range of a profession, in tiles. Default 8.0. See below.
AssignVillagers(villagers) nil Assigns each villager in the array, given as Object values or object ids, to the profession furthest below its target share.
AssignVillager(villager) nil Assigns one Object now.

Food assignment uses livestock up to its limit, then forage up to its limit, then farms. When none of those has room, it uses forage and then livestock beyond their limits.

Wood, gold and stone villagers go to the closest resource that has one of the player's drop-off buildings (lumber camp or mining camp) within the profession's drop-off range. When no resource has one and a ConstructionPlacement was created with this VillagerOccupation, it queues a drop-off building next to the closest resource and sends the villager there.

ConstructionPlacement

Constructor: ConstructionPlacement.new(villagerOccupation)

Finds free building spots and orders villagers to build. It takes builders from the VillagerOccupation, which then leaves those villagers out of its own assignments.

In the methods below, structureType is a UnitObjectType. padding is the number of free tiles kept around the new building (default 1). Placement also keeps a band of tiles around town centers free (see SetTownCenterPadding()) unless bypassTownCenterPadding is true (default false).

Method Returns Description
Update() nil Reads the map into the placement grid and then calls ProcessBuildingRequests(). Call it every update before placing buildings.
SetTownCenterPadding(padding) nil Sets how many tiles around town centers stay free, from 0 to 1024. Default 3.
BuildStructure(structureType, builderUnitId, targetPos, direction?, padding?, bypassTownCenterPadding?) boolean Finds a free spot near the Vector3 targetPos and orders unit builderUnitId to build there. direction picks the side of targetPos to search: a PlacementDirection (default PlacementDirection.Center, all sides) or a Vector3 to search toward. When that side has no spot, all sides are searched. Returns true when the build order was sent.
BuildStructure(structureType, targetPos, direction?, padding?, bypassTownCenterPadding?) boolean Same, with the villager closest to targetPos as the builder.
BuildStructureAtTown(structureType, targetPos?, padding?, bypassTownCenterPadding?) boolean Builds near the player's first town center. See below.
FindBestPosition(structureType, targetPos, direction, padding, bypassTownCenterPadding?) Vector3 Returns the spot BuildStructure would use for a PlacementDirection, without building. Returns (-1, -1, -1) when there is none.
GetValidFarmPlacementTile() MapTile or nil Returns a free farm tile within the farm distance of one of the player's town centers, or else of a mill. The distances are set on the VillagerOccupation.
QueueBuildingRequest(structureType, targetPosition, priority?, padding?, bypassTownCenterPadding?, builderUnitId?, requireScouting?) nil Queues a building near targetPosition. See below.
QueueBuildingRequestAtTown(structureType, priority?, padding?, bypassTownCenterPadding?, builderUnitId?, requireScouting?) nil Queues a building near the player's first town center. requireScouting defaults to false.
ProcessBuildingRequests() nil Works on up to 3 queued requests, highest priority first.
IsStructureTypeQueued(structureType) boolean Returns whether a request for the type is queued or the player has an unfinished building of the type.
IsUnitAssignedToBuilding(unitId) boolean Returns whether the unit is the builder of a queued request.

BuildStructureAtTown first sends the closest villager to an unfinished building of structureType that no villager is working on, and returns true. Otherwise it builds near targetPos, searching on the side that faces the town center, or around the town center when targetPos is left out. When the game counts an unfinished building of the type that no villager can be sent to yet, the call returns false for 5 seconds before it places a new one.

Queued requests. priority is a BuildingRequestPriority (default MEDIUM). builderUnitId picks the builder; the default -1 takes the villager closest to the target. With requireScouting (default true for QueueBuildingRequest), the builder first walks to within 5 tiles of the target. A request ends once its build order is sent and the foundation exists or the builder is building. It is dropped after 45 seconds of scouting or 60 seconds in total. A new request is ignored when its type is already queued or has an unfinished building (farms excepted), or when its builder already serves another request.

Examples

Create the strategic components in Init():

---@type ResourceTracker
local resources

---@type VillagerOccupation
local villagers

local trackedProfessions = {
    { "Food", VillagerProfession.FOOD },
    { "Gold", VillagerProfession.GOLD },
    { "Stone", VillagerProfession.STONE },
    { "Wood", VillagerProfession.WOOD },
}

function Init()
    resources = ResourceTracker:new()
    villagers = VillagerOccupation:new(resources)
end

function Update()
    resources:Update()
    villagers:Update()

    for _, entry in ipairs(trackedProfessions) do
        local label = entry[1]
        local profession = entry[2]
        Log(label .. ": " .. villagers:GetVillagerCount(profession))
    end
end

Autonomous AI Base

A starting point for an economy script: it scouts, builds houses, trains villagers and keeps half of the villagers on food.

local tracker = nil
local villagerOcc = nil
local placement = nil

function Init()
    tracker = ResourceTracker:new()
    villagerOcc = VillagerOccupation:new(tracker)
    placement = ConstructionPlacement:new(villagerOcc)

    villagerOcc:SetPriorityPercentage(VillagerProfession.FOOD, 0.5)
end

function Update()
    EnableScouting()

    tracker:Update()
    placement:Update()

    if GetFact(Fact.HOUSING_HEADROOM) <= 2 then
        placement:BuildStructureAtTown(
            UnitObjectType.HOUSE_DARK_AGE,
            1,
            false
        )
    end

    TrainUnit(UnitObjectType.VILLAGER_MALE)

    -- With Sequential Actions on, only the first command in each Update()
    -- runs, so villager assignment goes last.
    villagerOcc:Update()
end