Inhaltsverzeichnis
Beschreibung
Der Alarm/Überstundentrick bewirkt, daß die Siedler sehr viel länger arbeiten, ohne daß ein Motivationsverlust auftritt. Dies wird erreicht, indem der Alarm oder die Überstunden regelmässig aktiviert, und Sekundenbruchteile später wieder deaktiviert wird. Spieler, die diesen Fehler im Spiel ausnutzen, können so in kürzerer Zeit deutlich mehr Resourcen abbauen als die, die es nicht tun.
Der Fehler ist in allen Version einschliesslich 1.05 vorhanden und ausnutzbar.
Ab Version 1.06 wird dieser Code nichtmehr benötigt! Dort wurde die Nutzung von Alarm und Overtime auf „alle 3 bzw 4 Minuten“ beschränkt.
Einzelspielermodus
Alarmlimit
Die folgende Funktion kann an eine beliebige Stelle ins Mapscript kopiert werden. Sie bewirkt, daß der Alarm mindestens 60 Sekunden aktiviert bleibt. Durch diesen Stillstand der Wirtschaft zieht man keinen Gewinn mehr aus der längeren Arbeitszeit. Somit ist es nurnoch sinnvoll, den Alarm zu seinem ursprünglichen Zweck, der Verteidigung, einzusetzen. Am Ende der FirstMapAction() muss die Funktion einmal aufgerufen werden:
EnableAlarmLimit();
Dies ist die Funktion:
function EnableAlarmLimit() GUIAction_ActivateAlarmOrig = GUIAction_ActivateAlarm; GUIAction_ActivateAlarm = function() alarmWait = Logic.GetCurrentTurn() + 600; GUIAction_ActivateAlarmOrig(); end GUIAction_QuitAlarmOrig = GUIAction_QuitAlarm; GUIAction_QuitAlarm = function() local turns = Logic.GetCurrentTurn(); if turns >= alarmWait then GUIAction_QuitAlarmOrig(); else Sound.PlayFeedbackSound( Sounds.VoicesWorker_WORKER_FunnyNo_rnd_10, 0 ); Message( "Der Alarm kann erst in " .. math.floor( ( alarmWait - turns ) / 10 ) .. " Sekunden wieder aufgehoben werden." ); end end end
Überstundenlimit
Die folgende Funktion kann an eine beliebige Stelle ins Mapscript kopiert werden. Sie bewirkt, daß die Überstunden in einem Gebäude mindestens 60 Sekunden aktiviert bleiben. Hierdurch tritt der reguläre Motivationsverlust bei längerer Arbeitszeit in Kraft. Somit hat man also keinen unfairen Vorteil mehr davon, da man sie nurnoch nutzen kann, wenn man den Motivationsverlust mit einer Kirche oder Zierobjekten kompensieren kann. Am Ende der FirstMapAction() muss die Funktion einmal aufgerufen werden:
EnableOvertimeLimit();
Dies ist die Funktion:
function EnableOvertimeLimit() tOvertimes = {}; GUI.ToggleOvertimeAtBuildingOrig = GUI.ToggleOvertimeAtBuilding; GUI.ToggleOvertimeAtBuilding = function( _id ) LimitOvertime( _id, GUI.ToggleOvertimeAtBuildingOrig ); end GUI.ForceSettlerToWorkOrig = GUI.ForceSettlerToWork; GUI.ForceSettlerToWork = function( _id ) LimitOvertime( _id, GUI.ToggleOvertimeAtBuildingOrig ); end LimitOvertime = function( _id, _func ) local knowntime = tOvertimes[_id]; local turns = Logic.GetCurrentTurn(); if not knowntime or turns > knowntime then _func( _id ); tOvertimes[_id] = turns + 600; else Sound.PlayFeedbackSound( Sounds.VoicesWorker_WORKER_FunnyNo_rnd_10, 0 ); Message( "Die Ueberstunden dauern noch mindestens " .. math.floor( ( knowntime - turns ) / 10 ) .. " Sekunden." ); end end end
Mehrspielermodus
Da die Sperrung der Funktionen für eine Minute die Spieler im Mehrspielermodus zu stark behindern könnte, gibt es hier Alternativfunktionen.
Alarmlimit
Anstatt die Deaktivierung des Alarms erst wieder nach einer Minute zu ermöglichen, kann den anderen Spielern auf einfach angezeigt werden, wer seinen Alarm (de)aktiviert hat. Somit sind andere Spieler in der Lage zu erkennen, wer den Fehler im Spiel ausnutzen will.
Mehrspielerkarten, die diesen Fix benutzen, sollten dies dem Spieler mitteilen. Beispielsweise durch eine Nachricht bei Spielstart.
Natürlich sollte man, wenn man diese Alarmvariante verwendet, nicht noch zusätzlich die Funktion zur Alarmbeschränkung verwenden.
Am Ende von GameCallback_OnGameStart() muss die Funktion einmal aufgerufen werden:
EnableAlarmNotice();
Dies ist die Funktion:
function EnableAlarmNotice() tAlarmCheckHQs = {}; tAlarmCheckHQs.tStatus = {}; tAlarmCheckHQs.tPlayers = {}; tAlarmCheckHQs.tNames = {}; local playerID = GUI.GetPlayerID(); local playerID = 99 assert( playerID ); local tHQTypes = { Logic.GetBuildingTypesInUpgradeCategory( UpgradeCategories.Headquarters ) }; local nHQTypes = table.remove( tHQTypes, 1 ); assert( nHQTypes > 0 ); assert( nHQTypes == table.getn( tHQTypes ) ); for currID = 1, 8 do if currID ~= playerID then for i = 1, nHQTypes do local tTempHQs = { Logic.GetPlayerEntities( currID, tHQTypes[i], 48 ) }; local nTempHQs = table.remove( tTempHQs, 1 ); assert( nTempHQs == table.getn( tTempHQs ) ); for k = 1, nTempHQs do local nHQID = tTempHQs[k]; assert( type( nHQID ) == "number" ); table.insert( tAlarmCheckHQs, nHQID ); tAlarmCheckHQs.tStatus[nHQID] = false; tAlarmCheckHQs.tPlayers[nHQID] = currID; local sHQName = Logic.GetEntityName( nHQID ); if not sHQName or sHQName == "" then sHQName = "DoNotChange" .. nHQID; Logic.SetEntityName( nHQID, sHQName ); end tAlarmCheckHQs.tNames[nHQID] = sHQName; end end end end Trigger.RequestTrigger( Events.LOGIC_EVENT_EVERY_TURN, "", "CheckAlarmNotice", 1 ); end function CheckAlarmNotice() assert( type( tAlarmCheckHQs ) == "table" ); for i = table.getn( tAlarmCheckHQs ), 1, -1 do local nID = tAlarmCheckHQs[i]; assert( type( nID ) == "number" ); local bIsDestroyed = false; if Logic.IsEntityDestroyed( nID ) then bIsDestroyed = true; local sHQName = tAlarmCheckHQs.tNames[nID]; assert( sHQName ); local nNewID = Logic.GetEntityIDByName( sHQName ); if nNewID and nNewID > 0 then bIsDestroyed = false; tAlarmCheckHQs[i] = nNewID; tAlarmCheckHQs.tStatus[nNewID] = tAlarmCheckHQs.tStatus[nID]; tAlarmCheckHQs.tStatus[nID] = nil; tAlarmCheckHQs.tPlayers[nNewID] = tAlarmCheckHQs.tPlayers[nID]; tAlarmCheckHQs.tPlayers[nID] = nil; tAlarmCheckHQs.tNames[nNewID] = tAlarmCheckHQs.tNames[nID]; tAlarmCheckHQs.tNames[nID] = nil; nID = nNewID; end end if bIsDestroyed then table.remove( tAlarmCheckHQs, i ); tAlarmCheckHQs.tStatus[nID] = nil; else local oldAlarmStatus = tAlarmCheckHQs.tStatus[nID]; assert( type( oldAlarmStatus ) == "boolean" ); if Logic.IsAlarmModeActive( nID ) ~= oldAlarmStatus then tAlarmCheckHQs.tStatus[nID] = not oldAlarmStatus; local nPlayerID = tAlarmCheckHQs.tPlayers[nID]; assert( type( nPlayerID ) == "number" ); Message( string.format( "Spieler %d (%s) hat %s.", nPlayerID, UserTool_GetPlayerName( nPlayerID ), oldAlarmStatus and "den Alarm aufgehoben" or "seine Siedlung in Alarmzustand versetzt" ) ); end end end end
Überstundenlimit
Hier kann das gleiche Script wie im Einzelspielermodus verwendet werden. Möglicherweise ist 60 Sekunden eine zu lange Zeit für den Mehrspielermodus.
Um diese auf beispielsweise 35 Sekunden zu reduzieren, muss die Zeile tOvertimes[_id] = turns + 600;
durch tOvertimes[_id] = turns + 350;
ersetzt werden.
Der Aufruf erfolgt hier nicht aus der FirstMapAction(), sondern vom Ende der Funktion GameCallback_OnGameStart().