Audit technique — revue de code

Valora · mise à jour « Forgemagie » v2.1

Revue statique du bundle client déployé sur la bêta, avec reconstruction des tables de données et des formules d'équilibrage.

Cible
beta.valora.gg
Build audité
index-GWYEpY4N.js
Version
v2.1 — 25 juil. 2026
Date de l'audit
25 juillet 2026
Constats
12 — dont 3 majeurs
Périmètre
Client uniquement (voir §2)

1Résumé exécutif

La fonctionnalité est cohérente dans son intention et son interface, mais elle repose sur un jeu de données qui n'a été migré qu'à 17 % (13 objets sur 78). Cette migration inachevée rend une ou plusieurs statistiques non forgeables sur 36 objets sur 78, dont les quatre armes mythiques de niveau 80–100 et les cinq Reliques. Par ailleurs, une erreur d'algèbre dans la formule de rendement du recyclage neutralise complètement la pondération de rareté des runes, ce qui produit un écart de coût réel de 1 à 270 entre statistiques.

Aucun de ces deux points n'est visible en jouant quelques minutes : la forge ne renvoie pas d'erreur, elle omet simplement les statistiques concernées, et l'objet disparaît parfois entièrement de la liste. C'est ce silence qui les rend prioritaires.

IDConstatSévéritéNature
RS-01Clés de statistiques non normalisées dans la forge — 36/78 objets amputésMajeurBug de données
RS-02Le poids de rune s'annule dans la formule de rendementMajeurBug d'équilibrage
RS-03Bêta injouable pour la fonctionnalité auditéeMajeurExploitation
RS-04Rune de Précision : valeur marchande à 0, invendable au PNJMoyenDonnée
RS-05Gain de critique invisible à l'écran (format + arrondi)MoyenAffichage
RS-06Progression Runiste : 0,09 % de l'XP débloque 100 % du contenuMoyenDesign
RS-07Confirmations asymétriques sur les actions destructricesMoyenUX
RS-08Notes de version : noms de runes inexistants ou trompeursMineurCommunication
RS-09Erreur trompeuse quand l'objet n'a pas d'instanceIdMineurBug
RS-10Poids 0.5 de la Rune de Vigueur entièrement inopérantMineurDonnée morte
RS-11Code et chaînes résiduelsMineurPropreté
RS-12Détection OVER impossible sur une fourchette fixeLatentPiège futur

Ordre de traitement suggéré : RS-03 en premier (sans quoi la fenêtre de test de 72 h ne produira aucun retour terrain), puis RS-01 et RS-02 qui touchent le cœur de la fonctionnalité, puis RS-04 et RS-05 qui sont des corrections courtes à fort effet perçu.

2Périmètre, méthode et limites

Ce qui a été audité

Ce qui n'a pas pu être audité

Le serveur est autoritaire. Le client se contente d'émettre deux RPC :

recycle(e,t){ return this.call("econ_recycle", t!=null?{id:e,instanceId:t}:{id:e}) }
upgrade(e,t){ return this.call("econ_upgrade", {instanceId:e, stat:t}) }

Le tirage de succès, la destruction, la dégradation et l'attribution réelle des runes se décident côté serveur, hors de portée de cet audit. Deux conséquences pratiques :

Test en jeu

La vérification empirique n'a pas pu être menée : les deux personnages de bêta disponibles (niveau 100) ont un sac vide ou sans équipement, et 0 et 18 pièces d'or respectivement. Voir RS-03. Tous les constats ci-dessous sont donc issus de l'analyse statique ; ils sont reproductibles par lecture du bundle, et chacun indique la donnée exacte permettant de le rejouer.

Convention de nommage

Le bundle est minifié : les identifiants cités (Eo, Ax, Lx, Fm…) sont des noms générés par le build, pas des noms de source. Chaque citation est accompagnée de la description sémantique de la fonction pour permettre de la retrouver dans le dépôt.

3Le système tel qu'implémenté

Table de forge

Configuration Ix : maxTier: 4, overmaxStepPct: 800. Chaque palier réussi ajoute 8 % du maximum de base de la statistique ; un objet mené au palier 4 dépasse donc son plafond de 32 %.

PalierSuccèsRunesOrDestructionRuniste requis
1100 %2 × poids2 0001
285 %3 × poids6 0005
365 %5 × poids15 00012
445 %8 × poids35 00025 %20

