Inhaltsverzeichnis

Einführung

Ein Countdown ist eine, auf dem Bildschirm eingeblendete, Zeit die abläuft. Dies sollte aus diversen Missionen bekannt sein.

Beliebt ist zum Beispiel „in 5 Minuten, 48 Sekunden greift der Gegner an“. Hiermit sollte man aber sparsam umgehen. Zum einen nimmt es die (eventuell gewollte) Überraschung, zum anderen setzt es den Spieler unter Druck. Das erzeugt Stress, und einige möchten gerne stressfrei siedeln.

Andererseits ist es natürlich schön zu wissen, daß die ersehnte Verstärkung, die einem helfen soll einen ansonsten vernichtenden Angriff zurückzuschlagen, in wenigen Minuten eintrifft. Vielleicht möchte man den Spieler auch genau wissen lassen, wie lange er ein Tor noch verteidigen muss bevor es geschlossen werden kann.

Sowohl der Start eines Timers, als auch dessen Ende sollten immer mit einem Briefing verbunden werden, damit der Spieler weiß was passiert / passieren wird. Der Start muss im „finished“ eines Briefings geschehen, da der Spieler sonst vielleicht das Briefing so schnell wie möglich „durchklicken“ möchte, um möglichst viel Zeit über zu haben. Der manuelle Stopp, also die Beendingung des Countdowns aufgrund eines anderen Ereignisses, muss vor dem Briefing geschehen, da ansonsten Sieg und Niederlage davon abhängen könnte, wie schnell der Spieler das Briefing durchklickt.

Es ist möglich sowohl sichtbare, als auch unsichtbare (stille) Countdowns zu starten. Es kann nur ein sichtbarer Countdown zur Zeit existieren. Natürlich können neben einem sichtbaren Countdown noch beliebig viele stille Countdowns gleichzeitig laufen.

Funktionsweise

Countdown starten

Id = StartCountdown( _Limit, _Callback, _Show )

_Limit sind die Sekunden die der Countdown läuft.
_Callback ist die Funktion, die aufgerufen wird wenn der Countdown abgelaufen ist; den Funktionsnamen ohne Klammern und Anführungszeichen angeben; die Callback Funktion ist optional, es wäre aber unlogisch keine anzugeben.
_Show auf true setzen wenn der Countdown angezeigt werden soll; wenn kein Wert oder false angegeben wird ist es ein stiller Countdown.
Die Funktion gibt die Id des Countdowns zurück. Diese wird benötigt, um den Countdown abbrechen zu können.

Countdown abbrechen

StopCountdown( _Id )

_Id kann eine Id eines vorher mit StartCountdown() gestarteten Countdowns sein – Wenn keine Id übergeben wird, werden alle laufenden Countdowns abgebrochen.

Anwendungsbeispiele

Einfach

Start eines sichtbaren 5 Minuten Countdowns. Sobald dieser abgelaufen ist wird OnCountdownFinished() aufgerufen:

StartCountdown( 5 * 60, OnCountdownFinished, true )

Start und Abbruch

Dieser Code kann zum Testen in eine neue Map kopiert werden. Er demonstriert das Starten und Abbrechen von Countdowns

--[[
  Am Anfang werden zwei Countdowns gestartet: Ein Sichtbarer und ein Stiller. Vom ersten wird die Id gespeichert.
  Der zweite unterbricht mit seiner Callback Funktion den ersten in der Hälfte der abgelaufenen Zeit.
  Dann wird ein stiller Countdown gestartet der in 10 Sekunden einen weiteren sichtbaren Countdown aufruft.
  Nach weiteren 20 Sekunden wird dann die Nachricht: "Countdown abgelaufen" ausgegeben
]]
 
function FirstMapAction()
    id = StartCountdown(20, nil, true)
    StartCountdown(10, CountdownBreak)
end
 
function CountdownBreak()
    StopCountdown(id)
    Message("Countdown abgebrochen")
    StartCountdown(10, NewCountdown)
