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

Metin2 Acce-systeem: accessoire socketing en absorptie

Het Metin2 acce-systeem is een costume-accessoiremechaniek die oudere servers nooit hadden, maar die op moderne private servers bijna standaard is geworden. Het idee is simpel: je "socket" een normaal item in een rug-accessoirecostume (de acce), en de acce absorbeert een percentage van de bonussen van dat item en past ze toe op het personage. In deze gids laat ik zien hoe ik de mechaniek vanaf nul toevoeg, zowel aan de server- als de clientkant.

Wat doet het acce-systeem precies?

Het klassieke costume-systeem verandert alleen het uiterlijk; acce gaat een stap verder. De speler draagt een accessoire dat het uiterlijk verandert en stopt er vervolgens een sterk harnas, een wapen of een ander item in. De acce verbruikt het item visueel niet — het "absorbeert" een vast percentage van de bonusstats (bijvoorbeeld schade tegen monsters, HP, kritieke kans) en geeft ze aan de speler als extra stats. Zo houdt de speler het gewenste uiterlijk én wint hij een verborgen bron van kracht. Het is een mooi systeem dat zowel verzamelen als machtsprogressie aan je server toevoegt.

Item proto: het acce-costume definiëren

Alles begint in de item proto. Acce-items zijn van het type ITEM_COSTUME zoals een normaal costume, maar hun subtype moet COSTUME_ACCE zijn. In de item-editor of de item_proto-tabel:

  • Type: COSTUME
  • SubType: ACCE
  • WearFlags: een flag voor het uitrustingsslot dat het accessoire gebruikt (meestal een apart WEAR_COSTUME_ACCE-slot).

Dit subtype vertelt de server "dit item is een acce en kan een ander item bevatten." Je hebt ook een .gr2-model en een icoon nodig voor het beeld, maar de mechaniek steunt volledig op het subtype en de sockets.

Sockets: het geabsorbeerde item opslaan

In Metin2 heeft elk item een paar socket-slots (normaal gebruikt voor metin-stenen / diamanten). Voor de acce hergebruiken we die sockets om informatie over het geplaatste item op te slaan. De schoonste aanpak is met constanten vast te leggen wat elke socket bevat:

// item.h — wat houden de sockets van de acce vast?
enum EAcceSocket
{
    ACCE_ABSORBED_VNUM_SLOT = 0,  // vnum van het geabsorbeerde item
    ACCE_ABSORB_PCT_SLOT    = 1,  // absorptiepercentage (bijv. 50 = 50%)
};

Wanneer de speler een item absorbeert in het acce-venster, schrijft de server de vnum van dat item naar socket0 en het berekende absorptiepercentage naar socket1. Omdat sockets samen met het item in de database worden opgeslagen, overleeft deze informatie zelfs een serverherstart — precies dat maakt het acce-systeem persistent.

De geabsorbeerde bonussen op de speler toepassen

Het echte werk is het berekenen van de bonussen van het geabsorbeerde item en deze aan het personage toevoegen terwijl de acce gedragen wordt. We lezen de geabsorbeerde vnum uit de socket van de acce, zoeken de proto van dat item op en vermenigvuldigen zijn apply-bonussen met het percentage:

// char_item.cpp — bonussen toepassen bij dragen / afnemen van de acce
void CHARACTER::__ApplyAcceAbsorb(LPITEM pAcce, bool bAdd)
{
    if (!pAcce || pAcce->GetSubType() != COSTUME_ACCE)
        return;

    DWORD dwVnum = pAcce->GetSocket(ACCE_ABSORBED_VNUM_SLOT);
    int   iPct   = pAcce->GetSocket(ACCE_ABSORB_PCT_SLOT);
    if (dwVnum == 0 || iPct <= 0)
        return;

    TItemTable * pProto = ITEM_MANAGER::instance().GetTable(dwVnum);
    if (!pProto)
        return;

    for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
    {
        BYTE bType  = pProto->aApplies[i].bType;
        long lValue = pProto->aApplies[i].lValue;
        if (bType == APPLY_NONE || lValue == 0)
            continue;

        long lAbsorbed = (lValue * iPct) / 100;
        ApplyPoint(bType, bAdd ? lAbsorbed : -lAbsorbed);
    }
}

