/** ** Checks if dependencies are met. ** ** @return true if the dependencies are met. ** ** @param l Lua state. ** Argument 1: player ** Argument 2: object which we want to check the dependencies of */ static int CclCheckDependency(lua_State *l) { LuaCheckArgs(l, 2); const char *object = LuaToString(l, 2); lua_pop(l, 1); const int plynr = TriggerGetPlayer(l); if (plynr == -1) { LuaError(l, "bad player: %i" _C_ plynr); } const CPlayer *player = &Players[plynr]; if (!strncmp(object, "unit-", 5)) { const CUnitType *unit_type = UnitTypeByIdent(object); if (!unit_type) { LuaError(l, "Invalid unit type: \"%s\"" _C_ object); } lua_pushboolean(l, CheckDependencies(unit_type, player)); } else if (!strncmp(object, "upgrade-", 8)) { const CUpgrade *upgrade = CUpgrade::Get(object); if (!upgrade) { LuaError(l, "Invalid upgrade: \"%s\"" _C_ object); } lua_pushboolean(l, CheckDependencies(upgrade, player)); } else { LuaError(l, "Invalid target of dependency check: \"%s\"" _C_ object); } return 1; }
/** ** Kill a unit ** ** @param l Lua state. ** ** @return Returns true if a unit was killed. */ static int CclKillUnit(lua_State *l) { LuaCheckArgs(l, 2); lua_pushvalue(l, 1); const CUnitType *unittype = TriggerGetUnitType(l); lua_pop(l, 1); const int plynr = TriggerGetPlayer(l); if (plynr == -1) { CUnitManager::Iterator it = std::find_if(UnitManager.begin(), UnitManager.end(), HasSameUnitTypeAs(unittype)); if (it != UnitManager.end()) { LetUnitDie(**it); lua_pushboolean(l, 1); return 1; } } else { CPlayer &player = Players[plynr]; std::vector<CUnit *>::iterator it = std::find_if(player.UnitBegin(), player.UnitEnd(), HasSameUnitTypeAs(unittype)); if (it != player.UnitEnd()) { LetUnitDie(**it); lua_pushboolean(l, 1); return 1; } } lua_pushboolean(l, 0); return 1; }
/** ** Player has the quantity of rescued unit-type near to unit-type. */ static int CclIfRescuedNearUnit(lua_State *l) { LuaCheckArgs(l, 5); lua_pushvalue(l, 1); const int plynr = TriggerGetPlayer(l); lua_pop(l, 1); const char *op = LuaToString(l, 2); const int q = LuaToNumber(l, 3); lua_pushvalue(l, 4); const CUnitType *unittype = TriggerGetUnitType(l); lua_pop(l, 1); const CUnitType *ut2 = CclGetUnitType(l); if (!unittype || !ut2) { LuaError(l, "CclIfRescuedNearUnit: not a unit-type valid"); } CompareFunction compare = GetCompareFunction(op); if (!compare) { LuaError(l, "Illegal comparison operation in if-rescued-near-unit: %s" _C_ op); } // Get all unit types 'near'. std::vector<CUnit *> table; FindUnitsByType(*ut2, table); for (size_t i = 0; i != table.size(); ++i) { CUnit ¢erUnit = *table[i]; std::vector<CUnit *> around; SelectAroundUnit(centerUnit, 1, around); // Count the requested units int s = 0; for (size_t j = 0; j != around.size(); ++j) { CUnit &unit = *around[j]; if (unit.RescuedFrom) { // only rescued units // Check unit type if (unittype == ANY_UNIT || (unittype == ALL_FOODUNITS && !unit.Type->Building) || (unittype == ALL_BUILDINGS && unit.Type->Building) || (unittype == unit.Type)) { // Check the player if (plynr == -1 || plynr == unit.Player->Index) { ++s; } } } } if (compare(s, q)) { lua_pushboolean(l, 1); return 1; } } lua_pushboolean(l, 0); return 1; }
/** ** Create a unit and place it on the map ** ** @param l Lua state. ** ** @return Returns the slot number of the made unit. */ static int CclCreateUnit(lua_State *l) { LuaCheckArgs(l, 3); lua_pushvalue(l, 1); CUnitType *unittype = CclGetUnitType(l); if (unittype == NULL) { LuaError(l, "Bad unittype"); } lua_pop(l, 1); Vec2i ipos; CclGetPos(l, &ipos.x, &ipos.y, 3); lua_pushvalue(l, 2); const int playerno = TriggerGetPlayer(l); lua_pop(l, 1); if (playerno == -1) { printf("CreateUnit: You cannot use \"any\" in create-unit, specify a player\n"); LuaError(l, "bad player"); return 0; } if (Players[playerno].Type == PlayerNobody) { printf("CreateUnit: player %d does not exist\n", playerno); LuaError(l, "bad player"); return 0; } CUnit *unit = MakeUnit(*unittype, &Players[playerno]); if (unit == NULL) { DebugPrint("Unable to allocate unit"); return 0; } else { if (UnitCanBeAt(*unit, ipos) || (unit->Type->Building && CanBuildUnitType(NULL, *unit->Type, ipos, 0))) { unit->Place(ipos); } else { const int heading = SyncRand() % 256; unit->tilePos = ipos; DropOutOnSide(*unit, heading, NULL); } UpdateForNewUnit(*unit, 0); lua_pushnumber(l, UnitNumber(*unit)); return 1; } }
/** ** Kill a unit at a location ** ** @param l Lua state. ** ** @return Returns the number of units killed. */ static int CclKillUnitAt(lua_State *l) { LuaCheckArgs(l, 5); lua_pushvalue(l, 1); const CUnitType *unittype = TriggerGetUnitType(l); lua_pop(l, 1); lua_pushvalue(l, 2); int plynr = TriggerGetPlayer(l); lua_pop(l, 1); int q = LuaToNumber(l, 3); if (!lua_istable(l, 4) || !lua_istable(l, 5)) { LuaError(l, "incorrect argument"); } Vec2i pos1; Vec2i pos2; CclGetPos(l, &pos1.x, &pos1.y, 4); CclGetPos(l, &pos2.x, &pos2.y, 5); std::vector<CUnit *> table; Select(pos1, pos2, table); int s = 0; for (std::vector<CUnit *>::iterator it = table.begin(); it != table.end() && s < q; ++it) { CUnit &unit = **it; if (unittype == ANY_UNIT || (unittype == ALL_FOODUNITS && !unit.Type->Building) || (unittype == ALL_BUILDINGS && unit.Type->Building) || unittype == unit.Type) { if ((plynr == -1 || plynr == unit.Player->Index) && unit.IsAlive()) { LetUnitDie(unit); ++s; } } } lua_pushnumber(l, s); return 1; }
/** ** Get a player's units ** ** @param l Lua state. ** ** @return Array of units. */ static int CclGetUnits(lua_State *l) { LuaCheckArgs(l, 1); const int plynr = TriggerGetPlayer(l); lua_newtable(l); if (plynr == -1) { int i = 0; for (CUnitManager::Iterator it = UnitManager.begin(); it != UnitManager.end(); ++it, ++i) { const CUnit &unit = **it; lua_pushnumber(l, UnitNumber(unit)); lua_rawseti(l, -2, i + 1); } } else { for (int i = 0; i < Players[plynr].GetUnitCount(); ++i) { lua_pushnumber(l, UnitNumber(Players[plynr].GetUnit(i))); lua_rawseti(l, -2, i + 1); } } return 1; }
/** ** Order a unit ** ** @param l Lua state. ** ** OrderUnit(player, unit-type, sloc, dloc, order) */ static int CclOrderUnit(lua_State *l) { LuaCheckArgs(l, 5); lua_pushvalue(l, 1); const int plynr = TriggerGetPlayer(l); lua_pop(l, 1); lua_pushvalue(l, 2); const CUnitType *unittype = TriggerGetUnitType(l); lua_pop(l, 1); if (!lua_istable(l, 3)) { LuaError(l, "incorrect argument"); } Vec2i pos1; pos1.x = LuaToNumber(l, 3, 1); pos1.y = LuaToNumber(l, 3, 2); Vec2i pos2; if (lua_rawlen(l, 3) == 4) { pos2.x = LuaToNumber(l, 3, 3); pos2.y = LuaToNumber(l, 3, 4); } else { pos2 = pos1; } if (!lua_istable(l, 4)) { LuaError(l, "incorrect argument"); } Vec2i dpos1; Vec2i dpos2; dpos1.x = LuaToNumber(l, 4, 1); dpos1.y = LuaToNumber(l, 4, 2); if (lua_rawlen(l, 4) == 4) { dpos2.x = LuaToNumber(l, 4, 3); dpos2.y = LuaToNumber(l, 4, 4); } else { dpos2 = dpos1; } const char *order = LuaToString(l, 5); std::vector<CUnit *> table; Select(pos1, pos2, table); for (size_t i = 0; i != table.size(); ++i) { CUnit &unit = *table[i]; if (unittype == ANY_UNIT || (unittype == ALL_FOODUNITS && !unit.Type->Building) || (unittype == ALL_BUILDINGS && unit.Type->Building) || unittype == unit.Type) { if (plynr == -1 || plynr == unit.Player->Index) { if (!strcmp(order, "move")) { CommandMove(unit, (dpos1 + dpos2) / 2, 1); } else if (!strcmp(order, "attack")) { CUnit *attack = TargetOnMap(unit, dpos1, dpos2); CommandAttack(unit, (dpos1 + dpos2) / 2, attack, 1); } else if (!strcmp(order, "patrol")) { CommandPatrolUnit(unit, (dpos1 + dpos2) / 2, 1); } else { LuaError(l, "Unsupported order: %s" _C_ order); } } } } return 0; }