Dans tout ce document, « chaîne » désigne la montée complète d'une statistique d'un objet, du palier 1 au palier 4 : 2+3+5+8 = 18 × poids en runes, et 58 000 or.

Table des runes

Le poids (weight) est le multiplicateur de coût en forge ; sell est le prix payé par le marchand PNJ.

RuneNom en jeuStatistiqueRaretéPoidsValeur PNJ
rune_mightRune de PuissanceForceCommune12
rune_wisdomRune de SagesseSavoirCommune12
rune_swiftnessRune de CéléritéAgilitéCommune12
rune_fortuneRune de FortuneFluxCommune12
rune_vigorRune de VigueurVitalitéCommune0.51
rune_ward_*Rune de Garde (×4)RésistancesPeu commune33
rune_powerRune de FrappeDégâtsPeu commune56
rune_precisionRune de PrécisionCritiqueRare300

Formules

// rendement du recyclage, par statistique — fonction Ax
rendement = niveauObjet × valeurStat × poids × (6000/10000) / (40 × poids)
// crit : valeurStat est multipliée par 100 en amont

// pas de progression par palier — fonction Px
pas = max(1, round(maxDeBase × 800/10000))          // stats entières
pas = max(0.001, round(maxDeBase × 0.08 × 1000)/1000) // crit

// coût en runes d'un palier — fonction Rx
coût = max(1, round(runeCount × max(1, poids)))

// XP de métier pour passer du niveau n à n+1 — fonction at
xp = 4 × n²

4Constats

RS-01 Clés de statistiques non normalisées dans la forge Majeur

Statut
Confirmé par analyse statique — 36 objets sur 78
Portée
Client uniquement
Symptôme
Silencieux : aucune erreur, aucun message

Le moteur maintient deux vocabulaires pour les mêmes statistiques. Un vocabulaire historique — esprit, intelligence, adresse, chance — et le vocabulaire courant — savoir, agilite, flux. La fonction Ot() traduit le premier vers le second :

function Ot(o){
  if(!o) return {};
  const e = {...o};
  return e.esprit       != null && (e.savoir  = (e.savoir ??0)+e.esprit,       delete e.esprit),
         e.intelligence != null && (e.savoir  = (e.savoir ??0)+e.intelligence, delete e.intelligence),
         e.adresse      != null && (e.agilite = (e.agilite??0)+e.adresse,      delete e.adresse),
         e.chance       != null && (e.flux    = (e.flux   ??0)+e.chance,       delete e.chance),
         e
}

Le recyclage l'applique. La forge, non. Les deux fonctions sont voisines dans le même module :

// recyclage — passe par lu(), donc par Ot()
function Lx(o,e,t,i){ … const n = lu(o,t); for(const a of Object.keys(n)){ … } }
function lu(o,e){ return Ot(e ?? S[o]?.bonuses) }

// forge — lit les clés brutes de la définition d'objet
function Eo(o){
  const e = S[o];
  return …: Object.keys(e.bonuses).filter(t => bl(o,t)!=null && Zs(t)!=null)
}
function bl(o,e){ … const t = S[o]?.bonusRange?.[e]; return t ? t[1] : void 0 }

Deux modes de panne distincts

Mode A — clé historique des deux côtés. bonuses et bonusRange disent tous les deux chance ou intelligence. Ils sont cohérents entre eux, bl() répond correctement, mais aucune rune n'est enregistrée sous ces clés : la table xi indexe flux et savoir. C'est le test Zs(t)!=null qui rejette.

relic_whisper  bonuses {chance:14}       bonusRange {chance:[10,18]}       Eo() → []
mystic_ring    bonuses {intelligence:3}  bonusRange {intelligence:[2,4]}   Eo() → []

Mode B — désaccord entre les deux tables. bonuses dit adresse, bonusRange dit agilite. C'est bl() qui renvoie undefined.

veilleur_dagger  bonuses    {attack:16, adresse:34, force:12, crit:.14}
                 bonusRange {force:[9,15], agilite:[25,43], attack:[12,20], crit:[.1,.18]}
                 Eo()       → ["attack","force","crit"]     // agilité absente

Aggravation : l'objet disparaît de la liste

La construction de la liste latérale filtre les objets sans statistique forgeable :

