Skip to content

Game data and world

Use global queries to find game data. Then use methods on the returned Player, Object, or MapTile value. Check every result because a match can be loading or changing state.

local player = GetAssignedPlayer()
if player ~= nil then
    local town_centers = player:GetTownCenters()
end

Query availability

Calls documented as returning value, available or costs, available return two Lua values. Check the boolean before using the first result. When it is false, a numeric result can be zero or a partial count, and a cost array can be empty or incomplete. Those results do not establish a real zero or a free technology or object. Sequential reads are live queries, not an atomic snapshot.

local count, available = GetUnitTypeCount(83)
if available then
    LogInfo("Known villager count: " .. count)
end

Existing scripts that capture only the first return value still receive it. Calls that forward all return values also forward the availability boolean. These contracts apply to the global functions below; check the separate Player method reference before using the equivalent method.

Match and players

Call Result
GetAssignedPlayer() Assigned Player, or nil.
GetAssignedPlayerId() Assigned player ID, or 0.
GetPlayerById(playerId) Player, or nil.
GetPlayerCount() count, available: player count and read availability.
IsEnemyPlayer(player) true when the assigned player treats player as an enemy, false for another known relation, or nil when unavailable.
GetGameTime() Whole match seconds, or nil when the native clock is unavailable. Zero is a valid time.
GetTimeInCurrentAge() Assigned player's whole current-age seconds, or nil when unavailable. Zero is valid.
IsGamePaused() Pause state.
IsMenuOpen() true when no playable match is active.
GetVictoryCondition() value, available: victory condition and read availability.
GetVictoryPlayer() Winning Player, or nil.
IsDeathMatchGame() Death Match state.

Use Player methods for data about one player. See Lua values and game objects.

Economy and technology

Call Result
GetAttribute(attribute) Assigned-player native attribute value, or nil when unavailable (including the ambiguous native -1 error sentinel).
CanAfford(objectType, isBuilding) true when the assigned player can afford an object.
GetTechCost(technology) costs, available: array of positive technology costs and read availability.
GetObjectCost(objectType[, multiplier = 1]) costs, available: array of positive object costs and read availability.
CanResearch(technology) Research availability, or nil when required queries fail.
IsTechnologyResearched(technology) Research completion state.
IsObjectTypeAvailable(objectType) Availability for the assigned player.
GetUnitTypeCount(unitType) count, available: Completed assigned-player unit count.
GetUnitTypeCountTotal(unitType) count, available: Unit count, including incomplete objects.
GetBuildingTypeCount(buildingType) count, available: Completed assigned-player building count.
GetBuildingTypeCountTotal(buildingType) count, available: Building count, including incomplete objects.
GetTotalUnitCount() count, available: Completed assigned-player unit count.
GetTotalUnitCountTotal() count, available: Unit count, including incomplete objects.
GetTotalBuildingCount() count, available: Completed assigned-player building count.
GetTotalBuildingCountTotal() count, available: Building count, including incomplete objects.

Use PlayerAttribute, Technology, and UnitObjectType constants when the enum index supplies a name. The isBuilding value selects building or unit affordability.

Each cost entry has named fields and array fields:

local costs, available = GetTechCost(Technology.LOOM)
if available then
    for _, cost in ipairs(costs) do
        LogInfo(string.format("resource %d: %d", cost.resourceId, cost.amount))
    end
end

The same values are also available as cost[1] and cost[2]. An empty array with available == true means the read found no positive resource costs.

Objects

Call Result
GetObjectById(objectId) Object, or nil.
GetObjectsByType(objectType) Array of matching objects.
GetObjectsByTypes(objectTypes[, ...]) Array matching any supplied type.
GetObjectsByClass(unitClass) Array matching a class.
GetObjectsInArea(a, b) Objects inside an inclusive 2D rectangle.

GetObjectsByTypes accepts one or more integer type IDs, or one dense integer array. GetObjectsInArea(a, b) accepts two { x, y } values. It includes both rectangle edges.

The result is a current object list, not a permanent match record. Save object IDs and query them again when you need them later.

Map

Call Result
GetMapWidth() width, available: map width and read availability.
GetMapHeight() height, available: map height and read availability.
GetMapTile(position) MapTile, or nil.
GetAllMapTiles() Array of valid MapTile values.

GetMapTile accepts { x, y } or adjacent x, y numbers. It rounds down fractional coordinates.

GetAllMapTiles() creates one value for every tile. Use GetMapTile() when you need a small area or a repeated check.

Specialized queries

CalculatePathDistance, object-type data, diagnostics, fact shortcuts, and Xs* queries are version-sensitive. Use them only when the normal API lacks the data that you need. See Low-level queries and diagnostics.

Availability of legacy numeric facts

GetFact, GetUnitTypeCount, GetUnitTypeCountTotal, GetBuildingTypeCount, GetBuildingTypeCountTotal, the four GetTotalUnitCount/GetTotalBuildingCount variants, GetPlayerCount, GetMapWidth, GetMapHeight, and GetVictoryCondition now return a second boolean indicating whether the native read succeeded. Their first result is preserved for existing single-value callers. When the flag is false, ignore that result: it can be a default zero or a partial live count. This availability flag does not make sequential live reads an atomic snapshot.

local count, available = GetUnitTypeCount(83)
if available then
    print("Known villager count: " .. count)
end

Code that forwards all return values now forwards the availability flag too; use a single local variable when only the legacy number is intended.

GetTechCost(techId) and GetObjectCost(objectType, multiplier) return costs, available. The existing first result remains an array of positive {resourceId, amount} entries. If availability is false, the array must not be interpreted as the true cost; empty or partial data does not establish affordability. An empty table with availability true means the native read found no positive resource costs. As with numeric facts, forwarding all results includes the flag.

local costs, available = GetObjectCost(83)
if available then
    for _, cost in ipairs(costs) do
        print(cost.resourceId, cost.amount)
    end
end