/* virtual */ void CContentTypeText::Parse(lua_State *l) { Assert(lua_istable(l, -1) || lua_isstring(l, -1)); if (lua_isstring(l, -1)) { this->Text = CclParseStringDesc(l); lua_pushnil(l); // ParseStringDesc eat token } else { for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) { const char *key = LuaToString(l, -2); if (!strcmp(key, "Text")) { this->Text = CclParseStringDesc(l); lua_pushnil(l); // ParseStringDesc eat token } else if (!strcmp(key, "Font")) { this->Font = CFont::Get(LuaToString(l, -1)); } else if (!strcmp(key, "Centered")) { this->Centered = LuaToBoolean(l, -1); } else if (!strcmp(key, "Variable")) { const char *const name = LuaToString(l, -1); this->Index = UnitTypeVar.VariableNameLookup[name]; if (this->Index == -1) { LuaError(l, "unknown variable '%s'" _C_ LuaToString(l, -1)); } } else if (!strcmp(key, "Component")) { this->Component = Str2EnumVariable(l, LuaToString(l, -1)); } else if (!strcmp(key, "Stat")) { this->Stat = LuaToBoolean(l, -1); } else if (!strcmp(key, "ShowName")) { this->ShowName = LuaToBoolean(l, -1); } else { LuaError(l, "'%s' invalid for method 'Text' in DefinePanelContents" _C_ key); } } } }
/** ** Get a player's units in rectangle box specified with 2 coordinates ** ** @param l Lua state. ** ** @return Array of units. */ static int CclGetUnitsAroundUnit(lua_State *l) { const int nargs = lua_gettop(l); if (nargs != 2 && nargs != 3) { LuaError(l, "incorrect argument\n"); } const int slot = LuaToNumber(l, 1); const CUnit &unit = UnitManager.GetSlotUnit(slot); const int range = LuaToNumber(l, 2); bool allUnits = false; if (nargs == 3) { allUnits = LuaToBoolean(l, 3); } lua_newtable(l); std::vector<CUnit *> table; if (allUnits) { SelectAroundUnit(unit, range, table, HasNotSamePlayerAs(Players[PlayerNumNeutral])); } else { SelectAroundUnit(unit, range, table, HasSamePlayerAs(*unit.Player)); } size_t n = 0; for (size_t i = 0; i < table.size(); ++i) { if (table[i]->IsAliveOnMap()) { lua_pushnumber(l, UnitNumber(*table[i])); lua_rawseti(l, -2, ++n); } } return 1; }
/** ** Create a missile on the map ** ** @param l Lua state. ** */ static int CclCreateMissile(lua_State *l) { const int arg = lua_gettop(l); if (arg < 6 || arg > 7) { LuaError(l, "incorrect argument"); } const std::string name = LuaToString(l, 1); const MissileType *mtype = MissileTypeByIdent(name); if (!mtype) { LuaError(l, "Bad missile"); } PixelPos startpos, endpos; CclGetPos(l, &startpos.x, &startpos.y, 2); CclGetPos(l, &endpos.x, &endpos.y, 3); const int sourceUnitId = LuaToNumber(l, 4); const int destUnitId = LuaToNumber(l, 5); const bool dealDamage = LuaToBoolean(l, 6); const bool mapRelative = arg == 7 ? LuaToBoolean(l, 7) : false; CUnit *sourceUnit = sourceUnitId != -1 ? &UnitManager.GetSlotUnit(sourceUnitId) : nullptr; CUnit *destUnit = destUnitId != -1 ? &UnitManager.GetSlotUnit(destUnitId) : nullptr; if (mapRelative == false) { if (sourceUnit != nullptr) { startpos += sourceUnit->GetMapPixelPosTopLeft(); } if (destUnit != nullptr) { endpos += destUnit->GetMapPixelPosTopLeft(); } } //Wyrmgus start // Missile *missile = MakeMissile(*mtype, startpos, endpos); Missile *missile = MakeMissile(*mtype, startpos, endpos, 0); //Wyrmgus end if (!missile) { return 0; } if (dealDamage) { missile->SourceUnit = sourceUnit; } missile->TargetUnit = destUnit; return 0; }
/** ** Parse the Condition for spell. ** ** @param l Lua state. ** @param autocast pointer to autocast to fill with data. ** ** @note: autocast must be allocated. All data already in is LOST. */ static void CclSpellAutocast(lua_State *l, AutoCastInfo *autocast) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int args = lua_rawlen(l, -1); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, -1, j + 1); ++j; if (!strcmp(value, "range")) { autocast->Range = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "min-range")) { autocast->MinRange = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "position-autocast")) { lua_rawgeti(l, -1, j + 1); autocast->PositionAutoCast = new LuaCallback(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "combat")) { autocast->Combat = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "attacker")) { autocast->Attacker = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "corpse")) { autocast->Corpse = Ccl2Condition(l, LuaToString(l, -1, j + 1)); } else if (!strcmp(value, "priority")) { lua_rawgeti(l, -1, j + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, -1, 1); std::string var = LuaToString(l, -1); int index = UnitTypeVar.VariableNameLookup[var.c_str()];// User variables if (index == -1) { if (!strcmp(var.c_str(), "Distance")) { index = ACP_DISTANCE; } else { fprintf(stderr, "Bad variable name '%s'\n", var.c_str()); Exit(1); } } autocast->PriorytyVar = index; lua_pop(l, 1); autocast->ReverseSort = LuaToBoolean(l, -1, 2); lua_pop(l, 1); } else if (!strcmp(value, "condition")) { if (!autocast->Condition) { autocast->Condition = new ConditionInfo; } lua_rawgeti(l, -1, j + 1); CclSpellCondition(l, autocast->Condition); lua_pop(l, 1); } else { LuaError(l, "Unsupported autocast tag: %s" _C_ value); } } }
static int CclSetUseTextureCompression(lua_State *l) { LuaCheckArgs(l, 1); #if defined(USE_OPENGL) || defined(USE_GLES) if (CclInConfigFile) { UseGLTextureCompression = LuaToBoolean(l, 1); } #endif return 0; }
/** ** Set the active triggers */ static int CclSetActiveTriggers(lua_State *l) { const int args = lua_gettop(l); ActiveTriggers = new bool[args]; for (int j = 0; j < args; ++j) { ActiveTriggers[j] = LuaToBoolean(l, j + 1); } return 0; }
/** ** Parse the condition Panel. ** ** @param l Lua State. */ static ConditionPanel *ParseConditionPanel(lua_State *l) { Assert(lua_istable(l, -1)); ConditionPanel *condition = new ConditionPanel; for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) { const char *key = LuaToString(l, -2); if (!strcmp(key, "ShowOnlySelected")) { condition->ShowOnlySelected = LuaToBoolean(l, -1); } else if (!strcmp(key, "HideNeutral")) { condition->HideNeutral = LuaToBoolean(l, -1); } else if (!strcmp(key, "HideAllied")) { condition->HideAllied = LuaToBoolean(l, -1); } else if (!strcmp(key, "ShowOpponent")) { condition->ShowOpponent = LuaToBoolean(l, -1); } else { int index = UnitTypeVar.BoolFlagNameLookup[key]; if (index != -1) { if (!condition->BoolFlags) { size_t new_bool_size = UnitTypeVar.GetNumberBoolFlag(); condition->BoolFlags = new char[new_bool_size]; memset(condition->BoolFlags, 0, new_bool_size * sizeof(char)); } condition->BoolFlags[index] = Ccl2Condition(l, LuaToString(l, -1)); continue; } index = UnitTypeVar.VariableNameLookup[key]; if (index != -1) { if (!condition->Variables) { size_t new_variables_size = UnitTypeVar.GetNumberVariable(); condition->Variables = new char[new_variables_size]; memset(condition->Variables, 0, new_variables_size * sizeof(char)); } condition->Variables[index] = Ccl2Condition(l, LuaToString(l, -1)); continue; } LuaError(l, "'%s' invalid for Condition in DefinePanelContents" _C_ key); } } return condition; }
/** ** Set the video fullscreen mode. ** ** @param l Lua state. */ static int CclSetVideoFullScreen(lua_State *l) { LuaCheckArgs(l, 1); if (CclInConfigFile) { // May have been set from the command line if (!VideoForceFullScreen) { Video.FullScreen = LuaToBoolean(l, 1); } } return 0; }
/** ** Set fog of war on/off. ** ** @param l Lua state. */ static int CclSetFogOfWar(lua_State *l) { LuaCheckArgs(l, 1); Map.NoFogOfWar = !LuaToBoolean(l, 1); if (!CclInConfigFile && Map.Fields) { UpdateFogOfWarChange(); // FIXME: save setting in replay log //CommandLog("input", NoUnitP, FlushCommands, -1, -1, NoUnitP, "fow off", -1); } return 0; }
/** ** Define a world map terrain type. ** ** @param l Lua state. */ static int CclDefineWorldMapTerrainType(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::string terrain_name = LuaToString(l, 1); int terrain_id = GetWorldMapTerrainTypeId(terrain_name); CWorldMapTerrainType *terrain_type = nullptr; if (terrain_id == -1) { terrain_type = new CWorldMapTerrainType; terrain_type->Name = terrain_name; terrain_type->ID = WorldMapTerrainTypes.size(); WorldMapTerrainTypes.push_back(terrain_type); WorldMapTerrainTypeStringToIndex[terrain_name] = terrain_type->ID; } else { terrain_type = WorldMapTerrainTypes[terrain_id]; } // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Tag")) { terrain_type->Tag = LuaToString(l, -1); } else if (!strcmp(value, "HasTransitions")) { terrain_type->HasTransitions = LuaToBoolean(l, -1); } else if (!strcmp(value, "Water")) { terrain_type->Water = LuaToBoolean(l, -1); } else if (!strcmp(value, "BaseTile")) { terrain_type->BaseTile = GetWorldMapTerrainTypeId(LuaToString(l, -1)); } else if (!strcmp(value, "Variations")) { terrain_type->Variations = LuaToNumber(l, -1); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Change the shared vision from player to another player. ** ** @param l Lua state. ** ** @return FIXME: should return old state. */ static int CclSetSharedVision(lua_State *l) { LuaCheckArgs(l, 3); const int base = LuaToNumber(l, 1); const bool shared = LuaToBoolean(l, 2); const int plynr = LuaToNumber(l, 3); SendCommandSharedVision(base, shared, plynr); return 0; }
/** ** Create a missile on the map ** ** @param l Lua state. ** */ static int CclCreateMissile(lua_State *l) { LuaCheckArgs(l, 6); const std::string name = LuaToString(l, 1); const MissileType *mtype = MissileTypeByIdent(name); if (!mtype) { LuaError(l, "Bad missile"); } PixelPos startpos, endpos; if (!lua_istable(l, 2) || lua_rawlen(l, 2) != 2) { LuaError(l, "incorrect argument !!"); } lua_rawgeti(l, 2, 1); startpos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 2, 2); startpos.y = LuaToNumber(l, -1); lua_pop(l, 1); if (!lua_istable(l, 3) || lua_rawlen(l, 3) != 2) { LuaError(l, "incorrect argument !!"); } lua_rawgeti(l, 3, 1); endpos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, 3, 2); endpos.y = LuaToNumber(l, -1); lua_pop(l, 1); const int sourceUnitId = LuaToNumber(l, 4); const int destUnitId = LuaToNumber(l, 5); const bool dealDamage = LuaToBoolean(l, 6); CUnit *sourceUnit = sourceUnitId != -1 ? &UnitManager.GetSlotUnit(sourceUnitId) : NULL; CUnit *destUnit = destUnitId != -1 ? &UnitManager.GetSlotUnit(destUnitId) : NULL; if (sourceUnit != NULL) { startpos += sourceUnit->GetMapPixelPosTopLeft(); } if (destUnit != NULL) { endpos += destUnit->GetMapPixelPosTopLeft(); } Missile *missile = MakeMissile(*mtype, startpos, endpos); if (!missile) { return 0; } if (dealDamage) { missile->SourceUnit = sourceUnit; } missile->TargetUnit = destUnit; return 0; }
static int CclSetUseOpenGL(lua_State *l) { LuaCheckArgs(l, 1); #if defined(USE_OPENGL) || defined(USE_GLES) if (CclInConfigFile) { // May have been set from the command line if (!ForceUseOpenGL) { UseOpenGL = LuaToBoolean(l, 1); } } #endif return 0; }
/** ** Ask the sound system to play the specified sound. ** ** @param l Lua state. */ static int CclPlaySound(lua_State *l) { const int args = lua_gettop(l); if (args < 1 || args > 2) { LuaError(l, "incorrect argument"); } lua_pushvalue(l, 1); CSound *id = CclGetSound(l); lua_pop(l, 1); bool always = false; if (args == 2) { always = LuaToBoolean(l, 2); } PlayGameSound(id, MaxSampleVolume, always); return 0; }
/** ** Handle cheats ** ** @return 1 if a cheat was handled, 0 otherwise */ int HandleCheats(const std::string &input) { int ret; #if defined(DEBUG) || defined(PROF) if (input == "ai me") { if (ThisPlayer->AiEnabled) { // FIXME: UnitGoesUnderFog and UnitGoesOutOfFog change unit refs // for human players. We can't switch back to a human player or // we'll be using the wrong ref counts. #if 0 ThisPlayer->AiEnabled = false; ThisPlayer->Type = PlayerPerson; SetMessage("AI is off, Normal Player"); #else SetMessage("Cannot disable 'ai me' cheat"); #endif } else { ThisPlayer->AiEnabled = true; ThisPlayer->Type = PlayerComputer; if (!ThisPlayer->Ai) { AiInit(*ThisPlayer); } SetMessage("I'm the BORG, resistance is futile!"); } return 1; } #endif int base = lua_gettop(Lua); lua_getglobal(Lua, "HandleCheats"); if (!lua_isfunction(Lua, -1)) { DebugPrint("No HandleCheats function in lua.\n"); return 0; } lua_pushstring(Lua, input.c_str()); LuaCall(1, 0, false); if (lua_gettop(Lua) - base == 1) { ret = LuaToBoolean(Lua, -1); lua_pop(Lua, 1); } else { DebugPrint("HandleCheats must return a boolean"); ret = 0; } return ret; }
/* virtual */ void CContentTypeFormattedText2::Parse(lua_State *l) { Assert(lua_istable(l, -1)); for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) { const char *key = LuaToString(l, -2); if (!strcmp(key, "Format")) { this->Format = LuaToString(l, -1); } else if (!strcmp(key, "Font")) { this->Font = CFont::Get(LuaToString(l, -1)); } else if (!strcmp(key, "Variable")) { const char *const name = LuaToString(l, -1); this->Index1 = UnitTypeVar.VariableNameLookup[name]; this->Index2 = this->Index1; if (this->Index1 == -1) { LuaError(l, "unknown variable '%s'" _C_ name); } } else if (!strcmp(key, "Component")) { this->Component1 = Str2EnumVariable(l, LuaToString(l, -1)); this->Component2 = Str2EnumVariable(l, LuaToString(l, -1)); } else if (!strcmp(key, "Variable1")) { const char *const name = LuaToString(l, -1); this->Index1 = UnitTypeVar.VariableNameLookup[name]; if (this->Index1 == -1) { LuaError(l, "unknown variable '%s'" _C_ name); } } else if (!strcmp(key, "Component1")) { this->Component1 = Str2EnumVariable(l, LuaToString(l, -1)); } else if (!strcmp(key, "Variable2")) { const char *const name = LuaToString(l, -1); this->Index2 = UnitTypeVar.VariableNameLookup[name]; if (this->Index2 == -1) { LuaError(l, "unknown variable '%s'" _C_ LuaToString(l, -1)); } } else if (!strcmp(key, "Component2")) { this->Component2 = Str2EnumVariable(l, LuaToString(l, -1)); } else if (!strcmp(key, "Centered")) { this->Centered = LuaToBoolean(l, -1); } else { LuaError(l, "'%s' invalid for method 'FormattedText2' in DefinePanelContents" _C_ key); } } }
/* virtual */ void Spell_AreaAdjustVital::Parse(lua_State *l, int startIndex, int endIndex) { for (int j = startIndex; j < endIndex; ++j) { const char *value = LuaToString(l, -1, j + 1); ++j; if (!strcmp(value, "hit-points")) { this->HP = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "mana-points")) { this->Mana = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "shield-points")) { this->Shield = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "range")) { this->Range = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "use-mana")) { this->UseMana = LuaToBoolean(l, -1, j + 1); } else { LuaError(l, "Unsupported area-adjust-vitals tag: %s" _C_ value); } } }
/** ** Reveal the complete map. ** ** @param l Lua state. */ static int CclRevealMap(lua_State *l) { //Wyrmgus start // LuaCheckArgs(l, 0); //Wyrmgus end if (CclInConfigFile || !Map.Fields) { FlagRevealMap = 1; } else { //Wyrmgus start // Map.Reveal(); bool only_person_players = false; const int nargs = lua_gettop(l); if (nargs == 1) { only_person_players = LuaToBoolean(l, 1); } Map.Reveal(only_person_players); //Wyrmgus end } return 0; }
/* virtual */ void Spell_Demolish::Parse(lua_State *l, int startIndex, int endIndex) { for (int j = startIndex; j < endIndex; ++j) { const char *value = LuaToString(l, -1, j + 1); ++j; if (!strcmp(value, "range")) { this->Range = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "damage")) { this->Damage = LuaToNumber(l, -1, j + 1); //Wyrmgus start } else if (!strcmp(value, "basic-damage")) { this->BasicDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "piercing-damage")) { this->PiercingDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "fire-damage")) { this->FireDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "cold-damage")) { this->ColdDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "arcane-damage")) { this->ArcaneDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "lightning-damage")) { this->LightningDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "air-damage")) { this->AirDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "earth-damage")) { this->EarthDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "water-damage")) { this->WaterDamage = LuaToNumber(l, -1, j + 1); } else if (!strcmp(value, "hack-damage")) { this->HackDamage = LuaToBoolean(l, -1, j + 1); } else if (!strcmp(value, "pierce-damage")) { this->PierceDamage = LuaToBoolean(l, -1, j + 1); } else if (!strcmp(value, "blunt-damage")) { this->BluntDamage = LuaToBoolean(l, -1, j + 1); } else if (!strcmp(value, "damage-self")) { this->DamageSelf = LuaToBoolean(l, -1, j + 1); } else if (!strcmp(value, "damage-friendly")) { this->DamageFriendly = LuaToBoolean(l, -1, j + 1); } else if (!strcmp(value, "damage-terrain")) { this->DamageTerrain = LuaToBoolean(l, -1, j + 1); //Wyrmgus end } else { LuaError(l, "Unsupported demolish tag: %s" _C_ value); } } }
/* virtual */ void CContentTypeCompleteBar::Parse(lua_State *l) { for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) { const char *key = LuaToString(l, -2); if (!strcmp(key, "Variable")) { const char *const name = LuaToString(l, -1); this->varIndex = UnitTypeVar.VariableNameLookup[name]; if (this->varIndex == -1) { LuaError(l, "unknown variable '%s'" _C_ name); } } else if (!strcmp(key, "Height")) { this->height = LuaToNumber(l, -1); } else if (!strcmp(key, "Width")) { this->width = LuaToNumber(l, -1); } else if (!strcmp(key, "Border")) { this->hasBorder = LuaToBoolean(l, -1); } else if (!strcmp(key, "Color")) { const char *const colorName = LuaToString(l, -1); this->colorIndex = GetColorIndexByName(colorName); if (colorIndex == -1) { LuaError(l, "incorrect color: '%s' " _C_ colorName); } } else { LuaError(l, "'%s' invalid for method 'CompleteBar' in DefinePanelContents" _C_ key); } } // Default value and checking errors. if (this->height <= 0) { this->height = 5; // Default value. } if (this->width <= 0) { this->width = 50; // Default value. } if (this->varIndex == -1) { LuaError(l, "variable undefined for CompleteBar"); } }
/** ** Call the lua function HandleCommandKey */ bool HandleCommandKey(int key) { int base = lua_gettop(Lua); lua_getglobal(Lua, "HandleCommandKey"); if (!lua_isfunction(Lua, -1)) { DebugPrint("No HandleCommandKey function in lua.\n"); return false; } lua_pushstring(Lua, SdlKey2Str(key)); lua_pushboolean(Lua, (KeyModifiers & ModifierControl)); lua_pushboolean(Lua, (KeyModifiers & ModifierAlt)); lua_pushboolean(Lua, (KeyModifiers & ModifierShift)); LuaCall(4, 0); if (lua_gettop(Lua) - base == 1) { bool ret = LuaToBoolean(Lua, base + 1); lua_pop(Lua, 1); return ret; } else { LuaError(Lua, "HandleCommandKey must return a boolean"); return false; } }
/** ** Define a world map tile. ** ** @param l Lua state. */ static int CclDefineWorldMapTile(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::pair<int,int> tile_position; CclGetPos(l, &tile_position.first, &tile_position.second, 1); WorldMapTile *tile = new WorldMapTile; tile->Position.x = tile_position.first; tile->Position.y = tile_position.second; // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "World")) { CWorld *world = CWorld::GetWorld(LuaToString(l, -1)); if (world != nullptr) { tile->World = world; } else { LuaError(l, "World doesn't exist."); } } else if (!strcmp(value, "Terrain")) { int terrain = GetWorldMapTerrainTypeId(LuaToString(l, -1)); if (terrain != -1) { tile->Terrain = terrain; } else { LuaError(l, "Terrain doesn't exist."); } } else if (!strcmp(value, "Resource")) { int resource = GetResourceIdByName(LuaToString(l, -1)); if (resource != -1) { tile->Resource = resource; } else { LuaError(l, "Resource doesn't exist."); } } else if (!strcmp(value, "Capital")) { tile->Capital = LuaToBoolean(l, -1); } else if (!strcmp(value, "CulturalTerrainNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int terrain = GetWorldMapTerrainTypeId(LuaToString(l, -1, j + 1)); if (terrain == -1) { LuaError(l, "Terrain doesn't exist."); } ++j; std::string name_type = "terrain-" + NameToIdent(WorldMapTerrainTypes[terrain]->Name); CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); tile->CulturalTerrainNames[std::pair<int,int>(terrain, civilization->ID)].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "FactionCulturalTerrainNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int terrain = GetWorldMapTerrainTypeId(LuaToString(l, -1, j + 1)); if (terrain == -1) { LuaError(l, "Terrain doesn't exist."); } ++j; std::string name_type = "terrain-" + NameToIdent(WorldMapTerrainTypes[terrain]->Name); ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); tile->FactionCulturalTerrainNames[std::pair<int,CFaction *>(terrain, PlayerRaces.Factions[faction])].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "CulturalResourceNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int resource = GetResourceIdByName(LuaToString(l, -1, j + 1)); if (resource == -1) { LuaError(l, "Resource doesn't exist."); } ++j; std::string name_type = "resource-tile-" + DefaultResourceNames[resource]; CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); tile->CulturalResourceNames[std::pair<int,int>(resource, civilization->ID)].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "FactionCulturalResourceNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int resource = GetResourceIdByName(LuaToString(l, -1, j + 1)); if (resource == -1) { LuaError(l, "Resource doesn't exist."); } ++j; std::string name_type = "resource-tile-" + DefaultResourceNames[resource]; ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); tile->FactionCulturalResourceNames[std::pair<int,CFaction *>(resource, PlayerRaces.Factions[faction])].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "CulturalSettlementNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); tile->CulturalSettlementNames[civilization->ID].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "FactionCulturalSettlementNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); tile->FactionCulturalSettlementNames[PlayerRaces.Factions[faction]].push_back(TransliterateText(cultural_name)); } } else if (!strcmp(value, "Claims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } tile->FactionClaims.push_back(PlayerRaces.Factions[faction]); } } else if (!strcmp(value, "HistoricalOwners")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string owner_faction_name = LuaToString(l, -1, j + 1); if (!owner_faction_name.empty()) { int owner_faction = PlayerRaces.GetFactionIndexByName(owner_faction_name); if (owner_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ owner_faction_name.c_str()); } tile->HistoricalOwners[year] = PlayerRaces.Factions[owner_faction]; } else { tile->HistoricalOwners[year] = nullptr; } } } else if (!strcmp(value, "HistoricalClaims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string claimant_faction_name = LuaToString(l, -1, j + 1); int claimant_faction = PlayerRaces.GetFactionIndexByName(claimant_faction_name); if (claimant_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ claimant_faction_name.c_str()); } tile->HistoricalClaims[year] = PlayerRaces.Factions[claimant_faction]; } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } if (tile->World == nullptr) { LuaError(l, "Tile (%d, %d) is not assigned to any world." _C_ tile->Position.x _C_ tile->Position.y); } return 0; }
/** ** Set God mode. ** ** @param l Lua state. */ static int CclSetGodMode(lua_State *l) { LuaCheckArgs(l, 1); GodMode = LuaToBoolean(l, 1); return 0; }
/** ** Define a text. ** ** @param l Lua state. */ static int CclDefineText(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::string text_name = LuaToString(l, 1); CText *text = GetText(text_name); if (!text) { text = new CText; Texts.push_back(text); text->Name = text_name; } // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Author")) { text->Author = LuaToString(l, -1); } else if (!strcmp(value, "Translator")) { text->Translator = LuaToString(l, -1); } else if (!strcmp(value, "Publisher")) { text->Publisher = LuaToString(l, -1); } else if (!strcmp(value, "CopyrightNotice")) { text->CopyrightNotice = LuaToString(l, -1); } else if (!strcmp(value, "Notes")) { text->Notes = LuaToString(l, -1); } else if (!strcmp(value, "Year")) { text->Year = LuaToNumber(l, -1); } else if (!strcmp(value, "InitialPage")) { text->InitialPage = LuaToNumber(l, -1); } else if (!strcmp(value, "Chapters")) { const int args = lua_rawlen(l, -1); for (int j = 0; j < args; ++j) { lua_rawgeti(l, -1, j + 1); CChapter *chapter = new CChapter; text->Chapters.push_back(chapter); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table for variations)"); } const int subargs = lua_rawlen(l, -1); for (int k = 0; k < subargs; ++k) { value = LuaToString(l, -1, k + 1); ++k; lua_rawgeti(l, -1, k + 1); if (!strcmp(value, "name")) { chapter->Name = LuaToString(l, -1); } else if (!strcmp(value, "introduction")) { chapter->Introduction = LuaToBoolean(l, -1); } else if (!strcmp(value, "text")) { const int subsubargs = lua_rawlen(l, -1); for (int n = 0; n < subsubargs; ++n) { chapter->Pages.push_back(LuaToString(l, -1, n + 1)); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } lua_pop(l, 1); } lua_pop(l, 1); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Set debugging flag of AI script ** ** @param l Lua state ** ** @return Number of return values */ static int CclAiDebug(lua_State *l) { LuaCheckArgs(l, 1); AiPlayer->ScriptDebug = LuaToBoolean(l, 1); return 0; }
/** ** Define an AI player. ** ** @param l Lua state. */ static int CclDefineAiPlayer(lua_State *l) { const unsigned int playerIdx = LuaToNumber(l, 0 + 1); Assert(playerIdx <= PlayerMax); DebugPrint("%p %d\n" _C_(void *)Players[playerIdx].Ai _C_ Players[playerIdx].AiEnabled); // FIXME: lose this: // Assert(!Players[playerIdx].Ai && Players[playerIdx].AiEnabled); PlayerAi *ai = Players[playerIdx].Ai = new PlayerAi; ai->Player = &Players[playerIdx]; // Parse the list: (still everything could be changed!) const int args = lua_gettop(l); for (int j = 1; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; if (!strcmp(value, "ai-type")) { const char *aiName = LuaToString(l, j + 1); CAiType *ait = GetAiTypesByName(aiName); if (ait == NULL) { lua_pushfstring(l, "ai-type not found: %s", aiName); } ai->AiType = ait; ai->Script = ait->Script; } else if (!strcmp(value, "script")) { ai->Script = LuaToString(l, j + 1); } else if (!strcmp(value, "script-debug")) { ai->ScriptDebug = LuaToBoolean(l, j + 1); } else if (!strcmp(value, "sleep-cycles")) { ai->SleepCycles = LuaToNumber(l, j + 1); } else if (!strcmp(value, "force")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); lua_rawgeti(l, j + 1, 0 + 1); const int cclforceIdx = LuaToNumber(l, -1); UNUSED(cclforceIdx); const int forceIdx = ai->Force.FindFreeForce(AiForceRoleDefault); lua_pop(l, 1); for (int k = 1; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *value = LuaToString(l, -1); lua_pop(l, 1); ++k; if (!strcmp(value, "complete")) { ai->Force[forceIdx].Completed = true; --k; } else if (!strcmp(value, "recruit")) { ai->Force[forceIdx].Completed = false; --k; } else if (!strcmp(value, "attack")) { ai->Force[forceIdx].Attacking = true; --k; } else if (!strcmp(value, "defend")) { ai->Force[forceIdx].Defending = true; --k; } else if (!strcmp(value, "role")) { lua_rawgeti(l, j + 1, k + 1); value = LuaToString(l, -1); lua_pop(l, 1); if (!strcmp(value, "attack")) { ai->Force[forceIdx].Role = AiForceRoleAttack; } else if (!strcmp(value, "defend")) { ai->Force[forceIdx].Role = AiForceRoleDefend; } else { LuaError(l, "Unsupported force tag: %s" _C_ value); } } else if (!strcmp(value, "types")) { lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); for (int subk = 0; subk < subsubargs; ++subk) { lua_rawgeti(l, -1, subk + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); ++subk; lua_rawgeti(l, -1, subk + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); AiUnitType queue; queue.Want = num; queue.Type = UnitTypeByIdent(ident); ai->Force[forceIdx].UnitTypes.push_back(queue); } lua_pop(l, 1); } else if (!strcmp(value, "units")) { lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); for (int subk = 0; subk < subsubargs; ++subk) { lua_rawgeti(l, -1, subk + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); ++subk; #if 0 lua_rawgeti(l, -1, subk + 1); const char *ident = LuaToString(l, -1); UNUSED(ident); lua_pop(l, 1); #endif ai->Force[forceIdx].Units.Insert(&UnitManager.GetSlotUnit(num)); } lua_pop(l, 1); } else if (!strcmp(value, "state")) { lua_rawgeti(l, j + 1, k + 1); ai->Force[forceIdx].State = AiForceAttackingState(LuaToNumber(l, -1)); lua_pop(l, 1); } else if (!strcmp(value, "goalx")) { lua_rawgeti(l, j + 1, k + 1); ai->Force[forceIdx].GoalPos.x = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "goaly")) { lua_rawgeti(l, j + 1, k + 1); ai->Force[forceIdx].GoalPos.y = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(value, "must-transport")) { // Keep for backward compatibility } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } } else if (!strcmp(value, "reserve")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Reserve[resId] = num; } } else if (!strcmp(value, "used")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Used[resId] = num; } } else if (!strcmp(value, "needed")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Needed[resId] = num; } } else if (!strcmp(value, "collect")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int num = LuaToNumber(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->Collect[resId] = num; } } else if (!strcmp(value, "need-mask")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *type = LuaToString(l, -1); lua_pop(l, 1); const int resId = GetResourceIdByName(l, type); ai->NeededMask |= (1 << resId); } } else if (!strcmp(value, "need-supply")) { ai->NeedSupply = true; --j; } else if (!strcmp(value, "exploration")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { Vec2i pos; lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 3) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, -1, 1); pos.x = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, -1, 2); pos.y = LuaToNumber(l, -1); lua_pop(l, 1); lua_rawgeti(l, -1, 3); const int mask = LuaToNumber(l, -1); lua_pop(l, 1); lua_pop(l, 1); AiExplorationRequest queue(pos, mask); ai->FirstExplorationRequest.push_back(queue); } } else if (!strcmp(value, "last-exploration-cycle")) { ai->LastExplorationGameCycle = LuaToNumber(l, j + 1); } else if (!strcmp(value, "last-can-not-move-cycle")) { ai->LastCanNotMoveGameCycle = LuaToNumber(l, j + 1); } else if (!strcmp(value, "unit-type")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); int i = 0; if (subargs) { ai->UnitTypeRequests.resize(subargs / 2); } for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); ++k; lua_rawgeti(l, j + 1, k + 1); const int count = LuaToNumber(l, -1); lua_pop(l, 1); ai->UnitTypeRequests[i].Type = UnitTypeByIdent(ident); ai->UnitTypeRequests[i].Count = count; ++i; } } else if (!strcmp(value, "upgrade")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); ai->UpgradeToRequests.push_back(UnitTypeByIdent(ident)); } } else if (!strcmp(value, "research")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, j + 1, k + 1); const char *ident = LuaToString(l, -1); lua_pop(l, 1); ai->ResearchRequests.push_back(CUpgrade::Get(ident)); } } else if (!strcmp(value, "building")) { CclParseBuildQueue(l, ai, j + 1); } else if (!strcmp(value, "repair-building")) { ai->LastRepairBuilding = LuaToNumber(l, j + 1); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; }
/** ** Enable display of terrain in minimap. ** ** @param l Lua state. */ static int CclSetMinimapTerrain(lua_State *l) { LuaCheckArgs(l, 1); UI.Minimap.WithTerrain = LuaToBoolean(l, 1); return 0; }
/** ** Define a province. ** ** @param l Lua state. */ static int CclDefineProvince(lua_State *l) { LuaCheckArgs(l, 2); if (!lua_istable(l, 2)) { LuaError(l, "incorrect argument (expected table)"); } std::string province_name = LuaToString(l, 1); CProvince *province = GetProvince(province_name); if (!province) { province = new CProvince; province->Name = province_name; province->ID = Provinces.size(); Provinces.push_back(province); } std::string name_type = "province"; // Parse the list: for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "World")) { CWorld *world = CWorld::GetWorld(LuaToString(l, -1)); if (world != nullptr) { province->World = world; world->Provinces.push_back(province); } else { LuaError(l, "World doesn't exist."); } } else if (!strcmp(value, "Water")) { province->Water = LuaToBoolean(l, -1); } else if (!strcmp(value, "Coastal")) { province->Coastal = LuaToBoolean(l, -1); } else if (!strcmp(value, "CulturalNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1)); ++j; if (!civilization) { continue; } std::string cultural_name = LuaToString(l, -1, j + 1); province->CulturalNames[civilization->ID] = TransliterateText(cultural_name); } } else if (!strcmp(value, "FactionCulturalNames")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } ++j; std::string cultural_name = LuaToString(l, -1, j + 1); province->FactionCulturalNames[PlayerRaces.Factions[faction]] = TransliterateText(cultural_name); } } else if (!strcmp(value, "Claims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument (expected table)"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { ++j; int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1)); if (faction == -1) { LuaError(l, "Faction doesn't exist."); } province->FactionClaims.push_back(PlayerRaces.Factions[faction]); } } else if (!strcmp(value, "Regions")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { CRegion *region = GetRegion(LuaToString(l, -1, j + 1)); if (region == nullptr) { LuaError(l, "Region doesn't exist."); } province->Regions.push_back(region); region->Provinces.push_back(province); } } else if (!strcmp(value, "HistoricalOwners")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string owner_faction_name = LuaToString(l, -1, j + 1); if (!owner_faction_name.empty()) { int owner_faction = PlayerRaces.GetFactionIndexByName(owner_faction_name); if (owner_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ owner_faction_name.c_str()); } province->HistoricalOwners[year] = PlayerRaces.Factions[owner_faction]; } else { province->HistoricalOwners[year] = nullptr; } } } else if (!strcmp(value, "HistoricalClaims")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; ++j; std::string claimant_faction_name = LuaToString(l, -1, j + 1); int claimant_faction = PlayerRaces.GetFactionIndexByName(claimant_faction_name); if (claimant_faction == -1) { LuaError(l, "Faction \"%s\" doesn't exist." _C_ claimant_faction_name.c_str()); } province->HistoricalClaims[year] = PlayerRaces.Factions[claimant_faction]; } } else if (!strcmp(value, "HistoricalCultures")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; std::string historical_civilization_name = LuaToString(l, -1, j + 1); if (!historical_civilization_name.empty()) { CCivilization *historical_civilization = CCivilization::GetCivilization(historical_civilization_name); if (historical_civilization) { province->HistoricalCultures[year] = historical_civilization->ID; } } } } else if (!strcmp(value, "HistoricalPopulation")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; int historical_population = LuaToNumber(l, -1, j + 1); province->HistoricalPopulation[year] = historical_population; } } else if (!strcmp(value, "HistoricalSettlementBuildings")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; std::string building_type_ident = LuaToString(l, -1, j + 1); int building_type = UnitTypeIdByIdent(building_type_ident); if (building_type == -1) { LuaError(l, "Unit type \"%s\" doesn't exist." _C_ building_type_ident.c_str()); } ++j; province->HistoricalSettlementBuildings[building_type][year] = LuaToBoolean(l, -1, j + 1); } } else if (!strcmp(value, "HistoricalModifiers")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, -1); for (int j = 0; j < subargs; ++j) { int year = LuaToNumber(l, -1, j + 1); ++j; std::string upgrade_ident = LuaToString(l, -1, j + 1); CUpgrade *modifier = CUpgrade::Get(upgrade_ident); if (modifier == nullptr) { LuaError(l, "Upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str()); } ++j; province->HistoricalModifiers[modifier][year] = LuaToBoolean(l, -1, j + 1); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } if (province->World == nullptr) { LuaError(l, "Province \"%s\" is not assigned to any world." _C_ province->Name.c_str()); } return 0; }
/** ** Define a button. ** ** @param l Lua state. */ static int CclDefineButton(lua_State *l) { LuaCheckArgs(l, 1); if (!lua_istable(l, 1)) { LuaError(l, "incorrect argument"); } ButtonAction ba; // // Parse the arguments // lua_pushnil(l); while (lua_next(l, 1)) { const char *value = LuaToString(l, -2); if (!strcmp(value, "Pos")) { ba.Pos = LuaToNumber(l, -1); } else if (!strcmp(value, "Level")) { ba.Level = LuaToNumber(l, -1); } else if (!strcmp(value, "AlwaysShow")) { ba.AlwaysShow = LuaToBoolean(l, -1); } else if (!strcmp(value, "Icon")) { ba.Icon.Name = LuaToString(l, -1); } else if (!strcmp(value, "Action")) { value = LuaToString(l, -1); if (!strcmp(value, "move")) { ba.Action = ButtonMove; } else if (!strcmp(value, "stop")) { ba.Action = ButtonStop; } else if (!strcmp(value, "attack")) { ba.Action = ButtonAttack; } else if (!strcmp(value, "repair")) { ba.Action = ButtonRepair; } else if (!strcmp(value, "harvest")) { ba.Action = ButtonHarvest; } else if (!strcmp(value, "button")) { ba.Action = ButtonButton; } else if (!strcmp(value, "build")) { ba.Action = ButtonBuild; } else if (!strcmp(value, "train-unit")) { ba.Action = ButtonTrain; } else if (!strcmp(value, "patrol")) { ba.Action = ButtonPatrol; } else if (!strcmp(value, "stand-ground")) { ba.Action = ButtonStandGround; } else if (!strcmp(value, "attack-ground")) { ba.Action = ButtonAttackGround; } else if (!strcmp(value, "return-goods")) { ba.Action = ButtonReturn; } else if (!strcmp(value, "cast-spell")) { ba.Action = ButtonSpellCast; } else if (!strcmp(value, "research")) { ba.Action = ButtonResearch; } else if (!strcmp(value, "upgrade-to")) { ba.Action = ButtonUpgradeTo; } else if (!strcmp(value, "unload")) { ba.Action = ButtonUnload; } else if (!strcmp(value, "cancel")) { ba.Action = ButtonCancel; } else if (!strcmp(value, "cancel-upgrade")) { ba.Action = ButtonCancelUpgrade; } else if (!strcmp(value, "cancel-train-unit")) { ba.Action = ButtonCancelTrain; } else if (!strcmp(value, "cancel-build")) { ba.Action = ButtonCancelBuild; } else { LuaError(l, "Unsupported button action: %s" _C_ value); } } else if (!strcmp(value, "Value")) { if (!lua_isnumber(l, -1) && !lua_isstring(l, -1)) { LuaError(l, "incorrect argument"); } char buf[64]; const char *s2; if (lua_isnumber(l, -1)) { snprintf(buf, sizeof(buf), "%ld", (long int)lua_tonumber(l, -1)); s2 = buf; } else { s2 = lua_tostring(l, -1); } ba.ValueStr = s2; } else if (!strcmp(value, "Allowed")) { value = LuaToString(l, -1); if (!strcmp(value, "check-true")) { ba.Allowed = ButtonCheckTrue; } else if (!strcmp(value, "check-false")) { ba.Allowed = ButtonCheckFalse; } else if (!strcmp(value, "check-upgrade")) { ba.Allowed = ButtonCheckUpgrade; } else if (!strcmp(value, "check-unit-variable")) { ba.Allowed = ButtonCheckUnitVariable; } else if (!strcmp(value, "check-units-or")) { ba.Allowed = ButtonCheckUnitsOr; } else if (!strcmp(value, "check-units-and")) { ba.Allowed = ButtonCheckUnitsAnd; } else if (!strcmp(value, "check-units-not")) { ba.Allowed = ButtonCheckUnitsNot; } else if (!strcmp(value, "check-network")) { ba.Allowed = ButtonCheckNetwork; } else if (!strcmp(value, "check-no-network")) { ba.Allowed = ButtonCheckNoNetwork; } else if (!strcmp(value, "check-no-work")) { ba.Allowed = ButtonCheckNoWork; } else if (!strcmp(value, "check-no-research")) { ba.Allowed = ButtonCheckNoResearch; } else if (!strcmp(value, "check-attack")) { ba.Allowed = ButtonCheckAttack; } else if (!strcmp(value, "check-upgrade-to")) { ba.Allowed = ButtonCheckUpgradeTo; } else if (!strcmp(value, "check-research")) { ba.Allowed = ButtonCheckResearch; } else if (!strcmp(value, "check-single-research")) { ba.Allowed = ButtonCheckSingleResearch; } else { LuaError(l, "Unsupported action: %s" _C_ value); } } else if (!strcmp(value, "AllowArg")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } std::string allowstr; const unsigned int subargs = lua_rawlen(l, -1); for (unsigned int k = 0; k < subargs; ++k) { const char *s2 = LuaToString(l, -1, k + 1); allowstr += s2; if (k != subargs - 1) { allowstr += ","; } } ba.AllowStr = allowstr; } else if (!strcmp(value, "Key")) { ba.Key = *LuaToString(l, -1); } else if (!strcmp(value, "Hint")) { ba.Hint = LuaToString(l, -1); } else if (!strcmp(value, "Description")) { ba.Description = LuaToString(l, -1); } else if (!strcmp(value, "CommentSound")) { ba.CommentSound.Name = LuaToString(l, -1); } else if (!strcmp(value, "ButtonCursor")) { ba.ButtonCursor = LuaToString(l, -1); } else if (!strcmp(value, "Popup")) { ba.Popup = LuaToString(l, -1); } else if (!strcmp(value, "ForUnit")) { if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } // FIXME: ba.UnitMask shouldn't be a string std::string umask = ","; const unsigned subargs = lua_rawlen(l, -1); for (unsigned int k = 0; k < subargs; ++k) { const char *s2 = LuaToString(l, -1, k + 1); umask += s2; umask += ","; } ba.UnitMask = umask; if (!strncmp(ba.UnitMask.c_str(), ",*,", 3)) { ba.UnitMask = "*"; } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } lua_pop(l, 1); } AddButton(ba.Pos, ba.Level, ba.Icon.Name, ba.Action, ba.ValueStr, ba.Allowed, ba.AllowStr, ba.Key, ba.Hint, ba.Description, ba.CommentSound.Name, ba.ButtonCursor, ba.UnitMask, ba.Popup, ba.AlwaysShow); return 0; }
/** ** Enable/disable the fancy buildings. ** ** @param l Lua state. */ static int CclSetFancyBuildings(lua_State *l) { LuaCheckArgs(l, 1); FancyBuildings = LuaToBoolean(l, 1); return 0; }