gearCells(e){
  for(const i of this.player.inventory){
    …|| e==="upgrade" && Eo(i.id).length===0 || t.push({…})
  }
}

Conséquence : la Relique du Murmure et l'Anneau mystique ne sont pas affichés du tout dans l'onglet Forgemagie. Le joueur ne voit pas le message ui.runesmith.no_upgradable_stats — il ne voit rien. Cette chaîne est de fait du code mort pour ces objets.

Objets touchés — extrait haut niveau

Niv.ObjetStatistique perdueModeReste forgeable
100Colossus Blade mythiqueAgilitéBattack, force, vitalité, crit
100Watcher's Dagger mythiqueAgilité (34 — sa plus grosse statistique)Battack, force, crit
80Obsidian Glaive mythiqueAgilitéBattack, force, crit
80Bloodstone Dagger mythiqueAgilité (21–35)Battack, force, crit
60Cobalt Blade mythiqueFluxAagilité, attack, crit
60Opal Dagger épiqueFluxAagilité, attack, crit
20Relique du MurmureFluxAaucune — objet absent de la liste
10Anneau mystiqueSavoirAaucune — objet absent de la liste

Les cinq Reliques sont touchées. La liste complète des 36 objets figure en annexe A.

L'indice qui explique tout. La table Wg/Ug — 13 objets — utilise les clés courantes et ne présente aucun défaut. Les 65 autres objets ne sont jamais passés par cette table et ont conservé leurs clés historiques. Il s'agit d'une migration de données commencée puis interrompue, pas d'une erreur de logique.

Dommage collatéral

Pour les objets en mode A, la même absence de normalisation touche l'affichage : mi() cherche bonusRange['flux'] sur un jet déjà normalisé, alors que la table dit chance. Ces objets perdent donc aussi leur fourchette (min–max) et leur couleur de qualité de jet, en infobulle comme à l'hôtel des ventes. Le joueur ne peut pas juger si son arme a bien roulé.

Correctif proposé

Les deux moitiés sont nécessaires, corriger une seule laisse l'autre mode actif :

  1. Normaliser à la source. Appliquer Ot() à bonuses et à bonusRange au moment de la construction du catalogue, une fois pour toutes. C'est le correctif structurel : il supprime les deux modes et prévient toute récidive sur un futur objet.
  2. À défaut, en ceinture et bretelles : Eo() itère sur Object.keys(Ot(e.bonuses)) et bl() résout la clé via Ot() avant lecture.

Test de non-régression suggéré : pour chaque objet du catalogue, vérifier que Eo(id) retourne exactement les clés de Ot(bonuses) qui possèdent une rune. L'assertion tient en cinq lignes et couvre définitivement la classe de bug.

RS-02 Le poids de rune s'annule dans la formule de rendement Majeur

Statut
Confirmé dans le code client ; effet réel à confirmer côté serveur
Portée
Aperçu joueur certain ; économie réelle probable

La fonction de rendement du recyclage multiplie puis divise par le même terme :

function Ax(o,e,t,i){
  const s = xi[Zs(e) ?? ""];
  if(!s) return 0;
  const r = S[o],
        n = Math.max(1, Math.floor(r?.levelReq ?? 1)),
        a = e === "crit" ? Math.abs(t)*100 : Math.abs(t);
  return a <= 0 ? 0 : n*a*s.weight*(i.yieldPct/1e4)/(i.levelDiv*s.weight);
}

L'évaluation se faisant de gauche à droite, s.weight se simplifie exactement. Le rendement se réduit à niveau × valeur × 0,015, quelle que soit la rareté de la rune. Or le coût, lui, applique bien le poids (Rx). La rareté ne joue donc que d'un côté de l'équation.

Écart mesuré sur des objets réels du catalogue, en nombre d'objets à recycler pour financer une chaîne complète de la même statistique :

ObjetStatistiqueRecyclage rendChaîne coûteRatio
Amulette du Gardien (72)Flux 4549181 objet finance 2,7 chaînes
Ceinturon du Fossoyeur (66)Force 2424181 objet finance 1,3 chaîne
Capuche du Fossoyeur (58)Agilité 76183,0 objets par chaîne
Amulette du Gardien (72)Dégâts 669015,0 objets par chaîne
Amulette du Gardien (72)Critique 6,3 %754077,1 objets par chaîne
Anneau spectral (38)Critique 4,3 %2540270,0 objets par chaîne

