Tout ce qui a été publié par Smooth
-
ChallengeBonus
Which reward a fight's challenges give: an experience bonus or a drop bonus. The type is named; its values are not. Kind enum · Area Game.Challenge The bonus kind of a fight's challenges, carried by ChallengeBonusChoiceSelectedEvent.challenge_bonus and by the bonus-choice request. THE VALUES ARE NOT NAMED HERE. Beta declares CHALLENGE_EXPERIENCE_BONUS = 0 and CHALLENGE_DROP_BONUS = 1, but enum numbers are not trusted across builds and nothing read so far separates them by behaviour. Keep the value you received and echo it back unchanged. Not sent on its own — an enum is never sent on its own. inferred Used by ChallengeBonusChoiceRequest ChallengeBonusChoiceSelectedEvent No fields you may set.
-
ChallengeAddEvent
Adds one challenge to the current fight's challenge list, or replaces the one with the same id. Kind event · Area Game.Challenge One challenge of the current fight, as a full challenge record: its id, targets, state and bonuses. WHAT TO DO WHEN YOU RECEIVE IT 1. Look the challenge up by the record's challenge id in the fight's challenge list. 2. INSERT OR REPLACE. The client removes an entry with the same id, then adds the new one, so the record is the challenge's whole current state, not a delta. 3. Resolve the challenge id in the game data (the challenge definition: name, description, icon) if you need to show or reason about it. 4. SEND NOTHING BACK. IT IS ONE CHALLENGE. The whole list arrives in ChallengeListEvent; a later change of only the targets arrives in ChallengeTargetsEvent, and the outcome in ChallengeResultEvent. PADDING. Builds pad this message with unread members (a bool, a repeated bool, a second record); the challenge record the client reads is the only member named. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this the server announces a challenge when it becomes active in the fight; no request asks for it Fields #FieldTypeMeaningYou set it 2challengetype not documented yetThe challenge to add, or to replace when one with the same id is already listed.never
-
AttackMonsterRequest
Attacks a monster group on the current map, starting a fight against it. Carries the group's actor id. Kind request · Area Game.Roleplay Starts a fight against one monster group of the map you are on. HOW TO SEND IT 1. BE IN ROLEPLAY, ON THE GROUP'S MAP. The group is named by its actor id, the ActorPositionInformation.actor_id it was announced with in GameRolePlayShowActorsEvent or in the map's contents. Monster groups have NEGATIVE actor ids. 2. WALK TO IT FIRST, THE WAY THE CLIENT DOES. The official client sends MapMovementRequest toward the group and remembers the group. It sends this message when the walk is over: - normally right after MapMovementConfirmRequest; - also when the server refuses the walk with MapMovementRefusedEvent: the client puts the character back on the cell the server gives and attacks anyway; - at once, with no walk, when the character already stands on the destination. 3. PUT THE GROUP'S ACTOR ID IN AttackMonsterRequest.monster_group_id. Nothing else. 4. WAIT FOR THE FIGHT. In a capture the first answer was EntitiesDispositionEvent with the attacker's cell and direction, about 30ms later, then two FightTeamUpdateEvent (one per team). Once the fight map was loaded and ContextReadyRequest sent, FightStartingEvent, FightJoinEvent and one FightFighterShowEvent per fighter followed. THE ID IS AN ACTOR ID, NOT A MONSTER TEMPLATE ID. It is the group's contextual id on this map (for example -20002), the same id the fight then reports as its defender (FightStartingEvent.defender_id) and as the monster team's leader. A monster id from the game data is not accepted in its place. PADDING. Builds add unread members beside the id (a nested record on 3.7, a second int64 on 3.6.12.16). Fill only the recovered member. OBSERVED (one capture, 3.7.8.7): monster_group_id -20002, followed ~30ms later by EntitiesDispositionEvent carrying only the attacker, then by the fight set-up. When you may send it Requires roleplay_context inferred Raised by: a user action followed by a walk: the player clicks a monster group; the client walks toward it and attacks the group it remembered once the walk ends, also when the server refuses the walk with MapMovementRefusedEvent, and at once when the character already stands on the destination cell inferred Related messages You will then receive EntitiesDispositionEvent observed — about 30ms later, the attacker's own disposition as the fight is set up, then the fighters' placement dispositions; 1 observation You will then receive FightTeamUpdateEvent observed — about 70ms later, two back to back, one per team of the new fight (yours led by you, the monsters' led by the group id); 1 observation You will then receive FightStartingEvent observed — about 640ms later, once the client had loaded the fight map and sent ContextReadyRequest; 1 observation Fields #FieldTypeMeaningYou set it 2monster_group_idint64Actor id of the monster group to attack, as announced on the current map (negative for monster groups). (actor id (contextual, map-scoped)) Observed: -20002required
-
ArenaUpdatePlayerInformationEvent
The character's Kolizeum standing for each arena mode, and the end of any Kolizeum ban. Store it; nothing is sent back. Kind event · Area Game.Arena The character's Kolizeum standing: one ArenaRank per arena mode in ArenaUpdatePlayerInformationEvent.arena_ranks, and the end of any Kolizeum ban in ArenaUpdatePlayerInformationEvent.ban_end_date. WHAT TO DO WHEN YOU RECEIVE IT 1. For each entry, REPLACE what you hold for its ArenaRank.arena_type. The client files the entries in a table keyed by arena type, overwriting the previous entry for that type; types absent from the message keep their old entry. 2. Store the ban end date. 3. SEND NOTHING BACK. The handler builds no request; it hands the whole table to the Kolizeum window. THE BAN DATE IS A STRING, NOT A NUMBER. The client parses it with DateTime.Parse(value, InvariantCulture, RoundtripKind) - an ISO 8601 style timestamp - and keeps its ticks. It parses unconditionally; what the server sends when there is no ban is not visible in the client. Builds pad this message with a second, never-walked list of the same record, and with unread messages and strings. The real list is the one the client walks; the real date is the one string it parses. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this no request in the arena area asks for it; beta's arena requests register, unregister, answer a fight proposal or switch the reward mode Fields #FieldTypeMeaningYou set it 1ban_end_datestringWhen the character's Kolizeum ban ends, as a date string. Parsed with DateTime.Parse(value, InvariantCulture, RoundtripKind).never 2arena_ranksrepeated ArenaRankOne standing per arena mode; each replaces the one held for its arena type. A list of ArenaRank.never
-
ArenaType
Which Kolizeum mode a standing belongs to. The type is named; its values are not. Kind enum · Area Game.Arena The Kolizeum mode ArenaRank.arena_type refers to. The client uses the value only as a key, so you can do the same: keep one ArenaRank per value. THE VALUES ARE NOT NAMED HERE. Beta declares three modes, ONE_VS_ONE = 0, TWO_VS_TWO = 1 and THREE_VS_THREE = 2, but enum numbers are not trusted across builds and nothing in the client's code separates the values. From 3.5 on the enum has FOUR values, and the client's own mirror of it has four too (plus -1 for none), so the fourth is a real mode rather than padding; which one is not visible in the client. Not sent on its own — an enum is never sent on its own. inferred Used by ArenaRank No fields you may set.
-
ArenaRank
The character's Kolizeum league, rating, best results and fight counts in one arena mode. Kind struct · Area Game.Arena The character's standing in ONE Kolizeum mode (ArenaRank.arena_type): the current league and rating (ArenaRank.league_ranking, a LeagueRanking), the best ones reached, and today's and the season's fight and victory counts. A record inside ArenaUpdatePlayerInformationEvent, never sent on its own. KEY IT BY arena_type: the client keeps exactly one per arena type and the newest one replaces the old. The client turns each into its Kolizeum display record, looking both league ids up in its arena-league data for a name and an icon. Its seven counters share one wire type and move between field numbers on every build; they are named here from where the client copies each one, never from their numbers. Not sent on its own — it is a record inside ArenaUpdatePlayerInformationEvent, never sent on its own. inferred Used by ArenaUpdatePlayerInformationEvent Fields #FieldTypeMeaningYou set it 1best_league_idint32Id of the best league reached; the client looks the league up in its arena-league data.never 2daily_victory_countint32Kolizeum fights won today in this mode.never 3fight_needed_for_ladderint32Fights still needed before the character appears on the ladder.never 4arena_typeArenaTypeWhich Kolizeum mode this standing is for; the key the client files it under. An ArenaType. Its values are not named: the client never distinguishes them in code that survives obfuscation.never 5season_fight_countint32Kolizeum fights fought this season in this mode.never 6daily_fight_countint32Kolizeum fights fought today in this mode.never 7season_victory_countint32Kolizeum fights won this season in this mode.never 8best_ratingint32Best rating reached in this arena mode.never 9league_rankingLeagueRankingThe current league, rating and ladder position in this mode. A LeagueRanking.never
-
AreaFightModifierUpdateEvent
The fight modifiers (spell pairs) in effect in the character's current area. An empty list means none. Kind event · Area Game.Area The list of fight modifiers that apply to fights in the area the character is in. Each modifier is a spell pair from the game data (SpellPairs). REPLACE, DON'T MERGE. The list is the whole current set: keep it as the active modifiers and drop the previous ones. An EMPTY list is meaningful: no modifier applies here. WHAT THE CLIENT DOES WITH IT It stores the list as the current modifiers and, for each spell pair, prints a chat line naming it ("current fight modificator" / "new fight modificator"). Nothing is sent back. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this the server pushes the area's modifiers; no request asks for them. An empty list arrives where no modifier applies Fields #FieldTypeMeaningYou set it 1spell_pairsrepeated int32The spell pairs that modify fights in this area. (spell pair ids (DataCenter SpellPairs)) The whole current set: an empty list means no modifier applies.never
-
Anomaly
What an anomaly destination offers: its XP and loot bonus, minutes left, and (3.7) which anomaly it is. Kind struct · Area Game.Teleportation The details of an anomaly destination, carried by TeleportDestination.anomaly when the destination's type is TELEPORTER_ANOMALY. It is never sent on its own. HOW TO READ IT - bonus_pourcentage: the anomaly's experience and loot bonus, in percent (120 means +120%). The client shows it as "Bonus: 120%". - remaining_time: how long the anomaly stays open, in MINUTES. The client shows it as "Time remaining: N minutes" and keeps a countdown. - anomaly_id (3.7.x and later): which anomaly this is. The client looks it up in its anomaly data to show the guardian monster's name. Nothing here is sent back: to go there, use the destination's own map_id. LIVE CAPTURE (3.7.4.4): four anomaly destinations, all with bonus 120, remaining times 12, 77, 22 and 13, anomaly ids 6, 10, 10 and 16. Builds pad this record with an unread int32, or (3.7.4.4) an unread int32 and an unread nested {int32, bool}. Not sent on its own — it is only ever the TeleportDestination.anomaly member. proven Used by TeleportDestination Fields #FieldTypeMeaningYou set it 1anomaly_idint32Which anomaly this is; the client looks it up to show the guardian monster's name. 3.7.x and later. (anomaly data id) Not in beta; absent from builds before 3.7.never 4remaining_timeint64How long the anomaly stays open, in minutes. (minutes)never 5bonus_pourcentageint32The anomaly's experience and loot bonus, in percent (120 = +120%). (percent)never
-
ActionInformation
What choosing an NPC dialog reply does: an action type and its arguments (a quest or quest step id for quest actions). Kind struct · Area Game.Npc One effect of an NPC dialog reply, inside VisibleReply.actions: what the server will do when you choose the reply. id the action type. The client recognises the quest actions (it treats ids up to 34 and the ids 905 and 911 specially) and derives the reply's icon from them. parameters the action's arguments. For a quest action the first one is the quest id or the quest step id; the client looks it up in its quest data to decide whether the icon shows a main, event, repeatable or ordinary quest. Nothing is sent because of an action: pick the reply with NpcDialogReplyRequest and the server performs it. SCHEMA CHANGE IN 3.6. Up to 3.5 an action carried id and a bool is_repeatable instead of parameters; the client then took the icon's repeatability from that bool. From 3.6 it carries the arguments and the client reads repeatability from the quest data. This signature describes the current form only. Not sent on its own — it only travels inside VisibleReply.actions. inferred Used by VisibleReply Fields #FieldTypeMeaningYou set it 2idint32The action type. (NPC reply action id) The client compares it with the quest action ids to choose the reply's icon.never 4parametersrepeated int32The action's arguments; for a quest action the first is a quest id or quest step id. The client reads only the first one, and only to look the quest up for the icon. Replaced is_repeatable (bool) in 3.6; name invented, no oracle names it.never
-
AchievementsEvent
The full list of achievements the character has completed. Replace what you hold with it; nothing is sent back. Kind event · Area Game.Achievement The full list of achievements the character has completed, one AchievedAchievement per entry. WHAT TO DO WHEN YOU RECEIVE IT 1. REPLACE the list you hold with this one. It is the whole list, not a change: the client empties its own list and rebuilds it from the entries. 2. SEND NOTHING BACK. The handler builds no request. 3. An entry whose AchievedAchievement.finished_level is above 0 still has its reward to claim; AchievementRewardRequest claims it. KEY ENTRIES BY AchievedAchievement.achievement_id. That is how the client finds an entry again, for example when the reward result for one achievement arrives. Some builds declare a second, never-read list of the same record beside the real one. The real list is the one the client walks. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this no request in the achievement area asks for it; the requests there ask for one category's details, the almost-finished list or the pioneer ranks Fields #FieldTypeMeaningYou set it 1achieved_achievementsrepeated AchievedAchievementEvery achievement the character has completed. A list of AchievedAchievement; the whole list, which replaces the previous one.never
-
AchievementFinishedEvent
The character just completed one achievement. Kind event · Area Game.Achievement One achievement was just completed. The payload is the same AchievedAchievement record that AchievementsEvent lists. WHAT TO DO WHEN YOU RECEIVE IT 1. ADD the record to the completed achievements you hold, keyed by AchievedAchievement.achievement_id. It is one new entry, not a new list. 2. If AchievedAchievement.finished_level is above 0, the reward is waiting: claim it with AchievementRewardRequest when you want it. 3. SEND NOTHING BACK. The client only announces it: an "achievement unlocked" message, and dedicated popups for some Temporis and expedition rewards. THE OTHER MEMBERS ARE PADDING. This build declares a bool and a SECOND AchievedAchievement beside the real one. The client reads only the one this record maps as achievement - do not read the other. When you may send it Requires character_loaded observed Related messages Unsolicited - nothing you send causes this the server sends it when an achievement completes; no request asks for it Fields #FieldTypeMeaningYou set it 3achievementAchievedAchievementThe achievement that was just completed. An AchievedAchievement, the same record AchievementsEvent lists.never
-
AchievedAchievement
One achievement the character has completed: which one, who completed it, the level it was finished at and its pioneer rank. Kind struct · Area Game.Achievement One achievement the character has completed: which achievement (AchievedAchievement.achievement_id), who completed it (AchievedAchievement.achieved_by), the level it was finished at (AchievedAchievement.finished_level) and its pioneer rank (AchievedAchievement.pioneer_rank). A shared record, not a message anyone sends. AchievementsEvent carries the full list of them; two further achievement events carry exactly one each - the "you just finished an achievement" notice and the announcement of someone else's achievement - and have no signature here yet. HOW THE CLIENT USES IT - achievement_id is the key. The client looks the achievement up in its achievement data by this id, and matches a reward result against its records by it. - finished_level is read through the generated accessor, so an absent value reads as 0. The client treats a value above 0 as "reward not claimed yet": when the reward result for that achievement arrives, it checks the value is above 0 and sets it to 0. See AchievementRewardRequest for claiming. - pioneer_rank is copied into the client's record and read nowhere else on 3.6.12.16. WIRE NUMBERS MOVE. The four members take different field numbers on every build, and builds pad the record with an unread string, a second int64 or a second int32. Match the members by the rules above, never by number. Not sent on its own — it is a record embedded in the achievement events, never sent on its own. inferred Used by AchievementFinishedEvent AchievementsEvent Fields #FieldTypeMeaningYou set it 1achievement_idint32Which achievement was completed; the key the client looks it up and matches reward results by. (achievement id)never 2achieved_byint64Who completed it: an id the client stores without interpreting it further. The name says who achieved it; that it is a character id is inferred from the name and the int64 type, not from client behaviour.never 3finished_levelint32Optional. Above 0 while the reward is still unclaimed; the client sets it to 0 when the reward result arrives. Explicit presence: absent is not the same as zero. Read through the generated accessor, so an absent value reads as 0.never 4pioneer_rankint32The character's pioneer rank for this achievement; the client keeps it but reads it nowhere else on 3.6.12.16.never
-
AccountSubscriptionElapsedDurationUpdateEvent
How long the account's subscription has run so far, pushed by the server and stored as-is. Kind event · Area Game.Account Carries the account's elapsed subscription duration. The client copies the value unchanged into its player-state service and does nothing else with it in the handler. DO NOT CONFUSE IT WITH AccountInformationUpdateEvent, which carries the subscription END DATE as Unix seconds. Both are a single int64 in the same account file; this one is never converted to a date by the client. ZERO IS THE PROTOBUF DEFAULT, so a zero cannot be told apart from an absent field. The message may carry further members that no dumped build reads; they keep their obfuscated names. When you may send it Requires authenticated observed Related messages Unsolicited - nothing you send causes this the server pushes account state; no request asks for it Fields #FieldTypeMeaningYou set it 1subscription_elapsed_durationint64The account's elapsed subscription duration, as the server counts it. The client stores it unchanged in its account state; no dumped build converts it, so its unit is not proven.never
-
Planning
Choisissez quand chaque bot est en jeu, semaine après semaine, et laissez Asterobot le connecter, lancer son paquet et le déconnecter à l'heure. Read this page in English Un planning dit à Asterobot quand un bot doit être en jeu : des plages hebdomadaires, comme le lundi de 08:00 à 12:30. Au début d'une plage, Asterobot connecte le bot et lance son paquet. À la fin, Asterobot demande au script de finir ce qu'il fait, puis l'arrête et déconnecte le bot. Chaque bot a son propre planning. Définir un planning Dans le Gestionnaire de bots, ouvrez le menu du bot et cliquez sur Planning…. Vérifiez que Activé est allumé. Un nouveau planning démarre activé, sauf si le bot ne peut pas en suivre un (voir Ce dont un planning a besoin). Choisissez le Fuseau horaire dans lequel vos plages sont écrites. Un nouveau planning démarre avec celui de votre navigateur. Pour chaque jour, cliquez sur Ajouter une plage et tapez quand la plage commence et finit. Un planning contient jusqu'à 200 plages, et ne fait rien tant qu'il n'en a aucune. Une plage qui finit avant ou au moment où elle commence finit le lendemain, et l'indique par le lendemain : le lundi de 22:00 à 06:00 finit le mardi à 06:00. De 00:00 à 00:00, c'est la journée entière. Vérifiez l'aperçu Semaine : une barre par jour, remplie là où le bot est en jeu. Réglez le Temps pour finir (minutes), de 0 à 30. Il vaut 5 pour un nouveau planning. La fin d'une plage l'explique. Cliquez sur Enregistrer. Asteroboard affiche Planning enregistré, et la colonne Planning du Gestionnaire de bots montre ce que le bot fait ensuite. Un planning enregistré s'applique aussitôt. Dans une plage, le bot se connecte et se lance en moins d'une seconde. En dehors, un bot qui s'est connecté de lui-même est arrêté, comme à la fin d'une plage. Éteindre Activé laisse le bot tel quel : connecté ou non, son script lancé ou non. Si l'enregistrement échoue, Asteroboard affiche Impossible d'enregistrer le planning avec la raison. Les plages qui se chevauchent ou se touchent n'en font qu'une : le lundi de 22:00 à 06:00 et le mardi de 06:00 à 10:00 gardent le bot en jeu du lundi 22:00 au mardi 10:00, sans déconnexion à 06:00. Une plage de 00:00 à 00:00 chaque jour garde le bot toujours connecté. Les heures sont celles de l'horloge du fuseau horaire du planning, à la minute près. Au changement d'heure, les plages suivent l'horloge : une plage entièrement comprise dans l'heure sautée au printemps n'a pas lieu cette nuit-là, et une plage comprise dans l'heure répétée en automne a lieu deux fois. Au début d'une plage Asterobot fait ce que feraient Connecter puis Lancer : Il connecte le bot avec son compte Ankama et choisit un serveur, selon la sélection de serveur du bot. Il ouvre la connexion au serveur de jeu. Il lance le paquet du bot, ou le dernier paquet ou script direct chargé. Un bot déjà connecté voit seulement son paquet lancé, et un bot dont le script tourne déjà est laissé tranquille. Personne n'est peut-être devant l'ordinateur au début d'une plage, alors une connexion planifiée ne vous demande jamais rien. Quand la sélection de serveur du bot ne peut pas choisir un serveur seule, par exemple parce que le serveur imposé est fermé pour maintenance, la tentative échoue au lieu d'afficher Choisissez un serveur, et Asterobot réessaie plus tard, comme ci-dessous. Pendant une plage Asterobot vérifie le bot chaque seconde tant que la plage dure : Quand le bot est déconnecté, parce que le serveur de jeu l'a expulsé, a fermé pour maintenance ou que le réseau a coupé, ou parce que la connexion a échoué, il le reconnecte. Quand le script s'est arrêté, après une erreur par exemple, il le relance. Il attend avant chaque nouvel essai : 1 minute, puis 2, puis 5, puis 10, et ensuite toutes les 10 minutes. L'attente repart de 1 minute une fois que le bot est resté 10 minutes en jeu avec son script lancé, et à chaque début et fin de plage. Chaque essai et chaque échec est écrit dans la Console du bot, sur des lignes qui commencent par Schedule:. Une connexion qui échoue apparaît aussi dans l'alerte Impossible de connecter ce bot de la page du bot, comme quand vous cliquez sur Connecter. Certains échecs reviennent tant que vous n'agissez pas, comme un compte Ankama qu'il faut reconnecter dans le Gestionnaire de comptes. Asterobot continue d'essayer toutes les 10 minutes, et le bot revient de lui-même à l'essai qui suit votre correction. En dehors d'une plage, Asterobot ne fait rien entre deux débuts ou fins de plage. Un bot que vous connectez vous-même reste connecté jusqu'à la fin de la prochaine plage. La fin d'une plage À la fin d'une plage, Asterobot demande au script du bot de finir ce qu'il fait, attend qu'il ait fini, ou que le Temps pour finir soit écoulé, puis arrête le script et déconnecte le bot, comme le fait Déconnecter. Le script doit être écrit pour cela. Un paquet qui ne gère pas cette demande est arrêté aussitôt, comme avec un Temps pour finir de 0, même en plein combat. Play, stop and reload montre aux auteurs de scripts comment la gérer. Warning Un arrêt immédiat peut laisser le personnage en plein combat, en plein échange ou en plein trajet. Laissez au paquet le temps de finir s'il sait s'en servir. Si la plage suivante commence pendant que le script finit, l'arrêt va quand même jusqu'au bout, et le bot se reconnecte juste après. À la main Vous pouvez toujours utiliser les commandes du bot. Connecter, Commencer l'attente, Déconnecter, Lancer et Arrêter prennent la main sur le planning jusqu'à son prochain début ou sa prochaine fin de plage : d'ici là, Asterobot ne connecte, ne lance et ne déconnecte pas ce bot. La colonne Planning affiche Suspendu jusqu'à avec l'heure. Un clic qu'Asterobot refuse ne change rien. Au prochain début ou à la prochaine fin de plage, le planning reprend la main. Pour mettre fin plus tôt à cette suspension, ouvrez Planning… et cliquez sur Enregistrer. Un bot toujours connecté n'a pas de prochain changement : sa suspension dure jusqu'à ce que vous enregistriez à nouveau son planning ou redémarriez Asterobot. Un clic pendant que le script finit, à la fin d'une plage, prend aussi la main : Arrêter laisse le bot connecté, et Déconnecter le déconnecte aussitôt. Charger ou décharger un paquet, changer les réglages et envoyer des messages du jeu ne prennent pas la main sur le planning. Ce dont un planning a besoin Activé ne peut être allumé que pour un bot qui a : Besoin Pourquoi Message sous Activé Un compte Ankama Un bot sans compte ne peut que relayer une partie que vous lancez vous-même. Un planning a besoin d'un compte Ankama : un bot sans compte ne peut que relayer une partie que vous lancez vous-même. Un paquet Un script direct ne compte pas, car il ne survit pas à un redémarrage. Un planning a besoin d'un paquet : chargez-en un d'abord. Un script direct ne compte pas, car il ne survit pas à un redémarrage. Une sélection de serveur autre que Me demander à chaque fois Personne n'est peut-être là pour répondre. Un planning a besoin d'une sélection de serveur autre que « Me demander à chaque fois », car personne n'est peut-être là pour répondre. Si l'une de ces conditions disparaît pendant que le planning est activé, par exemple quand vous déchargez le paquet, le planning est en pause : il ne connecte et ne lance plus le bot, mais le déconnecte toujours à la fin d'une plage. La colonne Planning dit pourquoi, et le planning reprend de lui-même une fois le problème corrigé. La colonne Planning La colonne Planning du Gestionnaire de bots montre ce que le planning de chaque bot fait ensuite. Les heures sont dans le fuseau horaire du planning, avec le jour quand ce n'est pas aujourd'hui. Affiche Signification Un tiret Le bot n'a pas de planning. Désactivé Le planning est éteint. En pause · pas de compte, En pause · pas de script ou En pause · serveur demandé à chaque fois Le planning est activé, mais le bot ne peut pas le suivre. Voir Ce dont un planning a besoin. Arrêt · avant une heure Le script a été prié de finir, et il est arrêté à cette heure au plus tard. Suspendu jusqu'à une heure, ou Suspendu Vous avez pris la main. Voir À la main. Nouvel essai à une heure La connexion ou le lancement a échoué, et Asterobot réessaie à cette heure. Survolez-le pour lire pourquoi. Se déconnecte à une heure Le bot est dans une plage, qui finit à cette heure. Se connecte à une heure Le bot est hors plage, et la suivante commence à cette heure. Toujours connecté Les plages couvrent toute la semaine. Aucune plage Le planning est activé, mais n'a aucune plage : il ne fait donc rien. Copier un planning vers d'autres bots Ouvrez Planning… sur le bot dont vous voulez copier le planning. Sous Copier vers…, choisissez les autres bots. Cliquez sur Copier. Chaque bot reçoit les plages, le fuseau horaire et le temps pour finir affichés dans la fenêtre, enregistrés ou non. Chaque bot garde son propre Activé, et un bot qui n'avait pas de planning reçoit celui-ci éteint. Asteroboard affiche Planning copié avec les bots concernés, et Impossible de copier le planning vers avec le nom du bot et la raison pour chaque échec. Ce qu'un planning ne fait jamais Il ne touche jamais un bot qui attend votre client de jeu ou qui le relaie. La partie vous appartient, au début d'une plage comme à sa fin. Il ne connecte pas un bot pendant qu'un autre bot relaie une partie sur le même compte Ankama, ce qui déconnecterait la personne qui joue. Asterobot reconnaît le compte une fois que le bot planifié a été en jeu pendant l'une de ses plages depuis le démarrage d'Asterobot. Il réessaie plus tard, comme après un échec. Il ne connecte pas tant qu'Asterobot ne peut pas confirmer votre compte asterobot.net. Il attend sans compter cela comme un échec, et déconnecte toujours les bots à la fin de leurs plages. Limites Un planning ne tourne que pendant qu'Asterobot tourne. Quand Asterobot démarre pendant une plage, le bot se connecte aussitôt. Asterobot ne voit pas un client Dofus qui ne passe pas par lui. Si vous jouez ainsi le compte d'un bot planifié, la connexion du bot au début de la plage suivante est refusée puis réessayée, ou met fin à votre partie. Lequel des deux arrive n'a pas été vérifié. Un bot peut rester en jeu jusqu'à son temps pour finir après la fin de sa plage, quand son script l'utilise en entier. Pour aller plus loin États et commandes Déconnecter, supprimer et redémarrer Play, stop and reload, pour les auteurs de scripts.
-
Schedule
Choose when each bot is in the game, week by week, and let Asterobot connect it, play its package and disconnect it on time. A schedule tells Asterobot when a bot should be in the game, as a set of weekly time slots such as Monday from 08:00 to 12:30. When a time slot starts, Asterobot connects the bot and plays its package. When it ends, Asterobot asks the script to finish what it's doing, then stops it and disconnects the bot. Each bot has its own schedule. Set up a schedule In Bot Manager, open the bot's menu and click Schedule…. Make sure On is switched on. A new schedule starts switched on, unless the bot can't follow one (see What a schedule needs). Pick the Time zone your time slots are written in. A new schedule starts with your browser's time zone. For each day, click Add a time slot and type its start and end times. A schedule holds up to 200 time slots, and does nothing until it has one. A time slot that ends at or before its start time ends the next day, and is marked next day: Monday 22:00 to 06:00 ends on Tuesday at 06:00. 00:00 to 00:00 covers the whole day. Check the Week preview: one bar per day, filled in where the bot will be in the game. Set the Time to finish (minutes), from 0 to 30. It's 5 for a new schedule. When a time slot ends explains it. Click Save. Asteroboard shows Schedule saved, and the Schedule column of Bot Manager shows what the bot will do next. A saved schedule applies immediately. During a time slot, the bot connects and starts playing within a second. Outside a time slot, a bot that signed in by itself is stopped, just as at the end of a time slot. Switching On off leaves the bot as it is, whether or not it's connected and its script is running. If saving fails, Asteroboard shows Couldn't save the schedule with the reason. Time slots that overlap or touch count as one: Monday 22:00 to 06:00 and Tuesday 06:00 to 10:00 keep the bot in the game from Monday 22:00 to Tuesday 10:00, without disconnecting at 06:00. A time slot from 00:00 to 00:00 on every day keeps the bot connected all the time. Times follow the clock of the schedule's time zone, to the minute. When the clocks change for daylight saving time, the time slots follow the clock: a time slot that fits entirely inside the hour skipped in spring doesn't happen that night, and one inside the hour repeated in autumn happens twice. When a time slot starts Asterobot does what Connect followed by Play would do: It signs the bot in with its Ankama account and selects a server, according to the bot's server selection. It opens the connection to the game server. It plays the bot's package, or whichever package or inline script was loaded last. If the bot is already connected, Asterobot only plays its package, and if its script is already running, the bot is left alone. Nobody may be at the computer when a time slot starts, so a scheduled connection never asks you anything. If the bot's server selection can't pick a server on its own, for example because the forced server is down for maintenance, the attempt fails instead of showing Pick a server, and Asterobot tries again later, as described below. During a time slot Asterobot checks the bot every second for as long as the time slot lasts: If the bot gets disconnected, because the game server kicked it, closed for maintenance or the network dropped, or because connecting failed, Asterobot connects it again. If the script stops, after an error for example, Asterobot starts it again. It waits before each new try: 1 minute, then 2, then 5, then 10, and every 10 minutes after that. The wait goes back to 1 minute once the bot has stayed in the game with its script running for 10 minutes, and whenever a time slot starts or ends. Each try and each failure is written to the bot's Console, on lines starting with Schedule:. A failed connection also shows up in the Couldn't connect this bot alert on the bot's page, just as when you click Connect. Some failures keep happening until you step in, such as an Ankama account that has to be signed in again in Account Manager. Asterobot keeps trying every 10 minutes, and the bot comes back on its own at the first try after you fix the problem. Outside time slots, Asterobot does nothing between the end of one time slot and the start of the next. A bot you connect yourself stays connected until the next time slot ends. When a time slot ends When a time slot ends, Asterobot asks the bot's script to finish what it's doing and waits until it has, or until the Time to finish runs out. It then stops the script and disconnects the bot, as Disconnect does. The script has to be written to handle this. A package that doesn't is stopped immediately, as with a Time to finish of 0, even in the middle of a fight. Play, stop and reload shows script writers how to handle it. Warning Stopping immediately can leave the character in the middle of a fight, a trade or a trip. Give the package time to finish if it can use it. If the next time slot starts while the script is still finishing, the stop still goes ahead, and the bot connects again right after. Taking over by hand You can still use the bot's controls. Connect, Start waiting, Disconnect, Play and Stop put the schedule on hold until its next time slot starts or ends: until then, Asterobot doesn't connect, play or disconnect that bot. The Schedule column shows On hold until and the time. A click that Asterobot refuses changes nothing. When the next time slot starts or ends, the schedule takes over again. To end the hold sooner, open Schedule… and click Save. A bot that is always connected has no next change, so a hold on it lasts until you save its schedule again or restart Asterobot. Clicking while the script is finishing at the end of a time slot also takes over: Stop leaves the bot connected, and Disconnect disconnects it immediately. Loading or unloading a package, changing settings and sending game messages don't put the schedule on hold. What a schedule needs On can only be switched on for a bot that has: Needs Why Message under On An Ankama account A bot without one can only relay a game you sign in to yourself. A schedule needs an Ankama account: a bot without one can only relay a game you sign in to yourself. A package An inline script doesn't count, since it doesn't survive a restart. A schedule needs a package: load one first. An inline script doesn't count, since it doesn't survive a restart. A server selection other than Ask me each time Nobody may be around to answer. A schedule needs a server selection other than "Ask me each time", since nobody may be around to answer. If one of these goes away while the schedule is on, for example when you unload the package, the schedule is paused: it no longer connects or plays the bot, but still disconnects it when a time slot ends. The Schedule column says why, and the schedule resumes on its own once you fix the problem. The Schedule column The Schedule column of Bot Manager shows what each bot's schedule will do next. Times are in the schedule's time zone, with the day when it isn't today. Shows Meaning A dash The bot has no schedule. Off The schedule is switched off. Paused · no account, Paused · no script or Paused · server asked each time The schedule is on, but the bot can't follow it. See What a schedule needs. Stopping by a time The script has been asked to finish, and will be stopped at that time at the latest. On hold until a time, or On hold You took over by hand. See Taking over by hand. Retrying at a time Connecting or playing failed, and Asterobot will try again at that time. Hover over it to see why. Disconnects at a time The bot is in a time slot, which ends at that time. Connects at a time The bot is outside its time slots, and the next one starts at that time. Always connected The time slots cover the whole week. No time slots The schedule is on, but has no time slots, so it does nothing. Copy a schedule to other bots Open Schedule… on the bot whose schedule you want to copy. Under Copy to…, pick the other bots. Click Copy. Each bot gets the time slots, the time zone and the time to finish shown in the dialog, whether or not you saved them. Each bot keeps its own On setting, and a bot that had no schedule gets this one switched off. Asteroboard shows Schedule copied with the bots it was copied to, and Couldn't copy the schedule to with the bot's name and the reason for each one that failed. What a schedule never does It never touches a bot that is waiting for your game client or relaying it. That game is yours, at the start of a time slot as at its end. It doesn't sign in while another bot relays a game on the same Ankama account, because that would disconnect the person playing. Asterobot recognizes the account once the scheduled bot has been in the game during one of its time slots since Asterobot started. It tries again later, as after a failure. It doesn't connect while Asterobot can't confirm your asterobot.net account. It waits without counting this as a failure, and still disconnects bots when their time slots end. Limits A schedule only runs while Asterobot is running. If Asterobot starts during a time slot, the bot connects immediately. Asterobot can't see a Dofus client that doesn't go through it. If you play a scheduled bot's account that way, the bot's connection at the next time slot is either refused and tried again, or ends your game. Which of the two happens hasn't been checked. A bot can stay in the game for up to its time to finish after its time slot ends, if its script uses all of it. Where to go next States and controls Disconnect, delete and restart Play, stop and reload, for script writers.
-
0.5.0
0.5.0 - 13/10/2026 ✨ AjoutéLes bots peuvent suivre un planning hebdomadaire. Vous choisissez leurs créneaux horaires, dans le fuseau horaire de votre choix, et Asterobot connecte chaque bot, lance son package et le déconnecte à la fin du créneau, sans intervention humaine. La configuration s'effectue dans le Bot Manager d'Asteroboard : consultez le changelog d'Asteroboard. Un bot planifié assure lui-même sa continuité : s'il est déconnecté ou si son script s'arrête pendant un créneau, Asterobot le relance après 1, 2 et 5 minutes, puis toutes les 10 minutes. Une connexion planifiée ne s'interrompt jamais pour vous poser une question : lorsqu'aucun serveur ne peut être sélectionné automatiquement, le bot réessaie plus tard. À la fin d'un créneau, un script peut terminer son travail en cours pendant un maximum de 30 minutes, une durée configurable pour chaque planning, au lieu d'être interrompu au milieu d'une tâche. onStopRequest() indique au script qu'il est temps de terminer son travail, et session.scheduleEndsAt lui indique quand son créneau se termine, afin qu'il ne commence pas une tâche longue juste avant la fin. Vous gardez le contrôle : connecter, déconnecter, lancer ou arrêter manuellement un bot planifié suspend son planning jusqu'au début ou à la fin du prochain créneau. Un planning peut contenir jusqu'à 200 créneaux horaires. Un planning activé sans aucun créneau ne fait rien. Son activation ne risque donc jamais de déconnecter un bot par surprise. Un planning mis en pause, par exemple après le déchargement du package du bot, reste modifiable. Lorsque Asterobot démarre pendant un créneau horaire, le bot se connecte et commence immédiatement à jouer. L'API d'Asterobot et les assistants IA connectés à Asterobot peuvent définir le planning d'un bot. Le guide utilisateur dispose d'une nouvelle page Schedule, disponible en anglais et en français. La référence des scripts documente désormais onStopRequest(), offStopRequest() et session.scheduleEndsAt. Les comptes protégés par Ankama Shield fonctionnent en mode Full socket. Lorsqu'Ankama Shield demande un code de sécurité, Ankama l'envoie par e-mail et vous le saisissez dans Asteroboard : consultez le changelog d'Asteroboard. Dès lors, les bots du compte se connectent comme le ferait l'Ankama Launcher, à l'aide du certificat Shield du compte, sans qu'un nouveau code soit demandé jusqu'à la prochaine reconnexion du compte. Pour le moment, seuls les codes envoyés par e-mail sont pris en charge : un compte protégé par Ankama Authenticator l'indique lors de sa connexion. Tant qu'Ankama Shield attend un code, les bots du compte attendent également et aucun e-mail supplémentaire n'est envoyé. L'erreur de connexion du bot indique où le code a été envoyé. Vous pouvez demander un nouveau code à tout moment. Chaque compte possède son propre appareil Shield, c'est-à-dire l'ordinateur qu'il présente à Ankama Shield. Celui-ci est créé lors de l'ajout du compte, comme le HWID d'un bot. Plusieurs comptes peuvent partager un même appareil pour apparaître comme provenant d'un seul ordinateur, ou chacun disposer du sien. Modifier cet appareil déconnecte le compte de Shield : à la prochaine connexion, le compte s'authentifie à nouveau et un nouveau code est demandé. L'API d'Asterobot et les assistants IA connectés à Asterobot peuvent saisir un code Shield, en demander un nouveau et définir l'appareil Shield d'un compte. Ils sont également informés lorsqu'Ankama envoie un code. Sur un bot qui relaie la partie à laquelle vous jouez, Asterobot empêche le rapport du mod loader de Dofus d'être transmis à Ankama. Dofus envoie ce rapport lorsqu'il détecte un chargeur de mods, tel que MelonLoader ou BepInEx, dans son dossier. Asterobot bloque ce rapport dès le début de la session, avant même que vous appuyiez sur Play et que le package soit exécuté. La Console du bot consigne chaque rapport bloqué. 82 messages de jeu supplémentaires disposent désormais d'un nom et de toutes leurs données, permettant aux scripts de les lire et de les envoyer sans avoir à deviner leur structure. Les scripts peuvent suivre un combat dans son intégralité, de l'attaque jusqu'au résultat, ainsi que les équipes décrites par FightTeamInformation et FightTeamMembersInformation : AttackMonsterRequest, FightJoinRequest, FightJoinEvent, FightStartingEvent, FightStartEvent, FightLeaveEvent, FightEndEvent, FightSpectatePlayerRequest, FightOptionToggleRequest, FightOptionUpdateEvent, FightTeamUpdateEvent, FightTeamRemoveMemberEvent, FightFighterShowEvent, FightSynchronizeEvent, FightRefreshCharacterStatsEvent, FightPingsRequest, FightPingsEvent, AreaFightModifierUpdateEvent, EntitiesDispositionEvent, GameActionAcknowledgementRequest, SequenceStartEvent et SequenceEndEvent. Les options de combat utilisent FIGHT_OPTION_SET_SECRET, FIGHT_OPTION_SET_TO_PARTY_ONLY, FIGHT_OPTION_SET_CLOSED et FIGHT_OPTION_ASK_FOR_HELP. Les scripts peuvent positionner le personnage avant un combat, échanger sa place avec celle d'un coéquipier et signaler qu'il est prêt : FightPlacementPossiblePositionsEvent, FightPlacementPositionRequest, FightReadyRequest, FightHumanReadyStateEvent, FightPlacementSwapPositionsEvent, FightPlacementSwapPositionsAcceptRequest, FightPlacementSwapPositionsCancelRequest, FightPlacementSwapPositionsCancelledEvent et FightPlacementSwapPositionsErrorEvent. Les scripts peuvent jouer leurs tours et lancer des sorts sur une cellule ou sur une cible : FightNewRoundEvent, FightTurnEvent, FightTurnStartPlayingEvent, FightTurnReadyRequest, FightIsTurnReadyEvent, FightTurnFinishRequest, FightTurnEndEvent, GameActionFightCastRequest et GameActionFightCastOnTargetRequest. Les scripts peuvent relever les défis de combat, depuis leur proposition jusqu'à leur résultat : ChallengeProposalEvent, ChallengeListEvent, ChallengeAddEvent, ChallengeNumberEvent, ChallengeSelectionRequest, ChallengeSelectedEvent, ChallengeValidateRequest, ChallengeReadyRequest, ChallengeModSelectRequest, ChallengeModSelectedEvent, ChallengeBonusChoiceRequest, ChallengeBonusChoiceSelectedEvent, ChallengeTargetsRequest, ChallengeTargetsEvent et ChallengeResultEvent. Les scripts peuvent utiliser les zaaps et autres téléporteurs : les destinations proposées et leur coût, chacune représentée par un TeleportDestination avec son Anomaly lorsqu'il y en a une, la téléportation elle-même, la liste des zaaps connus du personnage et son point de réapparition : TeleportDestinationsEvent, TeleportRequest, WaypointPriceRequest, WaypointPriceResponse, ZaapKnownListEvent, ZaapRespawnSaveRequest et ZaapRespawnUpdatedEvent. Le type de téléporteur est identifié par TELEPORTER_ZAAP, TELEPORTER_SUBWAY, TELEPORTER_PRISM, TELEPORTER_HAVEN_BAG ou TELEPORTER_ANOMALY. Les scripts peuvent gérer la banque, ses objets et ses kamas : ExchangeStartedWithStorageEvent, StorageInventoryContentEvent, ExchangeObjectMoveRequest, ExchangeMoveKamaRequest, StorageObjectUpdateEvent et StorageObjectRemovedEvent. Les scripts peuvent également détecter le démarrage ou la validation d'une quête, la réussite d'un succès, l'obtention d'un objet, l'apparition ou la disparition d'un prisme, la dépense ou la réinitialisation des points de caractéristiques, et bien plus encore : QuestStartedEvent, QuestValidatedEvent, GuideModQuitRequest, AchievementFinishedEvent, ObjectAddedEvent, CharacterCharacteristicUpgradeRequest, ResetCharacterCharacteristicsRequest, JobBookSubscribeRequest, PrismAddOrUpdateEvent, PrismRemoveEvent, ChatPrivateCopyMessageEvent, ContextQuitRequest, ContextRefreshEntityLookEvent et AccountSubscriptionElapsedDurationUpdateEvent. Les scripts qui demandent eux-mêmes au jeu le chargement de chaque nouvelle carte peuvent le signaler à l'aide de answerMapLoads(). Asterobot leur laisse alors gérer ce chargement, évitant ainsi qu'une même carte soit demandée deux fois. 🔄 ModifiéLes scripts s'exécutent de la même manière sur tous les ordinateurs : sur un PC lent ou très sollicité, ils s'exécutent simplement plus tard, jamais différemment. Chaque message du jeu parvient au script dans l'ordre de réception, et le nombre d'opérations qu'un script peut effectuer simultanément dépend uniquement du script lui-même, et non de l'ordinateur ou du réseau. Les scripts, ainsi que les packages en cours d'installation, peuvent s'exécuter pendant 5 secondes d'affilée au lieu d'un quart de seconde, ce qui permet aux scripts plus lourds de fonctionner également sur des ordinateurs modestes. Les messages envoyés par un script sont transmis dans l'ordre où il les envoie, même lorsqu'il est arrêté ou rechargé, et avant que le bot ne se déconnecte ou que le personnage ne se déplace à sa demande. Un script qui attend une réponse juste après un envoi la reçoit toujours, quelle que soit la rapidité de réponse du jeu. send() ignore son option timeout, puisqu'il n'a rien à attendre. Un script qui bloque ou modifie les messages du jeu a toujours le dernier mot, même lorsqu'il est très sollicité, dès que vous appuyez sur Play et pendant toute la durée d'un rechargement. Sur un bot qui relaie votre partie, un script de ce type qui s'exécute lentement oblige également votre jeu à attendre. Les paramètres que vous appliquez et les boutons d'action sur lesquels vous cliquez sont toujours transmis à un script en cours d'exécution, même lorsqu'il est très sollicité. Les messages du jeu qu'un script n'écoute pas ont un coût de traitement presque nul. Un script ne s'arrête en raison d'un retard que lorsque l'ordinateur ne parvient réellement plus à suivre, avec plus de 8 Mo de messages du jeu en attente. La page du bot indique alors la raison de l'arrêt. Sur un bot qui relaie votre partie, votre jeu continue même dans ce cas. Lorsque la connexion au jeu se ferme, le script traite d'abord tous les messages reçus auparavant, notamment la raison de la fermeture communiquée par le serveur, puis s'arrête. Les requêtes de données du jeu provenant de plusieurs bots et onglets SQL sont exécutées à tour de rôle, selon le principe du premier arrivé, premier servi. Le délai de 10 secondes d'une requête ne commence qu'une fois son tour arrivé. Les autres opérations de lecture des données du jeu ne disposent d'aucune limite de temps propre. Sur un bot qui se connecte automatiquement, Asterobot demande le chargement de chaque nouvelle carte après le délai nécessaire au client Dofus pour la charger, comme le ferait le jeu lui-même, et uniquement lorsqu'aucun script ne s'en charge. Lorsqu'un serveur de connexion refuse le serveur choisi par un bot pour le motif introduit dans les versions récentes de Dofus, l'erreur de connexion du bot affiche le nom du motif, NOT_ALLOWED, au lieu d'un simple numéro. Les requêtes d'Asterobot auprès du service de gestion des comptes d'Ankama correspondent encore plus fidèlement à celles de l'Ankama Launcher : mêmes en-têtes et même ordre des paramètres. Dépendances mises à jour. 🐛 CorrigéLes paramètres d'un script, configurés dans l'onglet Settings d'un bot, sont conservés lors du redémarrage d'Asterobot et lorsque vous changez le compte ou la version du jeu du bot. Auparavant, ils étaient réinitialisés aux valeurs par défaut du package. Cliquer sur Connect sur un bot pendant que son compte ou sa version du jeu est en cours de modification ne connecte plus le bot en cours de remplacement, ce qui laissait une session de jeu sans aucun contrôle. AccountInformationUpdateEvent est désormais le message qui fournit la date de fin de l'abonnement. Le message qu'il désignait auparavant indique la durée écoulée depuis le début de l'abonnement du compte et porte désormais le nom AccountSubscriptionElapsedDurationUpdateEvent.
-
Paysan, les champs d'Astrub
Superbe! Je test ça, il t'as pas manqué des messages ou des features ? N'hésites pas à me dire, et je rajoute tout ce qu'il manque. Tu voulais pas directement le mettre dans la librairie ? ici https://asterobot.net/files/category/2-librairie/ normalement tu peux uploader
-
0.4.0
0.4.0 - 07/10/2026✨ AjoutéLes bots peuvent se rendre sur n'importe quelle carte, quelle que soit la distance, carte après carte : en traversant les bords des cartes, les escaliers, les soleils, les portes, les échelles et les téléporteurs, en suivant la même carte de déplacement du monde que celle utilisée par le jeu pour le pilotage automatique de ses montures. Lorsque le jeu refuse un passage, le trajet trouve un autre itinéraire ; lorsque le personnage atterrit à un endroit inattendu, il planifie à nouveau son parcours à partir de là. Si un combat survient en cours de route, le bot attend qu’il se termine, puis le voyage reprend à l’endroit où se trouve le personnage après le combat. n bot se trouvant dans une maison ou une dimension en sort d’abord. Les étapes nécessitant une quête, un objet, un niveau ou une race sont vérifiées par rapport aux informations que le jeu a fournies au bot concernant son personnage. Celles qui ne peuvent pas être vérifiées ne sont tentées que s’il n’y a pas d’autre solution, sauf indication contraire de votre part. Chaque étape s’accompagne d’une estimation de la durée nécessaire. L’onglet Carte d’Asteroboard comporte une carte Voyage : choisissez une carte, par son identifiant ou en cliquant sur la carte du monde, visualisez l’itinéraire sur la carte du monde et sur la carte sélectionnée, effectuez le voyage, suivez le parcours étape par étape et mettez-y fin. Les scripts disposent de la fonction travel(), avec un callback onLeg avant chaque étape, de route() pour visualiser l’itinéraire sans se déplacer, de trip() pour voir où en est un voyage et de stopTravel() pour l’interrompre, quelle que soit la personne qui l’a lancé. Les scripts disposent de fonctions pour déterminer où aller : findMaps() (par sous-zone, zone, monstre, ressource, zaap ou coordonnées), mapAt(), mapInfo(), nearest(), nearestWith() 🔄 ModifiéAsterobot fonctionne avec Dofus 3.7.4.4, et uniquement avec cette version. Téléchargez-le et extrayez à nouveau ses données de jeu à partir de Game Manager. La version 3.7 de Dofus a modifié certaines données de jeu lues par les scripts et les requêtes SQL : Niveaux des monstres : les résistances s'appellent désormais reduction_earth, reduction_fire, reduction_water, reduction_air et reduction_neutral ; grade_xp est devenu xp, pa_dodge et pm_dodge sont désormais pa_lost_dodge et mp_lost_dodge, bonus_range est devenu range_bonus, et une trentaine de nouvelles statistiques ont été ajoutées. Les effets des objets et des niveaux de sorts indiquent de quel effet il s’agit dans action_id, qui s’appelait auparavant effect_id. guild_raids_rewards comporte désormais experience_ratio et kamas_ratio, et spell_states comporte effects au lieu de effects_ids. Dans les cellules d’une carte, floor s’appelle désormais altitude, et les champs nonWalkableDuringFight et nonWalkableDuringRP ont disparu : un combat bloque les cellules non praticables. Le champ blocked_in_fight de maps__cell_summary les recense. Les éléments interactifs d’une carte conservent leur cellule, leur identifiant d’interaction, leur identifiant graphique et leur comportement d’affichage ; la clé d’identifiant est interactionId. Trois nouvelles tables : anomalies, document_types et infinite_dream_drop_pools. Les vues Terrain et Combat de la visionneuse de carte n’affichent plus les mentions Bloqué hors combat et Bloqué en combat, que Dofus 3.7 a supprimées de ses cartes. Un bot dont le champ Proxy était laissé vide se connectait auparavant directement. Il suit désormais le proxy de son compte, ce qui ne change rien tant que vous n’en avez pas attribué un à ce compte.
-
0.2.7
0.2.7 - 07/10/2026✨ AjoutéL'onglet Carte d'un bot comporte une carte Voyage qui permet au bot de se rendre sur n'importe quelle carte, quelle que soit la distance, carte après carte : en passant par les bords des cartes, les escaliers, les soleils, les portes et les échelles. Il faut pour cela un Asterobot capable de se déplacer. Choisissez votre destination comme vous le souhaitez : naviguez jusqu'à elle sur la carte du monde ou sur la carte, ce qui remplit le champ ID de la carte, ou saisissez son ID. Un clic sur une case de la carte du monde affiche la liste des cartes qui s'y trouvent, avec à côté de chacune un bouton indiquant immédiatement le chemin pour s'y rendre. Un clic droit sur la case propose la même chose, sous forme de menu. Lorsque vous parcourez une carte autre que celle du bot, l'option Se rendre sur la carte, située à côté de Retour au bot, permet de s'y rendre immédiatement. Afficher l’itinéraire répertorie chaque étape avant votre départ, avec la carte vers laquelle elle mène, la durée approximative de chaque étape et la longueur totale du trajet. La carte du monde affiche un point sur chaque carte de l’itinéraire et une épingle sur la destination, tandis que la carte du bot indique le point de départ de l’étape suivante. L'option Étapes avec condition détermine si le bot peut effectuer des étapes nécessitant un élément qu'Asterobot ne peut pas vérifier, comme une quête ou un objet : Uniquement s'il n'y a pas d'autre solution (réglage par défaut), Dès qu'elles permettent de gagner du temps ou Jamais. Ces étapes sont signalées par la mention Condition non vérifiée, et la condition du jeu est indiquée dans leur info-bulle. La carte suit le voyage en temps réel : En route ou En combat, l’étape en cours, le temps restant estimé et les étapes refusées par le jeu, jusqu’à Arrivé, Échec ou Arrêt. Arrêt met fin au voyage une fois l’étape en cours terminée, de sorte que le personnage ne s’arrête jamais en cours de route. 🔄 ModifiéLa visionneuse de cartes affiche les cartes de Dofus 3.7. La mention Bloqué en combat, dans le résumé de la visionneuse de cartes, recense les cases inaccessibles : dans Dofus 3.7, il s'agit de celles bloquées par un combat. La liste des messages de l'outil Réseau reste fluide même lorsque les messages affluent. Les adresses d'Asteroboard sont sensibles à la casse : une adresse saisie avec d'autres majuscules n'ouvre plus la page. Mise à jour des dépendances. 🗑️ SuppriméCombat bloqué à l'extérieur et Combat bloqué à l'intérieur dans les vues Terrain et Combat de la visionneuse de cartes, que Dofus 3.7 a supprimées de ses cartes.
-
Harvest and move on
A script that harvests what its character can on each map of a route, then takes the next map, with recipes for doors, suns, zaaps and maps whose side leads to several maps. This script walks a route of maps. On each map it harvests every resource its character can, then leaves by the next side of the route. It shows how a script finds what can be used on a map, uses it, waits while a harvest lasts, and changes map, with asterobot:movement doing the walking. Recipes at the end cover doors, suns, zaaps and maps whose side leads to several maps. You need a MITM bot, as Your first bot sets up, a character with a gathering job on a map that has resources it can harvest, and to know how to create a package and run it, as in Create a package. The script Create a package named harvest-route, replace the contents of its index.js with this code, and save: import { botInfo, botWarn, currentMap, session } from "asterobot:bot"; import { record } from "asterobot:gamedata"; import { changeMap, useElement } from "asterobot:movement"; import { send, wait } from "asterobot:protocol"; // The sides to leave by, one map after the other. Write your own route here. const ROUTE = ["right", "right", "bottom"]; // A harvest action gathers an item, and the skills table says which one. // Every other action (use, save, open, sit...) gathers none. function harvests(skillId) { return (record("skills", skillId)?.gathered_ressource_item ?? -1) > 0; } // The elements of the character's map with a harvest action on offer right // now, and that action. function harvestable() { return (currentMap()?.elements ?? []).flatMap((element) => { const skill = element.skills.find((offer) => harvests(offer.id)); return skill ? [{ id: element.id, skillId: skill.id }] : []; }); } async function harvestMap() { for (const { id, skillId } of harvestable()) { try { const use = await useElement(id, { skill: skillId }); botInfo(`Harvesting element ${id} for ${use.duration} ms`); // The character stays busy until the game says the harvest is over. if (use.duration > 0) { await wait( (traffic) => traffic.type === "InteractiveUseEndedEvent" && traffic.payload?.elementId === id, { timeout: use.duration + 5000 }, ); } } catch (error) { // Harvested by someone else meanwhile, out of reach, or refused by the // game: leave it and try the next one. botWarn(`Couldn't harvest element ${id}: ${String(error)}`); } } } export default async function behavior(launch) { // A new game connection starts with this message. MITM bots never launch // with "initial": the Dofus client has already identified their session. if (launch.reason === "initial") { await send("IdentificationRequest", { ticketKey: session.gameToken, languageCode: session.language, }); } for (const side of ROUTE) { await harvestMap(); try { const { mapId, cellId } = await changeMap(side); botInfo(`Left by the ${side}: now on map ${mapId}, cell ${cellId}`); } catch (error) { botWarn(`Couldn't leave by the ${side}: ${String(error)}`); return; } } await harvestMap(); botInfo("Route done"); } How it works Finding what to harvest currentMap() lists the map's interactive elements in elements. Each one has its id and the actions it offers right now in skills, each with the skill id. A resource that was just harvested offers nothing until it regrows, so it's left out on its own. The elements don't say what they are. The skill does: each skill is a row of the game data's skills table, and a harvest skill's gathered_ressource_item is the item it gathers, such as 289, wheat, for skill 45. Other skills, such as 184, "Use", have -1 there. To harvest only one kind of resource, compare gathered_ressource_item with that item's id instead. harvestable() reads the map once, when harvestMap() starts. By the time the script gets to an element, another player may have harvested it: useElement() then rejects, and the script moves on. Using an element useElement(id, { skill }) does what the Dofus client does when the player clicks the element: the character walks within reach of it, then the game is asked to use it. Naming the skill matters on elements that offer several actions: without it, useElement() rejects with move: the element offers several actions; name the one to use. The promise resolves as soon as the game accepts the use, with duration, how long the harvest lasts in milliseconds. During that time the character can't use anything else, and useElement() would reject with move: the character is still using an element. So the script waits for InteractiveUseEndedEvent about that element, which the game sends when the harvest is over. Like every wait(), it has a timeout, here the harvest's duration and five seconds more. Moving on changeMap(side) walks the character to the exit of that side it reaches soonest, takes it to the next map, and resolves once the new map has loaded, so the next harvestMap() reads the new map's elements. When a side has no exit, or none the character can walk to, it rejects, and the script stops there with a line in the console. What the script sends useElement() and changeMap() send the walks, the confirmations a Full socket bot needs, InteractiveUseRequest and MapChangeRequest. On a MITM bot your Dofus client loads each new map. The script itself sends nothing but the identification, on a Full socket bot. On a Full socket bot The identification doesn't take a Full socket bot's character into the game: choosing the character and entering the world are a script's too. @asterobot:base does all of it. In a package that depends on base, replace the identification block with await connect() from @asterobot:base, which resolves once the character stands on its map. Base also asks for every new map, and changeMap() would do it after 3 seconds if nothing did. Run it Start waiting on your MITM bot, start Dofus and sign in, and choose a character with a gathering job. Walk it to a map with resources it can harvest. Change ROUTE to the sides that lead from that map to the next ones you want to harvest. In the editor, pick the bot and click Run. On the bot's page, open Console and keep only Script in Sources. Your character walks to each resource and harvests it, then leaves the map, as if you had clicked. Don't click in Dofus while it runs: your own walk would replace the script's. The lines look like this: Harvesting element 489389 for 3000 ms Harvesting element 489391 for 3000 ms Couldn't harvest element 489402: GoError: move: the server refused the use (element 489402) Left by the right: now on map 154010883, cell 293 Harvesting element 490017 for 3000 ms Route done The bot's Map tab shows the same walks live, and its Resources and objects list turns each harvested resource Unavailable. Recipes These pieces go inside a script like the one above, which already imports botInfo, botWarn, currentMap, record, changeMap, useElement and wait. Add query from asterobot:gamedata where a recipe uses it. Go through a door A door, a staircase or a teleporter is an element whose action takes the character to another map. The game's travel graph says which elements of a map do it, with the action to use and the map they lead to: const result = await query( `SELECT t.transition_id, t.skill_id, destination.map_id FROM world_transitions t JOIN world_vertices origin ON origin.uid = t.from_uid JOIN world_vertices destination ON destination.uid = t.to_uid WHERE origin.map_id = ? AND t.type = 32`, [Number(currentMap().mapId)], ); // [elementId, skillId, destinationMapId] for each door of the map, or nothing // when the bot's game version has no game data. const doors = result?.rows ?? []; useElement() resolves once the game accepts the use, and the new map comes a moment later. To go on once it has loaded, wait for its MapComplementaryInformationEvent, started before the use so it can't be missed: const [elementId, skillId] = doors[0]; const before = currentMap().mapId; await Promise.all([ wait( (traffic) => traffic.type === "MapComplementaryInformationEvent" && traffic.payload?.mapId !== before, { timeout: 30000 }, ), useElement(elementId, { skill: skillId }), ]); On a Full socket bot, the new map only loads when something asks for it: @asterobot:base does, or your script answers MapCurrentEvent and MapCurrentInstanceEvent itself. Unlike changeMap(), a door's use doesn't do it for you. Take a sun An exit drawn as a sun is an element whose only action is skill 339, Point Out an Exit. useElement() walks the character onto it, and resolves on the next map, once that map has loaded: const sun = currentMap()?.elements.find( (element) => element.skills.length === 1 && element.skills[0].id === 339, ); if (sun) { const { mapId } = await useElement(sun.id); botInfo(`Through the sun to map ${mapId}`); } Use a zaap A zaap offers two actions: 114, "Use", which opens its destinations, and 44, "Save", which saves it as your respawn point. Name the one you want: const zaap = currentMap()?.elements.find((element) => element.skills.some((offer) => offer.id === 44)); if (zaap) await useElement(zaap.id, { skill: 44 }); Choosing a destination after Use isn't built in: the game sends the destinations, and travelling to one is a message of its own. Leave from a given exit On a few maps, one side leads to different maps depending on the exit cell, such as the top and the bottom of the right side. Pass the cell to leave from: await changeMap("right", { cell: 475 }); Choose the exit shows how to list a side's exit cells and find which ones lead where. Try again after a refusal The game can refuse a walk, for example when another actor got in the way. The error's message says so, and a script can try again: async function changeMapPatiently(side, tries = 3) { for (let attempt = 1; ; attempt++) { try { return await changeMap(side); } catch (error) { if (attempt >= tries || !String(error).includes("the server refused the walk")) throw error; botWarn(`Walk refused, trying again (${attempt}/${tries})`); } } } asterobot:movement lists every error text these functions reject with. Ideas to take it further A route from the bot's settings. Declare the route as a setting, as Declare settings shows, so it changes without editing the script. Only one resource. Keep the elements whose skill gathers the item you want, with its id from Item names from game data. Stop when the pods are full. Inventory watcher follows the pods: end the route when they reach the maximum. Loop the route. Make it a circle, such as right, bottom, left, top, and run it until the script is stopped.
-
asterobot:verification
commitment(), publicKey() and proof(), which compute the bot's answers to the proof of identity the game server asks for on each game connection, with when to call each one and every error. Once a game session is open, the game server asks the client to prove who it is, in three exchanges. asterobot:verification computes what the bot answers with. Your script sends the messages, and the secrets behind the answers stay inside Asterobot: your code only ever sees the values that go on the wire. Only a Full socket bot needs it. On a MITM bot (man-in-the-middle: the bot relays the game session of a Dofus client that someone plays), the Dofus client answers these exchanges itself, and a script answering too would send each answer twice. Most scripts never import this module. @asterobot:base answers the three exchanges for every package that depends on it, on a Full socket bot, and leaves them to the Dofus client on a MITM bot. This page is for writing such a package yourself, or for understanding what base sends. import { commitment, publicKey, proof } from "asterobot:verification"; These are the module's only exports. There's no verification object to import. Export Returns What it gives you commitment() A string, right away The id of ClientIdRequest publicKey() A string, right away The challengeKey of ClientChallengeInitRequest proof() A string, right away The proof of ClientChallengeProofRequest Every value is a whole number written in base 10, which is how the three messages carry them. None of the functions returns a promise. The three exchanges The server sends Answer with Carrying ServerVerificationEvent ClientIdRequest id: commitment() ServerSessionReadyEvent ClientChallengeInitRequest challengeKey: publicKey() ServerChallengeEvent ClientChallengeProofRequest proof: proof(traffic.payload?.value) Answer each one as soon as it arrives, and only when it arrives: the Dofus client sends each of these requests from the handler of the message that asks for it, and from nowhere else. When they come ServerSessionReadyEvent closes the burst of messages that follows an accepted identification, once per connection. ServerVerificationEvent, then ServerChallengeEvent, come later and again from time to time: in captures, the first came about five and a half minutes into a session, and more followed. The client's code shows the poll can also arrive right after the connection opens, before the server has answered the identification. Register the handlers above the identification block, as the sample below does, so none can be missed. The challenge comes with a value or without one. Both happen, even on the same game launch. Without a value, the event is empty, and proof() works the challenge out itself. Send them with a uid The Dofus client sends these three requests with a uid of its own, and nothing ever answers them. Send them the same way, with correlated: true: await send("ClientIdRequest", { id: commitment() }, { correlated: true }); A plain send() would put -1 where the client puts a uid. A request() would wait for a response that never comes, and reject with context deadline exceeded once its timeout runs out. Sending explains the three ways to send. Answer at once Send each answer as soon as its event arrives. The server waits for each answer before its next step, so the three can't cross. commitment() commitment() returns a string. Each call draws a new random secret, keeps it inside Asterobot, and returns the value that proves it without revealing it. That secret replaces the previous one and is what the next proof() uses. So call it once for every ServerVerificationEvent, and never ahead of time: the Dofus client does the same, and a second call before the challenge makes the proof use the newer secret. Every call returns a different value. publicKey() publicKey() returns a string. It returns the bot's public key, which the server checks every proof against. It's the same value every time, and it belongs to the bot rather than to your script. It stays the same when the script stops and plays again, and across the bot's reconnections, as the key of a Dofus client stays the same for as long as the client runs. Captures confirm it: a client's proofs on two connections of one game launch both verify against the key it sent on the first. A bot gets a new key when Asterobot starts again, and when a change of its Ankama account or of its game version makes Asterobot rebuild it. proof() proof(challenge?) returns a string. Parameter Type Description challenge string, undefined or null The value of the ServerChallengeEvent you're answering, exactly as it arrived Pass traffic.payload?.value. The field is optional, so it's absent when the server sent no value, and proof() then answers the way the Dofus client does in that case: it works the challenge out itself, from the values of the exchange and the device identifier the bot sent when it signed in (see Device identifier). A bot that didn't sign in on its own uses an empty one. proof() draws nothing: it answers with the secret of the latest commitment(). Before the first commitment() of a bot, that secret is zero, which is also what the Dofus client answers with when a challenge comes before any ServerVerificationEvent. A complete example This script answers the three exchanges on a Full socket bot, and leaves them to the Dofus client on a MITM bot: import { session, botWarn } from "asterobot:bot"; import { on, send } from "asterobot:protocol"; import { commitment, publicKey, proof } from "asterobot:verification"; async function answer(type, payload) { try { // With a uid, as the Dofus client sends these three. await send(type, payload, { correlated: true }); } catch (error) { // An error that escapes a handler stops the whole script. botWarn(`Couldn't send ${type}:`, String(error)); } } export default async function behavior(launch) { // On a MITM bot the Dofus client answers these itself. if (!session.shared) { on("ServerVerificationEvent", () => answer("ClientIdRequest", { id: commitment() })); on("ServerSessionReadyEvent", () => answer("ClientChallengeInitRequest", { challengeKey: publicKey() })); on("ServerChallengeEvent", (traffic) => { try { answer("ClientChallengeProofRequest", { proof: proof(traffic.payload?.value) }); } catch (error) { // proof() throws for a value that isn't a number, and an error // thrown in a handler stops the whole script. botWarn("Couldn't answer the challenge:", String(error)); } }); } // A new game connection starts with this message. MITM bots never launch // with "initial": the Dofus client has already identified their session. if (launch.reason === "initial") { await send("IdentificationRequest", { ticketKey: session.gameToken, languageCode: session.language, }); } } A script that stops and plays again in the middle of a session keeps working with it: the key is the bot's, and a challenge is answered with the secret of the bot's latest commitment(), whichever run of the script made it. Checked against the real client The computation was read out of the Dofus client's code: the 768-bit group of RFC 2409 section 6.1 with G = 2, the proof (k + c·x) mod Q, and the challenge the client works out when the server sends none. The server checks a proof with G^proof = id × challengeKey^c (mod P). Asterobot's tests check all of it against the real client too. They hold two checks a Dofus client answered, taken from captures of one game launch: Check Challenge Result 1 None: the client worked it out The client's proof verifies against the challenge proof() works out 2 A value from the server The client's proof verifies against that value So the group, the proof and both kinds of challenge are the client's, and every answer these functions give passes the same check. The tests also cover the path from a script: a script answering the three events as the sample above does passes the check on both kinds of challenge. Errors Error Type Cause verification.proof challenge must be a decimal string, or undefined when the server sent none TypeError challenge is neither a string, undefined nor null verification: the challenge is not a decimal integer: "<challenge>" Error challenge isn't a whole number written in base 10. Spaces around it and a leading sign are accepted. String(error) gives TypeError: or GoError: followed by the text. The three functions throw when the top level of a module calls them while Asterobot reads the package's declarations, with an error that ends with not available while reading a package's declarations: see Declarations. Call them from your handlers. The Dofus protocol reference describes the six messages of the exchange.
-
Bot memory
How the memory a bot's scripts share works, what it keeps and for how long, how to keep state for one game connection or for the whole bot, and when it's emptied. A script's variables are gone every time it stops, whether through Stop, Run in the editor or a dropped connection. The bot's memory is where a script keeps what it must find again: a count, how far it got, a choice it made. It belongs to the bot, not to the script, and every package the bot runs reads and writes the same one. This page explains how it behaves and how to use it. asterobot:bot has the reference of its four functions. A first example This script counts the chat messages its bot receives. The count goes on across Stop and Play, and across reconnections: import { memory, session, botInfo } from "asterobot:bot"; import { on, send } from "asterobot:protocol"; const KEY = "@alice:chat-count/total"; export default async function behavior(launch) { on("ChatChannelMessageEvent", () => { const total = (memory.get(KEY) ?? 0) + 1; memory.set(KEY, total); botInfo(`${total} chat messages seen by this bot`); }); // A new game connection starts with this message. MITM bots never launch // with "initial": the Dofus client has already identified their session. if (launch.reason === "initial") { await send("IdentificationRequest", { ticketKey: session.gameToken, languageCode: session.language, }); } } Stop the script after three messages and play it again: the next message shows 4 chat messages seen by this bot. A variable in the module would have started again from 0. How it works The memory is a set of keys, each naming one value. Function What it does memory.get(key) Returns a copy of the value stored under key, or undefined memory.set(key, value) Stores a copy of value under key, replacing what was there memory.delete(key) Removes key, and returns whether it was there memory.keys() Returns every stored key, sorted All four are synchronous: the memory is held by Asterobot, in the computer's memory, and nothing is written to disk. Keys A key is a string of up to 256 bytes. Every package on the bot sees every key, so start yours with your package's name, as in @alice:chat-count/total. Two packages then never pick the same key by accident. Nothing checks it: it's a convention. Values A value is plain data: null, a boolean, a number, a string, a BigInt, an array or a plain object, nested at most 32 levels. BigInts stay BigInts, which matters for the ids messages carry, such as map and character ids. Anything else throws a TypeError that says where in the value the problem is. That includes undefined, a function, NaN, a Map, a Date, a symbol and an instance of a class. To remove a key, use memory.delete(), not undefined. To keep a Date, store date.getTime(). Values are copies set() stores a copy, and get() returns a new copy each time. Changing what you read changes nothing stored: import { memory } from "asterobot:bot"; const KEY = "@alice:farm/route"; // Adds a cell to the stored route. export function addCell(cell) { const route = memory.get(KEY) ?? { cells: [] }; route.cells.push(cell); // Changes this copy only. memory.set(KEY, route); // Now it's stored. } The keys of an object you read back come sorted by name, whatever order you wrote them in. How long it lasts The memory belongs to the bot. It's created with the bot, and it's gone only when the bot is: What happens The script's variables The bot's memory session.connectionId currentMap() Stop, then Play Start over Kept Same Kept Run from the editor, or loading another package Start over Kept Same Kept The script stops with an error Start over Kept Same Kept Apply on the bot's Package settings, or a bot setting other than its account or game version changed Kept: the script keeps running Kept Same Kept The game connection closes, and the bot connects again Start over Kept One more undefined until the character is on a map A new Dofus session through a MITM bot Start over Kept One more undefined until the character is on a map The bot's Ankama account or game version is changed Start over Emptied: the bot is rebuilt Counts from 1 again undefined The bot is deleted Gone Gone Asterobot restarts Gone Emptied for every bot Counts from 1 again undefined A bot can't read another bot's memory, and every bot has its own. Choosing how long your data lives The memory keeps everything until the bot goes away. Most data belongs to something shorter, so store what it belongs to next to it, and ignore a value that belongs to something else. For the whole bot Store the value as it is, as the first example does. It's there on every connection, until the bot is rebuilt or Asterobot restarts. For one game connection Much of what a script learns only holds for one game connection: the connection was identified, the character was selected, the server sent three polls. After a reconnection it's wrong, and must be ignored. session.connectionId says which connection a script runs on: a BigInt that grows by one each time the bot gets a new game connection, and stays the same for every start on one connection. Store it next to the value: import { memory, session, botInfo } from "asterobot:bot"; import { on, send } from "asterobot:protocol"; const KEY = "@alice:chat-count/connection"; export default async function behavior(launch) { on("ChatChannelMessageEvent", () => { // Only a count stored on this game connection goes on: after a // reconnection, it starts over. const stored = memory.get(KEY); const count = (stored?.connection === session.connectionId ? stored.count : 0) + 1; memory.set(KEY, { connection: session.connectionId, count }); botInfo(`${count} chat messages on this connection`); }); // A new game connection starts with this message. MITM bots never launch // with "initial": the Dofus client has already identified their session. if (launch.reason === "initial") { await send("IdentificationRequest", { ticketKey: session.gameToken, languageCode: session.language, }); } } launch.reason can't replace the id. "initial" means no start has succeeded on the connection yet: a start that fails half way, after sending something, leaves the next one "initial" on the same connection. See When a start counts. Keep the id inside the value rather than in the key. A key such as `@alice:chat-count/${session.connectionId}` adds a new key for every connection, and they pile up until the memory is full. With the id inside, each new connection's first set() replaces the old value. For one character The same bot can play different characters over time. For data about one character, store its id, from currentMap()?.characterId, next to the value, the same way as the connection's id. Keeping a connection's state A script that goes through steps, such as identifying and then waiting for its character, needs to know on each start how far the connection already got. Keep that in one object per connection, under one key, with the connection's id and a field for each step that has happened: import { memory, session, botInfo } from "asterobot:bot"; import { on, send } from "asterobot:protocol"; const KEY = "@alice:hello/connection"; // The state of the current connection: what's stored, if it was stored on // this connection, or a fresh state with only the id. function connectionState() { const stored = memory.get(KEY); return stored?.id === session.connectionId ? stored : { id: session.connectionId }; } // Adds fields to the current connection's state. function updateConnection(changes) { memory.set(KEY, { ...connectionState(), ...changes, id: session.connectionId }); } export default async function behavior(launch) { on("CharacterLoadingCompleteEvent", () => { updateConnection({ loadedAt: Date.now() }); }); const state = connectionState(); if (state.loadedAt !== undefined) { const seconds = Math.round((Date.now() - state.loadedAt) / 1000); botInfo(`The character has been loaded for ${seconds} s`); } // Recorded before sending: a script stopped right after the send must never // identify a second time on this connection. A MITM bot's Dofus client has // already identified the session. if (!state.identified && !session.shared) { updateConnection({ identified: true }); await send("IdentificationRequest", { ticketKey: session.gameToken, languageCode: session.language, }); } } This script uses the state to identify instead of launch.reason. That way it identifies exactly once per connection, even when a start fails half way. How this state behaves: A field is absent until its step has happened. A fresh state is { id } and nothing else, so state.loadedAt === undefined means "not loaded yet on this connection". Record before you send, when sending twice would be wrong. If the script stops between set() and send(), the next start knows it must not send again. The other order risks sending twice. Handlers keep it up to date, whichever step the script is at, so a script started again later reads what happened while it ran. It resets by itself on a new connection, without being deleted. The stored value keeps the old connection's id, so connectionState() reads it as a fresh state, and the first updateConnection() replaces it. It's empty after Asterobot restarts, like the rest of the memory. The bot comes back disconnected, so there's no connection left for it to describe anyway. @asterobot:base keeps its own state this way, under @asterobot:base/connection. Sharing between packages Every package the bot runs sees the same memory: its own package, its dependencies, and any package the bot plays later. A value one package stores is there for another to read. // In @alice:scout: remember where the bot saw an ash tree. import { memory } from "asterobot:bot"; export function sawAshTree(mapId, cellId) { const trees = memory.get("@alice:scout/ash-trees") ?? []; memory.set("@alice:scout/ash-trees", [...trees, { mapId, cellId }]); } // In @bob:harvest: read what the scout found, if anything. import { memory } from "asterobot:bot"; export function ashTrees() { return memory.get("@alice:scout/ash-trees") ?? []; } A map id read from a message is a BigInt, and it comes back a BigInt: ashTrees()[0].mapId === 153879301n. Only rely on keys a package says are meant to be shared, and only read them: the format of another package's key is that package's business, and can change with its next version. The keys of @asterobot:base are its own bookkeeping. Read them if you need to, and never write them. Writing safely A bot runs one script at a time, and all its packages run in that one script. The four functions are synchronous. So nothing else can write between your get() and your set(), as long as there's no await between them: import { memory, botInfo } from "asterobot:bot"; import { sleep } from "asterobot:timers"; const KEY = "@alice:chat-count/total"; export async function countLater() { await sleep(1000); // Read, change and write with no await in between. Reading before the // sleep would lose whatever a handler added during it. const total = (memory.get(KEY) ?? 0) + 1; memory.set(KEY, total); botInfo("Total:", total); } set() throws when a value isn't plain data or doesn't fit the limits. In a handler, catch it: an error that escapes a handler stops the whole script. import { memory, botWarn } from "asterobot:bot"; import { on } from "asterobot:protocol"; // Called from the entry function. export function rememberLastMessage() { on("ChatChannelMessageEvent", (traffic) => { try { memory.set("@alice:chat/last", traffic.payload?.content ?? null); } catch (error) { // An error that escapes a handler stops the whole script. botWarn("Couldn't store the message:", String(error)); } }); } Limits The limits are for the whole bot, all packages together: Limit Value Keys 1024 One key 256 bytes One value 64 KiB All values together 1 MiB Levels of arrays and objects in a value 32 A value's size is roughly the size of its JSON text, with every number counted as 8 bytes. memory.delete() frees what a key held. The memory is meant for small pieces of state, not for data sets: Limits gives the exact error each limit throws. While Asterobot reads your package's settings Asterobot also runs the top level of your modules when it reads your package's settings, without a bot. At that moment get() returns undefined, keys() returns an empty array, and set() and delete() throw, which makes the reading fail. So call the memory functions from your entry function and your handlers, as the samples on this page do, not from the top level of a module. See Declarations. Seeing what's stored On a bot's page, Tools > Memory lists every key with its value and when it last changed, under Key, Value and Last changed. It refreshes by itself when a script changes the memory, and only reads it. An empty memory shows Nothing stored yet. A BigInt shows as its digits followed by n, as in 153879301n, and null shows as a dash. When the list can't be read, the page shows Couldn't read this bot's memory. The refresh button next to the description reads it again. The asterobot:bot reference has every rule and error of the four functions, and Sessions covers what else changes from one game connection to the next. The next chapter, Game protocol, goes into messages in detail.
-
0.3.0
0.3.0 - 03/10/2026✨ AjoutéLes bots peuvent quitter leur carte par un côté. Le personnage se déplace jusqu’à la sortie la plus proche de ce côté, comme dans le jeu lorsque vous cliquez dans cette direction, puis arrive sur la carte suivante. Vous pouvez également choisir la sortie exacte, ce qui est utile sur les quelques cartes où un même côté mène à plusieurs endroits différents. Les bots peuvent utiliser les portes, les zaaps, les ressources et les ateliers. Le personnage se déplace d’abord suffisamment près, comme dans le jeu. Lorsqu’un élément propose plusieurs actions, vous pouvez choisir celle que vous souhaitez effectuer. Les bots peuvent emprunter les petits soleils qui mènent à une autre carte : le personnage se déplace dessus. Le changement de carte et l’utilisation d’éléments fonctionnent en mode Full socket et MITM, avec ou sans script exécuté sur le bot. Un bot n’effectue qu’un déplacement à la fois, que la demande provienne d’Asteroboard ou d’un script. Une deuxième requête est refusée avec un message explicite. Les cartes instanciées sont désormais suivies comme les autres cartes. Asteroboard 0.2.6 et les versions ultérieures utilisent toutes ces fonctionnalités dans l’onglet Map du bot : un bouton de chaque côté de la carte pour quitter par ce côté, Leave by the …, Use: … et Take this exit dans le menu contextuel, ainsi qu’un bouton pour chaque action dans Resources and objects. Les scripts disposent désormais de changeMap() et useElement() dans asterobot:movement, à côté de move(). @asterobot:base les propose également. currentMap() liste les éléments interactifs de la carte ainsi que les actions que chacun propose actuellement. Les proxys HTTP sont désormais pris en charge, en plus des proxys SOCKS5. De nombreux fournisseurs proposent des « proxys HTTP/HTTPS » : vous pouvez les utiliser. Certains n’autorisent que le trafic web sécurisé (port 443), ce qui suffit pour un compte mais pas pour la connexion du jeu d’un bot ; dans ce cas, utilisez un proxy SOCKS5 pour le bot. Il est désormais possible de définir un proxy pour chaque compte Ankama. Tout ce qu’Asterobot fait avec Ankama pour ce compte passe par celui-ci : la connexion automatique, le maintien de la session, Verify, ainsi que ce dont un bot a besoin pour se connecter. Cela est notamment utile lorsqu’Asterobot fonctionne sur un serveur loué dont l’adresse est refusée par le système de connexion d’Ankama. Les bots utilisent le proxy de leur compte par défaut, sauf si vous choisissez une autre configuration. Ainsi, un seul proxy défini sur un compte suffit pour l’ensemble des connexions. Un bot peut néanmoins avoir son propre proxy ou utiliser l’option Always connect directly. Plusieurs comptes peuvent partager un même proxy, afin de donner l’impression qu’ils se connectent depuis le même emplacement. Le navigateur utilisé pour la connexion automatique passe lui aussi par le proxy du compte, y compris avec les proxys SOCKS5 nécessitant un mot de passe, et ne peut pas révéler votre véritable adresse. Davantage de messages du jeu sont désormais reconnus par leur nom : progression des quêtes, métiers et crafts, tags de stockage, succès, classements d’arène et nombre de combats sur une carte. Un nouveau tutoriel est disponible dans le guide développeur : Harvest and move on. Il s’agit d’un script complet qui récolte une route de cartes, avec des exemples pour les portes, les soleils, les zaaps et le choix d’une sortie. 🔄 ModifiéLorsqu’un bot avait son champ Proxy vide, il se connectait auparavant directement. Il utilise désormais le proxy de son compte, ce qui ne change rien tant qu’aucun proxy n’est configuré sur le compte. Lorsque le serveur refuse un déplacement, move() échoue désormais immédiatement avec un message explicite au lieu d’attendre. Un proxy encore utilisé par un compte ne peut pas être supprimé, comme c’était déjà le cas pour les bots. Les pages Map et Proxies du guide utilisateur ont été réécrites. Les pages consacrées aux comptes, aux bots et au dépannage couvrent également les nouvelles options et les nouveaux messages, en anglais et en français. Mise à jour des dépendances. 🔒 SécuritéLorsqu’un proxy est manquant, Asterobot refuse désormais de se connecter au lieu de se connecter depuis votre propre adresse, aussi bien pour les comptes que pour les bots.
-
0.2.6
0.2.6 - 03/10/2026✨ AjoutéPortugais brésilien (pt-BR), comme langue d’interface aux côtés de l’anglais, du français et de l’espagnol. Les libellés qui désignent des éléments nommés par le jeu (« Inventory », « Haven Bag », les emplacements d’équipement) utilisent désormais les termes officiels du jeu dans chaque langue. Un onglet Memory sous les Tools d’un bot : il affiche ce que les scripts du bot ont enregistré dans sa mémoire partagée, ainsi que la date de dernière modification de chaque clé. L’onglet Map d’un bot permet désormais de déplacer le personnage, y compris pour quitter sa carte. Asteroboard ne planifie rien lui-même : il demande à Asterobot d’effectuer l’action, qui reproduit le comportement du client du jeu lors d’un clic. De chaque côté de la carte du bot, un bouton de déplacement situé à côté de la flèche permet de quitter la carte par ce côté, depuis la sortie que le personnage peut atteindre le plus rapidement. La flèche continue simplement d’ouvrir la carte adjacente à l’écran. Le bouton est grisé, avec la raison indiquée dans son infobulle, lorsque le bot ne peut pas se déplacer ou lorsque le graphe de déplacement ne permet pas d’atteindre la carte adjacente. Le menu contextuel accessible par clic droit propose Leave by the … sur une cellule de sortie, afin de quitter la carte depuis cette cellule, ainsi que Use: … et Take this exit pour les éléments présents sur la cellule. Resources and objects dispose désormais d’un bouton pour chaque action sur chaque ligne. Le bot n’effectue qu’un déplacement à la fois : les contrôles sont grisés pendant l’opération et, en cas d’échec, une notification affiche la raison fournie par Asterobot. La carte en temps réel suit désormais MapCurrentInstanceEvent, que le serveur envoie à la place de MapCurrentEvent pour une carte instanciée. L’onglet Map comporte désormais 14 messages ; par conséquent, pour un bot dont la carte en temps réel était déjà activée, le suivi est désactivé et doit être réactivé une fois. Pour les développeurs : useBotWalk prend désormais en charge changeMap et useElement, avec une même protection partagée avec walkTo ; DofusMapCellActions : les actions du clic droit reçoivent désormais les données de la carte de la cellule ainsi que les éléments présents dessus ; DofusMapSideActions : une page peut placer son propre bouton à côté de la flèche de chaque côté ; MapViewer et Atlas/Browser transmettent désormais les deux ; elementActions et EXIT_SKILL dans utils/botMap.ts ; les noms des éléments sont lus une seule fois sur la page puis transmis à la liste. Les nouvelles chaînes de caractères sont disponibles en en, fr, es et pt-BR. Proxys : Proxy Manager prend désormais en charge les proxys HTTP en plus des proxys SOCKS5 : la boîte de dialogue propose un choix Type, la liste affiche le type de chaque proxy et Used by indique les comptes utilisant un proxy (avec une icône représentant une personne) à côté des bots. Account Manager : un champ Proxy dans Add an account, une action Set proxy dans le menu de chaque ligne (boîte de dialogue Proxy for …) et une colonne Proxy. Le champ Proxy d’un bot propose Same as the account (…), qui est la valeur par défaut, Always connect directly, ou un proxy enregistré. La colonne Proxy du Bot Manager indique le proxy réellement utilisé par chaque bot, avec la mention « (account) » lorsque celui-ci utilise le proxy de son compte. Spécification OpenAPI : types de proxys, proxyName sur les comptes, PUT /accountmanager/{loginId}/proxy, ainsi que la nouvelle signification d’une valeur vide pour Bot.proxyName. Aide à la connexion sur la page d’accueil. Lorsque Asteroboard ne parvient pas à joindre Asterobot, un panneau Can't connect to your Asterobot? indique, dans l’ordre, les éléments à vérifier. Il apparaît après l’échec d’une tentative de connexion ou après 4 secondes de connexion en cours (une fenêtre de permission du navigateur sans réponse peut bloquer la connexion), puis disparaît dès que la connexion est établie. Start Asterobot : démarrer Asterobot et le laisser fonctionner. Allow your browser to connect to it : les navigateurs demandent désormais une autorisation avant qu’un site puisse se connecter à des applications présentes sur l’ordinateur ou sur le réseau local (Chrome depuis la version 142, Edge depuis la 143, Firefox à partir de la 151, Brave). Le panneau explique comment identifier la fenêtre d’autorisation et où l’autoriser après avoir manqué la fenêtre ou sélectionné Block : Apps on device (Local network access dans les anciennes versions) dans Chrome et Edge, Device apps and services dans Firefox, Localhost access dans Brave. Check the address : l’adresse à laquelle Asteroboard tente de se connecter, ainsi qu’un raccourci permettant d’ouvrir directement l’adresse d’Asterobot, qui revient ensuite ici avec la configuration déjà renseignée. Make sure nothing blocks it : vérifier le pare-feu, l’antivirus ainsi que les bloqueurs de publicités et de confidentialité. Lorsque le navigateur fournit l’état de la permission, cette étape affiche un badge Blocked, Not allowed yet ou Allowed. Un blocage affiche une alerte rouge en haut de page et, si l’autorisation est accordée alors que la page est ouverte, la reconnexion se fait immédiatement. Boutons Reload the page et Open Preferences. Pour les développeurs : useLocalNetworkPermission(url) lit la permission (loopback-network ou local-network, ou local-network-access pour Chrome 142–144) concernant un serveur présent sur cet appareil ou sur le réseau local ; le panneau se trouve dans Pages/Dashboard/ConnectionHelp.client.vue, avec ses chaînes sous content.dashboard.connectionHelp dans en, fr, es et pt-BR. 🔄 ModifiéLes nombres s'accordent : « 1 joueur », « 3 joueurs » au lieu de « joueur(s) », dans toutes les langues. En français et en portugais, 0 prend le singulier (« 0 joueur »). Les libellés qui nomment un élément du jeu reprennent les termes de DOFUS dans chaque langue : Havre-Sac, emplacements d'équipement (« Dofus ou Trophée »), catégories de l'inventaire, Zaap, Donjon… Traductions relues : typographie française (« guillemets », « 3 h 12 min »), « Temps de fonctionnement » au lieu de « Disponibilité », « cellules » au lieu de « cases », « Monocompte ». L'anglais passe à l'orthographe américaine. Résumé des réglages d'un comportement : « Réglages : 3 · Actions : 2 ». Mise à jour des dépendances 🐛 CorrigéCarte du bot : la carte quittée s'efface dès que le personnage change de carte, sans attendre que le jeu ait chargé la nouvelle. Un clic pendant le changement ne vise plus l'ancienne carte.
-
Faille proxy
Hello merci, je valide et ce sera résolu avec https://asterobot.net/forums/topic/6-%C3%A9tendre-la-gestion-des-proxies/#comment-7