[[http://www.siedler-games.de|{{:sg-link.jpg|}}]] ====== 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