Un facteur 730 entre le flux et le critique de l'Anneau spectral. En pratique : les statistiques principales passent OVER quasi gratuitement — un seul objet recyclé en finance deux ou trois montées complètes — pendant que le critique est hors d'atteinte.

L'or ne rééquilibre rien : les 58 000 or d'une chaîne sont identiques quelle que soit la statistique. Une chaîne de critique et une chaîne de vitalité coûtent le même or, pour un rapport de 1 à 30 en runes.

Argument en faveur de l'hypothèse « bug » plutôt que « choix ». En retirant uniquement le s.weight du dénominateur, l'échelle se resserre entre 0,4 et 2,8 objets par chaîne pour toutes les statistiques. Cette cohérence retrouvée suggère fortement que le facteur au dénominateur est un reliquat, et non une intention.

Note de portée : l'encart « Vous obtiendrez » du panneau de recyclage est calculé côté client par Lx(itemId, $x, rolled), donc avec cette formule. Si le serveur applique une formule corrigée, l'aperçu affiché au joueur est faux — ce qui reste un défaut à corriger, simplement pas au même endroit.

Correctif proposé

Trancher d'abord l'intention de design, puis aligner client et serveur sur la même constante :

  • Si la rareté doit peser sur le rendement : supprimer s.weight du dénominateur.
  • Si elle ne doit peser que sur le coût : supprimer s.weight du numérateur, et documenter que weight est un multiplicateur de coût seulement.

Dans les deux cas, écrire la formule sans terme simplifiable rend l'intention lisible à la relecture.

RS-03 La bêta ne permet pas d'exercer la fonctionnalité auditée Majeur

Statut
Observé en jeu — serveur Bêta I, 25 juil.
Portée
Exploitation / conditions de test

Les notes de version annoncent : « Pour cette bêta, tout le monde joue au niveau 100 : tu accèdes directement à la fin de partie et tu testes les nouveaux systèmes sans farmer. »

État constaté des deux personnages disponibles, tous deux niveau 100 :

PersonnageClasseÉquipement portéSacOrPV
BetaTestDuckArcanisteAucunVide01 / 1040
drsdSentinelleAucun25 consommables, aucun équipement182 / 1040

Or la fonctionnalité exige d'abord de l'équipement à recycler, puis 2 000 or pour le premier palier — le plus modeste. Un testeur qui se connecte pour la fenêtre de 72 h doit donc farmer avant de pouvoir toucher au système qu'on lui demande de tester, ce que la note de version présente précisément comme évité.

Point annexe à vérifier : les deux personnages apparaissent à 1 et 2 points de vie sur 1040 à la connexion, sans avoir combattu.

Correctif proposé

Doter les personnages de bêta d'un lot de départ : quelques pièces d'équipement de niveau 60–100 couvrant des statistiques variées (dont au moins une arme mythique et une Relique, qui sont justement les objets touchés par RS-01), une réserve de runes, et de quoi couvrir plusieurs chaînes complètes en or. Sans cela, la fenêtre de test ne produira que des retours sur l'interface, pas sur l'équilibrage.

RS-04 Rune de Précision : valeur marchande à 0 Moyen

Statut
Confirmé — donnée de catalogue

La signature du constructeur d'objets est T(id, nom, rareté, kind, icône, stack, sell, description). Les valeurs marchandes des runes suivent une série cohérente avec leur poids — jusqu'à la dernière :

rune_vigor      poids 0.5   sell 1
rune_might      poids 1     sell 2
rune_ward_*     poids 3     sell 3
rune_power      poids 5     sell 6
rune_precision  poids 30    sell 0   ← rupture de série

La conséquence n'est pas seulement cosmétique. Le prédicat de vendabilité est Pu(o) = fn(o) > 0, et il filtre la grille du marchand :

const t = this.player.inventory.filter(i => { if(!Pu(i.id)) return !1; … });

La rune la plus rare du jeu n'apparaît donc pas dans la liste de vente au PNJ : elle est invendable. L'hôtel des ventes n'est pas affecté — sourceItems() ne filtre que sur quest — donc l'affirmation « Toutes s'échangent librement à l'hôtel des ventes » des notes de version reste vraie. En revanche « la rare Rune de Précision […] vaut plus » est contredite par la donnée.

