/** ** Show Map Location ** ** @param l Lua state. */ static int CclShowMapLocation(lua_State *l) { // Put a unit on map, use its properties, except for // what is listed below LuaCheckArgs(l, 4); const char *unitname = LuaToString(l, 5); CUnitType *unitType = UnitTypeByIdent(unitname); if (!unitType) { DebugPrint("Unable to find UnitType '%s'" _C_ unitname); return 0; } CUnit *target = MakeUnit(*unitType, ThisPlayer); if (target != NULL) { target->Variable[HP_INDEX].Value = 0; target->tilePos.x = LuaToNumber(l, 1); target->tilePos.y = LuaToNumber(l, 2); target->TTL = GameCycle + LuaToNumber(l, 4); target->CurrentSightRange = LuaToNumber(l, 3); //Wyrmgus start UpdateUnitSightRange(*target); //Wyrmgus end MapMarkUnitSight(*target); } else { DebugPrint("Unable to allocate Unit"); } return 0; }
static void RemoveIndividualUpgradeModifier(CUnit &unit, const CUpgradeModifier *um) { Assert(um); if (um->Modifier.Variables[SIGHTRANGE_INDEX].Value) { if (!unit.Removed) { MapUnmarkUnitSight(unit); unit.CurrentSightRange = unit.Variable[SIGHTRANGE_INDEX].Value - um->Modifier.Variables[SIGHTRANGE_INDEX].Value; UpdateUnitSightRange(unit); MapMarkUnitSight(unit); } } for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) { unit.Variable[j].Enable |= um->Modifier.Variables[j].Enable; if (um->ModifyPercent[j]) { unit.Variable[j].Value = unit.Variable[j].Value * 100 / (100 + um->ModifyPercent[j]); unit.Variable[j].Max = unit.Variable[j].Max * 100 / (100 + um->ModifyPercent[j]); } else { unit.Variable[j].Value -= um->Modifier.Variables[j].Value; unit.Variable[j].Increase -= um->Modifier.Variables[j].Increase; } unit.Variable[j].Max -= um->Modifier.Variables[j].Max; unit.Variable[j].Max = std::max(unit.Variable[j].Max, 0); if (unit.Variable[j].Max > 0) { clamp(&unit.Variable[j].Value, 0, unit.Variable[j].Max); } } }
/** ** Apply the modifiers of an individual upgrade. ** ** @param unit Unit that will get the modifier applied ** @param um Upgrade modifier that does the effects */ void ApplyIndividualUpgradeModifier(CUnit &unit, const CUpgradeModifier *um) { Assert(um); if (um->Modifier.Variables[SIGHTRANGE_INDEX].Value) { if (!unit.Removed) { MapUnmarkUnitSight(unit); unit.CurrentSightRange = unit.Variable[SIGHTRANGE_INDEX].Value + um->Modifier.Variables[SIGHTRANGE_INDEX].Value; UpdateUnitSightRange(unit); MapMarkUnitSight(unit); } } for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) { unit.Variable[j].Enable |= um->Modifier.Variables[j].Enable; if (um->ModifyPercent[j]) { unit.Variable[j].Value += unit.Variable[j].Value * um->ModifyPercent[j] / 100; unit.Variable[j].Max += unit.Variable[j].Max * um->ModifyPercent[j] / 100; } else { unit.Variable[j].Value += um->Modifier.Variables[j].Value; unit.Variable[j].Increase += um->Modifier.Variables[j].Increase; } unit.Variable[j].Max += um->Modifier.Variables[j].Max; unit.Variable[j].Max = std::max(unit.Variable[j].Max, 0); if (unit.Variable[j].Max > 0) { clamp(&unit.Variable[j].Value, 0, unit.Variable[j].Max); } } if (um->ConvertTo) { CommandTransformIntoType(unit, *um->ConvertTo); } }
/* virtual */ void COrder_Die::Execute(CUnit &unit) { // Show death animation if (AnimateActionDie(unit) == false) { // some units has no death animation unit.Anim.Unbreakable = 0; } if (unit.Anim.Unbreakable) { return ; } const CUnitType &type = *unit.Type; // Die sequence terminated, generate corpse. if (type.CorpseType == NULL) { unit.Remove(NULL); //Wyrmgus start UnitClearOrders(unit); //Wyrmgus end unit.Release(); return ; } const CUnitType &corpseType = *type.CorpseType; Assert(type.TileWidth >= corpseType.TileWidth && type.TileHeight >= corpseType.TileHeight); // Update sight for new corpse // We have to unmark BEFORE changing the type. // Always do that, since types can have different vision properties. //Wyrmgus start // unit.Remove(NULL); MapUnmarkUnitSight(unit); //Wyrmgus end unit.Type = &corpseType; unit.Stats = &corpseType.Stats[unit.Player->Index]; //Wyrmgus start const unsigned int var_size = UnitTypeVar.GetNumberVariable(); std::copy(corpseType.Stats[unit.Player->Index].Variables, corpseType.Stats[unit.Player->Index].Variables + var_size, unit.Variable); //Wyrmgus end UpdateUnitSightRange(unit); //Wyrmgus start // unit.Place(unit.tilePos); MapMarkUnitSight(unit); //Wyrmgus end unit.Frame = 0; UnitUpdateHeading(unit); AnimateActionDie(unit); // with new corpse. }
bool COrder_Build::StartBuilding(CUnit &unit, CUnit &ontop) { const CUnitType &type = this->GetUnitType(); unit.Player->SubUnitType(type); CUnit *build = MakeUnit(const_cast<CUnitType &>(type), unit.Player); // If unable to make unit, stop, and report message if (build == NULL) { // FIXME: Should we retry this? unit.Player->Notify(NotifyYellow, unit.tilePos, _("Unable to create building %s"), type.Name.c_str()); if (unit.Player->AiEnabled) { AiCanNotBuild(unit, type); } return false; } build->Constructed = 1; build->CurrentSightRange = 0; // Building on top of something, may remove what is beneath it if (&ontop != &unit) { CBuildRestrictionOnTop *b; b = static_cast<CBuildRestrictionOnTop *>(OnTopDetails(*build, ontop.Type)); Assert(b); if (b->ReplaceOnBuild) { build->ResourcesHeld = ontop.ResourcesHeld; // We capture the value of what is beneath. build->Variable[GIVERESOURCE_INDEX].Value = ontop.Variable[GIVERESOURCE_INDEX].Value; build->Variable[GIVERESOURCE_INDEX].Max = ontop.Variable[GIVERESOURCE_INDEX].Max; build->Variable[GIVERESOURCE_INDEX].Enable = ontop.Variable[GIVERESOURCE_INDEX].Enable; ontop.Remove(NULL); // Destroy building beneath UnitLost(ontop); UnitClearOrders(ontop); ontop.Release(); } } // Must set action before placing, otherwise it will incorrectly mark radar delete build->CurrentOrder(); build->Orders[0] = COrder::NewActionBuilt(unit, *build); UpdateUnitSightRange(*build); // Must place after previous for map flags build->Place(this->goalPos); // HACK: the building is not ready yet build->Player->UnitTypesCount[type.Slot]--; if (build->Active) { build->Player->UnitTypesAiActiveCount[type.Slot]--; } // We need somebody to work on it. if (!type.BoolFlag[BUILDEROUTSIDE_INDEX].value) { UnitShowAnimation(unit, unit.Type->Animations->Still); unit.Remove(build); this->State = State_BuildFromInside; if (unit.Selected) { SelectedUnitChanged(); } } else { this->State = State_BuildFromOutside; this->BuildingUnit = build; unit.Direction = DirectionToHeading(build->tilePos - unit.tilePos); UnitUpdateHeading(unit); } return true; }
//Wyrmgus start //static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype) int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype) //Wyrmgus end { const CUnitType &oldtype = *unit.Type; if (&oldtype == &newtype) { // nothing to do return 1; } const Vec2i pos = unit.tilePos + oldtype.GetHalfTileSize() - newtype.GetHalfTileSize(); CUnit *container = unit.Container; //Wyrmgus start /* if (container) { MapUnmarkUnitSight(unit); } else { SaveSelection(); unit.Remove(NULL); if (!UnitTypeCanBeAt(newtype, pos)) { unit.Place(unit.tilePos); RestoreSelection(); // FIXME unit is not modified, try later ? return 0; } } */ if (!SaveGameLoading) { if (container) { MapUnmarkUnitSight(unit); } else { SaveSelection(); unit.Remove(NULL); if (!UnitTypeCanBeAt(newtype, pos)) { unit.Place(unit.tilePos); RestoreSelection(); // FIXME unit is not modified, try later ? return 0; } } } //Wyrmgus end CPlayer &player = *unit.Player; player.UnitTypesCount[oldtype.Slot]--; player.UnitTypesCount[newtype.Slot]++; if (unit.Active) { player.UnitTypesAiActiveCount[oldtype.Slot]--; player.UnitTypesAiActiveCount[newtype.Slot]++; } //Wyrmgus start if (unit.Character == NULL) { player.UnitTypesNonHeroCount[oldtype.Slot]--; player.UnitTypesNonHeroCount[newtype.Slot]++; } //Wyrmgus end player.Demand += newtype.Stats[player.Index].Variables[DEMAND_INDEX].Value - oldtype.Stats[player.Index].Variables[DEMAND_INDEX].Value; player.Supply += newtype.Stats[player.Index].Variables[SUPPLY_INDEX].Value - oldtype.Stats[player.Index].Variables[SUPPLY_INDEX].Value; // Change resource limit for (int i = 0; i < MaxCosts; ++i) { if (player.MaxResources[i] != -1) { player.MaxResources[i] += newtype.Stats[player.Index].Storing[i] - oldtype.Stats[player.Index].Storing[i]; player.SetResource(i, player.StoredResources[i], STORE_BUILDING); } } // adjust Variables with percent. const CUnitStats &newstats = newtype.Stats[player.Index]; //Wyrmgus start const CUnitStats &oldstats = oldtype.Stats[player.Index]; //Wyrmgus end for (unsigned int i = 0; i < UnitTypeVar.GetNumberVariable(); ++i) { //Wyrmgus start /* if (unit.Variable[i].Max && unit.Variable[i].Value) { unit.Variable[i].Value = newstats.Variables[i].Max * unit.Variable[i].Value / unit.Variable[i].Max; } else { unit.Variable[i].Value = newstats.Variables[i].Value; } if (i == KILL_INDEX || i == XP_INDEX) { unit.Variable[i].Value = unit.Variable[i].Max; } else { unit.Variable[i].Max = newstats.Variables[i].Max; unit.Variable[i].Increase = newstats.Variables[i].Increase; unit.Variable[i].Enable = newstats.Variables[i].Enable; } */ if (i == LEVEL_INDEX) { //if the unit's level changed in accordance to the difference between the levels of the two unit types, then its level change would be duplicated when leveling up, so let's skip the level variable here continue; } if (unit.Variable[i].Max && unit.Variable[i].Value) { unit.Variable[i].Value += newstats.Variables[i].Max - oldstats.Variables[i].Max; } else { unit.Variable[i].Value += newstats.Variables[i].Value - oldstats.Variables[i].Value; } if (i == KILL_INDEX || i == XP_INDEX) { unit.Variable[i].Value = unit.Variable[i].Max; } else { unit.Variable[i].Max += newstats.Variables[i].Max - oldstats.Variables[i].Max; unit.Variable[i].Increase += newstats.Variables[i].Increase - oldstats.Variables[i].Increase; unit.Variable[i].Enable = newstats.Variables[i].Enable; } //Wyrmgus end } //Wyrmgus start for (size_t i = 0; i < UnitTypes.size(); ++i) { if (newstats.UnitStock[i] != oldstats.UnitStock[i]) { unit.UnitStock[i] += newstats.UnitStock[i] - oldstats.UnitStock[i]; unit.UnitStock[i] = std::max(unit.UnitStock[i], 0); } } //Wyrmgus end //Wyrmgus start //change variation if upgrading (new unit type may have different variations) unit.ChooseVariation(&newtype); for (int i = 0; i < MaxImageLayers; ++i) { unit.ChooseVariation(&newtype, false, i); } //Wyrmgus end unit.Type = const_cast<CUnitType *>(&newtype); unit.Stats = &unit.Type->Stats[player.Index]; //Wyrmgus start //deequip the current equipment if they are incompatible with the new unit type for (int i = 0; i < MaxItemSlots; ++i) { for (size_t j = 0; j < unit.EquippedItems[i].size(); ++j) { if (!unit.CanEquipItemClass(unit.EquippedItems[i][j]->Type->ItemClass)) { unit.DeequipItem(*unit.EquippedItems[i][j]); } } } //Wyrmgus end //Wyrmgus start //change personal name if new unit type's civilization is different from old unit type's civilization if (unit.Character == NULL && !oldtype.Civilization.empty() && !newtype.Civilization.empty() && oldtype.Civilization != newtype.Civilization) { unit.UpdatePersonalName(); } //Wyrmgus end if (newtype.CanCastSpell && !unit.AutoCastSpell) { unit.AutoCastSpell = new char[SpellTypeTable.size()]; unit.SpellCoolDownTimers = new int[SpellTypeTable.size()]; memset(unit.AutoCastSpell, 0, SpellTypeTable.size() * sizeof(char)); memset(unit.SpellCoolDownTimers, 0, SpellTypeTable.size() * sizeof(int)); } UpdateForNewUnit(unit, 1); //Wyrmgus start /* // Update Possible sight range change UpdateUnitSightRange(unit); if (!container) { unit.Place(pos); RestoreSelection(); } else { MapMarkUnitSight(unit); } */ if (!SaveGameLoading) { // Update Possible sight range change UpdateUnitSightRange(unit); if (!container) { unit.Place(pos); RestoreSelection(); } else { MapMarkUnitSight(unit); //Wyrmgus start //if unit has a container, update the container's attack range, as the unit's range may have been changed with the upgrade container->UpdateContainerAttackRange(); //Wyrmgus end } } //Wyrmgus end //Wyrmgus start //update the unit's XP required, as its level or points may have changed unit.UpdateXPRequired(); //Wyrmgus end //Wyrmgus start /* // // Update possible changed buttons. // if (IsOnlySelected(unit) || &player == ThisPlayer) { // could affect the buttons of any selected unit SelectedUnitChanged(); } */ if (!SaveGameLoading) { // // Update possible changed buttons. // if (IsOnlySelected(unit) || &player == ThisPlayer) { // could affect the buttons of any selected unit SelectedUnitChanged(); } } //Wyrmgus end return 1; }
static void GameLogicLoop() { // Can't find a better place. // FIXME: We need find better place! SaveGameLoading = false; // // Game logic part // if (!GamePaused && NetworkInSync && !SkipGameCycle) { SinglePlayerReplayEachCycle(); ++GameCycle; MultiPlayerReplayEachCycle(); NetworkCommands(); // Get network commands TriggersEachCycle();// handle triggers UnitActions(); // handle units MissileActions(); // handle missiles PlayersEachCycle(); // handle players UpdateTimer(); // update game timer // // Work todo each second. // Split into different frames, to reduce cpu time. // Increment mana of magic units. // Update mini-map. // Update map fog of war. // Call AI. // Check game goals. // Check rescue of units. // switch (GameCycle % CYCLES_PER_SECOND) { case 0: // At cycle 0, start all ai players... if (GameCycle == 0) { for (int player = 0; player < NumPlayers; ++player) { PlayersEachSecond(player); } } break; case 1: break; case 2: break; case 3: // minimap update UI.Minimap.UpdateCache = true; break; case 4: break; case 5: // forest grow Map.RegenerateForest(); break; case 6: // overtaking units RescueUnits(); break; default: { // FIXME: assume that NumPlayers < (CYCLES_PER_SECOND - 7) int player = (GameCycle % CYCLES_PER_SECOND) - 7; Assert(player >= 0); if (player < NumPlayers) { PlayersEachSecond(player); } } } //Wyrmgus start if (GameCycle > 0 && GameCycle % (CYCLES_PER_SECOND * 10 * 3) == 0) { // every 10 seconds of gameplay = 1 hour for time of day calculations, change time of day every three hours if (!GameSettings.Inside) { // only change the time of the day if outdoors GameTimeOfDay += 1; if (GameTimeOfDay == MaxTimesOfDay) { GameTimeOfDay = 1; } } else { // indoors it is always dark (maybe would be better to allow a special setting to have bright indoor places? GameTimeOfDay = NoTimeOfDay; // make indoors have no time of day setting until it is possible to make light sources change their surrounding "time of day" } //update the sight of all units for (CUnitManager::Iterator it = UnitManager.begin(); it != UnitManager.end(); ++it) { CUnit &unit = **it; if (!unit.Destroyed) { MapUnmarkUnitSight(unit); UpdateUnitSightRange(unit); MapMarkUnitSight(unit); } } } //Wyrmgus end //Wyrmgus start // if (Preference.AutosaveMinutes != 0 && !IsNetworkGame() && GameCycle > 0 && (GameCycle % (CYCLES_PER_SECOND * 60 * Preference.AutosaveMinutes)) == 0) { // autosave every X minutes, if the option is enabled if (Preference.AutosaveMinutes != 0 && !IsNetworkGame() && !GrandStrategy && GameCycle > 0 && (GameCycle % (CYCLES_PER_SECOND * 60 * Preference.AutosaveMinutes)) == 0) { // autosave every X minutes, if the option is enabled //Wyrmgus end UI.StatusLine.Set(_("Autosave")); //Wyrmgus start // SaveGame("autosave.sav"); CclCommand("if (RunSaveGame ~= nil) then RunSaveGame(\"autosave.sav\") end;"); //Wyrmgus end } } UpdateMessages(); // update messages ParticleManager.update(); // handle particles CheckMusicFinished(); // Check for next song if (FastForwardCycle <= GameCycle || !(GameCycle & 0x3f)) { WaitEventsOneFrame(); } if (!NetworkInSync) { NetworkRecover(); // recover network } }
/** ** Transform a unit in another. ** ** @param unit unit to transform. ** @param newtype new type of the unit. ** ** @return 0 on error, 1 if nothing happens, 2 else. */ static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype) { const CUnitType &oldtype = *unit.Type; if (&oldtype == &newtype) { // nothing to do return 1; } const Vec2i pos = unit.tilePos + oldtype.GetHalfTileSize() - newtype.GetHalfTileSize(); CUnit *container = unit.Container; if (container) { MapUnmarkUnitSight(unit); } else { SaveSelection(); unit.Remove(NULL); if (!UnitTypeCanBeAt(newtype, pos)) { unit.Place(unit.tilePos); RestoreSelection(); // FIXME unit is not modified, try later ? return 0; } } CPlayer &player = *unit.Player; player.UnitTypesCount[oldtype.Slot]--; player.UnitTypesCount[newtype.Slot]++; player.Demand += newtype.Demand - oldtype.Demand; player.Supply += newtype.Supply - oldtype.Supply; // Change resource limit for (int i = 0; i < MaxCosts; ++i) { if (player.MaxResources[i] != -1) { player.MaxResources[i] += newtype.Stats[player.Index].Storing[i] - oldtype.Stats[player.Index].Storing[i]; player.SetResource(i, player.StoredResources[i], STORE_BUILDING); } } // adjust Variables with percent. const CUnitStats &newstats = newtype.Stats[player.Index]; for (unsigned int i = 0; i < UnitTypeVar.GetNumberVariable(); ++i) { if (unit.Variable[i].Max && unit.Variable[i].Value) { unit.Variable[i].Value = newstats.Variables[i].Max * unit.Variable[i].Value / unit.Variable[i].Max; } else { unit.Variable[i].Value = newstats.Variables[i].Value; } unit.Variable[i].Max = newstats.Variables[i].Max; unit.Variable[i].Increase = newstats.Variables[i].Increase; unit.Variable[i].Enable = newstats.Variables[i].Enable; } unit.Type = const_cast<CUnitType *>(&newtype); unit.Stats = &unit.Type->Stats[player.Index]; if (newtype.CanCastSpell && !unit.AutoCastSpell) { unit.AutoCastSpell = new char[SpellTypeTable.size()]; memset(unit.AutoCastSpell, 0, SpellTypeTable.size() * sizeof(char)); } UpdateForNewUnit(unit, 1); // Update Possible sight range change UpdateUnitSightRange(unit); if (!container) { unit.Place(pos); RestoreSelection(); } else { MapMarkUnitSight(unit); } // // Update possible changed buttons. // if (IsOnlySelected(unit) || &player == ThisPlayer) { // could affect the buttons of any selected unit SelectedUnitChanged(); } return 1; }
static void GameLogicLoop() { // Can't find a better place. // FIXME: We need find better place! SaveGameLoading = false; #ifdef USE_OAML if (enableOAML && oaml) { // Time of day can change our main music loop, if the current playing track is set for this SetMusicCondition(OAML_CONDID_MAIN_LOOP, Map.TimeOfDay[CurrentMapLayer]); } #endif // // Game logic part // if (!GamePaused && NetworkInSync && !SkipGameCycle) { SinglePlayerReplayEachCycle(); ++GameCycle; MultiPlayerReplayEachCycle(); NetworkCommands(); // Get network commands TriggersEachCycle();// handle triggers UnitActions(); // handle units MissileActions(); // handle missiles PlayersEachCycle(); // handle players UpdateTimer(); // update game timer // // Work todo each second. // Split into different frames, to reduce cpu time. // Increment mana of magic units. // Update mini-map. // Update map fog of war. // Call AI. // Check game goals. // Check rescue of units. // switch (GameCycle % CYCLES_PER_SECOND) { case 0: // At cycle 0, start all ai players... if (GameCycle == 0) { for (int player = 0; player < NumPlayers; ++player) { PlayersEachSecond(player); } } break; case 1: break; case 2: break; case 3: // minimap update UI.Minimap.UpdateCache = true; break; case 4: break; case 5: // forest grow Map.RegenerateForest(); break; case 6: // overtaking units RescueUnits(); break; //Wyrmgus start /* default: { // FIXME: assume that NumPlayers < (CYCLES_PER_SECOND - 7) int player = (GameCycle % CYCLES_PER_SECOND) - 7; Assert(player >= 0); if (player < NumPlayers) { PlayersEachSecond(player); } } */ //Wyrmgus end } //Wyrmgus start int player = (GameCycle - 1) % CYCLES_PER_SECOND; Assert(player >= 0); if (player < NumPlayers) { PlayersEachSecond(player); if ((player + CYCLES_PER_SECOND) < NumPlayers) { PlayersEachSecond(player + CYCLES_PER_SECOND); } } player = (GameCycle - 1) % CYCLES_PER_MINUTE; Assert(player >= 0); if (player < NumPlayers) { PlayersEachMinute(player); } //Wyrmgus end //Wyrmgus start for (size_t z = 0; z < Map.Fields.size(); ++z) { if (GameSettings.Inside || GameSettings.NoTimeOfDay || !Map.TimeOfDaySeconds[z]) { // indoors it is always dark (maybe would be better to allow a special setting to have bright indoor places? Map.TimeOfDay[z] = NoTimeOfDay; // make indoors have no time of day setting until it is possible to make light sources change their surrounding "time of day" continue; } if (GameCycle > 0 && GameCycle % (CYCLES_PER_SECOND * Map.TimeOfDaySeconds[z]) == 0) { Map.TimeOfDay[z] += 1; if (Map.TimeOfDay[z] == MaxTimesOfDay) { Map.TimeOfDay[z] = 1; } #ifdef USE_OAML if (enableOAML && oaml && z == CurrentMapLayer) { // Time of day can change our main music loop, if the current playing track is set for this SetMusicCondition(OAML_CONDID_MAIN_LOOP, Map.TimeOfDay[z]); } #endif //update the sight of all units for (CUnitManager::Iterator it = UnitManager.begin(); it != UnitManager.end(); ++it) { CUnit *unit = *it; if ( unit && unit->IsAlive() && unit->MapLayer == z && ( ((Map.TimeOfDay[z] == MorningTimeOfDay || Map.TimeOfDay[z] == DuskTimeOfDay) && unit->Variable[DAYSIGHTRANGEBONUS_INDEX].Value != 0) // if has day sight bonus and is entering or exiting day || ((Map.TimeOfDay[z] == FirstWatchTimeOfDay || Map.TimeOfDay[z] == DawnTimeOfDay) && unit->Variable[NIGHTSIGHTRANGEBONUS_INDEX].Value != 0) // if has night sight bonus and is entering or exiting night ) ) { MapUnmarkUnitSight(*unit); UpdateUnitSightRange(*unit); MapMarkUnitSight(*unit); } } } } //Wyrmgus end //Wyrmgus start // if (Preference.AutosaveMinutes != 0 && !IsNetworkGame() && GameCycle > 0 && (GameCycle % (CYCLES_PER_SECOND * 60 * Preference.AutosaveMinutes)) == 0) { // autosave every X minutes, if the option is enabled if (Preference.AutosaveMinutes != 0 && !IsNetworkGame() && !GrandStrategy && GameCycle > 0 && (GameCycle % (CYCLES_PER_MINUTE * Preference.AutosaveMinutes)) == 0) { // autosave every X minutes, if the option is enabled //Wyrmgus end UI.StatusLine.Set(_("Autosave")); //Wyrmgus start // SaveGame("autosave.sav"); CclCommand("if (RunSaveGame ~= nil) then RunSaveGame(\"autosave.sav\") end;"); //Wyrmgus end } } UpdateMessages(); // update messages ParticleManager.update(); // handle particles CheckMusicFinished(); // Check for next song if (FastForwardCycle <= GameCycle || !(GameCycle & 0x3f)) { WaitEventsOneFrame(); } if (!NetworkInSync) { NetworkRecover(); // recover network } }