aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Metin2 Arena-System: 1v1-Duelle und Turniere bauen

Ein Metin2 Arena-System ist ein eigener PvP-Inhalt, in dem Spieler in sicheren, fairen 1v1-Duellen gegeneinander antreten und am Ende ein Sieger bestimmt wird. In dieser Anleitung zeige ich, wie du eine Duellarena von Grund auf mit der Lua-Quest-Engine baust: Spieler zusammenführen, das Paar auf eine isolierte Karte teleportieren, PvP nur zwischen diesen beiden aktivieren, den Sieger erkennen und — wenn du willst — das Ganze an einen Turnierbaum anbinden. Das Ziel ist nicht, fertigen Code einzufügen, sondern die Bausteine zu verstehen, damit du das System an deinen eigenen Server anpassen kannst.

Wie funktioniert eine Arena?

Eine Duellarena ist im Wesentlichen eine Zustandsmaschine, die drei Fragen beantwortet: wer kämpft gegen wen, wo sie kämpfen und wer gewonnen hat. In Metin2 löst du das am saubersten, indem du den Kampf von der gemeinsamen Karte abkoppelst und ihn in einer eigenen Karten-Instanz spielst. So sind die beiden Gegner vor Einmischung von außen geschützt, kein anderer Spieler kann den Kampf stören und die Sieg-/Niederlage-Teleportation bleibt sauber.

  • Ein Anmelde-NPC oder -Item — der Spieler interagiert damit, um an der Warteschlange/dem Matchmaking teilzunehmen.
  • Eine Warteschlange — die Liste der auf eine Zuordnung wartenden Spieler; im einfachsten Fall ein Paar globaler Flags.
  • Ein Arena-Kartenindex — die im index-Datei definierte Nummer der leeren Karte, auf der das Duell gespielt wird.
  • Zustands-Flags — wer in der Warteschlange ist, wer in einem Match steckt und wer gewonnen hat, gespeichert mit pc.setqf und dem globalen set_quest_flag.

Der wichtige Unterschied: spielerbezogene Daten (ist dieser Spieler in einem Match, wie lautet die ID des Gegners) gehen in pc.setqf; serverweite Daten (ist jemand in der Warteschlange) gehen in set_quest_flag. Metin2 hat zwar eine eingebaute Duell- (Challenge-)Funktion, aber das ist ein Schlagabtausch auf der offenen Karte; für eine isolierte, kontrollierte und turnierfähige Arena ist der Bau deines eigenen quest-basierten Systems weitaus flexibler.

Spieler zusammenführen (Matchmaking)

Der erste Teil der Arena ist die Warteschlange. Wenn ein Spieler mit dem Anmelde-NPC spricht, wird er mit demjenigen zusammengeführt, der bereits wartet; ist niemand da, geht er selbst in die Warteschlange. Das einfachste Matchmaking nutzt ein einzelnes globales Flag, das „die ID des wartenden Spielers" enthält:

quest arena_anmeldung begin
    state start begin
        when 20399.chat."Der Arena beitreten" begin
            local meine_id = pc.get_player_id()
            local wartend = get_quest_flag("arena.wartend_pid")

            if wartend == 0 then
                -- Warteschlange leer: diesen Spieler auf Halt setzen
                set_quest_flag("arena.wartend_pid", meine_id)
                pc.setqf("arena_status", 1)        -- 1 = in der Warteschlange
                say("Warte, waehrend ein Gegner gesucht wird...")
                return
            end

            if wartend == meine_id then
                say("Du stehst bereits in der Warteschlange.")
                return
            end

            -- Zuordnung gefunden: Warteschlange leeren und Kampf starten
            set_quest_flag("arena.wartend_pid", 0)
            arena_starten(wartend, meine_id)
        end
    end
end

Hier gibt get_player_id() die eindeutige ID des Spielers zurück; sie bleibt gleich, selbst wenn der Spieler zwischen Karten wechselt, und ist daher ein sicherer Schlüssel, um Gegner zuzuordnen. arena_starten ist unsere eigene Hilfsfunktion, die die beiden IDs nimmt und den Kampf einrichtet. Auf einem echten Server würdest du der Warteschlange auch eine Level-/Ausrüstungsbeschränkung hinzufügen oder prüfen, ob der wartende Spieler noch online ist.

Auf eine isolierte Arena-Karte teleportieren