Correctif proposé

Attribuer une valeur cohérente avec la série. L'extrapolation du rapport poids/valeur des quatre autres paliers place la Rune de Précision autour de 30. Si le 0 est volontaire et signifie « non vendable au PNJ », l'exprimer par un champ dédié plutôt que par un prix nul, sans quoi l'intention est indistinguable d'un oubli.

RS-05 Le gain de critique est invisible à l'écran Moyen

Statut
Confirmé — affichage client

Le critique est stocké en fraction (0,063 pour 6,3 %) et formaté en pourcentage entier :

const h = r === "crit",
      p = b => h ? `${Math.round(b*100)}%` : String(Math.round(b));

Mais le pas de progression vaut 8 % du maximum de base, soit un demi-point de pourcentage sur les objets réels. Deux défauts se cumulent.

a) L'arrondi masque la progression. Séquence complète sur l'Anneau funéraire (max 0,071, pas +0,006) :

0.057 → "6%"   0.063 → "6%"   0.069 → "7%"   0.075 → "8%"   0.081 → "8%"

Le joueur paie 6 000 or et 90 Runes de Précision pour un palier 2 qui affiche 6 % → 6 %. Sur la Relique d'Ambre, trois paliers sur quatre sont invisibles.

b) Le chiffre du gain n'est pas formaté. Le bandeau central utilise la valeur brute, sans passer par p() :

${m > 0 ? `<div class="rd-rs-ba-gain">${F(l("ui.runesmith.stat_gain", {n: m}))}</div>` : ""}

La chaîne ui.runesmith.stat_gain valant +{n}, l'écran affiche +0.006 au lieu de +0,6 pt. Le message de succès (applyUpgradeOutcome) reproduit le même arrondi entier.

Correctif proposé

Afficher le critique avec une décimale (6,3 % → 6,9 %) et faire passer le gain par le même formateur que les valeurs avant/après. Le pas étant par construction inférieur à un point de pourcentage, un affichage entier ne peut structurellement pas rendre compte d'un palier.

RS-06 La progression Runiste ne tient pas sa promesse Moyen

Statut
Confirmé — design / communication

Le texte affiché dans le panneau des métiers (ui.jobs.runist_level_b) annonce :

« Recycler et perfectionner rapportent de l'XP de Runiste. Un niveau plus élevé débloque des paliers de forgemagie supérieurs. »

Le panneau affiche Niveau Runiste {n} / 200 avec une barre calculée sur e/200*100. Or les prérequis de la table de forge sont jobReq: 1, 1, 5, 12, 20 : le dernier palier — le seul comportant un risque de destruction — est débloqué au niveau 20.

La courbe d'XP des métiers d'artisanat est 4n² par niveau, soit en cumulé :

JalonXP cumuléePart du total
Niveau 20 — dernier palier débloqué9 8800,09 %
Niveau 200 — plafond du métier10 586 800100 %

Autrement dit, 0,09 % de la progression du métier débloque 100 % du contenu mécanique. Par ailleurs, jobLevel("runesmith") n'apparaît que quatre fois dans tout le bundle : l'affichage du badge de métier, deux notifications de montée de niveau, et le test G < b.jobReq. Rien d'autre ne dépend du niveau — ni bonus de réussite, ni réduction de coût.

Deux lectures possibles, à trancher côté design. Soit il manque un palier supplémentaire — l'interface l'annonce déjà : ui.runesmith.max_tier_reached dit « Palier maximum atteint · le palier exo arrive bientôt » et exo_soon_body évoque un palier ultime brûlant du $VALORA. Soit le plafond du métier devrait être aligné sur son contenu réel, autour de 20–25.

Correctif proposé

À court terme, reformuler la phrase pour ne plus promettre une progression qui s'arrête à 10 % de la barre. À moyen terme, donner un effet continu au niveau de métier — par exemple quelques points de base de réussite ou une réduction du coût en runes par tranche de niveaux — de sorte que la barre affichée corresponde à un gain réel.

RS-07 Confirmations asymétriques sur les actions destructrices Moyen

Statut
Confirmé — UX

Deux gardes différentes, aucune des deux alignée sur le coût réel de l'erreur.

