Aller au contenu

map — Carte & Déplacement

API carte et déplacement MoonBot Lua : se déplacer, changer de map, pathfinding, zaaps, cellules.

62 fonctions dans ce namespace.

Index


Référence

map.currentMap

map.currentMap()

returns string

Coordonnees "x,y".


map.currentMapId / id

map.currentMapId() / map.id()

returns number

ID de la map.


map.x / y

map.x() / map.y()

returns number

Coordonnees x et y.


map.dimensions / width / height

map.dimensions() / map.width() / map.height()

returns table {width, height} / number / number

Dimensions de la map actuelle. dimensions() renvoie une table {width, height}. width()/height() renvoient directement le nombre. Standard Retro = 15x17, mais les maps non-standard sont gerees (valeurs lues depuis le SWF).


map.currentCell / cellId

map.currentCell() / map.cellId()

returns number

Cellule actuelle.


map.currentArea / currentSubArea

map.currentArea() / map.currentSubArea()

returns string

Zone et sous-zone.


map.onMap

map.onMap(coords: string | number)

returns boolean

Verifie si sur la map ("x,y" ou ID).


map.changeMap

map.changeMap(direction: string)

blocking · returns boolean

Change de map : "right", "left", "top", "bottom".


map.moveToCell

map.moveToCell(cellId: number)

blocking · returns boolean

