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; };
/** ** Check if all requirements for upgrade research are met only one ** running research allowed. ** ** @param unit Pointer to unit for button. ** @param button Pointer to button to check/enable. ** ** @return True if enabled. */ bool ButtonCheckSingleResearch(const CUnit &unit, const ButtonAction &button) { if (ButtonCheckResearch(unit, button) && !unit.Player->UpgradeTimers.Upgrades[UpgradeIdByIdent(button.ValueStr)]) { return true; } return false; }
/** ** Return the allow state of an upgrade. ** ** @param player Check state for this player. ** @param ident Upgrade identifier. ** ** @note This function shouldn't be used during runtime, it is only for setup. */ char UpgradeIdentAllowed(const CPlayer *player, const std::string &ident) { int id; if ((id = UpgradeIdByIdent(ident)) != -1) { return UpgradeIdAllowed(player, id); } DebugPrint("Fix your code, wrong idenifier `%s'\n" _C_ ident.c_str()); return '-'; }
/** ** 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; }
/** ** Init AiHelper. ** ** @param aiHelper variable to initialise. ** ** @todo missing Equiv initialisation. */ static void InitAiHelper(AiHelper &aiHelper) { extern std::vector<ButtonAction *> UnitButtonTable; std::vector<CUnitType *> reparableUnits = getReparableUnits(); std::vector<CUnitType *> supplyUnits = getSupplyUnits(); std::vector<CUnitType *> mineUnits = getRefineryUnits(); for (std::vector<CUnitType *>::const_iterator i = supplyUnits.begin(); i != supplyUnits.end(); ++i) { AiHelperInsert(aiHelper.UnitLimit, 0, **i); } for (int i = 1; i < MaxCosts; ++i) { for (std::vector<CUnitType *>::const_iterator j = mineUnits.begin(); j != mineUnits.end(); ++j) { if ((*j)->GivesResource == i) { /* HACK : we can't mine TIME then use 0 as 1 */ AiHelperInsert(aiHelper.Refinery, i - 1, **j); } } for (std::vector<CUnitType *>::const_iterator d = UnitTypes.begin(); d != UnitTypes.end(); ++d) { CUnitType *type = *d; if (type->CanStore[i] > 0) { /* HACK : we can't store TIME then use 0 as 1 */ AiHelperInsert(aiHelper.Depots, i - 1, **d); } } } for (size_t i = 0; i != UnitButtonTable.size(); ++i) { const ButtonAction &button = *UnitButtonTable[i]; const std::vector<CUnitType *> &unitmask = getUnitTypeFromString(button.UnitMask); switch (button.Action) { case ButtonRepair : for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { for (std::vector<CUnitType *>::const_iterator k = reparableUnits.begin(); k != reparableUnits.end(); ++k) { AiHelperInsert(aiHelper.Repair, (*k)->Slot, **j); } } break; case ButtonBuild: { CUnitType *buildingType = UnitTypeByIdent(button.ValueStr); for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { AiHelperInsert(aiHelper.Build, buildingType->Slot, (**j)); } break; } case ButtonTrain : { CUnitType *trainingType = UnitTypeByIdent(button.ValueStr); for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { AiHelperInsert(aiHelper.Train, trainingType->Slot, (**j)); } break; } case ButtonUpgradeTo : { CUnitType *upgradeToType = UnitTypeByIdent(button.ValueStr); for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { AiHelperInsert(aiHelper.Upgrade, upgradeToType->Slot, **j); } break; } case ButtonResearch : { int researchId = UpgradeIdByIdent(button.ValueStr); for (std::vector<CUnitType *>::const_iterator j = unitmask.begin(); j != unitmask.end(); ++j) { AiHelperInsert(aiHelper.Research, researchId, **j); } break; } default: break; } } }
/** ** Parse Spell. ** ** @param l Lua state. */ static int CclDefineSpell(lua_State *l) { const int args = lua_gettop(l); const std::string identname = LuaToString(l, 1); SpellType *spell = SpellTypeByIdent(identname); if (spell != NULL) { DebugPrint("Redefining spell-type `%s'\n" _C_ identname.c_str()); } else { spell = new SpellType(SpellTypeTable.size(), identname); for (std::vector<CUnitType *>::size_type i = 0; i < UnitTypes.size(); ++i) { // adjust array for caster already defined if (UnitTypes[i]->CanCastSpell) { char *newc = new char[(SpellTypeTable.size() + 1) * sizeof(char)]; memcpy(newc, UnitTypes[i]->CanCastSpell, SpellTypeTable.size() * sizeof(char)); delete[] UnitTypes[i]->CanCastSpell; UnitTypes[i]->CanCastSpell = newc; UnitTypes[i]->CanCastSpell[SpellTypeTable.size()] = 0; } if (UnitTypes[i]->AutoCastActive) { char *newc = new char[(SpellTypeTable.size() + 1) * sizeof(char)]; memcpy(newc, UnitTypes[i]->AutoCastActive, SpellTypeTable.size() * sizeof(char)); delete[] UnitTypes[i]->AutoCastActive; UnitTypes[i]->AutoCastActive = newc; UnitTypes[i]->AutoCastActive[SpellTypeTable.size()] = 0; } } SpellTypeTable.push_back(spell); } for (int i = 1; i < args; ++i) { const char *value = LuaToString(l, i + 1); ++i; if (!strcmp(value, "showname")) { spell->Name = LuaToString(l, i + 1); } else if (!strcmp(value, "manacost")) { spell->ManaCost = LuaToNumber(l, i + 1); } else if (!strcmp(value, "range")) { if (!lua_isstring(l, i + 1) && !lua_isnumber(l, i + 1)) { LuaError(l, "incorrect argument"); } if (lua_isstring(l, i + 1) && !strcmp(lua_tostring(l, i + 1), "infinite")) { spell->Range = INFINITE_RANGE; } else if (lua_isnumber(l, i + 1)) { spell->Range = static_cast<int>(lua_tonumber(l, i + 1)); } else { LuaError(l, "Invalid range"); } } else if (!strcmp(value, "repeat-cast")) { spell->RepeatCast = 1; --i; } else if (!strcmp(value, "target")) { value = LuaToString(l, i + 1); if (!strcmp(value, "self")) { spell->Target = TargetSelf; } else if (!strcmp(value, "unit")) { spell->Target = TargetUnit; } else if (!strcmp(value, "position")) { spell->Target = TargetPosition; } else { LuaError(l, "Unsupported spell target type tag: %s" _C_ value); } } else if (!strcmp(value, "action")) { if (!lua_istable(l, i + 1)) { LuaError(l, "incorrect argument"); } const int subargs = lua_rawlen(l, i + 1); for (int k = 0; k < subargs; ++k) { lua_rawgeti(l, i + 1, k + 1); spell->Action.push_back(CclSpellAction(l)); lua_pop(l, 1); } } else if (!strcmp(value, "condition")) { if (!spell->Condition) { spell->Condition = new ConditionInfo; } lua_pushvalue(l, i + 1); CclSpellCondition(l, spell->Condition); lua_pop(l, 1); } else if (!strcmp(value, "autocast")) { if (!spell->AutoCast) { spell->AutoCast = new AutoCastInfo(); } lua_pushvalue(l, i + 1); CclSpellAutocast(l, spell->AutoCast); lua_pop(l, 1); } else if (!strcmp(value, "ai-cast")) { if (!spell->AICast) { spell->AICast = new AutoCastInfo(); } lua_pushvalue(l, i + 1); CclSpellAutocast(l, spell->AICast); lua_pop(l, 1); } else if (!strcmp(value, "sound-when-cast")) { // Free the old name, get the new one spell->SoundWhenCast.Name = LuaToString(l, i + 1); spell->SoundWhenCast.MapSound(); // Check for sound. if (!spell->SoundWhenCast.Sound) { spell->SoundWhenCast.Name.clear(); } } else if (!strcmp(value, "depend-upgrade")) { value = LuaToString(l, i + 1); spell->DependencyId = UpgradeIdByIdent(value); if (spell->DependencyId == -1) { lua_pushfstring(l, "Bad upgrade name: %s", value); } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } 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; }
/** ** Check for button enabled, if upgrade is ready. ** ** @param unit Pointer to unit for button. ** @param button Pointer to button to check/enable. ** ** @return True if enabled. */ bool ButtonCheckAbility(const CUnit &unit, const ButtonAction &button) { return unit.LearnedAbilities[UpgradeIdByIdent(button.AllowStr)]; }
/** ** 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; }
/** ** Game main loop. ** ** Unit actions. ** Missile actions. ** Players (AI). ** Cyclic events (color cycle,...) ** Display update. ** Input/Network/Sound. */ void GameMainLoop() { const EventCallback *old_callbacks; InitGameCallbacks(); old_callbacks = GetCallbacks(); SetCallbacks(&GameCallbacks); SetVideoSync(); GameCursor = UI.Point.Cursor; //Wyrmgus start GameEstablishing = false; //Wyrmgus end GameRunning = true; CParticleManager::init(); #ifdef REALVIDEO RealVideoSyncSpeed = VideoSyncSpeed; #endif CclCommand("if (GameStarting ~= nil) then GameStarting() end"); MultiPlayerReplayEachCycle(); //Wyrmgus start if (GameCycle == 0) { // so that these don't trigger when loading a saved game if (CurrentCampaign != NULL) { for (int i = 0; i < NumPlayers; ++i) { if (Players[i].Type != PlayerNobody && Players[i].Race != 0 && Players[i].Faction != -1) { if (CurrentCampaign->StartDate.year) { CCivilization *civilization = PlayerRaces.Civilizations[Players[i].Race]; CFaction *faction = PlayerRaces.Factions[Players[i].Race][Players[i].Faction]; for (std::map<std::string, std::map<CDate, bool>>::iterator iterator = civilization->HistoricalUpgrades.begin(); iterator != civilization->HistoricalUpgrades.end(); ++iterator) { int upgrade_id = UpgradeIdByIdent(iterator->first); if (upgrade_id == -1) { fprintf(stderr, "Upgrade \"%s\" doesn't exist.\n", iterator->first.c_str()); continue; } for (std::map<CDate, bool>::reverse_iterator second_iterator = iterator->second.rbegin(); second_iterator != iterator->second.rend(); ++second_iterator) { if (second_iterator->first.year == 0 || CurrentCampaign->StartDate >= second_iterator->first) { if (second_iterator->second && UpgradeIdentAllowed(Players[i], iterator->first.c_str()) != 'R') { UpgradeAcquire(Players[i], AllUpgrades[upgrade_id]); } else if (!second_iterator->second) { break; } } } } for (std::map<std::string, std::map<CDate, bool>>::iterator iterator = faction->HistoricalUpgrades.begin(); iterator != faction->HistoricalUpgrades.end(); ++iterator) { int upgrade_id = UpgradeIdByIdent(iterator->first); if (upgrade_id == -1) { fprintf(stderr, "Upgrade \"%s\" doesn't exist.\n", iterator->first.c_str()); continue; } for (std::map<CDate, bool>::reverse_iterator second_iterator = iterator->second.rbegin(); second_iterator != iterator->second.rend(); ++second_iterator) { if (second_iterator->first.year == 0 || CurrentCampaign->StartDate >= second_iterator->first) { if (second_iterator->second && UpgradeIdentAllowed(Players[i], iterator->first.c_str()) != 'R') { UpgradeAcquire(Players[i], AllUpgrades[upgrade_id]); } else if (!second_iterator->second) { break; } } } } for (std::map<std::pair<int, CFaction *>, int>::iterator iterator = faction->HistoricalDiplomacyStates.begin(); iterator != faction->HistoricalDiplomacyStates.end(); ++iterator) { //set the appropriate historical diplomacy states to other factions if (iterator->second == 0 || CurrentCampaign->StartDate.year >= iterator->first.first) { CPlayer *diplomacy_state_player = GetFactionPlayer(iterator->first.second); if (diplomacy_state_player) { CommandDiplomacy(i, iterator->second, diplomacy_state_player->Index); CommandDiplomacy(diplomacy_state_player->Index, iterator->second, i); if (iterator->second == DiplomacyAllied) { CommandSharedVision(i, true, diplomacy_state_player->Index); CommandSharedVision(diplomacy_state_player->Index, true, i); } } } } for (std::map<std::pair<CDate, int>, int>::iterator iterator = faction->HistoricalResources.begin(); iterator != faction->HistoricalResources.end(); ++iterator) { //set the appropriate historical resource quantities if (iterator->second == 0 || CurrentCampaign->StartDate >= iterator->first.first) { Players[i].SetResource(iterator->first.second, iterator->second); } } } } } if (CurrentCampaign->StartEffects) { CurrentCampaign->StartEffects->pushPreamble(); CurrentCampaign->StartEffects->run(); } } //if the person player has no faction, bring up the faction choice interface if (!GrandStrategy && ThisPlayer && ThisPlayer->Faction == -1) { char buf[256]; snprintf(buf, sizeof(buf), "if (ChooseFaction ~= nil) then ChooseFaction(\"%s\", \"%s\") end", ThisPlayer->Race != -1 ? PlayerRaces.Name[ThisPlayer->Race].c_str() : "", ""); CclCommand(buf); } if (!IsNetworkGame() && ThisPlayer && CurrentCustomHero != NULL) { Vec2i resPos; FindNearestDrop(*CurrentCustomHero->Type, ThisPlayer->StartPos, resPos, LookingW, ThisPlayer->StartMapLayer); CUnit *custom_hero = MakeUnitAndPlace(resPos, *CurrentCustomHero->Type, ThisPlayer, ThisPlayer->StartMapLayer); custom_hero->SetCharacter(CurrentCustomHero->Ident, true); } if (CurrentQuest != NULL && CurrentQuest->IntroductionDialogue != NULL) { CurrentQuest->IntroductionDialogue->Call(ThisPlayer->Index); } } //Wyrmgus end SingleGameLoop(); // // Game over // if (GameResult == GameExit) { Exit(0); return; } #ifdef REALVIDEO if (FastForwardCycle > GameCycle) { VideoSyncSpeed = RealVideoSyncSpeed; } #endif NetworkQuitGame(); EndReplayLog(); GameCycle = 0;//???? CParticleManager::exit(); FlagRevealMap = 0; ReplayRevealMap = 0; GamePaused = false; GodMode = false; SetCallbacks(old_callbacks); }
/** ** 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; }