Tout ce qui a été publié par Smooth
-
HavenBagFurnitureEvent
The furniture of the haven bag you are in: one Element per piece (cell, furniture id, orientation). Kind event · Area Game.Haven.Bag Place every Element of furniture on the current map: 1. Look the piece up in the haven-bag furniture data by element_id. 2. Put it on cell cell_id. 3. Mirror it when orientation is odd. The client does nothing with the list until the haven-bag map has finished loading: if the map is not ready yet, it waits for it, then places the furniture. Do the same. Do not send anything back. To change the furniture, enter edit mode and send HavenBagFurnitureRequest. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this the server sends the bag's furniture when you are in a haven bag; the client may receive it before the haven-bag map has finished loading Fields #FieldTypeMeaningYou set it 1furniturerepeated ElementEvery piece of furniture in the haven bag. Type Element.never
-
HavenBagEnterRequest
Asks to enter the haven bag of the character `owner` (the 'visit' entry of the friends and guild member lists). Kind request · Area Game.Haven.Bag Set owner to the character id of the player whose haven bag you want to enter: a friend or a guild member, as their contact entry gives it. Leave every other member at its default; the client never sets one. The client sends nothing else with it and waits for no direct answer: if the owner lets you in, you change map like any other map change. When you may send it Requires context_ready inferred Raised by: the player picks 'visit haven bag' (ui.havenbag.visit) on a friend or a guild member proven Related messages Reply not yet recovered: entering a haven bag is a map change: the new map arrives like any other map change. The answer messages have no signature here yet. Fields #FieldTypeMeaningYou set it 1ownerint64Character id of the player whose haven bag you want to enter. Observed: 14591459678required
-
HavenBagEditStartEvent
Your haven bag is now in furniture edit mode. Kind event · Area Game.Haven.Bag Switch to furniture edit mode: from now on you may move, add and remove furniture, and save the result with HavenBagFurnitureRequest. It carries nothing. Edit mode lasts until HavenBagEditFinishedEvent (empty too), which switches it off. Do not send anything back. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this the server switches your haven bag to edit mode after you ask to edit it (HavenBagEditRequest, not signed yet); nothing in the client waits for it
-
FighterResumeInfo
One controlled fighter's spell state in a running fight: its cooldowns and cast counts. Kind struct · Area Game.Fight One entry of FightResume.slaves_information. - FighterResumeInfo.slave_id: the fighter it describes. - FighterResumeInfo.spell_cool_downs: the remaining cooldown of each listed spell. - FighterResumeInfo.cast_counts: this turn's cast count of each spell. The client also reads two int32 counters from it (beta's predecessor record names them summon_count and bomb_count) and a list of int32; they are not named here. Not sent on its own — a record carried by FightResume, never sent on its own. inferred Used by FightResume Fields #FieldTypeMeaningYou set it 3slave_idint64The fighter this entry describes. (entity id) The client looks up that fighter's spell state and summon counters by it. Field name of beta's predecessor record FightResumeSlaves; no build names this record's fields.never 4spell_cool_downsrepeated FightSpellCoolDownRemaining cooldown of each listed spell of this fighter. Element type FightSpellCoolDown. Field name of beta's predecessor record FightResumeSlaves; no build names this record's fields.never 5cast_countsrepeated FightSpellCastThis fighter's cast count of each spell. Same role and name as RefreshSpellCastStateEvent.cast_counts. Element type FightSpellCast.never
-
FightTurn
A point in the fight timeline: a round and a turn order inside that round. Kind struct · Area Game.Common This name is not Ankama's. It was chosen for this documentation from proven client behaviour, and is a label rather than protocol documentation. Names one turn of the fight: which round, and which turn inside the round. Effects and marks use two of them to say when they start and when they end. HOW TO READ IT 1. FightTurn.round is the round number. 2. FightTurn.order is the position of the turn inside that round. 3. Compare two positions round first, then order. An effect lasting from start_turn to end_turn is active on every turn between them. Not sent on its own — a record carried by FightRemovableEffect and FightMark, never sent on its own. inferred Used by FightMark FightRemovableEffect Fields #FieldTypeMeaningYou set it 1orderint32The turn's position inside the round. After the client's FightTurn.order, the field the client stores it into.never 2roundint32The round number. After the client's FightTurn.round, the field the client stores it into.never
-
FightSpellsUpdateEvent
A fighter's new spell list and spell bar for the rest of the fight. Kind event · Area Game.Fight Gives ONE fighter a new spell list and spell bar, in the middle of a fight. It is played in the fight's sequence, like the other fight events: apply it in the order received. WHAT TO DO WHEN YOU RECEIVE IT 1. FIND the fighter: FightSpellsUpdateEvent.fighter_id. It is your character or a fighter you command (see FightControlEvent). 2. REPLACE that fighter's fight spell list with FightSpellsUpdateEvent.spells. When the fighter is your character, add your breed's own spells to it, as for SpellsEvent#human_spells. 3. REPLACE that fighter's spell bar with FightSpellsUpdateEvent.shortcuts. 4. SEND NOTHING BACK. The second list of spells in the message is never read by the client: ignore it. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this the server sends it when a fighter's spells change during a fight; no request asks for it Fields #FieldTypeMeaningYou set it 1shortcutsrepeated ShortcutThe fighter's whole spell bar; it replaces the previous one. Element type Shortcut, as in ShortcutBarContentEvent; each entry carries its slot.never 3fighter_idint64The fighter whose spells and spell bar change.never 4spellsrepeated SpellItemThe fighter's whole spell list for the fight; it replaces the previous one. Element type SpellItem. For your own character the client adds your breed's spells.never
-
FightResume
The spell state of the fighters you control in a running fight: global cast counts and, per fighter, cooldowns and cast counts. Kind struct · Area Game.Fight Carried by FightJoinRunningEvent.resume. - FightResume.slaves_information: one entry per fighter you control (FighterResumeInfo); restore each fighter's cooldowns and cast counts. - FightResume.global_cast_counts: the cast counts shared by all of them; the client hands them to every fighter's spell state. A third list (pairs of int32) is read by the client but not named here. Not sent on its own — a record carried by FightJoinRunningEvent, never sent on its own. inferred Used by FightJoinRunningEvent Fields #FieldTypeMeaningYou set it 1global_cast_countsrepeated FightSpellCastCast counts shared by every fighter you control. Same role and name as RefreshSpellCastStateEvent.global_cast_counts: the client hands it as the global cast counts to each fighter's spell state. Element type FightSpellCast.never 2slaves_informationrepeated FighterResumeInfoOne entry per fighter you control. Element type FighterResumeInfo. Field name of beta's FightResume, whose list held the predecessor record FightResumeSlaves; no build names this field since.never
-
FightMark
A mark laid on the fight map (glyph, trap, wall, portal, rune ...): who laid it, with which spell, on which cells, for how long. Kind struct · Area Game.Common A mark laid on the fight map: a glyph, a trap, a wall, a portal, a rune ... It is carried by MarkCells when it appears and by FightJoinRunningEvent.marks when you join a running fight. TO TRACK A MARK 1. Key it by FightMark.mark_id; UnmarkCells removes it by that id. 2. Its cells: for each entry of FightMark.cells, the cell and, when the entry has a zone size, the zone of that size around it (MarkedCell). 3. Who and what: FightMark.author_id laid it, for FightMark.team, with the spell FightMark.spell_id at level FightMark.spell_level; its kind is FightMark.mark_type (MarkType: GLYPH, TRAP, WALL, PORTAL, RUNE; value 5 is a sixth kind with no known name, value 6 is never used by the client). 4. What it does when triggered: for most kinds, the spell FightMark.first_param at level FightMark.second_param (one kind triggers its own spell). 5. FightMark.active says whether it currently triggers; it lasts from FightMark.start_turn to FightMark.end_turn (FightTurn positions). 6. FightMark.mark_impact_cell is the cell the spell targeted, and FightMark.cast_cell_id the cell it was cast from. One declared bool is never read: padding. Not sent on its own — a record carried by MarkCells and FightJoinRunningEvent, never sent on its own. inferred Used by FightJoinRunningEvent MarkCells Fields #FieldTypeMeaningYou set it 1teamTeamThe team the mark belongs to.never 2start_turnFightTurnThe turn the mark starts. Name ours, after FightTurnWindow(start). Type FightTurn (round, order).never 3mark_impact_cellint32The cell the spell that laid the mark targeted (its centre). (cell id)never 4mark_typeMarkTypeThe kind of mark (glyph, trap, wall, portal, rune ...). Its enum is MarkType: GLYPH, TRAP, WALL, PORTAL, RUNE, plus an unnamed sixth kind (value 5) and a value the client never converts (6).never 6author_idint64The fighter that laid the mark. (fighter id)never 7cellsrepeated MarkedCellThe cells the mark covers. Element type MarkedCell.never 8activeboolWhether the mark currently triggers.never 9third_paramint32Third parameter of the mark (for one kind, the colour of its cells). Name ours, after FightMark(param3).never 10effect_idint32The spell effect that laid the mark, when known. Explicit presence: absent is not the same as zero. Name ours, after FightMark(effectId). Optional: absent when unknown.never 11spell_idint32The spell that laid the mark. (spell id)never 12cast_cell_idint32The cell the spell was cast from. (cell id) Name ours, after the client's FightMark(castCellId).never 13second_paramint32Second parameter: for most kinds, the level of the triggered spell. Name ours, after FightMark(param2). The client uses it as the triggered spell's level.never 14end_turnFightTurnThe turn the mark ends. Name ours, after FightTurnWindow(end). Type FightTurn (round, order).never 15first_paramint32First parameter of the mark: for most kinds, the spell it triggers. Name ours, after FightMark(param1). The client looks it up as a spell id for the triggered spell.never 16spell_levelint32The level of that spell.never 17mark_idint32Identifier of the mark; UnmarkCells removes it by this id.never
-
FightJoinRunningEvent
Everything needed to pick up a fight already in progress: the round, when the fight started, the effects in play and your fighters' spell state. Kind event · Area Game.Fight Restores a fight that is already running, typically after a reconnection. WHAT TO DO WHEN YOU RECEIVE IT 1. Set the current round to FightJoinRunningEvent.game_turn. 2. Keep FightJoinRunningEvent.fight_start, when the fight started. 3. Apply FightJoinRunningEvent.effects, the effects currently on fighters. 4. Restore your fighters' spell state from FightJoinRunningEvent.resume (FightResume): cooldowns and cast counts per fighter you control, plus the global cast counts. 5. SEND NOTHING BACK. The marks on the map are in FightJoinRunningEvent.marks (FightMark). One more list travels with it (beta calls it the effect trigger counts); it is not named here. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this the server sends it when you join a fight already under way, notably after a reconnection; no request asks for it Fields #FieldTypeMeaningYou set it 1resumeFightResumeYour fighters' spell state to restore. Element type FightResume.never 2fight_startint32When the fight started. Unit not proven: the client only forwards it in a notification nothing consumes.never 4effectsrepeated FightRemovableEffectExtendedInformationThe effects currently on fighters. Element type FightRemovableEffectExtendedInformation.never 5game_turnint32The current round of the fight. The client files it as the round of its current turn value.never 6marksrepeated FightMarkThe marks on the map (glyphs, traps, walls ...). Element type FightMark.never
-
FightFighterRefreshEvent
A fighter already shown in the current fight changed cell, direction or look. Kind event · Area Game.Fight Updates one fighter you ALREADY show in the current fight. The record is an ActorPositionInformation: the fighter's id, its cell and direction (EntityDisposition), and its actor information with the new ActorInformation.look. WHAT TO DO WHEN YOU RECEIVE IT 1. Find the fighter by ActorPositionInformation.actor_id. It must already be known (from FightFighterShowEvent or FightSynchronizeEvent): the client does not create a fighter from this message, and its handler fails on an unknown id. 2. Set the fighter's cell to EntityDisposition.cell_id and its direction to EntityDisposition.direction. 3. Replace the look you keep for that fighter with the record's ActorInformation.look. 4. If a fight action sequence is running (between SequenceStartEvent and its end), the client also queues the redraw as a step of that sequence, so it is shown after the actions received before it. Apply your own state change at once; only the animation waits. 5. Send nothing back. No handler of this message builds a request. NOT A SPAWN. FightFighterShowEvent carries the same record plus static_pose and adds a fighter; this message carries no flag and only refreshes one. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this the server sends it when a fighter's position or look changes during the fight; no request asks for it Fields #FieldTypeMeaningYou set it 1informationActorPositionInformationThe fighter's id, its new cell and direction, and its new look. An ActorPositionInformation. The client reads its actor_id, the disposition's cell and direction, and the look of its actor information.never
-
ExchangeWeightEvent
Current and maximum weight of the storage you have open (bank, haven-bag chest): refresh its weight bar. Kind event · Area Game.Exchange The weight of the storage you have open, NOT your own inventory's weight (InventoryWeightEvent carries that). - current_weight: what the storage holds now. - max_weight: how much it can hold. THE TWO ARE BOTH INT32. DO NOT MIX THEM UP: in the capture max_weight is 3085 and current_weight 2379. The client only redraws the storage window's weight bar from it. Any other declared member is padding: ignore it. Do not send anything back. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this the server sends it whenever the open storage's weight changes; no request asks for it Fields #FieldTypeMeaningYou set it 1max_weightint32Weight the open storage can hold at most. Observed: 3085never 2current_weightint32Weight the open storage holds now. Observed: 2379never
-
Element
One piece of haven-bag furniture: which furniture, on which cell, facing which way. Kind struct · Area Game.Haven.Bag One piece of furniture, in HavenBagFurnitureEvent (what the bag contains) and in HavenBagFurnitureRequest (what you save). THE THREE MEMBERS ARE ALL INT32. DO NOT MIX THEM UP. - element_id: WHICH furniture. Look it up in the haven-bag furniture data. - cell_id: the map cell the piece stands on. - orientation: which way it faces. The client mirrors the piece when it is odd. Not sent on its own — a record inside the haven-bag furniture messages, never sent on its own. inferred Used by HavenBagFurnitureEvent HavenBagFurnitureRequest Fields #FieldTypeMeaningYou set it 1element_idint32Which furniture: its id in the haven-bag furniture data.required 2cell_idint32The map cell the piece stands on.required 3orientationint32Which way the piece faces; the client mirrors it when the value is odd.required
-
EffectDissipationState
What can remove an effect from a fighter: any dispel, only death, only a strong dispel, or nothing. Kind enum · Area Game.Common Carried by FightRemovableEffect.dissipation_state. A dispel removes every effect it is allowed to remove; check this value first: DISSIPATED goes with any dispel, DISSIPATED_BY_STRONG_DISPEL only with a strong one, DISSIPATED_BY_DEATH only when the carrier dies, REALLY_NOT_DISSIPATED never. Not sent on its own — an enum is never sent on its own. inferred Used by FightRemovableEffect Values ValueNumberMeaning DISSIPATED0Removed by any dispel. The client turns it into its dispellable code DISPELLABLE (beta's client name). DISSIPATED_BY_DEATH1Removed only when the carrier dies. The client turns it into its dispellable code DISPELLABLE_BY_DEATH (beta's client name). DISSIPATED_BY_STRONG_DISPEL2Removed only by a strong dispel (or death). The client turns it into its dispellable code DISPELLABLE_BY_STRONG_DISPEL (beta's client name). REALLY_NOT_DISSIPATED3Never removed by a dispel. The client turns it into its dispellable code REALLY_NOT_DISPELLABLE (beta's client name).
-
ChallengeState
Whether a fight challenge is completed, failed or still running. Kind enum · Area Game.Challenge The state of a Challenge. HOW TO READ IT 1. CHALLENGE_RUNNING: the challenge is in progress. 2. CHALLENGE_COMPLETED: it succeeded; its bonus applies. 3. CHALLENGE_FAILED: it failed. Not sent on its own — an enum is never sent on its own. inferred Used by Challenge Values ValueNumberMeaning CHALLENGE_COMPLETED0The challenge succeeded. CHALLENGE_FAILED1The challenge failed. CHALLENGE_RUNNING2The challenge is in progress.
-
Challenge
One fight challenge: which challenge, its experience and drop bonuses, its targets and its state. Kind struct · Area Game.Challenge One challenge of a fight (proposed, chosen or running). HOW TO READ IT 1. Challenge.challenge_id is the challenge in the game data (name, description). 2. Challenge.xp_bonus and Challenge.drop_bonus are its two rewards, in percent; the fight's ChallengeBonus says which of the two applies. 3. Challenge.targets are the fighters the challenge is about. 4. Challenge.state says whether it is running, completed or failed. One declared enum member is never read by the client: ignore it. Not sent on its own — a record carried by the challenge messages, never sent on its own. inferred Used by ChallengeAddEvent ChallengeListEvent ChallengeProposalEvent ChallengeSelectedEvent ChallengeTargetsEvent Fields #FieldTypeMeaningYou set it 1stateChallengeStateWhether the challenge is running, completed or failed. Enum ChallengeState.never 2challenge_idint32The challenge's id in the game data. The client looks it up in ChallengesDataRoot.never 3xp_bonusint32The experience bonus the challenge gives, in percent. Shown with the experience icon.never 4drop_bonusint32The drop bonus the challenge gives, in percent. Shown with the chest icon.never 5targetsrepeated type not documented yetThe fighters the challenge is about.never
-
BaseStatistics
Your character's seven fight totals: damage done, taken and blocked, shield applied, heals done and taken, enemies finished. Kind struct · Area Game.Fight Seven totals for one fighter over the whole fight, as the fight result screen shows them in your character's tab. Each value is a plain count; nothing is a rate. HOW TO READ IT 1. BaseStatistics.damage_done, BaseStatistics.damage_taken and BaseStatistics.blocked_damage are the damage totals. 2. BaseStatistics.applied_shield is the shield the fighter gave. 3. BaseStatistics.heal_done and BaseStatistics.heal_taken are the heal totals. 4. BaseStatistics.kill_count is the number of enemies the fighter finished. The per-category breakdown (by direct hit, poison, push ...) is in DetailedStatistics, not here. Not sent on its own — it travels inside FightStatisticsEvent.base_statistics, never sent on its own. inferred Used by FightStatisticsEvent Fields #FieldTypeMeaningYou set it 1applied_shieldint32Total shield points the fighter applied. Name of beta's FightStatisticsEvent member.never 2heal_doneint32Total healing the fighter gave. Name of beta's FightStatisticsEvent member.never 3heal_takenint32Total healing the fighter received. Name of beta's FightStatisticsEvent member.never 4damage_doneint32Total damage the fighter dealt. Name of beta's FightStatisticsEvent member.never 5damage_takenint32Total damage the fighter received. Name of beta's FightStatisticsEvent member.never 6blocked_damageint32Total damage the fighter blocked. Name of beta's FightStatisticsEvent member.never 7kill_countint32Number of enemies the fighter finished. Name of beta's FightStatisticsEvent member.never
-
ApplySpellModifierEvent
One spell modifier now applies to a fighter: add it to that fighter's modifiers. Kind event · Area Game.Spell Adds ONE modifier to ONE fighter. It is a change, not the whole list (FightControlEvent.spell_modifiers replaces the whole list). WHAT TO DO WHEN YOU RECEIVE IT 1. FIND the modifiers of the fighter ApplySpellModifierEvent.actor_id. Start an empty set if the fighter has none yet. 2. FIND the entry for the modifier's spell and modifier type (see SpellModifier). Create it when it is missing. 3. SET that entry's values for the modifier's action type. Leave the entry's other action types and the fighter's other entries as they are. 4. SEND NOTHING BACK. RemoveSpellModifierEvent undoes step 3 for one action type. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this the server sends it when an effect starts modifying a fighter's spell; no request asks for it Fields #FieldTypeMeaningYou set it 1modifierSpellModifierThe modifier to add: which spell, which property of it, how, and by how much. Element type SpellModifier.never 2actor_idint64The fighter whose spell modifiers change. (entity id) Observed: 783278080291never
-
AlterationsEvent
The complete list of your character's alterations (lasting effects with an expiry). Kind event · Area Game.Character The complete set of your character's alterations: lasting effects (boosts, maluses, states) that expire after a date or a number of fights. WHAT TO DO WHEN YOU RECEIVE IT 1. For each entry of AlterationsEvent.alterations (an Alteration), store or replace the alteration keyed by its id. 2. The client then publishes the whole set it holds; treat the list as the current state. 3. SEND NOTHING BACK. One declared repeated int32 is never read by the client: ignore it. When you may send it Requires character_loaded inferred Related messages Unsolicited - nothing you send causes this the server sends the full list when the character is loaded and after events that change it, such as the end of a fight Fields #FieldTypeMeaningYou set it 1alterationsrepeated AlterationEvery alteration of the character. Element type Alteration.never
-
AlterationExpirationType
How an alteration expires: never, at a date, or after a number of fights. Kind enum · Area Game.Common Says how to read Alteration#expiration_value. HOW TO READ IT 1. INFINITE: never expires; the value is not used. 2. DATE: expires at the date in the value. 3. FIGHT_COUNT, FIGHTS_WON_COUNT, FIGHTS_LOST_COUNT: the value is the number of fights (all, won or lost) left; expired at 0. Not sent on its own — an enum is never sent on its own. inferred Used by Alteration Values ValueNumberMeaning UNKNOWN0Unknown kind. INFINITE1Never expires. DATE2Expires at a date. FIGHT_COUNT3Expires after a number of fights. FIGHTS_WON_COUNT4Expires after a number of won fights. FIGHTS_LOST_COUNT5Expires after a number of lost fights.
-
Alteration
One lasting effect on the character: its data id, when it was created, how and when it expires, and its effects. Kind struct · Area Game.Common One alteration of your character. HOW TO READ IT 1. Alteration.alteration_id is the alteration's id in the game data (its name, description and category come from there). 2. Alteration.creation_time orders alterations: the client sorts them by it. 3. Alteration.expiration_type says how it expires (AlterationExpirationType); Alteration.expiration_value is the limit for that type: a date for DATE, a number of fights left for the fight counts (expired when it reaches 0). 4. Alteration.effects are its effects (ObjectEffect). Not sent on its own — a record carried by the alteration messages, never sent on its own. inferred Used by AlterationsEvent Fields #FieldTypeMeaningYou set it 1expiration_typeAlterationExpirationTypeHow the alteration expires. Enum AlterationExpirationType.never 2alteration_idint64The alteration's id in the game data. The client looks it up in the AlterationData root.never 3expiration_valueint64The expiry limit for that type: a date, or the fights left.never 4creation_timeint64When the alteration was created; the client sorts alterations by it.never 5effectsrepeated ObjectEffectThe alteration's effects. Element type ObjectEffect.never
-
Fight profile format
The exact JSON format of a fight profile, every field with its type, values and default, conditions, actions and targets, how extends merges, and every error and warning Asterobot reports. A fight profile is a JSON object. Players write them on the Fight Profiles page, where the editor shows the same JSON (Fight profiles), and packages ship them in export const fightProfiles (Ship fight profiles). This page is the complete format. What each setting does in a fight is explained, for players, in Profile settings and Rules and conditions. Every field is optional but name. A field left out plays its default, and a field Asterobot doesn't know is kept and ignored, so a profile written for a newer Asterobot still loads. { "version": 1, "name": "Air Cra", "role": "damage", "range": "ranged", "elements": ["air"], "risk": 40, "positioning": "kite", "spells": [{ "id": 32465, "use": "prefer" }], "rules": [ { "when": { "self.life": { "below": "30%" } }, "do": { "retreat": { "to": "outOfReach" } } } ] } Fields Field Type Values Default version number 1 1 name string Required, not blank description string "" extends string A profile's name: "Idle", a pool profile's, or a package's "<package>/<name>" "": none role string "damage", "tank", "support", "healer" The role the game ranks first for the character's class range string "auto", "melee", "mid", "ranged" "auto" elements array of strings "earth", "fire", "water", "air", "neutral" []: whatever hits hardest risk number 0 to 100 50 placement string "auto", "close", "far" "auto" positioning string "auto", "charge", "hold", "kite", "hide" "auto" focus string "auto", "lowestLife", "closest", "mostDangerous" "auto" allies string "ignore", "help", "protect" "help" pvp string "idle", "play" "idle" waitForAllies number 0 or more 0 parts object See parts Every part on weapon object See weapon Normal use, no limit spells array See spells [] opening object See opening No opening monsters array See monsters [] rules array See rules [] weights object See weights The role's weights challenges any Kept and ignored: challenges aren't played yet An empty string in a field that takes a word, such as "role": "", is the same as leaving it out. A word the field doesn't take is an error. parts Field Type Default When false placement boolean true The module doesn't place the character. ready boolean true The module doesn't say the character is ready. movement boolean true The character never walks in its turns. challenges boolean true No effect yet. Writing parts with some fields leaves the others true. weapon Field Type Values Default use string "prefer", "normal", "avoid", "never" "normal" maxPerTurn number 0 or more, 0 for no limit but the weapon's own 0 spells Each entry says what the profile does with one spell. Field Type Values Default id number A spell's id. Required, not 0: the weapon is set with weapon. use string "prefer", "normal", "avoid", "never" "normal" maxPerTurn number 0 or more, 0 for no limit but the spell's own 0 target string "any", "enemy", "ally", "self" "any" minTargets number 0 or more: the enemies a cast must hit 0 when object A condition, where target.life and target.distance test the fighter the spell is cast on Always opening Field Type Values firstTurn array Steps cast first in the character's first turn, before everyTurn's everyTurn array Steps cast first in each of its turns A step is a spell's id, "weapon", or { "spell": <id or "weapon">, "target": <target> } with a target. Steps are cast in order, each when it can be; a step that can't be cast is passed over. A spell listed twice is cast twice. monsters Field Type Values Default id number A monster's id race number A monster race's id focus string "first", "last", "ignore" As any other keepAway number 0 or more: the fewest cells the character ends its turns from it 0 noMelee boolean true: ends its turns at least 2 cells from it false Each entry needs id or race. It applies to every enemy it matches. weights An object of numbers, 0 or more, by scoring term: damage, kill, heal, control, buff, summon, safety, position, waste and allyHarm. A term left out keeps the role's weight. How a turn is scored gives each role's weights. Rules rules is an array of rules, applied in order. Each rule is an object: Field Type Value when object A condition. Left out, the rule always applies. do object Exactly one action. Actions do holds one of these keys: Key Value Kind cast { "spell": <id or "weapon">, "target": <target> }, target optional Forcing attack { "target": <target> }, target optional Forcing heal { "target": <target> }, target optional Forcing buff { "target": <target> }, target optional Forcing endTurn { "after": <seconds> }, after 0 or more, default 0 Forcing retreat { "to": "cover" } or { "to": "outOfReach" } Movement approach { "target": <target> }, target optional: the nearest enemy Movement keepDistance { "min": <cells>, "max": <cells> }, 0 for no bound Movement focus { "target": <target> } Modifier avoid { "spell": <id or "weapon">, "target": <target> }, either or both Modifier Every matching modifier applies. Of the movement rules, the first matching one applies. Of the forcing actions, the opening's steps come first and then the rules in order, and the first one that can be played now is the character's next action. How rules apply describes it in full. Targets A target is one of these strings, or an object: Target Names "self" The character "lowestLifeEnemy" The enemy with the least life left "lowestLifeAlly" The ally with the least life left, the character not counted "closestEnemy" The enemy nearest the character "mostDangerousEnemy" The enemy that could deal the character the most where it stands { "monster": <id> } An enemy of that monster { "race": <id> } An enemy of that monster race { "fighter": <id> } The fighter with that id in the fight Ties go to the lowest fighter id. Conditions A condition is an object whose keys are subjects, each with its test, and the groups all, any and not. It holds when every test and every group in it holds. { "self.life": { "below": "50%" }, "any": [{ "enemies.within": { "cells": 1, "atLeast": 1 } }, { "fight.round": { "atLeast": 5 } }], "not": { "self.state": { "is": 42 } } } Group Value Holds when all An array of conditions Every one holds any An array of conditions At least one holds not A condition It doesn't hold A test is an object with some of these fields: Field Type Holds when below number, or a percent as a string such as "30%" The value is strictly less above number, or a percent as a string The value is strictly more is number The count is exactly this, or that state, monster or race is there atLeast number The count is this or more atMost number The count is this or less cells number For within: the distance counted Subject Test fields Reads self.life below, above The character's life; a percent is of its maximum life self.shield below, above Its shield points; a percent is of its maximum life self.ap below, above Its AP self.mp below, above Its MP self.state is It is in that state enemy.state is A living enemy is in that state ally.state is A living ally, the character not counted, is in that state ally.life below, above A living ally's life is in that range; a percent is of that ally's maximum life enemies.count is, atLeast, atMost Living enemies, summons included allies.count is, atLeast, atMost Living allies, summons included, the character not counted enemies.within cells, then is, atLeast, atMost Living enemies within cells cells of the character allies.within cells, then is, atLeast, atMost Living allies within cells cells enemy.monster is That monster is among the living enemies enemy.race is A monster of that race is among the living enemies fight.round is, atLeast, atMost The fight's round fight.turn is, atLeast, atMost The character's turns in the fight, the current one included target.life below, above In a spell's when only: the life of the fighter it's cast on target.distance below, above In a spell's when only: that fighter's distance in cells A subject the module doesn't know never holds, with a warning. challenge is reserved for challenges and never holds yet. How extends merges A profile with extends starts from the profile it names and writes its own fields over it: Field Merged A string, number or boolean The profile's own replaces the extended one's An object (parts, weapon, opening) Field by field weights Term by term spells The extended profile's entries, then the profile's own; an entry with the same id replaces the extended one monsters The same, by id and race rules The extended profile's rules, then the profile's own The extended profile can't extend another one. A bot playing a profile that extends a package's profile plays the version of that package the bot plays, or else the newest installed. Errors Asterobot refuses a profile it can't play: the editor won't save it, an import is refused, and a pool file or a package's profile shows Can't be played on the Fight Profiles page, a bot set to it playing the default profile. The reason starts with fight: malformed profile:, followed by the field, in the JSON's own path, and what's wrong. Only the first problem is reported. Reason Cause <field>: a <type>, not a <json type> A field holds the wrong kind of value, such as a string where a number goes. The types are Go's: int, int32, float64, string, bool. version: required, 1 version is less than 1 name: required name is missing or blank <field>: "<value>" is not one of <values> A word a field doesn't take: role, range, placement, positioning, focus, allies, pvp, weapon.use, spells[i].use, spells[i].target, monsters[i].focus, rules[i].do.retreat.to, or a target's name risk: <n> is not from 0 to 100 risk out of range elements[i]: "<value>" is not earth, fire, water, air or neutral An unknown element <field>: <n> is below 0 A negative waitForAllies, weapon.maxPerTurn, spells[i].maxPerTurn, spells[i].minTargets, monsters[i].keepAway, weights.<term> or rules[i].do.endTurn.after spells[i].id: required: the weapon is the profile's weapon A spell entry without a spell, or with spell 0 monsters[i]: an id or a race is required A monster entry with neither <target>: names nobody A target object without monster, race or fighter rules[i].do: one action, not <n> A rule's do with no action, or more than one rules[i].do.keepDistance: min <a> is above max <b> min above a non-zero max fight: a spell is an id or "weapon": "<text>" A spell named by any other text when "<key>": <reason> A condition's test that isn't an object of the right shape extends: "<name>" extends another profile, and one level is all The extended profile extends another extends: "<name>": <reason> The extended profile can't be read spells[i] is the entry's place in the list, counted from 0, as in spells[0].use. A target's field is written in full, such as rules[2].do.attack.target or opening.firstTurn[0].target. Pool profiles have their own name errors when they're saved: fightprofiles: a profile's name can't be empty, start with @, or hold / or a character a file name can't, and fightprofiles: a profile already has this name. Warnings Warnings don't stop a profile from playing. The Fight Profiles page counts them and the editor lists them. Warning Cause version: <n> is newer than this module's 1: what it adds is ignored A profile written for a newer Asterobot <path>.<subject>: no such subject: never holds A condition's subject this Asterobot doesn't know weights.<name>: no such scoring term: ignored A weight with an unknown name extends: no profile has this name: its own fields play over the default profile The extended profile is missing spell <id>: not in the game data, ignored An id the newest installed game version doesn't have, also given as monster, monster race and state name: "<name>", but its file is "<file>.json": it plays as "<file>" A pool file whose name differs from its file name
-
Ship fight profiles
Ship fight profiles in a package with export const fightProfiles, so everyone who installs it can play them, with naming, versions, extends, how Asterobot reads them, testing and every error. A fight profile tells Asterobot's fight module how a bot plays its fights. Players make their own on the Fight Profiles page (Fight profiles), and a package can ship some too: a farming package can come with the profiles its fights are tuned for, and a package can exist only to share profiles. Once the package is installed, its profiles show on the Fight Profiles page, and any bot can play them. Where the declaration goes A package ships profiles in one object exported as fightProfiles from its index.js, next to parameters and actions. Each key is a profile's name within the package, and each value is a profile in the fight profile format: export const fightProfiles = { "air-cra": { version: 1, name: "Air Cra", description: "Hits from afar and steps back after casting.", role: "damage", range: "ranged", elements: ["air"], positioning: "kite", }, "air-cra-careful": { version: 1, name: "Air Cra, careful", extends: "@some-author:fighters/air-cra", risk: 20, }, }; For a package named @some-author:fighters, these are @some-author:fighters/air-cra and @some-author:fighters/air-cra-careful: the package's name, a /, then the key. That full name is the one a bot's Profile list shows, the one extends names, and the one players see on the Fight Profiles page with the Package source. Give each profile a name: the format requires one. The page and the bots go by the full name made from the key, whatever name says. fightProfiles is optional, and can sit in another file as long as index.js re-exports it: export { fightProfiles } from "./profiles.js". A profile is plain data. Asterobot reads each one as JSON.stringify would write it, so values can be computed or imported from another file, but functions and undefined disappear. The easiest way to write one is to build it on the Fight Profiles page, where the editor checks every value as you go, then Export it and paste the file's contents into fightProfiles. Which version plays A bot can play a package's profile whether or not it plays the package itself. The bot Plays the profile from Plays that package The version of the package it plays. Plays another package, or none The newest version of the package installed. The page lists each profile from the newest installed version. When you publish an update, its profiles replace the old ones for everyone who updates, and the profiles that extend them, yours or the players', follow. When a player removes your package, the bots set to one of its profiles play the default profile, and their console says so. So treat a profile's key like a public name: renaming one in an update leaves the bots set to the old name on the default profile. Extending A package's profile can extend another profile, with the same rules as the players' own (Extend another profile): one of the same package by its full name, another package's, or Idle. Only one level: a profile can't extend a profile that extends another. Players can extend yours too, and keep their changes on top of your updates. A profile can't extend one of the player's own profiles in a reliable way, since you don't know their names. How Asterobot reads them Asterobot reads fightProfiles with the package's other declarations: it runs the top level of the package's modules without calling the default export, then reads the exports. Declarations describes what the top level can and can't do at that moment. The Fight Profiles page reads the profiles of every installed package this way, whether a bot plays it or not, and keeps the result until the package's files change. Errors Two kinds of problem show in two places. The export's shape. These errors are declaration errors: they also stop the package's script from starting, as an error in parameters does (Declarations). Error Cause package "<package>": fightProfiles: must be an object, got <type> fightProfiles is exported, but isn't an object. package "<package>": fightProfiles: "<name>" must be an object A profile isn't an object. A profile's content. A profile with a value Asterobot can't use doesn't stop anything: the Fight Profiles page marks it Can't be played with the reason, and a bot set to it plays the default profile. Warnings, such as an id the game data doesn't have, show the same way. The fight profile format lists every error and warning. Test your profiles Install your package in your library, from its folder or a .zip (The editor, Zip and command line). Open Fight Profiles. Your profiles are listed with the Package source: check that each one is Ready, and read its warnings. Open one with View to see every setting as the editor reads it. Set a bot's Profile to it, switch on Play this bot's fights, and read the Turn log after a fight. To try a change, Copy the profile, edit the copy, then paste its JSON back into your package. Next, the Packages chapter describes the manifest, starting with every field of asterobot.json.
-
Fights
How scripts and Asterobot's fight module share a bot's fights: starting a fight from a script, knowing when it starts and ends, what the module sends and holds back, what a script must send when the module is off, and what's coming for scripts. Asterobot has a fight module that plays a bot's fights by itself, when the person running the bot switches it on: it places the character, says it's ready, plays every turn and answers everything the Dofus client answers during a fight. How it decides is set by fight profiles. The guide describes it for players: The fight module and Fight profiles. The module plays fights, it never starts one. Starting fights, and deciding what happens between them, is your script's job. Who does what Your script The fight module, switched on The fight module, switched off Walking to a group and attacking it Yes Never Never Answering the fight map's load Yes Nothing Placement and ready Yes, for the parts its profile leaves on Nothing Playing the character's turns Yes Nothing Answering the server during the fight (acknowledgements, ready for the next turn) Yes Nothing Everything after the fight Yes Nothing Nothing The person running the bot chooses whether the module plays, on the bot's Fight tab. Your script can't switch it yet. Write your package so it works either way, or say in its description that it expects the module on. Start a fight A Dofus client attacks a monster group by walking onto the group's cell, then sending AttackMonsterRequest with the group's actor id. The server then removes the group from the map and switches the character into a fight. To know which actors of the map are monster groups, read the map's contents when they arrive: a monster group's actorInformation.rolePlayActor holds a monsterGroupActor. The ids and cells of the actors standing on the map now are in currentMap(). import { currentMap, botWarn } from "asterobot:bot"; import { on, send, wait } from "asterobot:protocol"; import { move } from "asterobot:movement"; // The actor ids of the monster groups the server placed on the map, read // each time a map's contents arrive, after every fight included. const groups = new Set(); on("MapComplementaryInformationEvent", (traffic) => { groups.clear(); for (const actor of traffic.payload?.actors ?? []) { if (actor.actorInformation?.rolePlayActor?.monsterGroupActor) groups.add(actor.actorId); } }); // Walks onto a monster group and attacks it. Resolves with true once the // fight has started, false when the group was gone or the attack got no answer. async function attack() { const group = currentMap()?.actors.find((actor) => groups.has(actor.id)); if (!group) return false; await move(group.cellId); await send("AttackMonsterRequest", { monsterGroupId: group.id }); try { await wait( (traffic) => traffic.type === "ContextCreationEvent" && traffic.payload?.context === "FIGHT", { timeout: 5000 }, ); return true; } catch { // The group walked away while the character walked to it: the server // doesn't answer an attack from a cell the group left. botWarn("The attack got no answer"); return false; } } Call attack() once the character stands on a map, for example after @asterobot:base has taken a Full socket bot into the game. Groups walk around. When one moves while the character walks to it, the server ignores the attack, and the Dofus client walks again and attacks from the group's new cell. Do the same: try again after a failed attack, from a fresh currentMap(). Groups that arrive later come with GameRolePlayShowActorsEvent, in the same actors shape, and ContextRemoveElementEvent removes the ones that leave. A script that waits on a map for groups to come back reads those too. Know when a fight starts and ends What How A fight starts ContextCreationEvent with context: "FIGHT". The MapCurrentEvent that follows names the fight's map. The fight ends ContextCreationEvent with context: "ROLE_PLAY", after FightEndEvent, then the world map the character is now on. After a defeat, that's another map. Whether a fight is under way, at any moment character().inFight from asterobot:character, true from the first switch to the second. To wait for a fight to end, give the wait a long timeout: fights can last many minutes. await wait( (traffic) => traffic.type === "ContextCreationEvent" && traffic.payload?.context === "ROLE_PLAY", { timeout: 30 * 60_000 }, ); Your script keeps running during the fight, and its handlers keep receiving every message the server sends, fight messages included. travel() waits out a fight that starts on the way, and @asterobot:base leaves the fight's map to the fight module. While the module plays Don't send fight actions. Moves, spells and the end of the turn sent by a script would reach the server alongside the module's, and the turn would go wrong. The module doesn't hold back what a script sends. Your interceptors don't see the clicks it holds. On a relayed session, the module is asked first about every message the Dofus client sends. The clicks it holds back, the moves, spells and turn ends of the person playing, and placement or ready when the profile decides them, go neither to the server nor to your interceptors. Every other message reaches them as usual. Its console lines are the bot's. The module writes what it does in the bot's console, such as The fight module casts a spell, between your script's lines. When the module is off With the module off, Asterobot sends nothing during a fight. On a relayed session, the person's Dofus client plays it. On a Full socket bot, nothing answers the server unless your script does, and the fight doesn't move: the server waits for each fighter's answer before the next turn. A script that plays fights itself sends what the Dofus client sends: The fight's map. After MapCurrentEvent names it, FightPingsRequest (empty) then ContextReadyRequest with mapId, the fight map's id. Unlike a world map, no MapInformationRequest. Placement, optionally: FightPlacementPositionRequest with cellId, a cell of the character's team from FightPlacementPossiblePositionsEvent, and entityId, the character's id. Ready: FightReadyRequest with isReady: true. Without it, the fight starts when the placement countdown runs out. Its turns: when FightTurnEvent names the character, MapMovementRequest to walk, GameActionFightCastRequest with spellId and cell to cast (spell 0 for the weapon or bare hands, a fighter aimed at through its cell), and FightTurnFinishRequest to end the turn. Acknowledgements: GameActionAcknowledgementRequest with actionId, the action id of each outermost sequence the character authored, as SequenceEndEvent gives it, and valid: true. The server doesn't wait for them, but the Dofus client sends them. Ready for the next turn: FightTurnReadyRequest with isReady: true for every FightIsTurnReadyEvent. The server waits for this one. The Dofus protocol reference describes each message and its fields. It's a lot of work to do well, which is what the module is for. Ship fight profiles A package can ship fight profiles alongside its script: they show on the Fight Profiles page of everyone who installs it, and any bot can play them. See Ship fight profiles, and the Fight profile format for every field. Coming soon Note Coming soon. A module for scripts, asterobot:fight, will let a package switch the fight module on and off, set its speed, follow its decisions as events, and answer at each decision point, such as placement, the choice of challenges or each action of a turn, to play part of a fight itself. Until then, a script reads a fight from its messages, and the module plays it as its profile says. That's the end of the protocol chapter. The next one, Game data, covers reading items, monsters, maps and texts from a script.
-
Combats
Des réponses courtes sur le module de combat, les profils de combat, jouer soi-même un combat, Turbo, le PvP, les challenges, les invocations et les mises à jour de Dofus. Read this page in English Comment les bots jouent leurs combats, et comment changer leur façon de faire. Un bot peut-il combattre tout seul ? Oui. Activez Jouer les combats de ce bot dans l'onglet Combat du bot, et le module de combat place le personnage, le déclare prêt et joue chaque tour, en mode Full socket comme en mode MITM. Voir Le module de combat. Le bot attaque-t-il les monstres de lui-même ? Non. Le module de combat joue les combats, il ne les lance pas. Attaquer un groupe, c'est le travail du paquet du bot, ou le vôtre sur une session relayée. Une fois le combat commencé, le module prend la main. Ai-je besoin d'un profil de combat ? Non. Avec Profil laissé vide, le bot joue le profil par défaut, qui s'adapte à n'importe quel personnage : le rôle que sa classe joue en premier, la portée de ses sorts, les sorts qu'il a vraiment. Créez un profil quand vous voulez qu'il joue autrement. Voir Profils de combat. Est-ce que ça marche pour toutes les classes ? Oui. Le module n'a aucun coup écrit pour une classe. Il lit chaque sort, chaque effet et chaque monstre dans les données du jeu et calcule ce que le personnage peut faire : une nouvelle classe, un nouveau sort ou un sort rééquilibré se joue donc sans attendre de mise à jour d'Asterobot, une fois la nouvelle version du jeu extraite. Voir Comment le module décide. Puis-je jouer un combat moi-même sur une session relayée ? Oui. Désactivez le module dans l'onglet Combat : vous jouez dès le tour suivant. Pour ne vous garder que certaines parties, comme le placement, désactivez-les plutôt dans les Parties du profil. Tant que le module joue, vos clics pour ce qu'il décide sont retenus, et le client de jeu vous le dit. Voir Sur une session relayée. Turbo est-il sans risque ? Turbo décide la même chose que les autres vitesses, mais répond aussitôt après chaque sort, plus vite qu'aucun vrai client de jeu. Le serveur l'accepte, mais cela se remarque facilement. Normale joue au rythme du client de jeu. Voir Vitesse. Joue-t-il les défis et les autres combats contre des joueurs ? Pas par défaut : dans un combat qui n'est pas contre des monstres, le module répond seulement à ce à quoi le client de jeu répond de lui-même. Réglez Combats hors monstres sur Jouer dans le profil pour qu'ils soient joués, en sachant que le module ne connaît pas encore les sorts des personnages ennemis. Voir Réglages du profil. Fait-il les challenges ? Pas encore : le module ne choisit pas les challenges. Sur une session relayée, les choisir reste à vous. Pourquoi mon invocation ne fait-elle rien ? Les invocations qui jouent seules, comme celles de l'Osamodas, jouent normalement. Les invocations que vous contrôlez vous-même, comme les fées de l'Eniripsa, ne sont pas encore jouées par le module : leur tour s'écoule au bout de 15 secondes. Voir Problèmes de combat. Comment partager un profil ? Exportez-le sur la page Profils de combat et envoyez le fichier .json. L'autre personne ouvre Importer. Un paquet peut aussi fournir des profils, que reçoivent tous ceux qui l'installent. Voir Partager des profils. Que deviennent mes profils quand Dofus est mis à jour ? Rien : ils désignent les sorts, les monstres et les états par leurs identifiants dans le jeu, que les mises à jour gardent. Quand une mise à jour retire quelque chose qu'un profil désigne, le profil joue quand même et affiche un avertissement comme spell 12345: not in the game data, ignored. Extrayez la nouvelle version du jeu pour que le module connaisse les nouvelles règles.
-
Problèmes de combat
Pourquoi un bot ne fait rien en combat, passe ses tours, joue un profil que vous n'avez pas choisi, voit ses actions refusées encore et encore ou ignore vos clics sur une session relayée, et que faire dans chaque cas. Read this page in English Quand le module de combat ne joue pas comme vous l'attendez, deux endroits vous disent pourquoi. L'onglet Console du bot indique quand un combat commence, si le module le joue, et chaque action qu'il envoie. Le Journal des tours de l'onglet Combat garde chaque décision des 10 derniers combats, avec ce que chacune a compté (Le module de combat). Le bot ne fait rien en combat Vérifiez, dans l'ordre : Le module est désactivé. La console indique A fight started: the fight module is off and sends nothing. Activez Jouer les combats de ce bot dans l'onglet Combat du bot. Un changement fait pendant un combat s'applique au tour suivant. Le combat n'est pas contre des monstres. La console indique This fight isn't against monsters: the fight module only answers what the client answers by itself, and decides nothing. C'est le comportement par défaut pour les défis, les agressions et les autres combats contre des joueurs : réglez Combats hors monstres sur Jouer dans le profil si vous voulez qu'ils soient joués (Jeu). Le profil désactive ses parties. Idle ne place rien et passe chaque tour. Vérifiez Parties dans la section Jeu du profil. Le personnage est mort. Un personnage mort n'a plus rien à décider : le module continue de répondre au jeu jusqu'à la fin du combat. Le bot passe chaque tour au bout de quelques secondes Il joue Idle, ou un profil avec une règle qui termine le tour. Idle passe chaque tour au bout de 5 secondes. Choisissez un autre profil dans l'onglet Combat, ou laissez Profil vide pour le profil par défaut. Dans votre propre profil, cherchez Passer chaque tour au bout de (secondes) dans Jeu, et les règles Terminer le tour. Le bot joue le profil par défaut au lieu du mien La console indique The fight profile can't be played: the default profile plays, avec la raison. Le profil a été supprimé, il a une erreur, ou son paquet a été retiré. Ouvrez Profils de combat : un profil marqué Injouable donne la raison quand vous le survolez, et l'éditeur l'affiche au-dessus du formulaire. Corrigez-le et sauvegardez, ou choisissez un autre profil. Le profil est relu au combat suivant. La console indique The fight profile extends a missing profile: it plays its own fields over the default profile quand le profil qu'il étend n'existe plus. Réglez Étend sur un profil existant, ou sur Aucun. Le bot ne se déclare jamais prêt Il attend son groupe : Attendre les alliés, dans la section Jeu du profil, demande plus de personnages dans son équipe qu'il n'en est arrivé. Le compte à rebours du placement lance quand même le combat quand il arrive à sa fin. Baissez le nombre, ou vérifiez que les autres bots rejoignent bien le même combat. Avec la partie Prêt désactivée, le module ne déclare pas du tout le personnage prêt : le compte à rebours lance le combat. Sans réponse revient sans cesse Sans réponse, dans le journal des tours, veut dire que le serveur n'a pas pris une action dans les 3 secondes. Le module écarte ce sort, ou les déplacements depuis cette case, pour le reste du tour, et décide de nouveau sans, si bien qu'un combat n'y reste jamais bloqué. La console indique The server didn't answer the fight module's action: it decides again without it, ou The server refused the fight module's action: it decides again without it quand le jeu a dit non. Le module calcule ce qui est possible comme le fait le jeu : un refus veut donc dire qu'il s'est trompé sur quelque chose, le plus souvent sur les PA et PM qu'un ennemi retire au personnage quand il s'éloigne de lui. Quand la même action est refusée encore et encore, notez le combat dans le journal des tours et prévenez l'équipe d'Asterobot (Obtenir de l'aide). Mes clics ne font rien pendant un combat Sur une session relayée, tant que le module joue un combat, les clics que vous faites pour ce que son profil décide sont retenus, et votre client de jeu affiche « Le module de combat d'Asterobot joue ce combat : le jeu ne prend pas en compte ce que vous faites ici. Désactivez le module pour jouer dès le tour suivant. » Désactivez le module dans l'onglet Combat pour jouer vous-même dès le tour suivant, ou désactivez dans le profil les parties que vous voulez garder, comme Placement. Le tour d'une invocation s'écoule Les invocations que vous contrôlez vous-même, comme les fées de l'Eniripsa, ne sont pas encore jouées par le module : leur tour s'écoule au bout de 15 secondes. Sur une session relayée, le module retient aussi vos clics pendant leur tour. Évitez de lancer ces sorts en attendant, avec Utilisation réglée sur Jamais pour eux dans les Sorts du profil. Le module joue mal Pas de données du jeu. La console indique The fight module couldn't read the game data: it plays on without it. Extrayez la version du jeu du bot. Un réglage joue contre le personnage. Une portée de mêlée sur une classe à distance, un risque bas sur un tank : le journal des tours montre ce que chaque décision a compté. Comparez avec Comment le module décide, et changez un réglage à la fois. Turbo. Il décide la même chose que les autres vitesses, mais répond plus vite qu'aucun vrai client de jeu : voir Vitesse. Des noms ou des icônes manquent dans l'éditeur de profil L'éditeur lit les noms et les icônes dans les données du jeu. Sans version du jeu extraite, les sorts, les monstres et les états s'affichent par leur identifiant. Les icônes apparaissent une fois les données du jeu extraites par un Asterobot qui les extrait : après une mise à jour d'Asterobot, extrayez de nouveau la version du jeu dans Gestionnaire de jeux (Extraire les données du jeu).