/** ** Need a unit. ** ** @param l Lua state. ** ** @return Number of return values */ static int CclAiNeed(lua_State *l) { LuaCheckArgs(l, 1); InsertUnitTypeRequests(CclGetUnitType(l), 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; }
/** ** Upgrade an unit to an new unit-type. ** ** @param l Lua state. */ static int CclAiUpgradeTo(lua_State *l) { LuaCheckArgs(l, 1); CUnitType *type = CclGetUnitType(l); InsertUpgradeToRequests(type); lua_pushboolean(l, 0); return 1; }
/** ** Define a force, a groups of units. ** ** @param l Lua state. */ static int CclAiForce(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument"); } int force = LuaToNumber(l, 1); if (force < 0 || force >= AI_MAX_FORCES) { LuaError(l, "Force out of range: %d" _C_ force); } AiForce &aiforce = AiPlayer->Force[AiPlayer->Force.getScriptForce(force)]; int args = lua_rawlen(l, 2); for (int j = 0; j < args; ++j) { lua_rawgeti(l, 2, j + 1); CUnitType *type = CclGetUnitType(l); lua_pop(l, 1); ++j; lua_rawgeti(l, 2, j + 1); int count = LuaToNumber(l, -1); lua_pop(l, 1); if (!type) { // bulletproof continue; } // Use the equivalent unittype. type = UnitTypes[UnitTypeEquivs[type->Slot]]; // Look if already in force. size_t i; for (i = 0; i < aiforce.UnitTypes.size(); ++i) { AiUnitType *aiut = &aiforce.UnitTypes[i]; if (aiut->Type->Slot == type->Slot) { // found if (count) { aiut->Want = count; } else { aiforce.UnitTypes.erase(aiforce.UnitTypes.begin() + i); } break; } } // New type append it. if (i == aiforce.UnitTypes.size()) { AiUnitType newaiut; newaiut.Want = count; newaiut.Type = type; aiforce.UnitTypes.push_back(newaiut); } } AiAssignFreeUnitsToForce(); lua_pushboolean(l, 0); return 1; }
/** ** Get the unit-type. ** ** @param l Lua state. ** ** @return The unit-type pointer. */ const CUnitType *TriggerGetUnitType(lua_State *l) { const char *unit = LuaToString(l, -1); if (!strcmp(unit, "any")) { return ANY_UNIT; } else if (!strcmp(unit, "units")) { return ALL_FOODUNITS; } else if (!strcmp(unit, "buildings")) { return ALL_BUILDINGS; } return CclGetUnitType(l); }
/** ** Wait for a unit. ** ** @param l Lua State. ** ** @return Number of return values */ static int CclAiWait(lua_State *l) { LuaCheckArgs(l, 1); const CUnitType *type = CclGetUnitType(l); const int *unit_types_count = AiPlayer->Player->UnitTypesCount; const AiRequestType *autt = FindInUnitTypeRequests(type); if (!autt) { // Look if we have this unit-type. if (unit_types_count[type->Slot]) { lua_pushboolean(l, 0); return 1; } // Look if we have equivalent unit-types. if (type->Slot < (int)AiHelpers.Equiv.size()) { for (size_t j = 0; j < AiHelpers.Equiv[type->Slot].size(); ++j) { if (unit_types_count[AiHelpers.Equiv[type->Slot][j]->Slot]) { lua_pushboolean(l, 0); return 1; } } } // Look if we have an upgrade-to request. if (FindInUpgradeToRequests(type)) { lua_pushboolean(l, 1); return 1; } DebugPrint("Broken? waiting on %s which wasn't requested.\n" _C_ type->Ident.c_str()); lua_pushboolean(l, 0); return 1; } // // Add equivalent units // unsigned int n = unit_types_count[type->Slot]; if (type->Slot < (int)AiHelpers.Equiv.size()) { for (size_t j = 0; j < AiHelpers.Equiv[type->Slot].size(); ++j) { n += unit_types_count[AiHelpers.Equiv[type->Slot][j]->Slot]; } } // units available? if (n >= autt->Count) { lua_pushboolean(l, 0); return 1; } lua_pushboolean(l, 1); return 1; }
/** ** Set the number of units. ** ** @param l Lua state ** ** @return Number of return values */ static int CclAiSet(lua_State *l) { LuaCheckArgs(l, 2); lua_pushvalue(l, 1); CUnitType *type = CclGetUnitType(l); lua_pop(l, 1); AiRequestType *autt = FindInUnitTypeRequests(type); if (autt) { autt->Count = LuaToNumber(l, 2); // FIXME: 0 should remove it. } else { InsertUnitTypeRequests(type, LuaToNumber(l, 2)); } 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; } }
/** ** Get player data. ** ** @param l Lua state. */ static int CclGetPlayerData(lua_State *l) { if (lua_gettop(l) < 2) { LuaError(l, "incorrect argument"); } lua_pushvalue(l, 1); const CPlayer *p = CclGetPlayer(l); lua_pop(l, 1); const char *data = LuaToString(l, 2); if (!strcmp(data, "Name")) { lua_pushstring(l, p->Name.c_str()); return 1; } else if (!strcmp(data, "RaceName")) { lua_pushstring(l, PlayerRaces.Name[p->Race].c_str()); return 1; } else if (!strcmp(data, "Resources")) { LuaCheckArgs(l, 3); const std::string res = LuaToString(l, 3); const int resId = GetResourceIdByName(l, res.c_str()); lua_pushnumber(l, p->Resources[resId] + p->StoredResources[resId]); return 1; } else if (!strcmp(data, "StoredResources")) { LuaCheckArgs(l, 3); const std::string res = LuaToString(l, 3); const int resId = GetResourceIdByName(l, res.c_str()); lua_pushnumber(l, p->StoredResources[resId]); return 1; } else if (!strcmp(data, "MaxResources")) { LuaCheckArgs(l, 3); const std::string res = LuaToString(l, 3); const int resId = GetResourceIdByName(l, res.c_str()); lua_pushnumber(l, p->MaxResources[resId]); return 1; } else if (!strcmp(data, "UnitTypesCount")) { CUnitType *type; LuaCheckArgs(l, 3); type = CclGetUnitType(l); lua_pushnumber(l, p->UnitTypesCount[type->Slot]); return 1; } else if (!strcmp(data, "AiEnabled")) { lua_pushboolean(l, p->AiEnabled); return 1; } else if (!strcmp(data, "TotalNumUnits")) { lua_pushnumber(l, p->GetUnitCount()); return 1; } else if (!strcmp(data, "NumBuildings")) { lua_pushnumber(l, p->NumBuildings); return 1; } else if (!strcmp(data, "Supply")) { lua_pushnumber(l, p->Supply); return 1; } else if (!strcmp(data, "Demand")) { lua_pushnumber(l, p->Demand); return 1; } else if (!strcmp(data, "UnitLimit")) { lua_pushnumber(l, p->UnitLimit); return 1; } else if (!strcmp(data, "BuildingLimit")) { lua_pushnumber(l, p->BuildingLimit); return 1; } else if (!strcmp(data, "TotalUnitLimit")) { lua_pushnumber(l, p->TotalUnitLimit); return 1; } else if (!strcmp(data, "Score")) { lua_pushnumber(l, p->Score); return 1; } else if (!strcmp(data, "TotalUnits")) { lua_pushnumber(l, p->TotalUnits); return 1; } else if (!strcmp(data, "TotalBuildings")) { lua_pushnumber(l, p->TotalBuildings); return 1; } else if (!strcmp(data, "TotalResources")) { LuaCheckArgs(l, 3); const std::string res = LuaToString(l, 3); const int resId = GetResourceIdByName(l, res.c_str()); lua_pushnumber(l, p->TotalResources[resId]); return 1; } else if (!strcmp(data, "TotalRazings")) { lua_pushnumber(l, p->TotalRazings); return 1; } else if (!strcmp(data, "TotalKills")) { lua_pushnumber(l, p->TotalKills); return 1; } else if (!strcmp(data, "SpeedResourcesHarvest")) { LuaCheckArgs(l, 3); const std::string res = LuaToString(l, 3); const int resId = GetResourceIdByName(l, res.c_str()); lua_pushnumber(l, p->SpeedResourcesHarvest[resId]); return 1; } else if (!strcmp(data, "SpeedResourcesReturn")) { LuaCheckArgs(l, 3); const std::string res = LuaToString(l, 3); const int resId = GetResourceIdByName(l, res.c_str()); lua_pushnumber(l, p->SpeedResourcesReturn[resId]); return 1; } else if (!strcmp(data, "SpeedBuild")) { lua_pushnumber(l, p->SpeedBuild); return 1; } else if (!strcmp(data, "SpeedTrain")) { lua_pushnumber(l, p->SpeedTrain); return 1; } else if (!strcmp(data, "SpeedUpgrade")) { lua_pushnumber(l, p->SpeedUpgrade); return 1; } else if (!strcmp(data, "SpeedResearch")) { lua_pushnumber(l, p->SpeedResearch); return 1; } else { LuaError(l, "Invalid field: %s" _C_ data); } return 0; }
/** ** Get player data. ** ** @param l Lua state. */ static int CclGetPlayerData(lua_State *l) { CPlayer *p; const char *data; if (lua_gettop(l) < 2) { LuaError(l, "incorrect argument"); } lua_pushvalue(l, 1); p = CclGetPlayer(l); lua_pop(l, 1); data = LuaToString(l, 2); if (!strcmp(data, "Name")) { lua_pushstring(l, p->Name.c_str()); return 1; } else if (!strcmp(data, "RaceName")) { lua_pushstring(l, PlayerRaces.Name[p->Race]); return 1; } else if (!strcmp(data, "Resources")) { const char *res; int i; LuaCheckArgs(l, 3); res = LuaToString(l, 3); for (i = 0; i < MaxCosts; ++i) { if (!strcmp(res, DefaultResourceNames[i])) { break; } } if (i == MaxCosts) { LuaError(l, "Invalid resource \"%s\"" _C_ res); } lua_pushnumber(l, p->Resources[i]); return 1; } else if (!strcmp(data, "UnitTypesCount")) { CUnitType *type; LuaCheckArgs(l, 3); type = CclGetUnitType(l); lua_pushnumber(l, p->UnitTypesCount[type->Slot]); return 1; } else if (!strcmp(data, "AiEnabled")) { lua_pushboolean(l, p->AiEnabled); return 1; } else if (!strcmp(data, "TotalNumUnits")) { lua_pushnumber(l, p->TotalNumUnits); return 1; } else if (!strcmp(data, "NumBuildings")) { lua_pushnumber(l, p->NumBuildings); return 1; } else if (!strcmp(data, "Supply")) { lua_pushnumber(l, p->Supply); return 1; } else if (!strcmp(data, "Demand")) { lua_pushnumber(l, p->Demand); return 1; } else if (!strcmp(data, "UnitLimit")) { lua_pushnumber(l, p->UnitLimit); return 1; } else if (!strcmp(data, "BuildingLimit")) { lua_pushnumber(l, p->BuildingLimit); return 1; } else if (!strcmp(data, "TotalUnitLimit")) { lua_pushnumber(l, p->TotalUnitLimit); return 1; } else if (!strcmp(data, "Score")) { lua_pushnumber(l, p->Score); return 1; } else if (!strcmp(data, "TotalUnits")) { lua_pushnumber(l, p->TotalUnits); return 1; } else if (!strcmp(data, "TotalBuildings")) { lua_pushnumber(l, p->TotalBuildings); return 1; } else if (!strcmp(data, "TotalResources")) { const char *res; int i; LuaCheckArgs(l, 3); res = LuaToString(l, 3); for (i = 0; i < MaxCosts; ++i) { if (!strcmp(res, DefaultResourceNames[i])) { break; } } if (i == MaxCosts) { LuaError(l, "Invalid resource \"%s\"" _C_ res); } lua_pushnumber(l, p->TotalResources[i]); return 1; } else if (!strcmp(data, "TotalRazings")) { lua_pushnumber(l, p->TotalRazings); return 1; } else if (!strcmp(data, "TotalKills")) { lua_pushnumber(l, p->TotalKills); return 1; } else { LuaError(l, "Invalid field: %s" _C_ data); } return 0; }