Differences Between the C++ and Lua API¶
Most of the API follows the conventions of the C++ API and can be used in exactly the same ways, although there are exceptions in cases where either:
- The Lua programming language does not have the same capabilities as C++, so things must be done a different way
- It makes more sense to do something in a “Lua way” rather than the “C++ way”
This page documents all such differences.
All classes¶
Every bound class has a static member function isInstance which can be used to determine if a userdata value (an instance of a C++ class) is an instance of that class.
function determineType(unknown)
if BWAPI.Position.isInstance(unknown) then
print("It's a Position")
elseif BWAPI.TilePosition.isInstance(unknown) then
print("It's a TilePosition")
elseif BWAPI.Unit.isInstance(unknown) then
print("It's a Unit")
else
print("It's something else")
end
end
Interface derived classes (Game, Player, Unit, etc)¶
registerEvent()¶
Takes Lua functions for its action and condition parameters (note: condition can be nil)
local Broodwar = BWAPI.Broodwar
local pos = u:getPosition()
local lastErr = Broodwar:getLastError()
local action = function()
Broodwar:drawTextMap(pos, string.format("%c%s", BWAPI.Text.White, tostring(lastErr)))
end
Broodwar:registerEvent(action, nil, Broodwar:getLatencyFrames())
Functions that take a variable amount of string parameters in C++¶
All C++ functions that take variable amounts of strings now expect only a single string.
Note
Any formatting must be done in Lua first (string.format), and then the formatted string can be passed into the function like normal.
Game.sendTextEx()¶
A new convenience function has been added to send text to allies: sendTextToAllies(), which fowards the method to sendTextEx() with true as the first parameter. The following two snippets are exactly equivalent:
BWAPI.Broodwar:sendTextEx(true, "your message")BWAPI.Broodwar:sendTextToAllies("your message")
Unit¶
cancelTrain() and getTrainingQueue()¶
All methods that deal with training slots have been changed to be one-indexed (like Lua), rather than zero-indexed (like C++). For example, to cancel the first unit being trained, you would now pass a slot of 1, whereas in C++ you’d pass a slot of 0. List of affected methods:
BWAPI.Unit.canCancelTrainSlot()BWAPI.Unit.cancelTrain()BWAPI.Unit.getTrainingQueue()BWAPI.UnitCommand.getSlot()BWAPI.UnitCommand.cancelTrain()BWAPI.Unitset.cancelTrain()
Similarly, getTrainingQueue() returns a Lua array-like table (which is one-indexed) instead of a std::list (which is zero-indexed). This allows for the following:
-- cancel the first dragoon found in the queue
local queue = building:getTrainingQueue()
for slot, unitType in ipairs(queue) do
if unitType == BWAPI.UnitTypes.Protoss_Dragoon then
building:cancelTrain(slot)
break
end
end
Warning
Iterating a training queue and canceling multiple slots while in the loop will result in unexpected behavior, as the slots will shift as things are canceled. For example, if you cancel slot 1 and then iterate to slot 2 and also cancel it, then you’ll actually be canceling what was originally in slot 3.
UnitType¶
whatBuilds()¶
Returns two values instead of a std::pair
local unitType, howMany = ut:whatBuilds()
requiredUnits()¶
Returns a Lua table of the format { [<unitTypeID>] = <howMany> }, where <unitTypeID> is the integer ID/Enum of a required UnitType (equal to UnitType:getID()) and <howMany> is the required number of that unit.
local scv = BWAPI.UnitTypes.SCV
local requiredUnits = scv:requiredUnits()
for unitTypeID, howMany in pairs(requiredUnits) do
local requiredUnitType = BWAPI.UnitType(unitTypeID)
local str = string.format("%s requires %d %s",
tostring(scv),
howMany,
tostring(requiredUnitType)
)
print(str)
end
SetContainer implementations (Unitset, Playerset, etc)¶
The set can be iterated one of two ways:
for x in set:iterator() dofor i, x in ipairs(set:asTable()) do
Also, any SetContainer types of the format ClassName::set are bound as ClassNameset, to match the naming convention of the other SetContainer types (Playerset, Unitset, etc). For example, UnitType::set is bound as BWAPI.UnitTypeset.
An additional convenience method, filter (e.g. BWAPI.Unitset.filter()), has been added to easily filter a set using a predicate function, as well as some aliases for filter and erase_if (see eraseIf(), keep_if(), keepIf()).
All lists (std::list, Position::list, UnitType::list, etc)¶
All C++ functions that return lists now return array-like Lua tables.
local nukeDots = BWAPI.Broodwar:getNukeDots()
for i, pos in ipairs(nukeDots) do
print(string.format("There's a nuke at %s", tostring(pos)))
end
UnitFilter¶
All functions that take a UnitFilter parameter now expect a Lua function that takes a unit and returns a boolean.
Note
BWAPI.Filter functions can be used by calling them with a Unit as the parameter (e.g. BWAPI.Filter.CanAttack(unit))
These filters can also be combined by using the normal Lua boolean operators and wrapping/returning the result in a function. The function can then be passed as an argument to functions that would normally take a UnitFilter in C++, like so:
local myFilter = function(unit)
return BWAPI.Filter.CanAttack(unit) and not BWAPI.Filter.IsOrganic(unit)
end
local closest = unit:getClosestUnit(myFilter)
BestFilter¶
All functions that take a BestUnitFilter parameter now expect a Lua function that takes two parameters: the current best unit, and the unit to compare to, and returns the best unit out of the two.
local bestFilter = function(a, b)
if b:getHitPoints() > a:getHitPoints() then
return b
end
return a
end
local best = BWAPI.Broodwar:getBestUnit(bestFilter, BWAPI.Filter.IsOrganic)
See also
Event and Game::getEvents¶
For now, the getEvents function of BWAPI.Game has been removed, and there are no bindings for the BWAPI.Event class. This is subject to change if it’s shown to be necessary.