Sobald eine Zuordnung gefunden ist, bewegen wir beide Spieler in eine frische Arena-Instanz. d.new_jump_all erstellt eine neue Karten-Instanz und teleportiert den aufrufenden Spieler dorthin; um den zweiten Spieler in dieselbe Instanz zu bekommen, zielen wir auf seine pid und teleportieren ihn zum selben Kartenindex. Ein kurzer Countdown vor dem Match gibt beiden Spielern einen Moment zur Vorbereitung:

function arena_starten(pid1, pid2)
    -- Gegner und Status auf beide Spieler schreiben
    pc.select_pc(pid1)
    pc.setqf("arena_status", 2)        -- 2 = im Match
    pc.setqf("arena_gegner", pid2)

    -- praktisches Vorgehen: gemeinsame Instanz + zwei Teleports:
    -- erst die neue Instanz mit einem Spieler erstellen, dann den
    -- anderen ueber seine pid zur selben Karte teleportieren.
end

In der Praxis ist das robusteste Vorgehen: rufe d.new_jump_all(ARENA_MAP_INDEX, x, y) mit einem Spieler auf, um die Instanz zu erstellen, wähle dann den zweiten Spieler mit pc.select_pc(pid2) und teleportiere ihn zum zweiten Spawnpunkt in derselben Instanz. Denk daran, dass die Koordinaten die lokalen Koordinaten der Karte sind — platziere die beiden Spieler in gegenüberliegenden Ecken, damit der Kampf fair beginnt. Ein kleiner „3... 2... 1... Kampf!"-Countdown per server_timer nach der Teleportation verbessert das Erlebnis erheblich.

PvP nur zwischen diesen beiden aktivieren

Der entscheidende Punkt der Arena ist, dass der Kampf nur zwischen den beiden zugeordneten Spielern stattfindet. Der zuverlässigste Weg ist, die Arena als Frei-PvP-Karte einzurichten: in den Karteneinstellungen markierst du diesen map_index als PvP-aktiviert, sodass jeder in der Arena angreifen kann — und die Isolation gewährleistest du, indem du nur zwei Spieler pro Instanz hineinlässt. Auf der Quest-Seite stellst du sicher, dass Spieler zuschlagen können, ohne von den Gilden-/Gildenkrieg-Flags blockiert zu werden, die offene Karten regeln.

-- wenn ein Spieler die Arena-Karte betritt
when <ARENA_MAP_INDEX>.enter begin
    pc.setqf("arena_status", 2)
    -- Flucht blockieren: Teleport-Items / unerwuenschten Schutz sperren
    pc.remove_affect(...)             -- unerwuenschte Schutzeffekte entfernen
    syschat("Du bist in der 1v1-Arena. Viel Glueck!")
end

Wenn du Source-Zugriff hast, ist die sauberste Lösung, eine Prüfung wie CHARACTER::IsAttackableMap anzupassen, um den Arena-map_index zu öffnen und die Friedenszonen-Regeln innerhalb der Arena zu deaktivieren. Ohne die Source anzufassen, kannst du es dennoch mit einem reinen Quest-Ansatz handhaben, indem du die Karte als Frei-PvP markierst und dich auf die Isolation verlässt; für kleine und mittelgroße Server ist das mehr als ausreichend.

Den Sieger erkennen

Ein Duell endet, wenn eine Seite stirbt. In der Metin2-Quest-Engine läuft der Trigger when dead im Kontext des Spielers, der gestorben ist; dort markierst du diesen Spieler als „Verlierer" und seinen Gegner als „Sieger". Dank der Gegner-ID, die wir in pc.setqf("arena_gegner") gespeichert haben, kennen wir den Sieger direkt:

when dead with pc.getqf("arena_status") == 2 begin
    local verlierer = pc.get_player_id()
    local sieger    = pc.getqf("arena_gegner")

    -- den Verlierer bereinigen und hinaus teleportieren
    pc.setqf("arena_status", 0)
    pc.setqf("arena_gegner", 0)
    pc.warp(STADT_X * 100, STADT_Y * 100)

    -- den Sieger auswaehlen, belohnen und hinaus teleportieren
    if pc.select_pc(sieger) then
        pc.setqf("arena_status", 0)
        pc.setqf("arena_gegner", 0)
        notice_all(pc.get_name() .. " hat die Arena gewonnen!")
        pc.give_item2(50300, 1)        -- Beispielbelohnung: eine Trophaee/Item
        pc.warp(STADT_X * 100, STADT_Y * 100)
    end
end