// recyclage : confirmation à partir de « rare » seulement
onRecycleClick(e){ this.busy || (St[e.def.rarity] >= 2 ? this.openRecycleConfirm(e) : this.doRecycle(e)) }

// forge : confirmation seulement si l'objet peut être détruit
onUpgradeClick(e,t,i){ this.busy || !i || (i.def.destroyChanceBps > 0 ? this.openUpgradeConfirm(e,t,i) : this.doUpgrade(e,t)) }

Conséquences :

Correctif proposé

Indexer la confirmation sur la valeur en jeu plutôt que sur la rareté ou le seul risque de destruction : confirmer dès qu'une tentative peut échouer (paliers 2 à 4) et pour tout recyclage. Un simple seuil en or ou une case « ne plus demander pour cet objet » suffit à ne pas alourdir le geste répétitif.

RS-08 Notes de version : noms de runes inexistants ou trompeurs Mineur

La note annonce : « les Runes de Puissance, de Protection et la rare Rune de Précision sont plus rares et valent plus ».

Nom citéObjet réelÉcart
Rune de Puissancerune_might — Force, commune, poids 1Ce nom existe en jeu, mais désigne la rune la plus abondante. Le texte visait probablement rune_power, nommée « Rune de Frappe ».
Rune de ProtectionN'existe pasLes runes de résistance s'appellent « Rune de Garde Terre / Flamme / Glace / Foudre ».
Rune de Précisionrune_precision — rare, poids 30Correct, mais valeur marchande à 0 (voir RS-04).

Un joueur suivant la note à la lettre cherchera « Rune de Puissance », trouvera la rune commune de Force, et en conclura qu'elle est rare. Aligner le texte sur les noms réellement affichés en jeu.

RS-09 Erreur trompeuse quand l'objet n'a pas d'instanceId Mineur

La liste latérale accepte les objets sans instance (gearCells ne teste pas instanceId), mais la forge les refuse et réutilise le message d'indisponibilité du service :

if(!this.econ?.authoritative() || e.instanceId == null){
  w.cue("ui_error"),
  this.setStatus(l("ui.runesmith.err_disabled"), "bad");   // « L'Atelier des Runes est momentanément indisponible. »
  …
}

Un objet listé mais non instancié produit donc un message annonçant une panne de service. Soit exclure ces objets de la liste, soit leur donner un message spécifique.

RS-10 Le poids 0.5 de la Rune de Vigueur est entièrement inopérant Mineur

La Rune de Vigueur est la seule à porter un poids inférieur à 1. Ce poids n'a d'effet nulle part :

La vitalité coûte donc exactement le même nombre de runes qu'une statistique commune de poids 1. Soit l'écrêtage doit disparaître, soit le poids doit valoir 1 — en l'état la donnée exprime une intention que le code n'applique pas. À traiter avec RS-02, dont il est le corollaire.

RS-11 Code et chaînes résiduels Mineur

RS-12 Détection OVER impossible sur une fourchette fixe Latent

Statut
Non déclenché aujourd'hui — 235 fourchettes vérifiées, aucune n'est plate

La fonction qui qualifie un jet, et donc décide de l'affichage du marqueur OVER, sort avant d'avoir testé le dépassement :

function Fm(o,e,t){          // o = valeur du jet, e = min, t = max
  if(!(t > e)) return "none";   // sortie anticipée
  if(o > t) return "exo";              // test OVER — jamais atteint si min == max
  if(o >= t) return "perfect";
  const i = (o-e)/(t-e);
  return i >= 2/3 ? "high" : i >= 1/3 ? "mid" : "low";
}

Le jour où un objet à statistique garantie est ajouté — fourchette [5,5] —, la forge fonctionnera mais le marqueur OVER restera invisible partout : sac, hôtel des ventes, échange. Le symptôme sera silencieux et difficile à rattacher à sa cause. Déplacer le test o > t avant la garde clôt le sujet définitivement.

5Annexes

Annexe A — Les 36 objets touchés par RS-01

Reconstruction du catalogue final après application du pipeline de fusion du bundle. « Mode A » : clé historique cohérente des deux côtés, rejet par Zs(). « Mode B » : désaccord entre bonuses et bonusRange, rejet par bl().

