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

Metin2 dungeon maken: een dungeon ontwerpen met Lua

Metin2 dungeon maken is de manier om spelers een privé-kaartervaring te bieden die je als groep betreedt, waar monsters in golven binnenkomen en aan het eind een boss met beloningen wacht. In deze gids loop ik door het bouwen van een dungeon vanaf nul — toegangsvoorwaarden, spelers naar de kaart teleporteren, het golf-systeem, de boss-fase, een tijdslimiet en het uitdelen van beloningen — allemaal met de Lua quest-engine. Het doel is geen kopiëren-plakken, maar de logica begrijpen zodat je je eigen content kunt ontwerpen.

Hoe werkt een dungeon?

In Metin2 is een dungeon eigenlijk een kaart-instance die speciaal voor een speler of groep wordt aangemaakt. Terwijl normale kaarten door iedereen worden gedeeld, verschijnt een dungeon als een aparte kopie voor elke groep, zodat twee verschillende groepen dezelfde dungeon spelen zonder elkaar te zien. De laag die deze instance maakt en beheert is de d. (dungeon) namespace in de quest-engine.

  • Toegangs-NPC of -item — interactie ermee triggert de dungeon.
  • Kaartindex (map_index) — het nummer van de lege kaart waarop de dungeon draait; het moet in het index-bestand gedefinieerd zijn.
  • Regen-/spawnbestanden — tekstbestanden die beschrijven op welk punt monsters spawnen.
  • Dungeon-flags — tellers die specifiek bij die dungeon horen (resterende monsters, golfnummer, starttijd), bijgehouden met d.setf/d.getf.

Het belangrijke onderscheid: data die aan de speler gekoppeld is, sla je op met pc.setqf, en data die aan de dungeon-instance gekoppeld is met d.setf. Omdat het golfaantal de hele groep aangaat, hoort het bij de dungeon, terwijl persoonlijke voortgang naar de speler wordt geschreven.

Toegangsvoorwaarden en naar binnen teleporteren

Een goede dungeon betreed je onder eerlijke voorwaarden. Typische controles: een minimumlevel, de eis dat je groepsleider bent, een cooldown en zo nodig een sleutel-item. Het voorbeeld hieronder controleert de voorwaarden wanneer een speler met een toegangs-NPC praat en teleporteert de groep naar een verse dungeon-instance:

quest dungeon_toegang begin
    state start begin
        when 20355.chat."Betreed de dungeon" begin
            if pc.get_level() < 40 then
                say("Je moet minstens level 40 zijn om binnen te gaan.")
                return
            end
            if party.is_party() and not party.is_leader() then
                say("Alleen de groepsleider kan de dungeon openen.")
                return
            end
            -- maak een nieuwe instance en teleporteer de groep
            d.new_jump_party(NEW_DUNGEON_MAP_INDEX, 32000, 32000)
        end
    end
end

Hier maakt d.new_jump_party een verse kaart-instance aan en verplaatst iedereen in de groep naar de opgegeven coördinaat. Voor een solo-dungeon gebruik je d.new_jump_all. De coördinaten zijn de lokale coördinaten van de kaart, niet de globale coördinaten die de hele wereld bestrijken.

Het golf-systeem opzetten

Het hart van een dungeon is het golf-systeem: een groep monsters spawnt, de volgende golf komt zodra ze allemaal dood zijn, en de boss verschijnt als laatste. De kernlogica heeft twee delen — spawnen (d.spawn_mob / d.regen_file) en tellen (ga naar de volgende stap wanneer er geen monsters meer zijn). Hier is de dungeon-specifieke flag d.setf("wave", n) een redder in nood.

-- draait wanneer de kaart-instance wordt aangemaakt
when <map_index>.enter begin
    d.setf("wave", 1)
    d.notice("Golf 1 begint!")
    d.spawn_mob(101, 32000, 32000)
    d.spawn_mob(101, 32050, 32010)
    d.spawn_mob(101, 31980, 32030)
end

-- triggert telkens wanneer een monster in de dungeon sterft
when kill begin
    if d.count_monster() > 0 then return end  -- er leven nog monsters
    local wave = d.getf("wave")
    if wave == 1 then
        d.setf("wave", 2)
        d.notice("Golf 2 komt eraan!")
        d.spawn_mob(102, 32000, 32000)
        d.spawn_mob(102, 32040, 32020)
    elseif wave == 2 then
        d.setf("wave", 3)
        d.notice("De boss is verschenen!")
        d.set_unique("boss", d.spawn_mob(2493, 32000, 32000))
    end
end

