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().