fm — Forgemagie¶
API forgemagie MoonBot Lua : améliorer un item, runes, scripts d'FM automatique.
20 fonctions dans ce namespace.
Index¶
Constantes slotsfm.isOpenfm.currentSlot / currentSlotNamefm.openfm.leavefm.canFusefm.putItemByUid / putRuneByUid / removeItemByUidfm.putItem / removeItemfm.putRunesForStatfm.clearSlotsfm.fuseOnce / fuseAllfm.waitForResultfm.lastBatch / successRatefm.itemEffectsfm.itemStatfm.slotRunesfm.availableRunesfm.runeStatfm.fuseUntilExemple — monter un métier de forgemagie (Rétro)
Référence¶
Constantes slots¶
Skill IDs des ateliers FM (163..169). Le module fm concerne les ateliers solo. Pour la FM cooperative (artisan/client), utiliser craft.forgemagicAction et craft.getState().cooperative_fm ; voir docs/forgemagie-cooperative.md.
fm.isOpen¶
returns boolean
True si un atelier FM est ouvert (exchange type 3 + skill 163..169).
fm.currentSlot / currentSlotName¶
returns number | string | nil
Skill id ou nom ("bottes", "amulette"...) de l'atelier courant.
fm.open¶
returns boolean
Ouvre un atelier FM sur la map courante. slot = fm.BOTTES..fm.AMULETTE ou "bottes".."amulette". Attend ECK3 (15s max).
fm.leave¶
returns boolean
Ferme l'atelier (envoie EV).
fm.canFuse¶
returns boolean
True si un objet ET une rune (ou potion de forgemagie) sont posés dans l'atelier : la condition du client officiel pour fusionner. Devient false après la fusion qui consomme la dernière rune posée : le serveur ne remet alors pas l'objet dans l'atelier.
fm.putItemByUid / putRuneByUid / removeItemByUid¶
returns boolean
Place/retire un objet ou une rune par uid (EMO+/EMO- brut). Sur Rétro, poser la pile entière de runes, comme le client officiel : fm.putRuneByUid(rune.uid, rune.quantity). Chaque fusion n'en consomme qu'une, puis le serveur remet lui-même l'objet et le reste de la pile dans l'atelier. L'objet change d'uid à chaque fusion : relire l'inventaire plutôt que réutiliser un uid gardé d'avant la fusion.
fm.putItem / removeItem¶
returns boolean
Place/retire par template id (resout l'uid via l'inventaire).
fm.putRunesForStat¶
returns number
Auto-selection : trouve la meilleure rune dispo ciblant statName et en place count. Ex: fm.putRunesForStat("vitalite", 50). Retourne le nombre pose (0 si aucune rune trouvee). Chaque fusion consomme une des runes posées : avec count = 1, seule la première fusion passe (voir fm.fuseOnce).
fm.clearSlots¶
returns boolean
Retire tous les items et runes de l'atelier.
fm.fuseOnce / fuseAll¶
returns boolean
fuseOnce lance une fusion (EK) : une rune posée est consommée et le serveur recrée l'objet avec un nouvel uid. Comme le client officiel, elle renvoie false sans rien envoyer si l'atelier n'a pas à la fois un objet et une rune (« Fusion non envoyee » dans les logs) : c'est le cas après la fusion qui consomme la dernière rune posée, le serveur ne remettant alors pas l'objet. fuseAll = « Fusionner tout » du client : une fusion puis une boucle côté serveur pour les n-1 suivantes (n = runes posées par défaut, pas de boucle en dessous de 3). Voir l'exemple « monter un métier de forgemagie ».
fm.waitForResult¶
returns table | nil
Attend le résultat d'une fusion. Retourne {successes, total, failures, success, impossible} ou nil si timeout (30s par defaut). success = fusion réussie (EcK) ; impossible = fusion refusée par le serveur (EcEI, « Cette recette ne donne rien » : objet ou rune absent, rien consommé, pas d'XP, atelier vidé ; « Fusion impossible » dans les logs). Un échec normal (EcEF) consomme la rune. Sans success/impossible (worker ancien), vérifier que inventory.countItem(runeId) a baissé.
fm.lastBatch / successRate¶
returns table / number
lastBatch()→{successes, total, failures}. successRate()→% (0..100) de la derniere batch.
fm.itemEffects¶
returns table
Parse le jet actuel de l'objet pose (la pièce qui n'est ni une rune ni une potion de forgemagie, même si une rune seule est posée avant elle). Chaque entree: {id, label, value, max}. Labels normalises: "vitalite", "force", "intelligence", "sagesse", "chance", "agilite", "pa", "pm", "portee", "cc", "dommages", "prospection", "soins", "invocations", "res_per_feu", etc.
fm.itemStat¶
returns number
Valeur actuelle d'un stat precis sur l'objet pose. Accepte les alias : "vitalite"/"vita"/"vi", "force"/"fo", "intelligence"/"int"/"ine", etc. Retourne 0 si le stat est absent.
fm.slotRunes¶
returns table
Runes actuellement dans l'atelier. Chaque entree: {uid, name, quantity, stat?, perFuse?}.
fm.availableRunes¶
returns table
Runes disponibles dans l'inventaire, filtrables par stat cible. Entree: {uid, templateId, name, quantity, stat?, perFuse?}.
fm.runeStat¶
returns table | nil
Decode une rune par son nom. Ex: fm.runeStat("Rune Pa Vi") → {stat="vitalite", perFuse=1}. Retourne nil si inconnue.
fm.fuseUntil¶
returns table
Fusionne en boucle jusqu'a ce qu'un stat atteigne target (ou manque de runes). Retourne {reached: bool, attempts: number, final: number}. maxAttempts par defaut = 500. Poser avant l'objet et la pile entière de runes : la boucle s'arrête dès que l'atelier n'a plus d'objet ou de rune.
Exemple — monter un métier de forgemagie (Rétro)¶
-- Atelier ouvert (fm.open), objet dans le sac, runes dans l'inventaire.
local OBJET, RUNE = 2411, 1519 -- Coiffe du Bouftou, Rune Fo
local function dansAtelier(templateId)
for _, it in ipairs(exchange.myItems()) do
if it.id == templateId then return it.quantity end
end
return 0
end
local function objetDuSac(templateId)
for _, it in ipairs(inventory.list()) do
if it.templateId == templateId and it.position < 0 then return it end
end
end
for _ = 1, 50 do
if dansAtelier(OBJET) == 0 then
local objet = objetDuSac(OBJET)
if not objet then break end
fm.putItemByUid(objet.uid) -- nouvel uid après chaque fusion
end
local rune = inventory.findByTemplate(RUNE)
if not rune then break end
if dansAtelier(RUNE) == 0 then
fm.putRuneByUid(rune.uid, rune.quantity) -- toute la pile
end
local avant = inventory.countItem(RUNE)
fm.fuseOnce()
fm.waitForResult(10000)
global.delay(global.random(350, 700))
if inventory.countItem(RUNE) >= avant then
global.printError("Fusion refusée : aucune rune consommée")
break
end
end
50 fusions, une rune consommée à chaque fois, comme dans le client officiel : la pile entière est posée une fois, puis le serveur remet lui-même l'objet (nouvel uid) et le reste de la pile après chaque fusion. Pour alterner deux runes, retirer la pile posée avec fm.removeItemByUid(uid, quantite) puis poser l'autre. L'XP de métier ne vient que des fusions réussies. Un « Craft echoue » répété sans rune consommée ni XP est un refus du serveur (objet ou rune absent de l'atelier), pas un objet « saturé » : l'exemple s'arrête dans ce cas.