Achtung: pc.warp erwartet Weltkoordinaten multipliziert mit 100 (In-Game-Kachelkoordinate × 100), während die Teleportation innerhalb einer Instanz lokale Koordinaten verwendet — diese beiden zu verwechseln ist der häufigste Anfängerfehler. Außerdem füge, damit ein Verbindungsabbruch kein Schlupfloch ist, eine „wenn du im Match bist, gewinnt dein Gegner"-Regel in when logout hinzu; sonst können Spieler, die kurz vor der Niederlage stehen, den Stecker ziehen und das Ergebnis löschen.

An einen Turnierbaum anbinden

Sobald das einzelne Duell funktioniert, ist ein Turnier nur dieselbe Logik wiederholt: Sieger steigen in die nächste Runde auf, Verlierer scheiden aus. Du hältst die Teilnehmer-IDs in fortlaufenden Flags (arena.runde1_0, arena.runde1_1, ...), schreibst den Sieger jedes Matches am Ende in die Liste der nächsten Runde und baust die Paarungen neu auf, wenn die Runde voll ist.

  • Anmeldefenster: nimm vor Turnierbeginn für einen festgelegten Zeitraum Anmeldungen an; friere die Liste beim Schließen ein.
  • Ungerade Anzahl (Freilos): ist die Teilnehmerzahl ungerade, gib einem ein automatisches Weiterkommen (Freilos); berechne das beim Aufbau der Liste.
  • Aufeinanderfolgende Matches: du kannst ein Match nach dem anderen spielen und die Arena belegt halten, oder mehrere Instanzen öffnen und Runden parallel laufen lassen.
  • Endbelohnung: gib ein spezielles Kostüm, einen Titel oder einen Yang-Preis nur dem Sieger des letzten Matches.

Indem du das Turnier mit einem server_timer steuerst, kannst du ihm einen Rhythmus wie „baue alle 5 Minuten die Paarungen der Runde" geben. Da die Logik mit einem einzelnen Duell identisch ist, ist das Turnier — sobald du einen soliden 1v1-Kern hast — nur eine darum gewickelte Hülle.

Häufige Fehler

  • Koordinatenverwirrung: Kachel × 100 für pc.warp, lokale Koordinaten für Teleports innerhalb einer Instanz. Verwechselst du sie, fällt der Spieler von der Karte.
  • Disconnect-Exploit: ohne when logout-Regel kann ein Spieler kurz vor der Niederlage sich ausloggen und das Ergebnis löschen. Behandle ein Logout als „der Gegner gewinnt".
  • Instanz-Leck: verlassen nicht beide Spieler die Instanz, wenn das Match endet, stapeln sich leere Arena-Instanzen. Schließe sowohl den Tod- als auch den Ausgangspfad mit warp.
  • Flag-Bereinigung: setzt du die Flags arena_status und arena_gegner am Ende eines Matches nicht zurück, betritt der Spieler sein nächstes Match in einem „halb-fertigen" Zustand und das System bricht.

Häufig gestellte Fragen

Reicht das eingebaute Duellsystem von Metin2 nicht aus?

Die eingebaute Challenge ist ein Kampf auf der offenen Karte, vor aller Augen und offen für Einmischung. Willst du eine isolierte Arena, einen fairen Start, eine Siegerbelohnung und vor allem ein Turnier, ist deine eigene quest-basierte Arena weitaus kontrollierter und flexibler. Du kannst auch beide nebeneinander anbieten.

Lässt sich eine Arena bauen, ohne die Source anzufassen?

Ja, in den meisten Fällen. Markierst du die Arena-Karte als Frei-PvP und lässt nur zwei Spieler pro Instanz hinein, erhältst du ein 1v1-System, das auf reiner Quest-Logik läuft. Für sehr feinkörnige PvP-Regeln (z. B. bestimmte Affects zwangsweise entfernen) erleichtert Source-Zugriff die Sache, ist aber nicht erforderlich.

Wie viele Matches können gleichzeitig laufen?

Da jedes Match in seiner eigenen Karten-Instanz läuft, ist die theoretische Grenze deine Hardware; jede Instanz verbraucht Speicher und CPU. Auf kleinen bis mittelgroßen Servern sind Dutzende gleichzeitiger Matches kein Problem. Bei sehr ausgelasteten Turnieren ist es sicherer, die Anzahl der Instanzen zu begrenzen und die Matches in eine Warteschlange zu stellen.

Möchtest du eine faire, isolierte und missbrauchssichere Arena für deinen Server? Von der Matchmaking-Warteschlange über die isolierte Duellkarte bis zur Siegererkennung und einem kompletten Turnierbaum kann ich das gesamte System bauen und testen. Um über dein Projekt zu sprechen, nimm Kontakt mit mir auf.

Bu kategorideki tüm yazılar →

Devamı için