Je roept deze functie aan waar het personage zijn stats herberekent — dus in ComputePoints() terwijl de gedragen items verwerkt worden:

// char.cpp — in ComputePoints() bij het verwerken van uitrusting
LPITEM pAcce = GetWear(WEAR_COSTUME_ACCE);
if (pAcce)
    __ApplyAcceAbsorb(pAcce, true);

Omdat ComputePoints() de stats vanaf nul opbouwt, voegen we hier altijd toe met true; als de speler de acce afneemt, wist de volgende herberekening de bonus automatisch. De bAdd-parameter is handig om de bonus live te verwijderen zonder volledige herberekening.

Het acce-venster: packetflow en client

Om de speler een item in de acce te laten slepen, heb je een UI-venster nodig. Dit wordt aan de clientkant getekend met uiacce.py (een Python root-bestand) en praat met de server via aangepaste packets. De typische flow is:

  • De speler klikt met rechts op de acce → de client stuurt HEADER_CG_ACCE_REFINE_OPEN, de server opent het venster.
  • De speler legt het acce-item en het te absorberen item in de slots.
  • Bij het indrukken van "Combineren" stuurt de client HEADER_CG_ACCE_REFINE; de server berekent het absorptiepercentage, schrijft de sockets en meldt het resultaat terug met HEADER_GC_ACCE_REFINE_RESULT.

Je moet deze packet-headers met hetzelfde nummer aan zowel client- als serverkant in packet.h definiëren — een verschil veroorzaakt een directe client-"crash." Vergeet ook niet de nodige regels aan locale_game.txt toe te voegen voor de venstertekst.

Absorptiepercentages en veelgemaakte fouten

Hoe je het absorptiepercentage bepaalt, is volledig een balanskeuze. Er zijn twee gangbare methoden: een vast percentage (bijvoorbeeld altijd 50%), of een variabel percentage uit een tabel op basis van het level/grade van het item. Een variabel percentage geeft een evenwichtiger resultaat, omdat je automatisch kunt begrenzen hoeveel zeer sterke items absorberen. Hier zijn de meestgemaakte fouten:

  • Sockets niet opgeslagen: zorg dat je na de absorptie het item in de database persisteert na de SetSocket()-aanroep; anders verdwijnt de bonus bij een herstart.
  • Dubbele bonus: roep je __ApplyAcceAbsorb zowel in ComputePoints als bij het uitrusten aan, dan wordt de bonus verdubbeld. Beheer het vanaf één plek.
  • Verkeerd uitrustingsslot: zonder apart WEAR-slot voor de acce botst het met het normale costume.
  • Packetnummer-mismatch: verschillen de client- en serverheaders, dan opent het venster niet of crasht het.

Veelgestelde vragen

Verdwijnt het item dat in de acce wordt gelegd?

In de klassieke mechaniek wel — het geabsorbeerde item wordt verbruikt en alleen zijn bonus blijft over. Sommige servers maken het item verwijderbaar; dan moet je ook de attributen van het item in de sockets opslaan en ze teruggeven bij een "verwijderen"-actie.

Wordt de acce-bonus beïnvloed door de levellimiet van het gedragen item?

Nee. De eigen LimitType-velden van de acce (zoals een levellimiet) gelden; de levelvereiste van het geabsorbeerde item wordt niet rechtstreeks toegepast. Je balanceert via de limieten van de acce zelf.

Kan dit systeem later aan een bestaande source worden toegevoegd?

Ja. Het acce-systeem is volledig modulair: een nieuw subtype, een paar functies, packet-headers en een clientvenster. Het is toe te voegen zonder bestaande quest-, item- of costume-systemen aan te raken.

Wil je een compleet acce-systeem op je server? Van proto tot clientvenster, van absorptiebalans tot databasepersistentie, ik bouw de hele keten — neem contact op.

Bu kategorideki tüm yazılar →

Devamı için