Le système acce Metin2 est une mécanique d'accessoire de costume que les anciens serveurs n'avaient pas, mais qui est devenue presque standard sur les serveurs privés modernes. L'idée est simple : on « sertit » un objet normal dans un costume d'accessoire de dos (l'acce), et l'acce absorbe un pourcentage des bonus de cet objet pour les appliquer au personnage. Dans ce guide, je montre comment j'ajoute la mécanique de zéro, côté serveur comme côté client.
Que fait réellement le système acce ?
Le système de costume classique ne change que l'apparence ; l'acce va plus loin. Le joueur équipe un accessoire qui modifie l'apparence, puis place à l'intérieur une armure puissante, une arme ou un autre objet. L'acce ne consomme pas l'objet visuellement : il « absorbe » un pourcentage fixe de ses bonus (par exemple dégâts contre les monstres, PV, chance de critique) et les accorde au joueur en stats supplémentaires. Le joueur garde donc l'apparence qu'il veut et gagne une source de puissance cachée. C'est un excellent système qui ajoute à la fois de la collection et de la progression de puissance à votre serveur.
Item proto : définir le costume acce
Tout commence dans l'item proto. Les objets acce sont de type ITEM_COSTUME comme un costume normal, mais leur sous-type doit être COSTUME_ACCE. Dans l'éditeur d'items ou la table item_proto :
- Type :
COSTUME - SubType :
ACCE - WearFlags : un flag pour l'emplacement d'équipement utilisé par l'accessoire (généralement un slot
WEAR_COSTUME_ACCEséparé).
Ce sous-type indique au serveur que « cet objet est un acce et peut contenir un autre objet ». Il faut aussi un modèle .gr2 et une icône pour le visuel, mais la mécanique repose entièrement sur le sous-type et les sockets.
Sockets : stocker l'objet absorbé
Dans Metin2, chaque objet possède quelques emplacements de socket (normalement utilisés pour les pierres metin / diamants). Pour l'acce, on réutilise ces sockets afin de stocker les informations de l'objet placé à l'intérieur. L'approche la plus propre consiste à définir avec des constantes ce que contient chaque socket :
// item.h — que contiennent les sockets de l'acce ?
enum EAcceSocket
{
ACCE_ABSORBED_VNUM_SLOT = 0, // vnum de l'objet absorbe
ACCE_ABSORB_PCT_SLOT = 1, // pourcentage d'absorption (ex. 50 = 50%)
};
Ainsi, quand le joueur absorbe un objet dans la fenêtre acce, le serveur écrit le vnum de cet objet dans socket0 et le pourcentage d'absorption calculé dans socket1. Comme les sockets sont sauvegardés en base de données avec l'objet, cette information survit même si le serveur redémarre — c'est exactement ce qui rend le système acce persistant.
Appliquer les bonus absorbés au joueur
Le vrai travail consiste à calculer les bonus de l'objet absorbé et à les ajouter au personnage tant que l'acce est équipé. On lit le vnum absorbé depuis le socket de l'acce, on récupère le proto de cet objet et on multiplie ses bonus apply par le pourcentage :
// char_item.cpp — appliquer les bonus quand l'acce est porte / retire
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);
}
}
Vous appelez cette fonction là où le personnage recalcule ses stats — c'est-à-dire dans ComputePoints() pendant le traitement des objets équipés :
// char.cpp — dans ComputePoints() lors du traitement de l'equipement
LPITEM pAcce = GetWear(WEAR_COSTUME_ACCE);
if (pAcce)
__ApplyAcceAbsorb(pAcce, true);
Comme ComputePoints() reconstruit les stats à partir de zéro, on ajoute toujours avec true ici ; quand le joueur retire l'acce, le recalcul suivant efface le bonus automatiquement. Le paramètre bAdd est pratique pour retirer le bonus à chaud, sans recalcul complet.
La fenêtre acce : flux de paquets et client
Pour que le joueur puisse glisser un objet dans l'acce, il faut une fenêtre d'interface. Elle est dessinée côté client avec uiacce.py (un fichier root Python) et communique avec le serveur via des paquets personnalisés. Le flux typique est :
- Le joueur fait un clic droit sur l'acce → le client envoie
HEADER_CG_ACCE_REFINE_OPEN, le serveur ouvre la fenêtre. - Le joueur place l'objet acce et l'objet à absorber dans les slots.
- En appuyant sur « Combiner », le client envoie
HEADER_CG_ACCE_REFINE; le serveur calcule le pourcentage d'absorption, écrit les sockets et renvoie le résultat avecHEADER_GC_ACCE_REFINE_RESULT.
Vous devez définir ces en-têtes de paquet avec le même numéro côté client et côté serveur dans packet.h — un décalage provoque un « crash » client immédiat. Pensez aussi à ajouter les lignes nécessaires dans locale_game.txt pour les textes de la fenêtre.
Taux d'absorption et erreurs fréquentes
La façon de déterminer le pourcentage d'absorption relève entièrement de votre choix d'équilibrage. Deux méthodes courantes : un taux fixe (par exemple toujours 50 %), ou un taux variable lu dans une table selon le niveau/grade de l'objet. Un taux variable donne des résultats plus équilibrés, car vous pouvez plafonner automatiquement l'absorption des objets très puissants. Voici les erreurs les plus fréquentes :
- Sockets non sauvegardés : après l'absorption, assurez-vous de persister l'objet en base après l'appel à
SetSocket(); sinon le bonus disparaît au redémarrage. - Bonus double : si vous appelez
__ApplyAcceAbsorbà la fois dansComputePointset à l'équipement, le bonus est doublé. Gérez-le depuis un seul endroit. - Mauvais slot d'équipement : sans slot
WEARséparé pour l'acce, il entre en conflit avec le costume normal. - Numéro de paquet incohérent : si les en-têtes client et serveur diffèrent, la fenêtre ne s'ouvre pas ou plante.
Questions fréquentes
L'objet placé dans l'acce disparaît-il ?
Dans la mécanique classique, oui — l'objet absorbé est consommé et seul son bonus subsiste. Certains serveurs rendent l'objet retirable ; dans ce cas, il faut aussi stocker ses attributs dans les sockets et les restituer lors d'un « retrait ».
Le bonus d'acce est-il affecté par la limite de niveau de l'objet porté ?
Non. Ce sont les champs LimitType propres à l'acce (comme une limite de niveau) qui s'appliquent ; le prérequis de niveau de l'objet absorbé n'est pas appliqué directement. Vous équilibrez via les limites de l'acce lui-même.
Ce système peut-il être ajouté à une source existante plus tard ?
Oui. Le système acce est entièrement modulaire : un nouveau sous-type, quelques fonctions, des en-têtes de paquet et une fenêtre client. Il s'ajoute sans toucher aux systèmes de quêtes, d'items ou de costumes existants.
Vous voulez un système acce complet sur votre serveur ? Du proto à la fenêtre client, de l'équilibrage de l'absorption à la persistance en base, je peux construire toute la chaîne — contactez-moi.