Deplace vers une cellule (attend l'arrivee).


map.gather

map.gather()

blocking · returns boolean

Recolte toutes les ressources.


map.gatherResource

map.gatherResource(cellId: number)

blocking · returns boolean

Recolte la ressource de la cellule cible avec le sequenceur dedie (portee de l'outil, approche et confirmation serveur). Retourne true uniquement apres confirmation de la recolte ; false si la ressource est indisponible, refusee ou si aucune confirmation n'arrive sous 30 s.


map.fight

map.fight()

blocking · returns boolean

Attaque le groupe de monstres le plus proche.


map.moveToward

map.moveToward(x: number, y: number)

blocking · returns boolean

Un pas de map vers les coordonnees cibles.


map.moveTowardMap

map.moveTowardMap(mapId: number)

blocking · returns boolean

Un pas de map vers la map cible.


map.worldDistance

map.worldDistance(x: number, y: number)

returns number

Distance en maps vers les coordonnees (-1 si inaccessible).


map.waitForMapChange

map.waitForMapChange(timeout?: number)

blocking · returns boolean

Attend un changement de map.


map.monsterGroups

map.monsterGroups()

returns table of {id: number, cellId: number, name: string, level: number, count: number, monsters: table of {id: number, name: string, level: number}}

Groupes de monstres sur la map. name = noms des monstres, level = niveau du groupe, count = nombre de monstres, monsters = détail de chaque monstre (template ID, nom, niveau individuel).


map.fightGroup

map.fightGroup(groupId: number)

blocking · returns boolean

Attaque un groupe de monstres spécifique par son ID (récupéré via map.monsterGroups()). Bloquant : attend la fin du combat. Retourne true si victoire, false si défaite ou groupe introuvable.


map.players

map.players()

returns table of {id: number, cellId: number, name: string, level: number}

Joueurs visibles sur la map.


map.npcs

map.npcs()

returns table of {id: number, cellId: number, name: string, templateId: number}

PNJ sur la map. id = ID acteur, templateId = ID du modele PNJ.


map.getActors / getActorById

map.getActors() / map.getActorById(id: number)

returns table / table | nil

Tous les acteurs (monstres + joueurs + PNJ) : {id, cellId, name, type}. type = 'monster'/'player'/'npc'.


map.getResources

map.getResources()

returns table of {cellId: number, gfxId: number, name: string}

Ressources recoltables sur la map.


map.interactiveObjects

map.interactiveObjects()

returns table of {cellId: number, gfxId: number}

Objets interactifs (ateliers, portes, etc).


map.useInteractive

map.useInteractive(cellId: number, skillIndex?: number)

blocking · returns boolean

Utilise un objet interactif avec deplacement automatique. Le trajet cible la cellule exacte de l'objet ; le serveur peut confirmer un arret sur une cellule adjacente valide. skillIndex: 1=premier skill (defaut), 2=deuxieme, etc. Pour une recolte, utiliser de preference map.gatherResource(). Pour un menu (zaap, atelier, porte, enclos), l'action peut reussir sans evenement GatherComplete : le boolean generique ne confirme donc pas toujours l'ouverture et peut retourner false apres une attente allant jusqu'a 30 s. Preferer l'API specialisee lorsqu'elle existe.


map.houseInstances

map.houseInstances()

returns table of {houseId: number, cellId: number, instanceId: number, owner: string, locked: boolean, price: number}

Maisons annoncees par le serveur sur la carte actuelle, avec leur porte et identifiant d'instance. Peut retourner une table vide avant reception des informations. Plusieurs entrees peuvent partager la meme cellule : choisir explicitement l'instance souhaitee. houseId et instanceId sont differents ; utiliser instanceId pour enterHouse. locked indique une serrure, sans garantir que votre personnage devra saisir un code.


map.enterHouse

map.enterHouse(cellId: number, code?: string, instanceId?: number)

blocking · returns boolean, reason: string

Entre dans une maison de la carte actuelle avec approche automatique de la porte et saisie du code seulement si le serveur le demande. code : chaine de 1 a 8 caracteres ASCII parmi 0-9 et _, avec au moins un chiffre, par exemple "001234" ; nil ou chaine vide pour tenter sans code. Les nombres Lua sont refuses pour ne pas perdre les zeros initiaux. Si le code comporte une case vide entre des chiffres, utiliser _ a cette position (par exemple "01_2") ; les tirets et les chaines composees uniquement de _ sont refuses. instanceId peut etre omis uniquement si une seule instance est annoncee pour cette porte ; sinon fournir celle de houseInstances(). Attente bornee a 30 s. true, "ok" signifie qu'une nouvelle carte a ete recue, chargee et que le personnage y est apparu, et que le serveur a confirme l'identite de la maison choisie. La fermeture de la fenetre de code ne suffit pas. false est accompagne d'une raison ; timeout signifie resultat non confirme, verifier la carte avant de reessayer. Aucun nouvel essai de code automatique. L'arret du script et la deconnexion interrompent l'attente.


map.openHouseChest

map.openHouseChest(cellId: number, code?: string)

blocking · returns boolean, reason: string

Ouvre un coffre de maison sur la carte actuelle (competence 104), avec approche automatique et saisie du code seulement si le serveur le demande. Etre deja dans la maison, sur la carte du coffre ; aucun instanceId ni proprietaire n'est necessaire. code : chaine de 1 a 8 caracteres ASCII parmi 0-9 et _, avec au moins un chiffre ; nil ou chaine vide pour essayer sans code. Les zeros initiaux et les cases vides internes sont conserves, par exemple "001234" ou "01_2" ; les nombres Lua sont refuses. Attente bornee a 30 s. true, "ok" confirme que la fenetre de stockage a ete ouverte et son contenu charge, meme si le coffre est vide. La fermeture du dialogue de code seule ne suffit pas. false est accompagne d'une raison et n'entraine aucun nouvel essai automatique. L'arret du script, la deconnexion, un changement de carte ou de fenetre interrompent l'attente. Apres succes, utiliser exchange.storageItems(), storageKamas(), putItem/getItem et exchange.leave() pour le stockage courant. npc.openCoffre() concerne uniquement le donjon forgeron.


Coffre de maison : exemple

local chestCell = 120 -- remplacer par la cellule de votre coffre
local ok, reason = map.openHouseChest(chestCell, nil)
if not ok then error("Ouverture non confirmee : " .. reason) end
print("Contenu charge : " .. #exchange.storageItems() .. " piles")
-- Transferts possibles dans le coffre courant :
-- exchange.putItem(templateId, quantity)
-- exchange.getItem(templateId, quantity)
-- exchange.leave()

Executer sur la carte interieure du coffre, apres une entree confirmee avec map.enterHouse() et les deplacements interieurs eventuellement necessaires. La cellule 120 est un exemple, pas une valeur universelle. Remplacer nil par le code connu du coffre, sous forme de chaine ; il peut etre different de celui de la porte. Ne pas afficher ou publier ce code. Le succes confirme le chargement du coffre ; les transferts exchange gardent leurs propres regles de confirmation. En cas d'echec, arreter cette sequence et verifier le contexte avant de reessayer.


Coffre de maison : resultats

local ok, reason = map.openHouseChest(cellId, code)

Raisons usuelles : code_required (code demande mais absent), wrong_code (code refuse), invalid_code / code_too_long (format/longueur), not_chest (pas de coffre sur cette cellule), no_path (coffre inaccessible), action_rejected (ouverture refusee), busy / not_ready (personnage indisponible), stale_map / map_changed (carte modifiee), unexpected_exchange (autre fenetre recue), exchange_closed (stockage ferme avant chargement), interrupted / cancelled / disconnected (tentative interrompue), timeout (ouverture ou contenu non confirme). Aucun nouvel essai de code automatique.


Entree maison : exemple

local doorCell = 123 -- remplacer par la cellule de votre porte
local selected = nil
for _, house in ipairs(map.houseInstances()) do
    if house.cellId == doorCell then
        if selected then error("Plusieurs maisons : choisir un instanceId") end
        selected = house
    end
end
if not selected then error("Informations de maison indisponibles") end
local ok, reason = map.enterHouse(doorCell, nil, selected.instanceId)
if not ok then error("Entree non confirmee : " .. reason) end

Exemple sans code. Pour une maison protegee dont vous connaissez le code, remplacer nil par une chaine telle que "001234". Ne pas afficher le code dans les logs ni le publier dans un script partage. Pour plusieurs instances, selectionner celle souhaitee dans houseInstances() ; ne pas choisir arbitrairement la premiere.


Entree maison : resultats

local ok, reason = map.enterHouse(cellId, code, instanceId)

Raisons usuelles : code_required (code demande mais absent), wrong_code (code refuse), invalid_code / code_too_long (format/longueur), instances_unavailable (liste non recue), instance_required (plusieurs maisons), invalid_instance / not_house (cible incorrecte), no_path (porte inaccessible), action_rejected (entree refusee), unexpected_map (destination differente de la maison choisie), busy / not_ready (personnage indisponible), stale_map / interrupted / cancelled / disconnected (contexte interrompu), timeout (confirmation non recue). Ne pas enchainer automatiquement les tentatives apres un refus ou un timeout.


Maisons et coffres dans le MapViewer

-- Porte : clic droit ou appui long > Entrer dans la maison
-- Coffre : clic, ou clic droit / appui long > Ouvrir le coffre

Le panneau de porte affiche les instances, leur proprietaire et la serrure. Choisir une instance si necessaire, puis saisir le code optionnel pour entrer. Sur la carte interieure, cliquer sur le coffre ouvre un panneau avec son propre code optionnel, sans selection d'instance. Les codes sont masques et ne sont pas memorises par l'interface. Les erreurs et interruptions restent visibles ; la fenetre ne se ferme sur un succes qu'apres confirmation. Le contenu du coffre utilise ensuite le panneau Banque / coffre, avec les operations de stockage existantes.


Limites des interactifs generiques

-- map.useInteractive / map.enterHouse / map.openHouseChest

Utiliser map.enterHouse() pour la porte et son instance, puis map.openHouseChest() pour un coffre sur la carte interieure. Ces appels gerent la demande de code et attendent la confirmation adaptee ; map.useInteractive() ne fournit pas ces garanties. Achat, vente et changement de serrure restent hors de cette API. Les enclos multi-instance ne sont pas couverts ; utiliser le Client natif pour ces variantes.


map.isWalkable / getWalkableCells

map.isWalkable(cellId) / map.getWalkableCells()

returns boolean / table

Verifie si une cellule est marchable / liste des cellules marchables.


map.getX / getY

map.getX(mapId) / map.getY(mapId)

returns number

Coordonnees d'une map depuis son ID (game data).


map.hasChanged

map.hasChanged()

returns boolean

True si la map a change. Se remet a false automatiquement.


map.openZaap / openZaapi

map.openZaap() / map.openZaapi()

blocking · returns boolean

Approche le zaap/zaapi avec le pathfinding officiel, ouvre son menu et attend la liste des destinations. Retourne true quand la liste est recue, false si aucune liste n'arrive sous 10 s.


map.useZaap / useZaapi

map.useZaap(mapId) / map.useZaapi(mapId)

blocking · returns boolean

Selectionne une destination dans le menu deja ouvert (WU pour un zaap, Wu pour un zaapi) et attend le changement de carte. Ces fonctions n'approchent pas de l'objet et ne l'ouvrent pas : appeler openZaap()/openZaapi() juste avant. En cas de timeout de 10 s, useZaapi() retourne false tandis que useZaap() leve actuellement une erreur Lua ; utiliser pcall pour un script tolerant aux echecs.


Sequence zaap recommandee

if not map.openZaap() then return false end
local ok, result = pcall(map.useZaap, mapId)
return ok and result == true

blocking · returns boolean

Enchainement autonome et tolerant aux echecs recommande. Pour un zaapi, utiliser openZaapi() puis useZaapi(mapId).


map.getZaapDestinations

map.getZaapDestinations()

returns table of {map_id: number, cost: number, name: string, area: string, x: number, y: number}

Liste des destinations disponibles apres openZaap() ou openZaapi().


map.saveZaap

map.saveZaap()

Sauvegarde le zaap actuel.


map.getPrisms

map.getPrisms()

returns table of {id: number, cellId: number, level: number, name: string, alignment: number, alignmentName: string, usable: boolean, reason: string?}

Prismes d'alignement presents sur la carte (sprite -10). alignment : 1 = Bonta, 2 = Brakmar. usable applique la regle du client officiel : le menu « Utiliser » n'est actif que pour un personnage du meme alignement que le prisme, jamais pour un neutre ni sous forme de mutant, et hors combat. reason explique un refus.


map.openPrism

map.openPrism(actorId?: number)

blocking · returns boolean, string?

Clique « Utiliser » sur le prisme (GA512) et attend sa fenetre de teleportation (Wp). Activer d'abord les ailes avec character.setWings(true) : le serveur peut refuser GA512 sans elles (Im1144). Sans actorId, prend le prisme de la carte. Comme dans le client officiel, aucun deplacement n'est necessaire. Retourne true quand la liste est recue, sinon false et la raison (alignement, combat, fenetre deja ouverte, pas de reponse en 10 s). Tant que la fenetre est ouverte, les deplacements sont refuses : appeler map.closePrism() si l'on ne se teleporte pas.


map.getPrismDestinations

map.getPrismDestinations()

returns table of {map_id: number, cost: number, attack_near: boolean, name: string, area: string, x: number, y: number} or nil

Destinations de la fenetre du prisme ouverte (nil si elle est fermee). attack_near vaut true quand le client affiche l'icone « prisme attaque a proximite ».


map.usePrism

map.usePrism(mapId: number, actorId?: number)

blocking · returns boolean, string?

Teleportation complete par prisme : ouvre la fenetre si besoin, verifie que la carte est proposee et que les kamas suffisent (comme le client), envoie Wp puis attend l'arrivee sur cette carte (10 s). En cas d'echec, referme la fenetre qu'elle a ouverte et retourne false avec la raison. Activer les ailes avant l'appel avec character.setWings(true) : sinon le serveur peut refuser des l'ouverture (Im1144), et sa raison est renvoyee aussitot.


map.closePrism

map.closePrism()

returns boolean

Ferme la fenetre du prisme (Ww). Retourne false si aucune n'est ouverte.


Exemple — se teleporter par prisme

-- Prisme de la carte -> destination en (x, y), si le prisme la propose.
local function prismeVers(x, y)
  local prisme = map.getPrisms()[1]
  if not prisme then return false, "aucun prisme sur cette carte" end
  if not prisme.usable then return false, prisme.reason end
  local ailesOk, raisonAiles = character.setWings(true)
  if not ailesOk then return false, raisonAiles end
  local ok, raison = map.openPrism(prisme.id)
  if not ok then return false, raison end
  for _, d in ipairs(map.getPrismDestinations() or {}) do
    if d.x == x and d.y == y then
      return map.usePrism(d.map_id)
    end
  end
  map.closePrism()
  return false, "destination absente de la liste du prisme"
end

blocking · returns boolean, string?

Active les ailes et teleporte vers la carte (x, y) depuis le prisme de la carte courante, si l'alignement du personnage le permet.


map.sendEmote / sit

map.sendEmote(emoteId) / map.sit()

Envoie une emote. sit() = emote 1.


Deplacement et combat — aliases

map.moveTo(cellId) / tryFight() / tryFightGroup(groupId) / tryFightGroupOnCell(cellId)

returns boolean

moveTo est un alias de moveToCell. Les fonctions tryFight ne lancent le combat que si le groupe cible est toujours present.


Informations de zone et distance

map.zoneInfo() / map.worldDistanceToMap(mapId) / map.neighbourId(direction)

returns table / number / number

zoneInfo decrit la zone courante et worldDistanceToMap calcule une distance de monde. neighbourId est un stub historique et retourne 0.


Utilitaires de carte

map.closeZaap() / map.slap()

returns boolean

Ferme l'interface zaap/zaapi ou envoie l'emote texte historique de slap.


Groupe de jeu

map.inviteToGroup(name) / leaveGroup() / acceptGroupInvite() / declineGroupInvite()

returns boolean

Inviter un joueur au groupe, quitter, accepter/refuser l'invitation en attente. acceptGroupInvite et declineGroupInvite retournent true seulement si une invitation etait reellement en attente ; sinon rien n'est envoye et le retour est false.


map.getPendingGroupInvite

map.getPendingGroupInvite()

returns inviterId: number, inviterName: string | nil

Invitation de groupe recue et pas encore traitee. Retourne 0, nil s'il n'y en a pas. Le paquet du jeu ne porte que des noms : inviterId vaut l'ID du joueur s'il est visible sur la map courante, sinon -1 (l'invitation est bien en attente, testez ~= 0). Les invitations traitees automatiquement (chef de groupe MoonBot, mode prive) ne sont pas exposees. L'invitation disparait quand elle est acceptee/refusee, quand le bot rejoint un groupe ou quand l'inviteur l'annule.


map.waitForGroupInvite

map.waitForGroupInvite(timeout?: number)

blocking · returns inviterId: number, inviterName: string | nil

Attend une invitation de groupe (retour immediat si une est deja en attente). Retourne 0, nil au bout du timeout (defaut 60000 ms). Exemple : local id, name = map.waitForGroupInvite(30000) if id ~= 0 then delay(math.random(1500, 4000)) map.declineGroupInvite() end


Infos groupe de jeu

map.getPartyMembers() / getPartyCount() / isInParty() / getPartyLeaderId() / isPartyLeader()

returns table / number / boolean / number / boolean

getPartyMembers()→table of {id: number, name: string, class_id: number, sex: boolean, level: number, life_percent: number}. getPartyCount()→number. isInParty()→boolean. getPartyLeaderId()→number. isPartyLeader()→boolean.


Defis entre joueurs

map.challengePlayer(id) / acceptChallenge(id?) / declineChallenge(id?) / cancelChallenge()

returns boolean

Proposer un defi amical, accepter/refuser le defi en attente, annuler son propre defi. acceptChallenge et declineChallenge visent le defi en attente (id optionnel pour ne repondre qu'a ce joueur) et retournent true seulement si un defi etait reellement en attente ; sinon rien n'est envoye et le retour est false.


map.aggressPlayer

map.aggressPlayer(target: number | string)

returns boolean

Demande une agression PvP contre un autre joueur visible sur la carte courante. target est son ID positif ou son nom exact (sans distinction de casse). L'appel Lua lance directement la demande ; le bouton de la MapViewer demande une confirmation. Retourne false si la cible ou l'action est indisponible, true si la commande est mise en file (le serveur peut encore la refuser). Les restrictions d'agression, l'etat du personnage et la presence de la cible sont reverifies avant envoi ; une commande devenue perimee lors d'un changement de carte est abandonnee. Exemple : local queued = map.aggressPlayer(123456). Accepte aussi map:aggressPlayer(target).


map.getPendingChallenge

map.getPendingChallenge()

returns challengerId: number, challengerName: string | nil

Defi PvP recu et pas encore traite. Retourne 0, nil s'il n'y en a pas. Le defi disparait quand il est accepte/refuse/annule, au changement de map et au debut d'un combat. En mode prive le defi est refuse automatiquement et n'est pas expose.


map.waitForChallenge

map.waitForChallenge(timeout?: number)

blocking · returns challengerId: number, challengerName: string | nil

Attend un defi PvP (retour immediat si un defi est deja en attente). Retourne 0, nil au bout du timeout (defaut 60000 ms). Exemple : local id, name = map.waitForChallenge(30000) if id ~= 0 then delay(math.random(2000, 5000)) map.declineChallenge(id) end


map.joinableFights

map.joinableFights()

returns table of {fightId: number, teamId: number, fighters: table of {id: number, name: string, level: number}}

Liste les combats joignables visibles sur la map (1 entree par equipe, teamId negatif). fightId est synthetique : plus petit |teamId| de la paire (les 2 equipes d'un meme combat partagent le meme fightId).


map.joinFight

map.joinFight(teamId: number)

returns boolean

Rejoint une equipe d'un combat en cours sur la map. teamId vient de joinableFights() (ex: -862).


map.exchangePlayer

map.exchangePlayer(playerId: number)

Demande un echange avec un joueur.