end
 
function NewCountdown()
    StartCountdown(20, CountdownFinished, true)
end
 
function CountdownFinished()
    Message("Countdown abgelaufen")
end

Respawn von Armeen

Angreifende Armeen erscheinen nach Ablauf eines sichtbaren Countdowns erneut.

function FirstMapAction()
    CreateArmyOne()
end
 
function CreateArmyOne()
    armyOne = {}
    armyOne.id = 1
    ...
    SetupArmy(armyOne)
 
    local troopDescription = {
        leaderType = Entities.PU_LeaderHeavyCavalry1,
        ...
    }
 
    for i = 1, 3 do
        EnlargeArmy(armyOne, troopDescription)
    end
 
    StartSimpleJob("ControlArmyOne")
end
 
function ControlArmyOne()
    if not armyOne.created then
        armyOne.created = not IsDead(armyOne)
        return false
    end
 
    if IsDead(armyOne) then
        -- Angreifende Armee ist tot. Nach 2 Minuten (120 Sekunden) soll die nächste Armee angreifen. Gleichzeitig wird ein Countdown im Spiel angezeigt.
        StartCountdown(120, CreateArmyOne, true)
        return true
    else
        -- Armee lebt noch. In die feindliche Stadt gehen und da alles niedermetzeln.
        Redeploy(armyOne, "enemycity", 5000)
    end
end

Benötigte Funktionen

Da die Verwendung der spielinternen Funktionen für Countdowns zu umständlich ist, wurden Comfort Funktionen dafür geschrieben, deren Verwendungsweise hier gezeigt wurde. Diese Funktionen müssen natürlich für die Verwendung unverändert ins Script kopiert werden.

function StartCountdown(_Limit, _Callback, _Show)
    assert(type(_Limit) == "number")
    assert( not _Callback or type(_Callback) == "function" )
 
    Counter.Index = (Counter.Index or 0) + 1
 
    if _Show and CountdownIsVisisble() then
        assert(false, "StartCountdown: A countdown is already visible")
    end
 
    Counter["counter" .. Counter.Index] = {Limit = _Limit, TickCount = 0, Callback = _Callback, Show = _Show, Finished = false}
 
    if _Show then
        MapLocal_StartCountDown(_Limit)
    end
 
    if Counter.JobId == nil then
        Counter.JobId = StartSimpleJob("CountdownTick")
    end
 
    return Counter.Index
end
 
function StopCountdown(_Id)
    if Counter.Index == nil then
        return
    end
 
    if _Id == nil then
        for i = 1, Counter.Index do
            if Counter.IsValid("counter" .. i) then
                if Counter["counter" .. i].Show then
                    MapLocal_StopCountDown()
                end
                Counter["counter" .. i] = nil
            end
        end
    else
        if Counter.IsValid("counter" .. _Id) then
            if Counter["counter" .. _Id].Show then
                MapLocal_StopCountDown()
            end
            Counter["counter" .. _Id] = nil
        end
    end
end
 
function CountdownTick()
    local empty = true
    for i = 1, Counter.Index do
        if Counter.IsValid("counter" .. i) then
            if Counter.Tick("counter" .. i) then
                Counter["counter" .. i].Finished = true
            end
 
            if Counter["counter" .. i].Finished and not IsBriefingActive() then
                if Counter["counter" .. i].Show then
                    MapLocal_StopCountDown()
                end
 
                -- callback function
                if type(Counter["counter" .. i].Callback) == "function" then
                    Counter["counter" .. i].Callback()
                end
 
                Counter["counter" .. i] = nil
            end
 
            empty = false
        end
    end
 
    if empty then
        Counter.JobId = nil
        Counter.Index = nil
        return true
    end
end
 
function CountdownIsVisisble()
    for i = 1, Counter.Index do
        if Counter.IsValid("counter" .. i) and Counter["counter" .. i].Show then
            return true
        end
    end
 
    return false
end