Nicht existenten Timer killen?

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • Hallo!


    Die Überschrift mag etwas konfus wirken, aber es geht tatsächlich darum einen sich wiederholten Timer zu killen, der gar nicht existiert.
    Das Ganze sieht ungefähr so aus:


    public OnPlayerDeath(...)
    {
    BleedOut(playerid); //Funktionsaufruf ohne direkt einen sich wiederholenden Timer zu starten.
    return 1;
    }


    forward BleedOut(playerid);
    public BleedOut(playerid)
    {
    if(!BeingRezzed[playerid])
    {
    KillTimer(BleedOutTimer[playerid]);
    BleedOutTimer[playerid] = SetTimerEx("BleedOut", 1000, true, "i", playerid);
    }
    if(BeingRezzed[playerid])
    {
    KillTimer(BleedOutTimer[playerid]);
    BleedOutTimer[playerid] = SetTimerEx("BleedOut", 1000/3, true, "i", playerid);
    }
    return 1;
    }


    Im Prinzip geht es nur um den ersten Durchlauf. Wenn jemand stirbt, wird er in eine Art "Downstate" versetzt. Wird er nicht wiederbelebt, hat der Timer ein Intervall von 1s. Wird er wiederbelebt, schrumpft das Intervall auf 333,33ms. Je nach Fall soll das Intervall sich anpassen.
    Wenn der Spieler also direkt stirbt, wird er ja nicht sofort wiederbelebt, also trifft der erste Fall zu, in dem, trotz allem, der Timer gekillt wird. Gibt es eine schönere Möglichkeit hierfür?

  • Ich bin mir nicht ganz sicher ob ich dein Prinzip richtig angenommen habe, aber so dürfte das auch klappen, wie du es haben willst:
    public OnPlayerDeath(...)
    {
    BleedOut(playerid);
    return 1;
    }


    forward BleedOut(playerid);
    public BleedOut(playerid)
    {
    if(!BeingRezzed[playerid]) BleedOutTimer[playerid] = SetTimerEx("BleedOut", 1000, false, "i", playerid);
    else BleedOutTimer[playerid] = SetTimerEx("BleedOut", 333, false, "i", playerid);
    return 1;
    }


    Da der Timer ja mit jedem Aufruf neu gestartet wird (was du ja machst) sparst du dir das KillTimer.
    Alternativ kannst du zwei Callbacks machen, eins für den langen Timer und eins für den kurzen Timer.
    ...unter der Bedingung, dass ich dich richtig verstanden habe. Falls nicht, sag Bescheid.

  • Mir ist eben erst selbst aufgefallen, dass der Timer bei jedem Funktionsaufruf neu gestartet wird. So hatte ich das eigentlich nicht beabsichtigt...^^


    Ich versuch das ganze mal anhand eines Beispiels zu erklären.


    Spieler A wird von Spieler B getötet, also auf 0HP gebracht.
    Spieler A verfällt in den Downstate Modus.
    Da Spieler A nicht von einem anderen Spieler wiederbelebt wird, verblutet A langsam. Hier zählt ein Timer mit einem Intervall von 1s die übrige "Lebenskraft" runter, bis sie auf 0 ist und der Spielet schließlich stirbt. In diesem Zeitraum bis der Spieler aber vollkommen verblutet ist, kann ein anderer Spieler herbeieilen und den Spieler wiedetbeleben.
    Also kommt ein Spieler C zu A und beginnt ihn wiederzubeleben. Hier soll dann der 1s Timer gekillt werden und der 333ms Timer einsetzen. Wenn Spieler C mitten im Prozess aufhört wiederzubeleben, dann schaltet der Timer wieder auf 1s um.
    Deswegen hab ich Killtimer ja immet zu Beginn hedes Statements gehabt, im Falle, dass die Bedingung umschwingt immer nur ein Timer aktiv ist, und nicht beide laufen.

  • Dann würde ich es ganz einfach machen.
    new bleedCount[MAX_PLAYERS];


    public OnPlayerDeath(playerid, killerid, reason)
    {
    BleedOutTimer[playerid] = SetTimerEx("BleedOut", 333, true, "i", playerid);
    return 1;
    }


    forward BleedOut(playerid);
    public BleedOut(playerid)
    {
    if(!BeingRezzed[playerid])
    {
    bleedCount[playerid]++;
    if(bleedCount[playerid] >= 3)
    {
    //Blut abziehen

    //-------------
    bleedCount[playerid] = 0;
    }
    }
    else
    {
    //Blut abziehen

    //-------------
    bleedCount[playerid] = 0;
    }
    return 1;
    }


    Und dort wo der Spieler nicht mehr verblutet (beim Tod oder bei der "Auferstehung") killst du den Timer dann entsprechend.
    if(BleedOutTimer[playerid] != -1) KillTimer(BleedOutTimer[playerid]);
    BleedOutTimer[playerid] = -1;


    Was macht der Code?
    Er ruft den Timer jede 333ms auf, wenn man nicht wiederbelebt wird, dann wird nur bei jedem dritten Aufruf Blut abgezogen, sonst bei jedem Aufruf.

  • Und wenn ich den Timer dann endgültig kille, setze ich den bleedCount wieder auf 0, oder wird das automatisch gemacht?
    Hab mir auch schon überlegt das gabze mit einem Count zu machen, danke für die code-technische Ausführung!

  • Kannst du machen, musst du aber nicht. Schöner wäre es wahrscheinlich, aber das merkt keiner, da das einzige was passiert, dass man eine halbe Sekunde früher das Blut einmalig abgezogen bekommt, an sich kein Problem.
    Aber wenn du deinen Code schön schreiben willst, dann setze es zu 0, entweder dort wo du den Timer startest oder dort wo du ihn beendest, das spielt keine Rolle.




    EDIT: (Post unten)
    Manyula: Da dein Problem behoben ist, wäre es gut, wenn du den Thread auf erledigt setzt. Danke! :)

    3HZXdYd.png

    Einmal editiert, zuletzt von Jeffry ()