int AddButton( int pos, int level, const char* IconIdent, enum _button_cmd_ action, const char* value, const void* func, const void* allow, int key, const char* hint, const char* umask ) { char buf[2048]; ButtonAction* ba = (ButtonAction*)malloc(sizeof(ButtonAction)); DebugCheck(!ba); //FIXME: perhaps should return error? ba->Pos = pos; ba->Level = level; ba->Icon.Name = (char*)IconIdent; ba->Icon.Icon = IconByIdent( IconIdent ); ba->Action = action; if( value ) { ba->ValueStr = strdup( value ); switch( action ) { case B_Magic: ba->Value = UpgradeIdByIdent( value ); break; case B_Train: ba->Value = UnitTypeIdByIdent( value ); break; case B_Research: ba->Value = UpgradeIdByIdent( value ); break; case B_UpgradeTo: ba->Value = UnitTypeIdByIdent( value ); break; case B_Build: ba->Value = UnitTypeIdByIdent( value ); break; default: ba->Value = atoi( value ); break; } } else { ba->ValueStr = NULL; ba->Value = 0; } ba->Allowed = func; if( allow ) { ba->AllowStr=strdup(allow); } else { ba->AllowStr=NULL; } ba->Key = key; ba->Hint = strdup( hint ); //FIXME: here should be added costs to the hint //FIXME: johns: show should be nice done? if ( umask[0] == '*' ) strcpy( buf, umask ); else sprintf( buf, ",%s,", umask ); ba->UMask = strdup( buf ); UnitButtonTable[UnitButtonCount++] = ba; DebugCheck( ba->Icon.Icon==-1 ); // just checks, that's why at the end return 1; };
/** ** Define which units are allowed and how much. */ static int CclDefineUnitAllow(lua_State *l) { const char *ident; int i; int args; int j; int id; args = lua_gettop(l); j = 0; ident = LuaToString(l, j + 1); ++j; if (strncmp(ident, "unit-", 5)) { DebugPrint(" wrong ident %s\n" _C_ ident); return 0; } id = UnitTypeIdByIdent(ident); i = 0; for (; j < args && i < PlayerMax; ++j) { AllowUnitId(&Players[i], id, LuaToNumber(l, j + 1)); ++i; } return 0; }
/** ** Define which units/upgrades are allowed. */ static int CclDefineAllow(lua_State *l) { const char *ident; const char *ids; int i; int n; int args; int j; int id; args = lua_gettop(l); for (j = 0; j < args; ++j) { ident = LuaToString(l, j + 1); ++j; ids = LuaToString(l, j + 1); n = strlen(ids); if (n > PlayerMax) { fprintf(stderr, "%s: Allow string too long %d\n", ident, n); n = PlayerMax; } if (!strncmp(ident, "unit-", 5)) { id = UnitTypeIdByIdent(ident); for (i = 0; i < n; ++i) { if (ids[i] == 'A') { AllowUnitId(&Players[i], id, UnitMax); } else if (ids[i] == 'F') { AllowUnitId(&Players[i], id, 0); } } } else if (!strncmp(ident, "upgrade-", 8)) { id = UpgradeIdByIdent(ident); for (i = 0; i < n; ++i) { AllowUpgradeId(&Players[i], id, ids[i]); } } else { DebugPrint(" wrong ident %s\n" _C_ ident); } } return 0; }
/** ** @brief Process data provided by a configuration file ** ** @param config_data The configuration data */ void CUpgradeModifier::ProcessConfigData(const CConfigData *config_data) { for (size_t i = 0; i < config_data->Properties.size(); ++i) { std::string key = config_data->Properties[i].first; std::string value = config_data->Properties[i].second; if (key == "apply_to") { value = FindAndReplaceString(value, "_", "-"); const int unit_type_id = UnitTypeIdByIdent(value.c_str()); if (unit_type_id != -1) { this->ApplyTo[unit_type_id] = 'X'; } else { fprintf(stderr, "Invalid unit type: \"%s\".\n", value.c_str()); } } else if (key == "remove_upgrade") { value = FindAndReplaceString(value, "_", "-"); CUpgrade *removed_upgrade = CUpgrade::Get(value); if (removed_upgrade) { this->RemoveUpgrades.push_back(removed_upgrade); } else { fprintf(stderr, "Invalid upgrade: \"%s\".\n", value.c_str()); } } else { key = SnakeCaseToPascalCase(key); int index = UnitTypeVar.VariableNameLookup[key.c_str()]; // variable index if (index != -1) { // valid index if (IsStringNumber(value)) { this->Modifier.Variables[index].Enable = 1; this->Modifier.Variables[index].Value = std::stoi(value); this->Modifier.Variables[index].Max = std::stoi(value); } else { // error fprintf(stderr, "Invalid value (\"%s\") for variable \"%s\" when defining modifier for upgrade \"%s\".\n", value.c_str(), key.c_str(), AllUpgrades[this->UpgradeId]->Ident.c_str()); } } else { fprintf(stderr, "Invalid upgrade modifier property: \"%s\".\n", key.c_str()); } } } }
/** ** 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; }
/** ** FIXME: docu */ int AddButton(int pos, int level, const std::string &icon_ident, ButtonCmd action, const std::string &value, void* actionCb, const ButtonCheckFunc func, const std::string &allow, const int key, const std::string &hint, const std::string &descr, const std::string &sound, const std::string &cursor, const std::string &umask, const std::string &popup, bool alwaysShow) { char buf[2048]; ButtonAction *ba = new ButtonAction; Assert(ba); ba->Pos = pos; ba->Level = level; ba->AlwaysShow = alwaysShow; ba->Icon.Name = icon_ident; ba->Payload = actionCb; // FIXME: check if already initited //ba->Icon.Load(); ba->Action = action; if (!value.empty()) { ba->ValueStr = value; switch (action) { case ButtonSpellCast: ba->Value = SpellTypeByIdent(value)->Slot; #ifdef DEBUG if (ba->Value < 0) { DebugPrint("Spell %s does not exist?\n" _C_ value.c_str()); Assert(ba->Value >= 0); } #endif break; case ButtonTrain: ba->Value = UnitTypeIdByIdent(value); break; case ButtonResearch: ba->Value = UpgradeIdByIdent(value); break; case ButtonUpgradeTo: ba->Value = UnitTypeIdByIdent(value); break; case ButtonBuild: ba->Value = UnitTypeIdByIdent(value); break; default: ba->Value = atoi(value.c_str()); break; } } else { ba->ValueStr.clear(); ba->Value = 0; } ba->Allowed = func; ba->AllowStr = allow; ba->Key = key; ba->Hint = hint; ba->Description = descr; ba->CommentSound.Name = sound; if (!ba->CommentSound.Name.empty()) { ba->CommentSound.MapSound(); } if (!ba->Popup.empty()) { CPopup *popup = PopupByIdent(ba->Popup); if (!popup) { fprintf(stderr, "Popup \"%s\" hasn't defined.\n ", ba->Popup.c_str()); Exit(1); } } ba->ButtonCursor = cursor; ba->Popup = popup; // FIXME: here should be added costs to the hint // FIXME: johns: show should be nice done? if (umask[0] == '*') { strcpy_s(buf, sizeof(buf), umask.c_str()); } else { sprintf(buf, ",%s,", umask.c_str()); } ba->UnitMask = buf; UnitButtonTable.push_back(ba); // FIXME: check if already initited //Assert(ba->Icon.Icon != NULL);// just checks, that's why at the end return 1; }
/** ** Define a new upgrade modifier. ** ** @param l List of modifiers. */ static int CclDefineModifier(lua_State *l) { const char *key; const char *value; CUpgradeModifier *um; int args; int j; args = lua_gettop(l); um = new CUpgradeModifier; memset(um->ChangeUpgrades, '?', sizeof(um->ChangeUpgrades)); memset(um->ApplyTo, '?', sizeof(um->ApplyTo)); um->Modifier.Variables = new CVariable[UnitTypeVar.NumberVariable]; um->UpgradeId = UpgradeIdByIdent(LuaToString(l, 1)); for (j = 1; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, j + 1, 1); key = LuaToString(l, -1); lua_pop(l, 1); #if 1 // To be removed. must modify lua file. if (!strcmp(key, "attack-range")) { key = "AttackRange"; } else if (!strcmp(key, "sight-range")) { key = "SightRange"; } else if (!strcmp(key, "basic-damage")) { key = "BasicDamage"; } else if (!strcmp(key, "piercing-damage")) { key = "PiercingDamage"; } else if (!strcmp(key, "armor")) { key = "Armor"; } else if (!strcmp(key, "hit-points")) { key = "HitPoints"; } #endif if (!strcmp(key, "regeneration-rate")) { lua_rawgeti(l, j + 1, 2); um->Modifier.Variables[HP_INDEX].Increase = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(key, "cost")) { int i; if (!lua_istable(l, j + 1) || luaL_getn(l, j + 1) != 2) { LuaError(l, "incorrect argument"); } lua_rawgeti(l, j + 1, 1); value = LuaToString(l, -1); lua_pop(l, 1); for (i = 0; i < MaxCosts; ++i) { if (!strcmp(value, DefaultResourceNames[i])) { break; } } if (i == MaxCosts) { LuaError(l, "Resource not found: %s" _C_ value); } lua_rawgeti(l, j + 1, 2); um->Modifier.Costs[i] = LuaToNumber(l, -1); lua_pop(l, 1); } else if (!strcmp(key, "allow-unit")) { lua_rawgeti(l, j + 1, 2); value = LuaToString(l, -1); lua_pop(l, 1); if (!strncmp(value, "unit-", 5)) { lua_rawgeti(l, j + 1, 3); um->ChangeUnits[UnitTypeIdByIdent(value)] = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "unit expected"); } } else if (!strcmp(key, "allow")) { lua_rawgeti(l, j + 1, 2); value = LuaToString(l, -1); lua_pop(l, 1); if (!strncmp(value, "upgrade-", 8)) { lua_rawgeti(l, j + 1, 3); um->ChangeUpgrades[UpgradeIdByIdent(value)] = LuaToNumber(l, -1); lua_pop(l, 1); } else { LuaError(l, "upgrade expected"); } } else if (!strcmp(key, "apply-to")) { lua_rawgeti(l, j + 1, 2); value = LuaToString(l, -1); lua_pop(l, 1); um->ApplyTo[UnitTypeIdByIdent(value)] = 'X'; } else if (!strcmp(key, "convert-to")) { lua_rawgeti(l, j + 1, 2); value = LuaToString(l, -1); lua_pop(l, 1); um->ConvertTo = UnitTypeByIdent(value); } else { int index; // variable index; index = GetVariableIndex(key); if (index != -1) { lua_rawgeti(l, j + 1, 2); if (lua_istable(l, -1)) { DefineVariableField(l, um->Modifier.Variables + index, -1); } else if (lua_isnumber(l, -1)) { um->Modifier.Variables[index].Enable = 1; um->Modifier.Variables[index].Value = LuaToNumber(l, -1); um->Modifier.Variables[index].Max = LuaToNumber(l, -1); } else { LuaError(l, "bad argument type for '%s'\n" _C_ key); } lua_pop(l, 1); } else { LuaError(l, "wrong tag: %s" _C_ key); } } } UpgradeModifiers[NumUpgradeModifiers++] = um; return 0; }
/** ** Define a new upgrade modifier. ** ** @param l List of modifiers. */ static int CclDefineModifier(lua_State *l) { const int args = lua_gettop(l); CUpgradeModifier *um = new CUpgradeModifier; memset(um->ChangeUpgrades, '?', sizeof(um->ChangeUpgrades)); memset(um->ApplyTo, '?', sizeof(um->ApplyTo)); um->Modifier.Variables = new CVariable[UnitTypeVar.GetNumberVariable()]; um->ModifyPercent = new int[UnitTypeVar.GetNumberVariable()]; memset(um->ModifyPercent, 0, UnitTypeVar.GetNumberVariable() * sizeof(int)); std::string upgrade_ident = LuaToString(l, 1); um->UpgradeId = UpgradeIdByIdent(upgrade_ident); if (um->UpgradeId == -1) { LuaError(l, "Error when defining upgrade modifier: upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str()); } for (int j = 1; j < args; ++j) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } const char *key = LuaToString(l, j + 1, 1); #if 0 // To be removed. must modify lua file. if (!strcmp(key, "attack-range")) { key = "AttackRange"; } else if (!strcmp(key, "sight-range")) { key = "SightRange"; } else if (!strcmp(key, "basic-damage")) { key = "BasicDamage"; } else if (!strcmp(key, "piercing-damage")) { key = "PiercingDamage"; } else if (!strcmp(key, "armor")) { key = "Armor"; } else if (!strcmp(key, "hit-points")) { key = "HitPoints"; } #endif if (!strcmp(key, "regeneration-rate")) { um->Modifier.Variables[HP_INDEX].Increase = LuaToNumber(l, j + 1, 2); } else if (!strcmp(key, "cost")) { if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 2) { LuaError(l, "incorrect argument"); } const char *value = LuaToString(l, j + 1, 1); const int resId = GetResourceIdByName(l, value); um->Modifier.Costs[resId] = LuaToNumber(l, j + 1, 2); } else if (!strcmp(key, "storing")) { if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 2) { LuaError(l, "incorrect argument"); } const char *value = LuaToString(l, j + 1, 1); const int resId = GetResourceIdByName(l, value); um->Modifier.Storing[resId] = LuaToNumber(l, j + 1, 2); } else if (!strcmp(key, "allow-unit")) { const char *value = LuaToString(l, j + 1, 2); if (!strncmp(value, "unit-", 5)) { um->ChangeUnits[UnitTypeIdByIdent(value)] = LuaToNumber(l, j + 1, 3); } else { LuaError(l, "unit expected"); } } else if (!strcmp(key, "allow")) { const char *value = LuaToString(l, j + 1, 2); if (!strncmp(value, "upgrade-", 8)) { um->ChangeUpgrades[UpgradeIdByIdent(value)] = LuaToNumber(l, j + 1, 3); } else { LuaError(l, "upgrade expected"); } } else if (!strcmp(key, "apply-to")) { const char *value = LuaToString(l, j + 1, 2); um->ApplyTo[UnitTypeIdByIdent(value)] = 'X'; } else if (!strcmp(key, "convert-to")) { const char *value = LuaToString(l, j + 1, 2); um->ConvertTo = UnitTypeByIdent(value); } else if (!strcmp(key, "research-speed")) { um->SpeedResearch = LuaToNumber(l, j + 1, 2); } else { int index = UnitTypeVar.VariableNameLookup[key]; // variable index; if (index != -1) { if (lua_rawlen(l, j + 1) == 3) { const char *value = LuaToString(l, j + 1, 3); if (!strcmp(value, "Percent")) { um->ModifyPercent[index] = LuaToNumber(l, j + 1, 2); } } else { lua_rawgeti(l, j + 1, 2); if (lua_istable(l, -1)) { DefineVariableField(l, um->Modifier.Variables + index, -1); } else if (lua_isnumber(l, -1)) { um->Modifier.Variables[index].Enable = 1; um->Modifier.Variables[index].Value = LuaToNumber(l, -1); um->Modifier.Variables[index].Max = LuaToNumber(l, -1); } else { LuaError(l, "bad argument type for '%s'\n" _C_ key); } lua_pop(l, 1); } } else { LuaError(l, "wrong tag: %s" _C_ key); } } } UpgradeModifiers[NumUpgradeModifiers++] = um; return 0; }