Niv.RaretéEmplacementObjetPerduReste forgeable
100mythiquearmeColossus Bladeagilitéattack, force, vitalité, crit
100mythiquearmeWatcher's Daggeragilitéattack, force, crit
80mythiquearmeObsidian Glaiveagilitéattack, force, crit
80mythiquearmeBloodstone Daggeragilitéattack, force, crit
60mythiquearmeCobalt Bladefluxagilité, attack, crit
60épiquearmeOpal Daggerfluxagilité, attack, crit
40mythiquearmeLame du Sermentagilitéattack, force, vitalité, crit
40mythiquearmeLame du Titanagilitéattack, force, crit
32épiquearmeGlaive doréagilitéattack, force, crit
30épiquearmeTranchant d'améthystefluxagilité, attack, crit
28épiquearmeDague sanglanteagilitéattack, force, crit
22épiquebouclierBouclier radieuxsavoirvitalité, resFlamme, resGlace
22épiquebottesJambières du seigneuragilitévitalité
22épiquearmeLame d'ébèneagilitéattack, force, crit
20épiqueamuletteAmulette d'émeraudesavoirvitalité
20épiquecapeCape d'ombreagilitévitalité
20reliquerelic2Relique d'Ambreagilitéforce, crit
20reliquerelic3Relique du Glas Noirsavoir, fluxvitalité, force, agilité
20reliquerelic4Relique du Veilleurfluxagilité
20reliquerelic5Relique du Trône Brisésavoirforce
20reliquerelic6Relique du Murmurefluxaucune — absente de la liste
20rarearmeÉpée d'argentfluxattack, crit
16rarebottesBottes du chasseuragilitéforce
15rareamuletteAmulette d'espritsavoirvitalité
14rareceintureCeinture mystiquesavoirvitalité
12peu communbottesBottes de l'Apprentiagilitévitalité
11peu communbottesBottes d'éclaireuragilitévitalité
10rareanneauAnneau mystiquesavoiraucune — absent de la liste
8rareanneauAnneau d'ossavoirvitalité
8peu communcasqueBéguin de l'Apprentiagilitévitalité
8peu communamuletteTalisman des boissavoirvitalité, agilité
7rarecasqueChapeau ensorcelésavoirvitalité
7peu communcapeCape de soie Azurineagilitévitalité
6peu communcapeCape du voyageuragilitévitalité
6communbottesBottes de voyageagilitévitalité
6peu communcapeCape de l'Apprentisavoirvitalité

Annexe B — Économie détaillée par objet

Rendement du recyclage et coût d'une chaîne complète (paliers 1 à 4), calculés avec les formules du bundle sur les valeurs de référence de Wg.

ObjetStatistiqueValeurRendementCoût chaîneRatio
Amulette du Gardien
niv. 72, mythique
Vitalité2325181 objet = 1,4 chaîne
Flux4549181 objet = 2,7 chaînes
Dégâts669015,0 objets / chaîne
Critique6,3 %754077,1 objets / chaîne
Anneau funéraire
niv. 62, épique
Vitalité1211181,6 objet / chaîne
Force3129181 objet = 1,6 chaîne
Savoir87182,6 objets / chaîne
Critique5,7 %5540108,0 objets / chaîne
Ceinturon du Fossoyeur
niv. 66, épique
Vitalité2525181 objet = 1,4 chaîne
Force2424181 objet = 1,3 chaîne
Dégâts669015,0 objets / chaîne
Anneau spectral
niv. 38, mythique
Vitalité106183,0 objets / chaîne
Agilité2414181,3 objet / chaîne
Force63186,0 objets / chaîne
Critique4,3 %2540270,0 objets / chaîne

Annexe C — Séquences d'affichage du critique

Valeur interne et rendu à l'écran, pour les quatre objets du catalogue portant du critique dans une fourchette. Les paliers dont l'affichage ne bouge pas sont ceux où le joueur ne voit aucun retour de son investissement.

ObjetMaxPasBase → palier 1 → 2 → 3 → 4
Anneau spectral0,054+0,0044% → 5% → 5% → 6% → 6%
Anneau funéraire0,071+0,0066% → 6% → 7% → 8% → 8%
Amulette du Gardien0,079+0,0066% → 7% → 8% → 8% → 9%
Relique d'Ambre0,040+0,0033% → 3% → 4% → 4% → 4%