d.count_monster() geeft het aantal monsters dat nog op de kaart staat; zodra het nul is, trigger je de volgende golf. De boss met d.set_unique een naam geven is belangrijk zodat je hem apart kunt volgen — daar komen we zo op.

De boss-fase en de dungeon afronden

De laatste golf spawnt meestal één enkele boss. Wanneer die boss sterft, is de dungeon succesvol voltooid: beloningen worden toegekend, een korte aftelling getoond en spelers worden naar buiten geteleporteerd. Omdat we de boss met d.set_unique hebben getagd, kunnen we zijn specifieke dood opvangen met d.is_unique_dead.

when kill with d.is_unique_dead("boss") begin
    d.notice("Dungeon voltooid! Gefeliciteerd.")
    -- beloning: yang en een item voor de hele groep
    d.kill_all()                      -- ruim op wat over is
    d.spawn_mob(20356, 32000, 32000)  -- beloningskist-NPC
    d.exit_all_at_time(10)            -- teleporteer iedereen na 10 s naar buiten
end

Hier ruimt d.kill_all() achtergebleven monsters op, terwijl d.exit_all_at_time alle spelers na het door jou opgegeven aantal seconden terugteleporteert. Wil je de beloning rechtstreeks uitdelen, loop dan bij de dood van de boss door de groepsleden en laat buit vallen via pc.give_item2 of je mob_drop-instellingen.

Tijdslimiet en de faalvoorwaarde

Dungeons krijgen spanning door tijdsdruk. Zet een aftelling; loopt die af, dan geldt de dungeon als mislukt en worden spelers naar buiten gezet. De timer van de quest-engine is hier ideaal voor:

when <map_index>.enter begin
    -- start een timer van 15 minuten
    d.set_warp_location(NEW_DUNGEON_MAP_INDEX, 32000, 32000)
    server_timer("dungeon_timeout", 60 * 15, get_server_timer_arg())
end

when dungeon_timeout.server_timer begin
    d.notice("Tijd om! Dungeon mislukt.")
    d.exit_all()
end

Wil je de timer met een UI-teller tonen, dan kun je spelers een aanroep in de stijl van d.set_timer sturen of periodieke waarschuwingen via notice. Het belangrijkste is om de timer te annuleren zodra succes (de dood van de boss) optreedt; anders valt er een "tijd om"-bericht binnen nadat de beloning al is opgehaald.

Veelgemaakte fouten

  • Verkeerd coördinatensysteem: globale coördinaten meegeven laat de speler buiten de kaart of op de verkeerde plek vallen. Gebruik voor teleporteren binnen de dungeon altijd lokale coördinaten.
  • Telfout: verlaag je je eigen teller met de hand in plaats van d.count_monster() te gebruiken, dan loopt de telling scheef wanneer een monster onverwacht sterft (bijv. valschade). Vertrouw waar mogelijk op de waarde die de engine telt.
  • Instance-lek: wordt de dungeon-instance niet opgeruimd als de groep vertrekt of uiteenvalt, dan stapelen lege kaarten zich op. Zowel de dood van de boss als de time-out moeten hun uitgang met d.exit_all sluiten.
  • Flag-verwarring: sla je het golfnummer op met pc.setqf, dan wordt het per speler apart geteld en breekt het systeem. De golf hoort bij de dungeon → d.setf.

Veelgestelde vragen

Heb ik een gloednieuwe kaart nodig voor een dungeon?

Je hebt een kaartindex nodig waarop de dungeon draait, maar dat hoeft geen vanaf nul getekende kaart te zijn; je kunt een bestaand leeg gebied als dungeon-kaart reserveren. Wat telt, is dat de index zo gedefinieerd is dat hij als instance gedupliceerd kan worden.

Kan ik solo- en groeps-dungeons uit dezelfde code bouwen?

Ja. Splits in het toegangsgedeelte met party.is_party() en roep d.new_jump_party aan voor een groep en d.new_jump_all voor een solospeler. De golf- en boss-logica blijft voor beide identiek; je schaalt simpelweg het aantal monsters/de moeilijkheid naar de groepsgrootte.

Hoe bescherm ik beloningen tegen misbruik?

Ken de beloning alleen toe binnen de boss-dood-trigger, nadat je de dungeon-flag op "voltooid" hebt gezet. Blokkeer een tweede uitkering in dezelfde instance met een d.getf("done")-controle, en voeg naast de timer een toegangs-cooldown toe.

Wil je een volledig gebalanceerde, exploit-bestendige dungeon voor je server? Ik kan het geheel bouwen en testen — van toegangsvoorwaarden tot golf- en boss-logica, beloning- en tijdssystemen. Om je project te bespreken, neem contact met me op.

Devamı için