Tout ce qui a été publié par Smooth
-
ExchangeTypesExchangerDescriptionForUserEvent
The ids of the items of one item type in the open auction house. Kind event · Area Game.Exchange The answer to ExchangeBidHouseTypeRequest. 1. Match it to your request by object_type: the client looks up the category it built from the auction house's types with this id. 2. Treat type_description as the item ids (GIDs) of that category. The client turns them into the item list of the buy window. 3. To see the offers for one of those items, ask for that item (the client sends its search request when an item is clicked). When you may send it Requires context_ready inferred Related messages Arrives after ExchangeBidHouseTypeRequest Fields #FieldTypeMeaningYou set it 1type_descriptionrepeated int32Item ids (GIDs) of that type in this auction house. Observed: 2563, 16522, 1681never 2object_typeint32The item type this list is for: the type_id you asked about. Observed: 59never
-
ExchangeObjectMovePricedRequest
Puts one lot of an inventory item on sale in the auction house at the price you choose. Kind request · Area Game.Exchange HOW TO SELL AN ITEM 1. Open the auction house in sell mode (ExchangeBidSellerStartedEvent). Its SellingConditions say which item types, lot sizes and level this house accepts, and the tax you will pay. 2. Optional: get the market prices with ExchangeBidHousePriceRequest. 3. Send this request: - object_uid = the uid of the stack in YOUR INVENTORY (not the gid); - quantity = the lot size, one of SellingConditions.quantities (1, 10, 100...), never more than the stack holds; - price = the price of the WHOLE lot, in kamas. 4. In the capture the server answers, in this order: - KamasUpdateEvent: the sale tax is taken right away; - ExchangeBidHouseItemAddedEvent: your new sale; - ExchangeBidHouseInListUpdatedEvent: the item's listing with the new cheapest prices; - ObjectDeletedEvent when the whole stack left your inventory (a partial lot updates the stack's quantity instead); - InventoryWeightEvent. One request sells ONE lot. To sell several lots, send one request per lot. When you may send it Requires context_ready inferred Raised by: the player confirms a sale in the auction-house sell window proven Related messages You will then receive ExchangeBidHouseItemAddedEvent observed — the server confirms the new sale with the item, its price and its delay Fields #FieldTypeMeaningYou set it 1object_uidint32The stack to sell: its uid in your inventory. Observed: 8567885required 2quantityint32The lot size to put on sale: one of the house's quantities (1, 10, 100...). Observed: 1required 3priceint64The asking price of the whole lot, in kamas. (kamas) Observed: 1required
-
ExchangeLeaveEvent
The current exchange window (trade, storage, auction house...) is closed by the server. Kind event · Area Game.Exchange Your current exchange is over: close its window and forget its state. 1. Check dialog_type. The client only acts when it is DIALOG_EXCHANGE (DialogType); other dialogs close through other messages. 2. Read success: whether the exchange ended successfully (a completed trade) or was simply closed. Switching an auction house from buy to sell mode sends this with success = false (absent on the wire), right before ExchangeBidSellerStartedEvent. Do not send anything back; a new exchange event follows if the server opens another one. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this the server closes the exchange itself, for example when an auction house switches from buy to sell mode Fields #FieldTypeMeaningYou set it 1dialog_typeDialogTypeWhich dialog closed; the exchange client only reacts to DIALOG_EXCHANGE. Observed: DIALOG_EXCHANGE Type DialogType.never 2successboolWhether the exchange ended successfully rather than being simply closed. Observed: falsenever
-
ExchangeBidSellerStartedEvent
The auction house is open in sell mode: its selling conditions and the items you already have on sale. Kind event · Area Game.Exchange You are now in the auction house's sell screen. 1. Read selling_conditions (SellingConditions): which item types this house accepts, the level cap, the sale tax and the modification tax. 2. Read objects: one ItemToSellInBid per item you ALREADY have on sale here, with its price and remaining delay. An empty list means you sell nothing here yet. In a capture, switching from buy to sell mode goes like this: the client sends NpcGenericActionRequest with the house's npc_contextual_id; the server answers ExchangeLeaveEvent (the buy exchange closes), InventoryContentEvent, then this event. The buy screen has its own event, ExchangeBidBuyerStartedEvent, which carries the conditions only. When you may send it Requires context_ready inferred Raised by: the player opens the auction house in sell mode (or switches from buy to sell through the NPC action) observed Related messages Reply not yet recovered: nothing answers this - it is inbound only. Switching from buy mode first closes the buy exchange (ExchangeLeaveEvent) and refreshes the inventory before this arrives. Fields #FieldTypeMeaningYou set it 1selling_conditionsSellingConditionsThe auction house's rules: item types, taxes, level cap, house and NPC ids. Type SellingConditions.never 3objectsrepeated ItemToSellInBidThe items you already have on sale in this auction house. Type ItemToSellInBid; empty when you sell nothing here.never
-
ExchangeBidPriceEvent
The market prices of one item: its average price and the cheapest price listed per lot size. Kind event · Area Game.Exchange The answer to ExchangeBidHousePriceRequest. Use it to choose the price of the lot you are about to sell with ExchangeObjectMovePricedRequest. 1. Check object_gid: the item these prices are for (the gid you asked about). 2. Read average_price: the item's average price, in kamas. -1 means the house has no average for it; the official client then shows a placeholder text and disables its "market price" button. 3. Read bid_price_for_seller (BidPriceForSeller): minimal_prices holds the cheapest price currently listed for each lot size, in the order of SellingConditions.quantities. Undercut the matching entry if you want to sell first. Do not send anything back. When you may send it Requires context_ready inferred Related messages Arrives after ExchangeBidHousePriceRequest Fields #FieldTypeMeaningYou set it 1bid_price_for_sellerBidPriceForSellerThe cheapest price currently listed for each lot size. Type BidPriceForSeller.never 2object_gidint32The item (template id) these prices are for: the gid of your price request. Observed: 310 The client never reads it; named as the message's only int32.never 3average_priceint64The item's average price; -1 when the house has none. (kamas) Observed: 7never
-
ExchangeBidHouseTypeRequest
Asks the open auction house for the items of one item type, optionally following it for updates. Kind request · Area Game.Exchange 1. Open the auction house first (ExchangeBidBuyerStartedEvent). 2. Pick a type_id from that event's selling_conditions.types. 3. Send one request per type you want to see. Set follow to keep receiving changes for that type; the client's type filter sends one request per type it adds. 4. Read the answer: ExchangeTypesExchangerDescriptionForUserEvent lists the item ids of that type. Any other declared member is never written by the client; leave it at its default. When you may send it Requires context_ready inferred Raised by: the auction-house item filter adds an item type (the player picks a category) proven Related messages You will then receive ExchangeTypesExchangerDescriptionForUserEvent inferred — the server answers with the ids of the items of that type on sale here Fields #FieldTypeMeaningYou set it 2type_idint32The item type to list; one of the open auction house's selling_conditions.types. Observed: 153required 3followboolWhether to keep following this type after the first answer. Observed: truerequired
-
ExchangeBidHouseSearchRequest
Asks the open auction house for every listing of one item, and starts or stops following that item. Kind request · Area Game.Exchange TO SEE THE OFFERS OF AN ITEM 1. Open the auction house (ExchangeBidBuyerStartedEvent) and pick an item id (GID), for example from ExchangeTypesExchangerDescriptionForUserEvent. 2. Send object_gid = that item, follow = true. 3. The answer is ExchangeTypesItemsExchangerDescriptionForUserEvent: one entry per listing, with its uid and prices. 4. While you follow the item, the server pushes changes to its listings, such as ExchangeBidHouseInListUpdatedEvent. TO STOP FOLLOWING Send the same item with follow = false (on the wire that is just the item id, because false is the default). The client does this: - when the player closes an opened item; - when opening one more item would exceed its limit of opened items. It drops the oldest item first, so one click sends an unfollow for the old item, then a follow for the new one; - when it unfollows everything, or when the item list closes. Keep the number of followed items small, and unfollow what you no longer watch: the real client never leaves items followed behind it. When you may send it Requires context_ready inferred Raised by: the player opens an item in the auction-house buy list (or uses 'search same items' from the sell list) proven Related messages You will then receive ExchangeTypesItemsExchangerDescriptionForUserEvent observed — the server answers with the item's listings; an unfollow is answered too, with an empty list Fields #FieldTypeMeaningYou set it 1object_gidint32The item (GID) whose listings you want. Observed: 28277required 2followbooltrue: start following this item's listings; false: stop following it. false is the protobuf default, so an unfollow carries only object_gid on the wire.optional
-
ExchangeBidHousePriceRequest
Asks the auction house for the current prices of one item before you put it on sale. Kind request · Area Game.Exchange HOW TO PRICE AN ITEM BEFORE SELLING IT 1. Open the auction house in sell mode (ExchangeBidSellerStartedEvent). 2. Send this request with object_gid = the item's TEMPLATE id (the gid, not the uid of your stack). 3. Wait for ExchangeBidPriceEvent: it gives the average price and the cheapest price currently listed for each lot size. 4. Choose your price, then sell with ExchangeObjectMovePricedRequest. The official client sends ExchangeBidHouseSearchRequest (follow = true) for the same gid at the same moment, so it also receives the item's offer list. That is optional: this request alone is enough to get the prices. When you may send it Requires context_ready inferred Raised by: the player picks an item to sell, from the inventory or from the list of items already on sale proven Related messages You will then receive ExchangeBidPriceEvent observed — the server answers with the average price and the cheapest price per lot size of that item Fields #FieldTypeMeaningYou set it 1object_gidint32The item's template id (gid) whose prices you want. Observed: 310required
-
ExchangeBidHouseItemAddedEvent
Confirms a new sale of yours in the auction house: the item, its price and its delay. Kind event · Area Game.Exchange Your ExchangeObjectMovePricedRequest succeeded: the lot is now on sale. Add it to your list of items on sale (the list ExchangeBidSellerStartedEvent gave you). - item (BidItem): the lot on sale. Its uid is the SALE's id in the auction house, not the uid your stack had in your inventory. - price: the price you asked for the whole lot, in kamas. - unsold_delay: how long the lot stays on sale before it comes back unsold, in seconds (2419200 = 28 days in the capture). The sale tax was already taken (KamasUpdateEvent just before). The item's listing update (ExchangeBidHouseInListUpdatedEvent) and your inventory update (ObjectDeletedEvent for a whole stack) follow. When you may send it Requires context_ready inferred Related messages Arrives after ExchangeObjectMovePricedRequest Fields #FieldTypeMeaningYou set it 1priceint64The price you asked for the whole lot. (kamas) Observed: 1never 2itemBidItemThe lot now on sale; its uid is the sale's id in the auction house. Type BidItem.never 3unsold_delayint64Time left before the lot comes back unsold. (seconds) Observed: 2419200never
-
ExchangeBidHouseInListUpdatedEvent
One listing you follow changed its prices or effects; replace your copy of it. Kind event · Area Game.Exchange Pushed for listings of items or item types you follow (ExchangeBidHouseSearchRequest or ExchangeBidHouseTypeRequest with follow = true). 1. Find the category by object_type, the item by object_gid, then the listing by object_uid. Listing uids come from ExchangeTypesItemsExchangerDescriptionForUserEvent. 2. Replace that listing's prices and effects with these. 3. If you do not hold that listing, ignore the event: the client only updates listings it already has. A NEW listing comes with a different event, the in-list "added" event. When you may send it Requires context_ready inferred Related messages Unsolicited - nothing you send causes this pushed for items and types you follow (search / type requests with follow = true), whenever a listing changes Fields #FieldTypeMeaningYou set it 1pricesrepeated int64The listing's new price per lot size, in kamas; 0 = that lot size is not offered. (kamas) Observed: 9198, 88420, 999993, 0never 2object_gidint32The item (GID) of that listing. Observed: 748never 3object_typeint32The item's type (category). Observed: 40never 4object_uidint32Id of the listing that changed (an object_uid from the item's listings). Observed: 2413never 5effectsrepeated ObjectEffectThe listing's item effects. Type ObjectEffect.never
-
ExchangeBidHouseBuyResultEvent
Closes a purchase: whether the lot you asked for was bought. Kind event · Area Game.Exchange The answer to ExchangeBidHouseBuyRequest, sent LAST: the kamas, item and listing updates of a successful purchase arrive before it. - bought = true: the lot is yours. Trust the inventory and kamas events that came just before for the details. - bought = false: nothing changed. Search the item again (ExchangeBidHouseSearchRequest) before retrying; the listing may be gone or its price may have changed. object_uid echoes the listing you tried to buy. The client itself ignores it and reacts to bought only, so match results to requests by order if you send several. One declared enum member is never read by any client; ignore it. When you may send it Requires context_ready inferred Related messages Arrives after ExchangeBidHouseBuyRequest Fields #FieldTypeMeaningYou set it 2object_uidint32The listing you tried to buy (object_uid of the request). Observed: 914 The client never reads it; named as the message's only int32.never 3boughtbooltrue if the lot was bought; false if nothing happened. Observed: truenever
-
ExchangeBidHouseBuyRequest
Buys one lot of one auction-house listing at the price you were shown. Kind request · Area Game.Exchange HOW TO BUY 1. Open the auction house in buy mode (ExchangeBidBuyerStartedEvent). 2. Get the item's listings: ExchangeBidHouseSearchRequest -> ExchangeTypesItemsExchangerDescriptionForUserEvent. Each BidExchangerObject carries an object_uid and one price per lot size. 3. Send this request: - object_uid = the listing you buy; - quantity = the lot size you buy (the client sends the size of the row the player clicked: 1, 10, 100...); - price = that lot's price exactly as listed. The client sends the price it displayed; it never computes one. 4. One request buys ONE lot. To buy several lots, send several requests, each with fresh data. WHAT COMES BACK (in this order in captures) - ExchangeBidHouseInListUpdatedEvent for that listing if you follow its item (its remaining lots and prices); - KamasUpdateEvent with your new kamas; - ObjectAddedEvent with the item in your inventory; - InventoryWeightEvent and a chat notice (TextInformationEvent); - ExchangeBidHouseBuyResultEvent with bought = true. If bought is false, nothing was bought. Refresh the listings (search again) before retrying, because a stale uid or price will keep failing. When you may send it Requires context_ready inferred Raised by: the player confirms a purchase in the auction-house buy window proven Related messages You will then receive ExchangeBidHouseBuyResultEvent observed — the server always closes the purchase with a result for the listing you named Fields #FieldTypeMeaningYou set it 1quantityint32The lot size you buy (1, 10, 100, ...): the row the player picked. Observed: 1required 3object_uidint32The listing to buy: an object_uid from the item's listings. Observed: 914required 5priceint64The price of that lot exactly as listed, in kamas. (kamas) Observed: 4required
-
ExchangeBidBuyerStartedEvent
The auction house is open in buy mode; carries its selling conditions. Kind event · Area Game.Exchange You are now in the auction house's buy screen. 1. Read selling_conditions. Its types list is the set of item categories you can browse here. 2. Keep its npc_contextual_id: the client uses it as the NPC id for further actions on this auction house. 3. To list the items of one category, ask for that type (the client sends one request per type id, with a follow flag). The sell screen opens with a different event that also carries the items you have on sale; this one carries the conditions only. When you may send it Requires context_ready inferred Raised by: the player opens an auction house in buy mode (from its NPC) inferred Related messages Reply not yet recovered: nothing answers this - it is inbound only. Browsing a category makes the client send the bid-house type request (one per type id), which has no signature yet. Fields #FieldTypeMeaningYou set it 1selling_conditionsSellingConditionsThe auction house's rules: item types, taxes, level cap, house and NPC ids. Type SellingConditions.never
-
DetailedStatistics
One fighter's end-of-fight statistics: damage, heals, shields, AP and MP, kills, and who the fighter is. Kind struct · Area Game.Fight One fighter's statistics for the fight that just ended; FightStatisticsEvent.detailed_statistics holds one per fighter, keyed by fighter id. Each member is one block of the results screen's Statistics tab. READ IT LIKE THIS 1. DetailedStatistics.fighter: who this is (a FighterIdentity record: player, monster, companion or summon). 2. Damage: DetailedStatistics.damage_done (dealt, with its breakdown) and DetailedStatistics.damage_taken (received). 3. Healing: DetailedStatistics.heal_done (given) and DetailedStatistics.heal_taken (received). 4. Shields: DetailedStatistics.shield_done (applied) and DetailedStatistics.shield_taken (received). 5. Points: DetailedStatistics.action_points and DetailedStatistics.movement_points, the same Point record for AP and for MP (dodged, not dodged, removed, removed by tackle, and their per-turn averages). 6. DetailedStatistics.kill: kills. A third Point-typed member and an enum member are never read by the client: ignore them. WHAT THE OFFICIAL CLIENT DOES. It converts the record into the Statistics tab: one block per member, filed under a fixed slot (damage done, damage taken, heal done, heal taken, shield done, shield taken, AP, MP, kills), each block built with its own translation keys (ui.fightResult.damageDealt, ...healReceived, ...shieldDealt, ...kill, ...) and the AP/MP blocks titled ui.stats.shortAP / ui.stats.shortMP. Not sent on its own — it travels as a value of FightStatisticsEvent.detailed_statistics, one per fighter. proven Fields #FieldTypeMeaningYou set it 1damage_donetype not documented yetThe damage the fighter dealt. A DamageDone record; the results screen labels it ui.fightResult.damageDealt.never 2heal_takentype not documented yetThe healing the fighter received. A HealTaken record; the results screen labels it ui.fightResult.healReceived.never 3shield_donetype not documented yetThe shield the fighter applied. A ShieldDone record; the results screen labels it ui.fightResult.shieldDealt.never 5movement_pointstype not documented yetWhat happened to the fighter's movement points (MP). A Point record, like action_points. Shown under the title ui.stats.shortMP.never 6shield_takentype not documented yetThe shield the fighter received. A ShieldTaken record; the results screen labels it ui.fightResult.shieldReceived.never 7damage_takentype not documented yetThe damage the fighter received. A DamageTaken record; the results screen labels it ui.fightResult.damageTaken.never 8fightertype not documented yetWho the fighter is. A FighterIdentity record (player, monster, companion or summon).never 9action_pointstype not documented yetWhat happened to the fighter's action points (AP). A Point record: dodged, not dodged, removed, removed by tackle, and per-turn averages. Shown under the title ui.stats.shortAP.never 11killtype not documented yetThe the fighter's kills. A Kill record; the results screen labels it ui.fightResult.kill.never 12heal_donetype not documented yetThe healing the fighter gave. A HealDone record; the results screen labels it ui.fightResult.healDealt.never
-
CharacterForceSelectionReadyRequest
Acknowledges a forced character selection. Empty payload. Kind request · Area Game.Character.Management Carries nothing - it only says "ready". 1. Wait for CharacterForceSelectionEvent. 2. Send this request, empty, as soon as the event arrives. 3. Send it once. The client guards it with a one-shot flag: a repeated event does not produce a second request. Any field a later build declares here is unused by the client and is left unresolved; send it empty. When you may send it Requires authenticated inferred Related messages Answers CharacterForceSelectionEvent
-
CharacterForceSelectionEvent
The server has selected your character for you. Empty payload; answer it. Kind event · Area Game.Character.Management Carries nothing. The server is not asking you to choose: the character is already decided, so do NOT send CharacterSelectionRequest for it. 1. Answer straight away with one empty CharacterForceSelectionReadyRequest. 2. Send that answer ONCE. The client keeps a one-shot flag and ignores repeats of this event once it has answered. The current build carries no character id (older protocols did). The character is the one this connection was transferred for. Any field a later build declares here is unread by the client and is left unresolved. When you may send it Requires authenticated inferred Raised by: the connection lands on a game server that already knows which character plays - the client handles it in its server-transfer service (fight / Kolizeum server switch) inferred Related messages You must then send CharacterForceSelectionReadyRequest proven — the handler of this event constructs the ready request unpopulated and hands it to the game connection
-
BidPriceForSeller
The cheapest price currently listed for one item, one entry per lot size. Kind struct · Area Game.Exchange The bid_price_for_seller member of ExchangeBidPriceEvent. - minimal_prices: one price per lot size, in the order of SellingConditions.quantities (1, 10, 100, 1000 in the capture). Each is the cheapest price another seller asks for a lot of that size right now. The official client lists them next to your sale so you can undercut them. - all_identical: the client never reads it. Ignore it. Not sent on its own — a record inside ExchangeBidPriceEvent, never sent on its own. inferred Used by ExchangeBidPriceEvent Fields #FieldTypeMeaningYou set it 1all_identicalboolNever read by the client; ignore it. Observed: true Named as the record's only bool.never 2minimal_pricesrepeated int64The cheapest listed price for each lot size, in the order of the house's quantities. (kamas) Observed: [4, 28, 996, 7999]never
-
BidItem
One lot on sale in the auction house: which item, its sale id, how many and its effects. Kind struct · Area Game.Exchange The item record of your sales. It is carried by ExchangeBidHouseItemAddedEvent.item and ItemToSellInBid.object. THE TWO IDS ARE BOTH INT32. DO NOT MIX THEM UP. - gid: the item's TEMPLATE id (what kind of item it is). Look it up in your item data. - uid: the id of THIS SALE in the auction house. It is NOT the uid the stack had in your inventory (310084 here, while the stack sold was 8567885). - quantity: the lot size (1, 10, 100...). - effects: the item's effects (ObjectEffect). Not sent on its own — a record inside the auction-house sell messages, never sent on its own. inferred Used by ExchangeBidHouseItemAddedEvent ItemToSellInBid Fields #FieldTypeMeaningYou set it 1gidint32The item's template id: what kind of item is on sale. Observed: 310 Name from beta ObjectItem, the type these slots used before BidItem.never 2effectsrepeated ObjectEffectThe effects of the item on sale. Type ObjectEffect. Name from beta ObjectItem, the type these slots used before BidItem.never 3uidint32The id of this sale in the auction house (not your inventory uid). Observed: 310084 Name from beta ObjectItem, the type these slots used before BidItem.never 4quantityint32The lot size on sale. Observed: 1 Name from beta ObjectItem, the type these slots used before BidItem.never
-
BidExchangerObject
One listing of an item: every lot with the same effects, with its id, its cheapest price per lot size and the effects. Kind struct · Area Game.Exchange An element of ExchangeTypesItemsExchangerDescriptionForUserEvent.item_descriptions. - object_uid identifies THIS LISTING: every lot of this item with exactly these effects, whoever sells it. Keep it: a later ExchangeBidHouseInListUpdatedEvent names it when its prices change, and you name it when you buy. It is NOT one seller's sale: after a purchase the listing keeps its uid and shows the next cheapest prices. - object_gid is the item (GID); the client looks it up in its item data. - prices holds one price per lot size: the cheapest lot of that size in this listing. A 0 means nobody sells that lot size here. - effects are the item's own effects (stats); for equipment, two listings of the same item can differ by them. Not sent on its own — a record inside ExchangeTypesItemsExchangerDescriptionForUserEvent, never sent on its own. inferred Used by ExchangeTypesItemsExchangerDescriptionForUserEvent Fields #FieldTypeMeaningYou set it 1object_gidint32The item (GID) on sale. Observed: 28277never 2pricesrepeated int64Price per lot size, in kamas; 0 = that lot size is not offered. (kamas) Observed: 67970, 599995, 0, 0never 3object_uidint32Id of this listing; updates and purchases name it. Observed: 87194never 4object_typeint32The item's type (category). The client never reads it; named as the record's remaining int32.never 5effectsrepeated ObjectEffectThe item's effects (stats). Type ObjectEffect.never
-
asterobot:character
character(), itemCount() and jobLevel(), which tell a script its character's level, kamas, energy, life, pods, whether it's in a fight, its items and its jobs, with when each one is known and every error. asterobot:character tells your script what the game has said about its character: level, kamas, energy, life, how full its bags are, whether it's in a fight, how many of an item it has and its job levels. Use it to decide what to do next, such as going to the bank when the bags are nearly full or resting when life is low. import { character, itemCount, jobLevel } from "asterobot:character"; These are the module's only exports. There's no character object grouping them. Export Returns What it gives you character() An object, right away Level, kamas, energy, life, pods, and whether a fight is under way itemCount() A number or undefined, right away How many of an item the character has jobLevel() A number or undefined, right away The level of one of its jobs None of the functions returns a promise, and none of them changes anything in the game. Where the values come from Asterobot follows the character itself, for the whole game session, from the messages the server sends: the character's selection, its characteristics, its inventory and the weight of its bags, its job list, and when it enters or leaves a fight. So a script started or reloaded in the middle of a session reads the character as it is, not only what it saw since it started. A value the game hasn't sent yet is missing, never guessed. character() leaves the property out, and itemCount() and jobLevel() return undefined. A missing value is never 0 or null, so a script can always tell "zero" from "not known yet". Every call asks again and returns a new value. Nothing updates by itself: read it again when you need it. character() character() returns an object with the properties below. Each one is a number, except inFight, and each one is absent until the game has sent it. Property Type Value level number The character's level kamas number The kamas it carries, not those in its bank energy number Its energy points life number Its life points. See Life. maxLife number The most life points it can have, erosion taken off weight number What its bags weigh, in pods maxWeight number The most its bags can weigh, in pods inFight boolean true while a fight is under way, false otherwise import { botInfo, botWarn } from "asterobot:bot"; import { character } from "asterobot:character"; const { weight, maxWeight, life, maxLife } = character(); if (weight !== undefined && maxWeight) { botInfo(`Bags: ${Math.round((100 * weight) / maxWeight)}%`); } if (life !== undefined && maxLife && life < maxLife / 2) { botWarn("Below half life"); } For a character carrying 98 pods out of 1075 with full life, the console shows Bags: 9%. The object is the script's own: changing it changes nothing, neither in Asterobot nor in the next call's answer. Life life and maxLife come from the character's characteristics, which the server sends as the character enters the world and later on. Asterobot works them out the way the Dofus client's character sheet does: the health points of the character's level and its vitality make the full amount, erosion takes the maximum down, and the life lost takes life down. Between two of these messages, life keeps the last value: it doesn't follow the regeneration while the character rests, nor the damage it takes during a fight. The server reports those in other messages, and the one that carries life, UpdateLifePointsEvent, has values whose meaning isn't known yet, so Asterobot doesn't read it. Treat life as the character's life at the last update, not to the second. Pods weight and maxWeight come from InventoryWeightEvent, which the server sends with both numbers whenever what the character carries changes. They're up to date as long as the session lasts. weight can be above maxWeight: the character is then overloaded. Fights inFight becomes true when the server switches the character into a fight, and false again when it switches it back to the world. Both switches come with ContextCreationEvent. It's false from the moment the character is selected, so a character that has entered the world and hasn't fought yet reads false, not "not known". travel() waits for the end of a fight by watching the same switch. itemCount() itemCount(itemId) returns how many of an item the character has, worn or in its bags, or undefined until the inventory is known. Parameter Type Description itemId number The item's id: a key of the game data's items table, as search() returns it import { botInfo } from "asterobot:bot"; import { itemCount } from "asterobot:character"; // 303 is Ash Wood. const ash = itemCount(303); if (ash !== undefined) botInfo(`Ash Wood: ${ash}`); An item the character has none of gives 0. Quantities follow the updates the server sends, so a stack that grows or shrinks is counted at once. Note Until the server sends the whole inventory again, which it does when the character enters the world, two changes aren't seen. An item the character gains in a new stack during the session, such as the first piece of a resource it didn't carry, isn't counted. And a stack it loses whole, such as one it puts entirely in the bank, sells or uses up, is still counted at its last quantity. The server adds and removes a stack with messages Asterobot doesn't read. jobLevel() jobLevel(jobId) returns the level of one of the character's jobs, 0 for a job it doesn't have, or undefined until the job list is known. Parameter Type Description jobId number The job's id: a key of the game data's jobs table, such as 2 for Lumberjack or 24 for Miner import { botInfo } from "asterobot:bot"; import { jobLevel } from "asterobot:character"; const lumberjack = jobLevel(2); if (lumberjack === 0) botInfo("This character isn't a lumberjack."); When the values are known The server sends most of these values as the character enters the world, before it's placed on its first map: Value Known from level, inFight The character's selection kamas, itemCount() The inventory, which follows the selection weight, maxWeight The weight of the bags, sent with the inventory jobLevel() The job list energy, life, maxLife, and kamas again The characteristics sent as the character enters the world In a recorded world entry, every value was known before the character was placed on its first map. Before the selection, character() is empty, except for a brief moment: the server sends the character's characteristics right before selecting it, and the selection then forgets them. In that recording, they gave the character 0 life and 0 energy, and the ones sent a moment later gave it full life and 10000 energy. So don't decide anything from character() until level is there. Values last as long as the game connection. They survive the script being stopped and played again, and they're forgotten when the bot connects again, until the server sends them for the new session. While Asterobot reads declarations When Asterobot reads a package's settings, steps and conditions, it runs the top level of its modules without a bot (see Declarations). There's no character then: character() returns an empty object, and itemCount() and jobLevel() return undefined, whatever you pass them. None of them throws, so importing asterobot:character at the top of a file is always safe. Errors Error Type Cause character.itemCount itemId must be an integer item id TypeError itemId isn't a whole number from -2147483648 to 2147483647, or isn't a number at all, such as a string or a BigInt character.jobLevel jobId must be an integer job id TypeError The same for jobId String(error) gives TypeError: followed by the text. character() never throws. The Dofus protocol reference describes the messages these values come from, if you'd rather follow one yourself.
-
Steps and conditions
Give your package's own functions to the Studio with export const steps and export const conditions, with their fields, what run receives and returns, the ref field that asks for game data, and the errors Asterobot reports. The Studio is where a plan is drawn: places on the world map, the order the bot visits them in, and what it does at each one. What a plan can do in the game comes from packages. A step is something done on a map, such as gathering, and a condition is a yes/no question, such as "are the bags fuller than 90%?". Your package gives the Studio its own steps and conditions by declaring them next to its settings and actions. Plans are played by @asterobot:base, so a package that draws them depends on it. The Studio shows how a player draws one with your steps and conditions. A function and its declaration A step or a condition is an ordinary function your package exports, which your own code can call like any other. The declaration only describes it for the Studio, and points to it with run. Steps go in an object exported as steps from index.js, and conditions in one exported as conditions: import { session, botInfo } from "asterobot:bot"; import { send } from "asterobot:protocol"; import { sleep } from "asterobot:timers"; /** Waits the given number of seconds, and ends early when the plan stops. */ export async function rest({ seconds }, context) { for (let waited = 0; waited < seconds; waited++) { // A plan only stops between steps, so a long step checks for itself. if (context?.stopping) return; await sleep(1000); } } /** Whether the clock of the computer running Asterobot has passed the hour. */ export function after({ hour }) { return new Date().getHours() >= hour; } /** @type {BehaviorSteps} */ export const steps = { rest: { label: "Rest", description: "Waits, and ends early when the plan stops.", args: { seconds: { type: "int", label: "Duration", unit: "seconds", default: 30, min: 1 }, }, run: rest, }, }; /** @type {BehaviorConditions} */ export const conditions = { after: { label: "After", args: { hour: { type: "int", label: "Hour", default: 20, min: 0, max: 23 }, }, run: after, }, }; 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, }); } // Declared for the Studio, and still an ordinary function. if (after({ hour: 20 })) botInfo("It's past 8 PM."); } Steps and conditions follow the rules of settings and actions about where they're declared: Only the exports of index.js count. The Studio will list them in the order you write them. A package can export any of parameters, actions, steps and conditions, or none of them. Asterobot reads them the way it reads settings, by running the top level of your modules without a bot. Declare settings describes what that means for your code. Each package declares its own, dependencies included. The Studio will offer the steps and conditions of the package you edit next to those of the packages it depends on. Asterobot never calls run, neither while it reads the declarations nor while your script plays: only a plan calls it, when a bot plays the plan. Steps and conditions aren't buttons either, so they never appear under Actions on the bot's page. A function you want both in a plan and on a button is declared twice, once in steps and once in actions. Fields Steps and conditions have the same fields. Only what run gives back differs. Field Required What it does label No The block's name in the Studio. Without it, the key is shown, such as rest. description No A line of help about what the block does. args No The values a plan gives on each call. Each one is declared exactly like a setting, with the same types, choices, bounds and defaults, and can ask for game data with ref. run Yes The function. Other fields are ignored. What run receives A plan calls run(args, context): args holds every argument you declared: the value set in the plan, or the argument's default when the plan leaves it out. An argument's value is checked with the same rules as a setting: the type, the choices, min and max. Without a default, an argument starts at its type's zero value, 0 for a number, or at its first choice when it has choices, as a setting does. When that breaks its own rules, such as min: 1, or when the argument asks for one id with ref, a plan can't leave it out: the Studio shows Argument <name> needs a value. and base refuses to play the plan until it's set. context says where the plan is: Field What it holds map The map the bot is on, as a number stop The stop of the plan being run, as the plan describes it lap How many times the plan has gone round, from 0 stopping true once the plan or the bot is asked to stop A plan only stops between steps. A step that can take long, such as rest above, checks context.stopping as it goes and returns early once it's true. When your own code calls the function, it passes whatever it wants, and there's no context unless you build one. Write context?.stopping, as above, in a function both a plan and your code call. What run returns A step's run may be async, and resolves with one of these: Nothing: the step did what it does on this map. { nothingToDo: true }: there was nothing to do on this map. Add retryAfter, a number of seconds, to say when there may be something again, such as { nothingToDo: true, retryAfter: 120 } for a resource that grows back in two minutes. A condition's run returns true or false, or a promise of one. Anything else, such as 1 or "yes", counts as an error. A step or a condition that throws, or whose promise rejects, has failed, and the plan decides what happens next. A condition about something the game hasn't told your script yet should throw, with a message saying what's missing, rather than guess an answer. Ask for game data with ref ref names the game data table that a setting's or an argument's numbers come from. It goes on an int, or an array of int, of any declaration: settings, the arguments of actions, steps and conditions. /** @type {BehaviorParameters} */ export const parameters = { monsters: { type: "array", of: "int", label: "Monsters to fight", ref: "monsters" }, subarea: { type: "int", label: "Subarea", ref: "sub_areas" }, }; The value is the name of a table of the game data, as the Game data tab shows it: monsters, items, jobs, maps, sub_areas, areas and so on. The script still reads plain numbers: keys of that table, the ids search() returns and record() looks up. See Lookups. Asterobot only checks that ref is a string. It doesn't check that the table exists, nor that the setting is an int, so a misspelled table name isn't reported. Asteroboard shows a search by name in place of the number box wherever the setting or the argument is edited: the bot's Settings tab, an action's dialog and the Studio. For maps, the number box stays, since maps have no names worth searching by. For maps, sub_areas and areas, Pick on the world map is offered too when a world map is on screen, as in the Studio. A table Asteroboard can't search keeps the plain number box. When Asterobot checks the declarations Asterobot checks steps and conditions at the same moments as settings: when a bot's Settings tab shows Package settings, when someone picks the package in the Add a bot dialog, and at every start of the script. Problems fall into the same two groups as for settings and actions. A mistake in the shape of the steps or conditions export stops the script from starting at all, and the Problems alert shows a text starting with read declarations of: Error Cause package "<package>": steps: must be an object, got <type> steps is exported, but isn't an object package "<package>": steps: "<step>" must be an object A step isn't an object package "<package>": steps: "<step>" declares no run function A step has no run package "<package>": steps: "<step>": run must be a function A step's run isn't a function package "<package>": steps: "<step>": args: must be an object, got <type> args isn't an object package "<package>": steps: "<step>": args: "<argument>" must be an object An argument isn't an object Conditions give the same texts with conditions: and the condition's name. A mistake in an argument doesn't stop the script, but it makes the whole package's declarations unreadable: Package settings shows Couldn't read this package's settings with the reason, and the script starts with no settings at all, even the ones that are fine. The reason starts with package "<package>" step "<step>": argument "<argument>": for a step's argument, or with package "<package>" condition "<condition>": argument "<argument>": for a condition's, followed by the texts Declarations lists for a setting. With default: 24 on the hour argument above, Package settings shows: my-package@1.0.0: read declarations: package "my-package" condition "after": argument "hour": parameter "hour" default: 24 is above the maximum 23 A ref that isn't a string is refused the same way, with ref must be a string, got <type>, on a setting as well as on an argument. Typing with JSDoc Put /** @type {BehaviorSteps} */ above export const steps, and /** @type {BehaviorConditions} */ above export const conditions, as in the example above. The editor then completes the fields, and marks a condition whose run returns something other than a boolean, and a step whose run returns something other than nothing or { nothingToDo }. These types need no import: Type What it describes BehaviorSteps The whole steps object BehaviorConditions The whole conditions object BehaviorStep One step BehaviorCondition One condition BehaviorBlockContext The context that run receives BehaviorStepResult What a step's run may resolve with Next, the Packages chapter describes the manifest, starting with every field of asterobot.json.
-
Le Studio
Dessiner sur la carte du monde ce que fait un bot, sans code : où il va, dans quel ordre, ce qu'il fait à chaque arrêt, et ce qui se passe quand quelque chose échoue. Read this page in English Le Studio est la partie de l'éditeur de paquet où vous dessinez ce que fait un bot au lieu de l'écrire. Vous dessinez un plan sur la carte du monde : les arrêts où va le bot, l'ordre dans lequel il en fait le tour, et à chaque arrêt les étapes qu'il y joue, comme attendre ou jouer un autre plan. Des conditions, comme le remplissage des sacs, décident si un arrêt ou une étape se joue, et quand le plan se termine. Le plan est enregistré comme un fichier du paquet, et @asterobot:base le joue quand un bot lance le paquet. Ce qu'il vous faut Il vous faut Pourquoi Un paquet local Le Studio s'ouvre dans l'éditeur de paquet, qui ne modifie que les paquets locaux. Pour partir du plan de quelqu'un d'autre, copiez-le dans l'un des vôtres : voir Les plans des autres paquets. @asterobot:base dans votre bibliothèque Base joue les plans et donne les conditions sur le personnage, comme son niveau ou le remplissage de ses sacs. Un paquet qui a des plans en dépend, et le Studio ajoute cette dépendance pour vous. Voir Installer base. Une version de jeu extraite La carte du monde est dessinée à partir des données de jeu. Voir Extraire les données de jeu. Un bot connecté à une partie Seulement pour jouer le plan. Dessiner ne demande aucun bot. La carte du monde affiche la version de jeu avec laquelle Asterobot est testé, quand ses données de jeu sont extraites. Un badge dans la barre d'outils de la carte donne son numéro, et le survoler indique que c'est la version que rencontrent les bots. Quand cette version n'est pas extraite, le Studio prend la plus récente des versions extraites et le badge indique Version incompatible : les identifiants de carte et les textes du jeu peuvent différer de ce que rencontre un bot. Quand aucune version n'est extraite, Aucune version du jeu extraite s'affiche à la place de la carte, et indique d'en extraire une dans le Gestionnaire de jeux : la carte apparaît alors d'elle-même, dès que la version est prête. Le panneau fonctionne en attendant, mais il n'y a rien sur quoi dessiner. Note Bientôt disponible. Base donnera des étapes qui agissent dans le jeu, comme récolter, combattre ou aller à la banque. Pour l'instant, elle ne donne que des conditions : un plan construit sur base seule voyage, attend, vérifie l'état du personnage et joue d'autres plans. Les étapes qui agissent dans le jeu viennent d'autres paquets, ou du vôtre : Étapes et conditions montre comment un paquet donne ses fonctions au Studio. Commencer un plan Un nouveau paquet qui commence avec le Studio Dans le Gestionnaire de bibliothèque, cliquez sur Nouveau paquet. Saisissez un Nom, et gardez ou changez la Version. Activez Commencer avec le Studio. Cliquez sur Créer et modifier. L'éditeur s'ouvre sur plans/main.js, un plan vide, dans le Studio. Le paquet reçoit aussi un index.js qui ne fait que jouer ce plan et transmettre ses réglages, et il dépend de @asterobot:base, dans la version installée la plus récente. Quand base n'est pas installée, @asterobot:base n'est pas installé apparaît sous l'interrupteur et Créer et modifier reste grisé jusqu'à ce que vous l'installiez à cet endroit. Voir Installer base. Un plan dans un paquet que vous avez déjà Ouvrez le paquet dans l'éditeur avec Modifier le code, depuis le Gestionnaire de bibliothèque ou depuis la page du paquet. En haut de Fichiers, cliquez sur plan, à côté de fichier. La boîte de dialogue Nouveau plan s'ouvre. Saisissez un Nom, comme farm : des lettres, des chiffres, - et _, en commençant par une lettre ou un chiffre. Le fichier qu'il devient, plans/farm.js, s'affiche sous le champ. Cliquez sur Nouveau plan, ou appuyez sur Entrée. La boîte de dialogue indique Lettres, chiffres, - et _ seulement. pour un nom qu'elle refuse, et Ce paquet a déjà un fichier à ce chemin. quand le plan remplacerait un fichier. Le nouveau plan s'ouvre dans le Studio sans aucun arrêt, avec un circuit Aller simple. Comme un fichier ajouté avec fichier, il n'existe dans le paquet qu'une fois enregistré. Si le paquet ne dépend pas encore de base, le Studio l'ajoute tout de suite à ses dépendances, dans la version installée la plus récente, et une notification le signale. Si base n'est pas installée du tout, la boîte de dialogue @asterobot:base n'est pas installé s'ouvre. Important Un plan ne se joue que si quelque chose le joue. Dans un paquet commencé avec le Studio, index.js joue plans/main.js. Tout autre plan se joue quand un plan en cours l'atteint, par une étape Jouer un plan ou une interruption, ou quand votre propre code le joue, comme le montre L'éditeur. Ajouter un plan à un paquet qui a son propre code ne change rien à ce que fait ce code. Tout fichier dont la première ligne le marque comme plan s'ouvre dans le Studio, quel que soit son dossier. Les plans ont leur propre icône dans Fichiers. Installer base Base peut s'installer depuis trois endroits : la boîte de dialogue Nouveau paquet local, celle qui s'ouvre après la création d'un plan, et Ajouter base aux dépendances dans l'alerte du panneau Le paquet ne dépend pas de @asterobot:base. Tous fonctionnent de la même façon : Collez l'ID ou le lien du fichier de base sur asterobot.net dans ID ou URL du fichier. Parcourir les paquets sur asterobot.net ouvre la bibliothèque du site si vous devez le trouver. Cliquez sur Prévisualiser, et vérifiez ce qui sera installé, comme dans Installer depuis le marché. Cliquez sur Installer. Quand cette version est déjà dans votre bibliothèque, le bouton devient L'utiliser. Dans l'éditeur, base est ensuite ajoutée aux dépendances du paquet. L'alerte du panneau s'affiche dès que le paquet ne dépend pas de base : son bouton Ajouter base aux dépendances ajoute la dépendance, ou ouvre la boîte de dialogue d'installation quand base n'est pas installée. L'écran Le Studio prend la place du code. La carte du monde est à gauche et le panneau à droite. Faites glisser la ligne entre les deux pour répartir la place : Asteroboard mémorise la position dans ce navigateur. La carte du monde est celle de l'onglet Cartes d'une page du jeu, avec sa recherche, ses interrupteurs, son zoom et sa liste de cartes du monde (voir Carte du monde). Ici, un clic sur une case n'ouvre pas la carte : il fait ce que fait l'outil en main. Le panneau commence par le nom du plan, Nommer ce plan, que la console du bot utilise aussi. À côté se trouvent Annuler, Rétablir et Voir le code. En dessous viennent quatre onglets : Circuit, Interruptions, Réglages et Problèmes. Tant qu'un plan est ouvert, la barre du haut de l'éditeur garde Enregistrer et Lancer, mais pas Jeu : le Studio a sa propre carte du monde. Le nombre d'erreurs qui s'y affiche compte aussi les problèmes des plans. Dessiner les arrêts Un arrêt, c'est un lieu et les étapes que le bot y joue. Les arrêts sont numérotés dans l'ordre du circuit, sur la carte et dans le panneau. Les outils sont dans la barre d'outils de la carte du monde : Outil Ce qu'il fait Sélection Sélectionne l'arrêt sous le pointeur. Cliquez à nouveau sur la même case pour passer d'un arrêt à l'autre sur cette case, cartes et zones d'abord. Un clic là où il n'y a aucun arrêt vide la sélection. Carte Ajoute un arrêt sur la carte de la case cliquée. Zone Peint les cases que vous survolez en glissant dans une zone : l'arrêt sélectionné quand c'est une zone, sinon une nouvelle. Maj+glisser efface des cases de la zone sélectionnée. Sous-zone Ajoute un arrêt sur la sous-zone sous le pointeur. Le numéro d'un arrêt sur la carte du monde se clique avec n'importe quel outil, et sélectionne cet arrêt. Tant que Zone est en main, glisser peint au lieu de déplacer la carte : prenez Sélection pour la déplacer. Carte. Quand plusieurs cartes partagent une case, comme une carte en extérieur et les intérieurs qui s'y ouvrent, une liste titrée avec les coordonnées de la case s'ouvre : Cartes en 4,-19. Chaque ligne donne l'ID d'une carte et sa sous-zone, et dans le graphe de trajets marque la carte où un trajet peut aller, en extérieur en général. Cliquez sur l'une d'elles pour l'ajouter, ou fermez la liste avec sa croix ou Échap. Un clic là où il n'y a aucune carte indique Aucune carte sur cette case. Zone. Chaque case peinte prend la carte où va un trajet sur cette case, celle qui est dans le graphe de trajets. Un glissé est une seule modification, annulée d'un coup. Le bot visite les cartes d'une zone de la plus proche à la plus lointaine. Sous-zone. L'arrêt couvre toutes les cartes de la sous-zone. Il n'y a pas d'outil pour une région : sélectionnez un arrêt et changez son Lieu en Une région, comme décrit dans Modifier un arrêt. Requête. Le bouton Requête, à côté de Arrêts dans l'onglet Circuit, ajoute un arrêt dont les cartes sont trouvées pendant que le plan se joue, d'après ce que vous nommez. Chaque champ est un interrupteur : activez ceux que vous voulez, remplissez-les, et cliquez sur Ajouter l'arrêt. Chaque champ activé restreint les cartes. Ajouter l'arrêt reste grisé tant qu'aucun champ autre que Avec un zaap n'est rempli : un zaap seul, ou rien du tout, prendrait toutes les cartes du jeu, et l'arrêt afficherait La requête doit nommer une sous-zone, une région, un monstre, une ressource, des coordonnées ou une carte du monde : sinon elle prend toutes les cartes du jeu. Champ Garde les cartes Sous-zone De cette sous-zone, cherchée par nom. Région De cette région, cherchée par nom. Monstre D'une sous-zone où vit ce monstre, cherché par nom. Ressource Où cet objet se récolte, comme le blé, cherché par nom. Avec un zaap Qui ont un zaap actif. X, Y À ces coordonnées. Id de la carte du monde Sur cette carte du monde. 1 est le Monde des Douze. Ce que montre la carte du monde Le lieu de chaque arrêt : la case d'une carte, les cases remplies d'une zone, le contour d'une sous-zone ou d'une région, avec le numéro de l'arrêt dessus. Une flèche de chaque arrêt vers le suivant. Quand le circuit se répète, une flèche en pointillés va du dernier arrêt au premier. L'arrêt sélectionné, dans une couleur à lui. Seulement les arrêts de la carte du monde affichée. Une flèche vers un arrêt d'une autre carte du monde, ou depuis lui, comme Incarnam, est un court départ de flèche avec une étiquette comme vers 4 · Incarnam. Cliquez sur l'étiquette pour afficher cette carte du monde. Un arrêt de type requête n'est pas dessiné, puisque ses cartes ne sont connues que pendant que le plan se joue, pas plus qu'une carte qui n'est sur aucune carte du monde, comme une instance ou une maison. Les flèches vont alors directement de l'arrêt d'avant à l'arrêt d'après. La liste des arrêts Arrêts, dans l'onglet Circuit, liste les arrêts dans l'ordre. Chaque ligne affiche le numéro de l'arrêt, son nom ou son lieu, son nombre d'étapes, sur aucune carte du monde pour une carte qui ne peut pas être dessinée, et un nombre en rouge quand quelque chose ne va pas. Cliquez sur une ligne pour sélectionner l'arrêt et centrer la carte du monde dessus. Faites glisser une ligne pour déplacer l'arrêt, ou utilisez les flèches qui apparaissent au survol. Les flèches sur la carte suivent. Sans aucun arrêt, la liste indique « Aucun arrêt pour l'instant : prenez l'outil Carte, Zone ou Sous-zone et cliquez sur la carte du monde. » Le circuit Le haut de l'onglet Circuit indique l'ordre dans lequel le bot visite les arrêts, et combien de fois. Quatre modèles règlent les deux à la fois : Modèle Ordre Répétition Ce que fait le bot Boucle Comme dessiné Sans fin Les arrêts dans leur ordre, encore et encore. Aller simple Comme dessiné Une fois Les arrêts dans leur ordre, une fois. Un nouveau plan commence ainsi. Balayage Le plus proche d'abord Sans fin L'arrêt le plus proche qui a encore du travail, encore et encore. Jusqu'à Comme dessiné Jusqu'à une condition Les arrêts dans leur ordre, jusqu'à ce qu'une condition soit vraie. Vous pouvez aussi régler Ordre et Répétition vous-même, par exemple un balayage jusqu'à une condition. Aucun modèle n'est alors mis en avant, et la ligne en dessous indique « Une autre combinaison d'ordre et de répétition. » Avec Jusqu'à une condition, la condition se trouve sous Jusqu'à ce que. Elle commence à « Après 60 min de jeu » : changez-la comme décrit dans Les conditions. Elle est vérifiée après chaque arrêt, et à la fin d'un tour une fois le tour compté, donc « Après le tour 3 » termine le plan juste à la fin du troisième tour. Un passage sur tout le circuit est un tour. Voici comment se déroule un tour : Comme dessiné prend les arrêts dans l'ordre de la liste. Le plus proche d'abord visite aussi chaque arrêt une fois par tour, mais choisit à chaque fois l'arrêt dont la carte est la plus proche. Un arrêt dont la condition Seulement si est fausse au moment où il arrive est passé pour ce tour. À un arrêt, le bot va sur ses cartes l'une après l'autre : d'abord celle où il se trouve, puis à chaque fois la plus proche des autres. Il y va par un trajet, carte après carte. Une carte qu'aucun trajet n'atteint est passée, avec une ligne dans la console du bot. Quand aucun trajet n'atteint aucune des cartes d'un arrêt, l'arrêt échoue. Sur chaque carte, le bot joue les étapes de l'arrêt dans l'ordre. Un arrêt sans étape est un point de passage : le bot ne fait qu'y passer. Une fois termine le plan après un tour. Sans fin et Jusqu'à une condition lancent le suivant. Un tour dure toujours au moins une seconde. Une étape venant d'un paquet peut signaler au plan qu'il n'y a plus rien à faire sur une carte pour le moment, par exemple quand tout y a été récolté, et quand revenir. Le bot laisse alors cette carte de côté jusqu'à ce moment, ou jusqu'au tour suivant, dans les deux ordres. Quand toutes les cartes restantes attendent, le bot attend que la première ait de nouveau du travail au lieu de tourner pour rien. Modifier un arrêt Sélectionnez un arrêt, dans la liste ou avec Sélection, et il s'ouvre sous la liste : Partie Ce qu'elle fait Nom Nommer cet arrêt (facultatif). Affiché dans la liste et dans la console du bot. Sans nom, c'est le lieu qui s'affiche. Icône corbeille Supprime l'arrêt, sans confirmation. Annuler le fait revenir. Lieu Où se trouve l'arrêt. Voir plus bas. Seulement si Une condition vérifiée quand l'arrêt arrive. Fausse : l'arrêt est passé pour ce tour, ce qui n'est pas un échec. Sans condition, il indique « Toujours visité. » et Ajouter une condition en ajoute une. En cas d'échec Ce qui se passe quand l'arrêt échoue. Voir Quand quelque chose échoue. Étapes Les étapes jouées sur chacune des cartes de l'arrêt. Voir Les étapes. Lieu commence par une liste de cinq types : Type Ce que vous réglez Une carte Id de la carte, saisi ou choisi avec Choisir sur la carte du monde. En dessous, les coordonnées de la carte et le nom de sa carte du monde, ou « Sur aucune carte du monde (une instance, une maison...) : affichée ici seulement ». Une zone (cartes peintes) Peinte avec Zone sur la carte du monde. Elle indique combien de cartes elle contient, combien ne sont sur aucune carte du monde, et Afficher les cartes les liste, chacune avec un bouton pour la retirer. Une sous-zone Cherchée par nom, ou choisie sur la carte du monde. En dessous, la carte du monde où elle se trouve. Une région La même chose, pour une région. Une requête, résolue pendant le jeu Les champs d'une requête, comme pour Requête. Changer de type garde ce qui peut l'être : une carte devient une zone de cette seule carte, une zone devient une carte avec sa première carte, et une carte ou une zone devient la sous-zone de sa première carte, ou une requête qui commence avec cette sous-zone. Sans rien à garder, une carte, une sous-zone ou une région commence vide, et l'arrêt affiche Le lieu de cet arrêt n'a pas encore été choisi. jusqu'à ce que vous en choisissiez une. 0 n'est jamais mis à sa place : c'est un ID comme un autre, la région 0 étant Amakna. Les champs qui nomment des données de jeu Un champ qui demande un monstre, un objet, un métier, une sous-zone ou toute autre donnée de jeu a une zone Chercher par nom. Tapez une partie d'un nom et choisissez-le dans la liste : chaque entrée affiche son ID, et l'ID s'affiche sous la zone une fois choisi. Un champ qui en prend plusieurs, comme une liste de monstres, garde chacun de ceux que vous choisissez. La liste indique « Tapez un nom pour chercher. », « Rien de ce nom. » ou « La recherche a échoué. » quand elle n'a rien à afficher. Les noms sont dans la langue choisie avec Langue sur une page du jeu. Les champs d'une carte, d'une sous-zone ou d'une région ont aussi Choisir sur la carte du monde. Cliquez dessus : le bouton indique « Cliquez sur la carte du monde... » et une barre sur la carte dit quoi cliquer, avec Annuler. Échap abandonne aussi. Pour une région, cliquez sur n'importe laquelle de ses cases. Une carte n'a pas de nom à chercher : saisissez son ID, ou choisissez-la. Les étapes Ajouter une étape, sur un arrêt sélectionné, ouvre la palette. Elle liste d'abord Les blocs du Studio, puis les étapes que donne chaque paquet, regroupées par paquet : le paquet que vous modifiez en premier, marqué « (ce paquet) », puis ses dépendances par ordre alphabétique. Chaque entrée a une ligne de description. Cliquez sur l'une d'elles pour l'ajouter à la fin des étapes de l'arrêt. Les paquets proposés sont celui que vous modifiez et ceux listés dans ses dépendances. Un paquet utilisé seulement par une dépendance n'est pas proposé. Une dépendance qui ne donne rien ici est listée en grisé en bas, avec la raison : Raison Que faire sa version dans le manifeste n'est pas exacte Donnez-lui une version exacte dans la fiche Manifeste du paquet. cette version n'est pas installée Installez cette version, ou changez la dépendance pour une version que vous avez. ses déclarations n'ont pas pu être lues Le paquet a une erreur. Voir Erreurs de paquet. Quand les déclarations du paquet lui-même ne peuvent pas être lues, le panneau affiche Les blocs du paquet lui-même n'ont pas pu être lus avec l'erreur, et la palette n'a pas les étapes et conditions du paquet tant que ce n'est pas corrigé. La palette est relue à chaque enregistrement, donc une étape que vous venez de déclarer dans le code du paquet apparaît une fois enregistrée. Les étapes du Studio Étape Champs Ce qu'elle fait Échoue quand Attendre Secondes, et Jusqu'à une fois activé Attend ce nombre de secondes, ou une durée au hasard entre Secondes et Jusqu'à. Commence à 5 secondes. Jamais Attendre que Jusqu'à ce que, une condition, et Abandonner après, en secondes, une fois activé Vérifie la condition tout de suite, puis chaque seconde jusqu'à ce qu'elle soit vraie. Abandonner après est dépassé d'abord, ou la condition ne peut pas répondre Jouer un plan Plan, un autre plan du paquet Joue ce plan ici, depuis le début de son circuit, puis continue. Avant l'étape suivante, le bot revient sur la carte de l'arrêt. Ce plan s'arrête sur un échec Écrire Message Écrit le message dans la console du bot. Jamais Arrêter Aucun Termine tout ce qui est joué, comme une fin normale : ce plan, et tout plan qui est en train de le jouer. Jamais Un champ facultatif s'affiche comme un interrupteur : activez-le pour le régler, et désactivez à nouveau son interrupteur pour le retirer. Jouer un plan ne propose que les autres plans du paquet, et indique « Le paquet n'a pas encore d'autre plan. » quand il n'y en a aucun. Un plan joué ainsi compte ses propres tours. Les étapes des paquets L'étape d'un paquet affiche son libellé, suivi des valeurs de ses arguments, comme « Gather: Wheat, Barley ». Les libellés et les descriptions sont dans la langue dans laquelle l'auteur du paquet les a écrits. Dépliez l'étape pour régler ses arguments : chacun est le même champ que dans l'onglet Réglages du bot (voir Les champs), avec le libellé, la description et les limites du paquet, et la recherche dans les données de jeu quand le paquet en demande. « Ne prend aucun argument. » signifie qu'il n'y a rien à régler. Un argument que vous n'avez pas changé prend la valeur par défaut du paquet quand le plan se joue, donc un plan suit le paquet quand son auteur change une valeur par défaut. Une fois un argument changé, Valeur par défaut le remet. Quand la valeur par défaut du paquet ne peut pas servir, parce qu'elle enfreint les règles de l'argument (un niveau d'au moins 1 commencerait à 0) ou parce que l'argument demande des données de jeu sans avoir de valeur par défaut, le champ reste vide et l'étape affiche L'argument <argument> a besoin d'une valeur. jusqu'à ce que vous le régliez. Depuis un réglage permet de le régler depuis la page du bot : voir Les réglages du plan. La fiche d'une étape Chaque étape est une fiche avec une phrase qui dit ce qu'elle fait, comme « Attendre 5 s ». En dessous, Seulement si : affiche sa condition quand elle en a une, et En cas d'échec : affiche toujours ce qui se passe quand elle échoue, même quand c'est le choix par défaut, Arrêter le plan. Cliquez sur la fiche, ou sur sa flèche, pour la déplier : ses arguments ou ses champs, Seulement si et En cas d'échec. Seulement si est vérifié juste avant l'étape. Fausse : l'étape est passée, ce qui n'est pas un échec. Sans condition, il indique « Toujours jouée. » Faites glisser une fiche par sa poignée pour la déplacer, ou utilisez ses flèches. L'icône corbeille la supprime, sans confirmation. Les conditions Une condition est une question à laquelle on répond par oui ou non. Elles servent dans le Seulement si d'un arrêt ou d'une étape, dans Attendre que, dans le Jusqu'à ce que du circuit, dans le Quand d'une interruption, et à l'intérieur d'autres conditions. Ajouter une condition ouvre la palette des conditions : Les blocs du Studio d'abord, puis les conditions que donnent les paquets. Condition Champs Vraie quand Toutes Conditions Chacune d'elles l'est. Elle commence avec une condition, et Ajouter une condition en ajoute d'autres. Au moins une Conditions Au moins l'une d'elles l'est. Non Condition Sa condition ne l'est pas. Temps de jeu Minutes Cette durée s'est écoulée depuis que le bot a lancé le plan. Dans un plan joué par un autre, le temps compte depuis le lancement du premier plan. Tours Tours, à partir de 1 Le circuit a été terminé ce nombre de fois. Heure De, À L'horloge de l'ordinateur qui exécute Asterobot indique une heure entre De, inclus, et À, exclu. Un De après À passe par minuit : de 22:00 à 06:00, c'est la nuit. La même heure dans les deux n'est jamais vraie. Hasard Probabilité, de 0 à 100 % Un tirage au sort, refait à chaque vérification, le dit. 0 n'est jamais vrai, 100 l'est toujours. Base donne ces conditions sur le personnage, avec les libellés qu'elle écrit en anglais : Condition Arguments Vraie quand Level at least Level, à partir de 1 Le niveau du personnage est au moins celui-là. Kamas at least Kamas Il porte au moins ce nombre de kamas. Life below Life, de 1 à 100 % Sa vie est sous cette part de son maximum. Bags above Bags, de 1 à 100 % Ses sacs sont plus remplis que cette part de ce qu'ils peuvent porter. In a fight Aucun Un combat est en cours. Has an item Item, cherché par nom, et How many, 1 par défaut Il porte au moins ce nombre de l'objet, équipé ou non. Job level at least Job, cherché par nom, et Level, à partir de 1 Ce métier est au moins à ce niveau. Un métier que le personnage n'a pas est au niveau 0. On a map Map Il se trouve sur cette carte. In a subarea Subarea Il se trouve dans cette sous-zone. In an area Area Il se trouve dans cette région. Le contraire de chacune, c'est Non autour d'elle. Une nouvelle condition commence avec les valeurs par défaut du paquet, et la plupart des arguments de base n'en ont aucune qui puisse servir : leurs champs restent vides, et la condition affiche L'argument <argument> a besoin d'une valeur. jusqu'à ce que vous les régliez. Seuls Kamas (0) et How many (1) peuvent rester tels quels. Chaque condition est une fiche avec sa phrase, comme « Entre 08:00 et 20:00 ». Dépliez-la pour modifier ses champs. Le bouton à flèches, Changer la condition, la remplace par une autre de la palette. La croix la supprime là où une condition est facultative : le Seulement si d'un arrêt ou d'une étape, et les conditions à l'intérieur de Toutes et Au moins une. Le Quand d'une interruption, le Jusqu'à ce que du circuit, Attendre que et Non en gardent toujours une : changez-la plutôt. Une condition qui ne peut pas répondre échoue, et le bloc qu'elle garde aussi. Les conditions de base échouent ainsi quand le jeu n'a pas encore indiqué quelque chose, comme les niveaux des métiers du personnage : elles ne devinent jamais. La console dit alors ce qui manque, par exemple the jobs aren't known yet. Quand quelque chose échoue Chaque arrêt et chaque étape a En cas d'échec : Choix Ensuite Arrêter le plan Le plan s'arrête, avec l'erreur dans la console du bot. C'est le choix par défaut. La passer, aller à l'étape suivante (pour une étape), Le passer, aller à l'arrêt suivant (pour un arrêt) Une ligne dans la console, puis le plan continue. Réessayer Nouvel essai jusqu'à Essais fois, de 1 à 10 (2 au départ), à Secondes entre deux essais d'intervalle (5 par défaut). Si ça échoue encore, il arrête le plan ou passe, selon votre choix. Un arrêt réessayé repart de zéro : ses cartes sont à nouveau trouvées et ses étapes rejouées depuis la première. Quoi Échoue quand Une étape L'étape d'un paquet signale une erreur. Son Seulement si ne peut pas répondre. Un Attendre que abandonne, ou sa condition ne peut pas répondre. Le plan que joue une étape Jouer un plan s'arrête sur un échec. La valeur d'un argument ne respecte pas les règles du paquet, par exemple un réglage du plan dont la valeur est sous le minimum de l'argument. Un arrêt Son lieu n'a aucune carte, ou ses cartes ne peuvent pas être trouvées. Aucun trajet n'atteint aucune de ses cartes. Un trajet vers l'une de ses cartes échoue, y compris un trajet que vous arrêtez depuis l'onglet Carte du bot. Son Seulement si ne peut pas répondre. Tout le plan, quoi que dise En cas d'échec Le Quand d'une interruption ne peut pas répondre, ou le plan qu'elle joue s'arrête sur un échec. Le Jusqu'à ce que du circuit ne peut pas répondre. Une étape qui échoue ne fait pas échouer son arrêt : seul le En cas d'échec de l'étape s'applique. Quand le plan s'arrête sur un échec, la console du bot reçoit une ligne d'erreur qui nomme le plan, l'arrêt et l'étape, et la raison : base: Astrub farm › 2 Wheat field (k3f9) › wait until (w4t6) failed: its condition still didn't hold after 60 s Les quatre caractères entre parenthèses sont l'ID du bloc dans le fichier du plan. Le Studio ne les affiche pas, mais Voir le code les montre. Les lignes de base sont en anglais, quelle que soit la langue d'Asteroboard. Avec le index.js qu'écrit Commencer avec le Studio, un plan qui s'arrête sur un échec arrête aussi le script : la page du bot affiche Le comportement s'est arrêté sur une erreur, avec un texte qui commence par unhandled Promise rejection:, suivi de la même erreur. Cliquez sur Lancer pour rejouer le plan, depuis le début de son circuit. Les interruptions Une interruption joue un autre plan quand une condition est vraie, puis revient au circuit ou le termine. « Quand les sacs sont remplis à plus de 90 %, jouer le plan de la banque, puis reprendre » est une interruption. Elles se trouvent dans l'onglet Interruptions. Ajouter une interruption en ajoute une avec ces champs : Champ Ce qu'il fait Nom La nommer (Banque quand plein). Affiché dans la console du bot. Quand La condition. Elle commence à « Après 60 min de jeu ». Jouer le plan Un autre plan du paquet. Tant que vous n'en choisissez pas, l'interruption a le problème Aucun plan choisi. Ensuite Reprendre où en était le circuit : le bot revient sur la carte où il était et joue l'étape qu'il allait jouer. Terminer ce plan : le plan auquel appartient l'interruption se termine là. Quand un autre plan le jouait, celui-ci continue. Les interruptions sont vérifiées dans leur ordre, en arrivant sur chaque carte et avant chaque étape. Jamais pendant une étape ou un trajet : une longue étape se termine d'abord. La première dont la condition est vraie joue son plan. Pendant que ce plan se joue, la même interruption n'est plus vérifiée, même depuis ce plan, donc « sacs pleins : banque » ne peut pas relancer le plan de la banque depuis le plan de la banque. Les interruptions du plan joué, elles, s'appliquent. Avec Reprendre où en était le circuit, le plan joué doit rendre la condition fausse : le plan de la banque vide les sacs. Quand la condition est encore vraie juste après ce plan, base arrête le plan plutôt que de rejouer le plan de la banque encore et encore, et la console dit quelle interruption : base: Astrub farm › interrupt Bank when full (i7w0) is still true after its plan plans/bank.js ran: that plan must make it false, or it would run again and again Un Hasard dans la condition ne compte pas contre elle, puisque la vérification suivante tire à nouveau. Les flèches montent ou descendent une interruption, et l'icône corbeille la supprime. Une interruption a besoin d'un autre plan à jouer : créez-le d'abord avec plan dans Fichiers. Les réglages du plan Un plan peut avoir ses propres réglages, qu'un joueur règle sur la page du bot, comme les monstres à combattre ou un niveau à atteindre. Ils se trouvent dans l'onglet Réglages. Ajouter un réglage en ajoute un, nommé setting, qui contient un nombre entier, 0 par défaut. Champ Ce qu'il fait Nom La clé du réglage. Des lettres, des chiffres et _, sans commencer par un chiffre, et pas __proto__. Il est renommé quand vous appuyez sur Entrée ou quittez la zone, en même temps que chaque argument qui l'utilise. Un nom déjà pris ou interdit est refusé avec « ne peut pas être le nom d'un réglage : il est déjà pris, ou n'est pas un nom qu'un script pourrait écrire. » Nombre d'utilisations inutilisé, utilisé une fois ou utilisé 3 fois : combien d'arguments prennent leur valeur dans ce réglage. Type bool (activé ou désactivé), string (texte), int (nombre entier), double (nombre décimal), array (liste) ou map (entrées avec une clé). Contenant Pour array et map : le type de ce qu'ils contiennent. Libellé Le nom qu'affiche la page du bot. Données du jeu Pour un nombre entier ou une liste de nombres entiers : la table des données de jeu d'où viennent les nombres, comme monsters, items, sub_areas, areas ou maps. La page du bot propose alors une recherche par nom. Minimum, Maximum Pour les nombres. Valeur par défaut La valeur tant qu'un joueur ne la change pas sur la page du bot. Un réglage en a besoin quand il ne pourrait pas commencer au zéro de son type : un nombre entier d'au moins 1 commencerait à 0, et un seul ID de données de jeu à 0, un ID que personne n'a choisi. Sans elle, le champ reste vide et le réglage affiche Il a besoin d'une valeur par défaut : sans elle, il commencerait à une valeur avec laquelle il ne peut pas tourner. L'icône corbeille supprime un réglage. Les arguments qui l'utilisaient affichent alors le problème Argument <argument> : le plan n'a pas de réglage <name>. Utiliser un réglage Dépliez une étape ou une condition d'un paquet et activez Depuis un réglage sous un argument. L'argument prend alors sa valeur dans le réglage du plan de même nom et de même type, ou dans un nouveau réglage créé à partir de l'argument lui-même : son libellé, ses limites, sa table de données de jeu, et sa valeur actuelle comme valeur par défaut, ou aucune valeur par défaut quand l'argument n'en a pas d'utilisable. Une liste permet ensuite de choisir un autre réglage du même type. Désactivez l'interrupteur pour redonner à l'argument la valeur par défaut du paquet. Tant qu'un joueur ne règle pas une autre valeur sur la page du bot, l'argument prend la valeur par défaut du réglage, qui doit donc convenir à l'argument : un réglage qui vaut 150 par défaut ne peut pas tenir lieu de pourcentage. Sinon, l'étape ou la condition affiche Argument <argument> : la valeur par défaut du réglage <setting> ne convient pas : <issue>. Une valeur réglée sur la page du bot est vérifiée quand l'étape ou la condition se joue, et une valeur qui ne convient pas à l'argument la fait échouer. Seuls les arguments des étapes et des conditions des paquets peuvent prendre un réglage. Les blocs du Studio prennent des valeurs fixes : les secondes d'un Attendre ne peuvent pas venir d'un réglage. Les afficher sur la page du bot Les réglages d'un plan n'arrivent dans l'onglet Réglages du bot qu'une fois que le index.js du paquet les transmet. L'onglet Réglages du Studio vous dit où vous en êtes : Ce que vous voyez Ce que cela signifie Ces réglages ne sont pas encore sur la page du bot, avec L'ajouter index.js ne les transmet pas. L'ajouter écrit dans index.js ce qui le fait : une ligne comme export { parameters } from "./plans/farm.js"; après les imports en haut, ou, quand index.js transmet déjà les réglages d'un autre plan, la fusion des deux. Une notification indique « Ajouté à index.js : enregistrez pour l'appliquer. » « index.js les réexporte maintenant : enregistrez pour voir ces réglages sur la page du bot. » index.js les transmet, mais n'est pas encore enregistré. index.js a ses propres réglages index.js déclare lui-même des réglages, pas seulement ceux des plans, et un second parameters entrerait en conflit avec eux. Le Studio n'ajoute rien et affiche les lignes à écrire à la main : L'éditeur les explique. Une fois enregistré, plus rien ne s'affiche. Un paquet commencé avec le Studio transmet déjà les réglages de plans/main.js. L'ajouter fonctionne aussi pour tous les autres plans, tant que index.js ne fait que rassembler les réglages des plans : il fusionne ceux du nouveau plan avec ceux qui y sont déjà. L'éditeur montre ce qu'il écrit. Sur la page du bot, les réglages d'un plan sont des réglages du paquet comme les autres, dans la fiche du paquet sous Réglages du paquet : voir Réglages et actions d'un paquet. Une valeur que vous y appliquez sert dès que l'argument la lit à nouveau, sans relancer le plan. Quand index.js ne transmet pas les réglages, le plan utilise la valeur par défaut de chaque réglage, et la console le signale avant que le bot ne bouge, en une ligne qui les nomme tous : base: Astrub farm: setting monsters isn't one of the package's settings, so its default is used: re-export the plan's settings from the package's entry Les plans d'un même paquet partagent les valeurs du bot : deux plans qui ont un réglage du même nom utilisent la même valeur, donc ils doivent lui donner le même type. Sinon, le réglage indique « Déclaré avec un autre type par : » suivi de chaque plan qui le déclare et de son type, et cela compte comme un problème. Les problèmes L'onglet Problèmes liste tout ce qui ne va pas dans le plan, avec un nombre en rouge sur l'onglet. Chaque problème dit ce qui ne va pas et où : Arrêt 2, Interruption 1, Réglage monsters, Circuit ou Plan. Cliquez sur l'un d'eux pour y aller. La même phrase s'affiche en rouge sous le bloc concerné, et la liste des arrêts compte les problèmes de chaque arrêt. Le nombre d'erreurs de l'éditeur ajoute les problèmes de tous les plans aux erreurs du code. Sans problème, l'onglet indique « Rien à redire à ce plan. » L'enregistrement reste possible avec des problèmes, car un plan est souvent enregistré à moitié fait. C'est base qui le refuse : quand le bot le joue, base vérifie tout le plan, et chaque plan qu'il joue, avant que le bot ne bouge. Un seul problème empêche le bot de bouger : la console affiche can't be run: après le nom du plan, suivi de chaque problème trouvé par base. Quelques problèmes que vous rencontrerez : Problème Que faire Le circuit n'a encore aucun arrêt. Ajoutez un arrêt. Aucun plan choisi. Choisissez le plan d'une étape Jouer un plan ou d'une interruption. Le plan <path> n'existe plus. Le fichier a été supprimé. Choisissez un autre plan. Argument <argument> : <issue>. Changez la valeur, comme un nombre au-dessus de son maximum. L'argument <argument> a besoin d'une valeur. Réglez l'argument : la valeur par défaut du paquet ne peut pas servir, ou il n'y en a pas. Argument <argument> : le plan n'a pas de réglage <name>. Le réglage a été supprimé ou renommé. Choisissez-en un autre, ou désactivez Depuis un réglage. Argument <argument> : la valeur par défaut du réglage <setting> ne convient pas : <issue>. Changez la Valeur par défaut du réglage, ou ses limites. Il a besoin d'une valeur par défaut : sans elle, il commencerait à une valeur avec laquelle il ne peut pas tourner. Donnez au réglage une Valeur par défaut. Le lieu de cet arrêt n'a pas encore été choisi. Choisissez la carte, la sous-zone ou la région de l'arrêt. La requête doit nommer une sous-zone, une région, un monstre, une ressource, des coordonnées ou une carte du monde : sinon elle prend toutes les cartes du jeu. Activez un champ de plus dans la requête. L'attente la plus longue est plus courte que la plus courte. Jusqu'à est inférieur à Secondes dans un Attendre. Il faut au moins une condition. Un Toutes ou un Au moins une est vide. @asterobot:base joue ce plan, mais le paquet n'en dépend pas. Cliquez sur Ajouter base aux dépendances dans l'alerte en haut du panneau. Le réglage <name> est déclaré avec des types différents par les plans du paquet Donnez-lui le même type dans chaque plan. Les blocs verrouillés Un bloc que le Studio ne peut pas modifier s'affiche verrouillé : « Lecture seule : fait avec un Studio plus récent, ou appelle quelque chose que le paquet n'a pas », suivi de la raison et du bloc tel que le fichier le contient. Cela arrive à un bloc fait avec une version plus récente du Studio, et à une étape ou une condition d'un paquet qui n'est plus une dépendance, qui ne donne aucun bloc ici, ou qui ne déclare plus cette fonction. Le Studio garde un bloc verrouillé exactement tel quel et l'enregistre sans le changer. Corrigez la cause, par exemple en ajoutant ou en installant la dépendance, ou supprimez le bloc avec son icône corbeille. Un circuit fait avec un Studio plus récent indique « Ce circuit a été fait avec un Studio plus récent : il est gardé tel quel. » Un plan qui ne peut pas s'ouvrir Quand un fichier de plan ne peut pas être lu, le Studio affiche Ce plan ne peut pas être ouvert dans le Studio à la place du plan, n'écrit jamais par-dessus le fichier, et propose Ouvrir comme code : Raison Cause Ce plan a été fait avec un Studio plus récent Un Asteroboard plus récent l'a écrit. Asteroboard se met à jour tout seul : rechargez la page une fois qu'il affiche Mise à jour disponible. Voir Mettre à jour Asterobot. Les repères du plan manquent : le fichier a été modifié à la main. Quelqu'un a modifié le code du fichier. Les données du plan sont illisibles Les données du plan dans le fichier sont cassées. Une partie du plan n'est pas ce qu'attend le Studio Les données du plan n'ont pas la bonne forme. Enregistrer, annuler et voir le code Un plan est l'un des fichiers du paquet. Enregistrer, ou Ctrl+S, l'enregistre avec les autres. Non enregistré et le point à côté de son nom dans Fichiers fonctionnent comme pour le code, et rien ne vous demande d'enregistrer quand vous quittez l'éditeur : les modifications non enregistrées sont perdues. L'éditeur donne tous les détails de l'enregistrement. Annuler et Rétablir, à côté du nom du plan, reviennent sur les modifications une par une. Quand le Studio a le focus, Ctrl+Z annule, Ctrl+Maj+Z ou Ctrl+Y rétablit, et Ctrl+S enregistre : cliquez d'abord dans le Studio. Sur Mac, utilisez Cmd. Saisir dans un champ, ou un glissé de Zone, compte comme une seule modification. L'ajouter est une modification de index.js, pas du plan : annulez-la dans le code de index.js. Voir le code affiche le fichier du plan dans l'éditeur de code, avec Revenir au Studio au-dessus et un rappel que ce qui y est modifié à la main est perdu la prochaine fois que le Studio enregistre le plan. Le Studio réécrit tout le fichier à chaque modification du plan, donc faites vos modifications dans le Studio. Jouer un plan Dans l'éditeur, Lancer enregistre le paquet et le lance sur le bot choisi à côté. Voir L'éditeur. Ou réglez le bot sur le paquet et cliquez sur Lancer, comme le montre Lancer un paquet. Le plan attend que le personnage soit sur sa carte, vérifie tout le plan, puis se met en route. Chaque démarrage commence au début du circuit : le plan ne reprend pas là où une exécution précédente s'est arrêtée. La Console du bot reçoit une ligne à chaque arrêt et à chaque étape, et pour chaque interruption, nouvel essai, étape passée, étape Écrire et erreur : base: Astrub farm › 1 Wheat field base: Astrub farm › 1 Wheat field › wait 5 s base: Astrub farm › 1 Wheat field › wait until base: Astrub farm › 2 3 maps Pendant que le bot voyage, son onglet Carte affiche le trajet, comme pour un trajet que vous lancez vous-même. Arrêter le trajet à cet endroit fait échouer l'arrêt, comme tout trajet qui échoue. Arrêter, sur la page du bot, arrête le script tout de suite, où que soit le plan. Quand une plage du planning du bot se termine, le plan se termine proprement, dans le Temps pour finir du planning : l'étape en cours se termine, un Attendre ou un Attendre que s'arrête tout de suite, et un trajet s'arrête une fois son étape en cours terminée, pour que le personnage ne s'arrête jamais au milieu d'un changement de carte. Une étape Arrêter termine le plan de la même façon, comme une fin normale. Un circuit Aller simple, ou un circuit qui se termine avec Jusqu'à une condition, termine le plan une fois fini. Le bot reste où il est. Note Bientôt disponible. Le Studio montrera où en est un bot dans son plan pendant qu'il le joue. En attendant, suivez-le dans la Console du bot. Les plans des autres paquets La page de chaque paquet a une fiche Plans qui liste ses plans, paquets du marché compris. Chaque ligne donne le nom du plan, son fichier et son nombre d'arrêts, ou illisible. « Aucun plan dans ce paquet. » signifie qu'il n'y en a aucun. Ouvrir affiche le plan dans le Studio, en lecture seule, sur une page à part : la carte du monde avec le plan dessiné dessus, et le panneau sans rien à modifier. Sélectionnez les arrêts pour les lire, dans la liste ou sur la carte. Le haut de la page affiche le paquet, le fichier du plan et Lecture seule. Pour un paquet local, Modifier le code ouvre le plan dans l'éditeur. Pour n'importe quel paquet, Copier dans... le copie dans l'un des vôtres. Quand la page ne peut pas afficher le plan, elle dit pourquoi : les fichiers du paquet n'ont pas pu être lus, le paquet n'a pas ce fichier, le fichier n'est pas un plan, ou l'une des raisons de Un plan qui ne peut pas s'ouvrir. Copier un plan dans votre paquet Cliquez sur Copier dans... sur la page du paquet ou sur celle du plan. La boîte de dialogue a pour titre le fichier du plan, comme Copier plans/farm.js. Choisissez un Paquet. Seuls vos paquets locaux sont listés. S'il n'y en a aucun, elle indique « Vous n'avez encore aucun paquet à vous. » Lisez ce que fera la copie. Fichiers liste chaque plan copié, avec le fichier qu'il devient dans votre paquet. Ajouté à ses dépendances liste les paquets qu'utilisent les plans et dont votre paquet ne dépend pas encore, ou indique « Rien à ajouter. » Cliquez sur Copier et ouvrir. La copie va dans le dossier plans de votre paquet, avec chaque plan qu'elle joue par des interruptions et des étapes Jouer un plan. Un plan dont le nom de fichier est déjà pris reçoit un numéro, comme plans/bank-2.js, et les plans qui le jouent sont modifiés en conséquence. Les dépendances sont ajoutées dans la version installée, y compris le paquet d'où vient le plan quand le plan utilise les propres étapes de ce paquet. Les fichiers comme les dépendances sont écrits dans votre paquet tout de suite, sans Enregistrer, et l'éditeur s'ouvre sur la copie, qui est désormais à vous. Message Ce qu'il signifie « Pas installés, à installer avant de jouer le plan : » suivi de paquets Des paquets qu'utilisent les plans et qui ne sont pas dans votre bibliothèque, donc qui ne peuvent pas être ajoutés comme dépendances. Installez-les d'abord. « Cités mais introuvables, laissés tels quels : » suivi de fichiers Des plans que joue le plan copié et qui n'existent pas dans le paquet d'origine. La copie les affiche comme problèmes. « Ce plan est illisible. » Le fichier du plan est cassé, donc il ne peut pas être copié. « Les fichiers de ce paquet n'ont pas pu être lus. » Asterobot n'a pas pu lire le paquet choisi. Choisissez-le à nouveau, ou un autre. « La copie a échoué. », ou la raison donnée par Asterobot La copie n'a pas abouti. Les réglages de la copie ne sont pas sur la page du bot tant que votre index.js ne les transmet pas : voir Les réglages du plan. Limites Une étape ou une condition d'un paquet n'apparaît que si ce paquet la déclare pour le Studio. Si vous écrivez des paquets, Étapes et conditions montre comment. Seuls le paquet que vous modifiez et ses propres dépendances, dans une version exacte installée, donnent des blocs. Les interruptions ne sont jamais vérifiées pendant une étape ou un trajet. Les cartes d'une sous-zone, d'une région ou d'une requête sont trouvées quand l'arrêt arrive, à partir des données de jeu de la version que joue le bot, pas de celle qu'affiche le Studio. Heure lit l'horloge de l'ordinateur qui exécute Asterobot, pas le fuseau horaire d'un planning. Les blocs du Studio ne prennent que des valeurs fixes, jamais un réglage. Les arrêts sont atteints par des trajets, avec les limites décrites dans Voyager vers une autre carte. Une modification faite à la main dans un fichier de plan est perdue la prochaine fois que le Studio l'enregistre. Les plans d'un paquet du marché peuvent être lus et copiés, jamais modifiés. Pour aller plus loin Réglages et actions d'un paquet, pour régler les réglages d'un plan sur un bot Lancer un paquet Étapes et conditions, pour donner vos propres fonctions au Studio L'éditeur, pour ce que contient un fichier de plan et comment du code le joue
-
The Studio
Draw what a bot does on the world map, without code: where it goes, in which order, what it does at each stop, and what happens when something fails. The Studio is the part of the package editor where you draw what a bot does instead of writing it. You draw a plan on the world map: the stops the bot goes to, the order it goes round them in, and at each stop the steps it runs there, such as waiting or playing another plan. Conditions, such as how full the bags are, decide whether a stop or a step runs, and when the plan ends. The plan is saved as a file of the package, and @asterobot:base plays it when a bot plays the package. What you need You need Why A local package The Studio opens in the package editor, which only edits local packages. To start from someone else's plan, copy it into one of yours: see Plans of other packages. @asterobot:base in your library Base plays plans and gives the conditions about the character, such as its level or how full its bags are. A package that has plans depends on it, and the Studio adds that dependency for you. See Install base. An extracted game version The world map is drawn from game data. See Extract game data. A bot connected to a game Only to play the plan. Drawing needs no bot. The world map shows the game version Asterobot is tested against when its game data is extracted. A badge in the map's toolbar gives its number, and resting the pointer on it says that it's the version bots meet. When that version isn't extracted, the Studio uses the most recent extracted one and the badge reads Incompatible version: map ids and game texts can differ from what a bot meets. When no version is extracted at all, No extracted game version stands where the map would be, and says to extract one in the Game Manager: the map then shows up on its own, as soon as the version is ready. The panel still works meanwhile, but there's nothing to draw on. Note Coming soon. Base will give steps that act in the game, such as gathering, fighting or going to the bank. For now it gives conditions only, so a plan built on base alone travels, waits, checks the character's state and plays other plans. Steps that act in the game come from other packages, or from your own: Steps and conditions shows how a package gives its functions to the Studio. Start a plan A new package that starts with the Studio In Library Manager, click New package. Type a Name, and keep or change the Version. Turn on Start with the Studio. Click Create and edit. The editor opens on plans/main.js, an empty plan, in the Studio. The package also gets an index.js that does nothing but play that plan and pass on its settings, and it depends on @asterobot:base, at the newest version installed. When base isn't installed, @asterobot:base isn't installed appears under the switch and Create and edit stays greyed out until you install it there. See Install base. A plan in a package you already have Open the package in the editor with Edit code, from Library Manager or from the package's page. At the top of Files, click plan, next to file. The New plan dialog opens. Type a Name, such as farm: letters, digits, - and _, starting with a letter or a digit. The file it becomes, plans/farm.js, shows under the field. Click New plan, or press Enter. The dialog says Letters, digits, - and _ only. for a name it refuses, and This package already has a file at that path. when the plan would replace a file. The new plan opens in the Studio with no stop and a One way circuit. Like a file added with file, it's only in the package once you save. If the package doesn't depend on base yet, the Studio adds it to the package's dependencies right away, at the newest version installed, and a notification says so. If base isn't installed at all, the @asterobot:base isn't installed dialog opens. Important A plan only plays when something plays it. In a package started with the Studio, index.js plays plans/main.js. Any other plan plays when a plan that's playing reaches it, through a Play a plan step or an interrupt, or when your own code plays it, as The editor shows. Adding a plan to a package that has its own code changes nothing about what that code does. Any file whose first line marks it as a plan opens in the Studio, whatever folder it's in. Plans have their own icon in Files. Install base Base can be installed from three places: the New local package dialog, the dialog that opens after you create a plan, and Add base to the dependencies in the panel's alert The package doesn't depend on @asterobot:base. They all work the same way: Paste the ID or the link of base's file on asterobot.net in File ID or URL. Browse packages on asterobot.net opens the site's library if you need to find it. Click Preview, and check what it will install, as in Install from the marketplace. Click Install. When that version is already in your library, the button is Use it instead. In the editor, base is then added to the package's dependencies. The alert in the panel shows whenever the package doesn't depend on base: its Add base to the dependencies button adds the dependency, or opens the install dialog when base isn't installed. The screen The Studio takes the place of the code. The world map is on the left and the panel on the right. Drag the line between them to share the room: Asteroboard remembers the position in this browser. The world map is the one from a Game page's Maps tab, with its search, its switches, its zoom and its list of world maps (see World map). Here a click on a square doesn't open the map: it does what the tool in hand does. The panel starts with the plan's name, Name this plan, which the bot's console uses too. Next to it are Undo, Redo and View as code. Under them come four tabs: Circuit, Interrupts, Settings and Problems. While a plan is open, the editor's top bar keeps Save and Run, but not Game: the Studio has its own world map. The error count there includes the plans' problems. Draw the stops A stop is a place and the steps the bot runs there. Stops are numbered in the order of the circuit, on the map and in the panel. The tools are in the world map's toolbar: Tool What it does Select Selects the stop under the pointer. Click the same square again to go through the stops on it, maps and zones first. A click where there's no stop clears the selection. Map Adds a stop on the map of the square you click. Zone Paints the squares you drag over into a zone: the selected stop when it's a zone, otherwise a new one. Shift+drag erases squares from the selected zone. Subarea Adds a stop on the subarea under the pointer. A stop's number on the world map can be clicked with any tool, and selects that stop. While Zone is in hand, dragging paints instead of moving the map: pick Select to move it. Map. When several maps share a square, such as an outdoor map and the interiors that open off it, a list titled with the square's coordinates opens: Maps at 4,-19. Each line gives a map's ID and its subarea, and in the travel graph marks the map a trip can go to, outdoors as a rule. Click one to add it, or close the list with its cross or Escape. A click where there's no map says No map stands on this square. Zone. Each square you paint takes the map a trip goes to on that square, the one in the travel graph. One drag is one change, undone in one go. The bot visits a zone's maps nearest first. Subarea. The stop covers every map of the subarea. There's no tool for an area: select a stop and change its Place to An area, as described in Edit a stop. Query. The Query button, next to Stops on the Circuit tab, adds a stop whose maps are found while the plan plays, from what you name. Each field is a switch: turn on the ones you want, fill them in, and click Add the stop. Every field you turn on narrows the maps. Add the stop stays greyed out until a field other than Has a zaap is set: a zaap alone, or nothing at all, would take every map of the game, and the stop would show The query must name a subarea, an area, a monster, a resource, coordinates or a world map: otherwise it picks every map of the game. Field Keeps the maps Subarea In that subarea, searched by name. Area In that area, searched by name. Monster In a subarea where that monster lives, searched by name. Resource Where that item is harvested, such as wheat, searched by name. Has a zaap With an active zaap. X, Y At those coordinates. World map id On that world map. 1 is the world of the Twelve. What the world map shows Each stop's place: a map's square, a zone's squares filled in, a subarea's or an area's outline, with the stop's number on it. An arrow from each stop to the next. When the circuit repeats, a dashed arrow goes from the last stop back to the first. The selected stop, in a colour of its own. Only the stops on the world map on screen. An arrow to or from a stop on another world map, such as Incarnam, is a short stub labelled like to 4 · Incarnam. Click the label to show that world map. A query stop isn't drawn, since its maps are only known while the plan plays, and neither is a map that's on no world map, such as an instance or a house. The arrows go straight from the stop before them to the stop after. The list of stops Stops, on the Circuit tab, lists the stops in order. Each line has the stop's number, its name or what its place is, its number of steps, on no world map for a map that can't be drawn, and a red count when something is wrong with it. Click a line to select the stop and centre the world map on it. Drag a line to move the stop, or use the arrows that appear when the pointer rests on it. The arrows on the map follow. With no stop yet, the list says "No stop yet: pick the Map, Zone or Subarea tool and click on the world map." The circuit The top of the Circuit tab says the order the bot visits the stops in, and how many times. Four presets set both at once: Preset Order Repeat What the bot does Loop As drawn Forever The stops in their order, again and again. One way As drawn Once The stops in their order, once. A new plan starts like this. Sweep Nearest first Forever The nearest stop that still has work, again and again. Until As drawn Until a condition The stops in their order, until a condition holds. You can also set Order and Repeat yourself, for example a sweep until a condition holds. No preset is highlighted then, and the line under them says "Another combination of order and repeat." With Until a condition, the condition is under Until. It starts as "After 60 min of play": change it as described in Conditions. It's checked after each stop, and at the end of a lap once the lap is counted, so "After lap 3" ends the plan right as the third lap ends. One time round the circuit is a lap. Here is how a lap goes: As drawn takes the stops in the order of the list. Nearest first visits every stop once per lap too, but each time it picks the stop whose map is nearest. A stop whose Only if condition is false when it comes up is skipped for this lap. At a stop, the bot goes to its maps one after the other: first the one it stands on, then the nearest of the others each time. It gets there by a trip, map after map. A map no trip reaches is skipped, with a line in the bot's console. When no trip reaches any of a stop's maps, the stop fails. On each map, the bot runs the stop's steps in order. A stop with no step is a waypoint: the bot only passes through. Once ends the plan after one lap. Forever and Until a condition start the next one. A lap always lasts at least a second. A step from a package can tell the plan there's nothing more to do on a map for now, for example when everything there has been gathered, and when to come back. The bot then leaves that map alone until that time, or until the next lap, in both orders. When every map left is waiting, the bot waits for the first one to have work again instead of going round for nothing. Edit a stop Select a stop, in the list or with Select, and it opens under the list: Part What it does Name Name this stop (optional). Shown in the list and in the bot's console. Without one, the place stands in. Trash icon Removes the stop, without asking. Undo brings it back. Place Where the stop is. See below. Only if A condition checked when the stop comes up. False: the stop is skipped for this lap, which isn't a failure. Without one, it says "Always visited." and Add a condition adds one. If it fails What happens when the stop fails. See When something fails. Steps The steps run on each of the stop's maps. See Steps. Place starts with a list of five kinds: Kind What you set A map Map id, typed or picked with Pick on the world map. Under it, the map's coordinates and the name of its world map, or "On no world map (an instance, a house...): shown here only". A zone (painted maps) Painted with Zone on the world map. It shows how many maps it holds, how many are on no world map, and Show the maps lists them, each with a button to remove it. A subarea Searched by name, or picked on the world map. Under it, the world map it's on. An area The same, for an area. A query, found while playing The fields of a query, as for Query. Changing the kind keeps what it can: a map becomes a zone of that one map, a zone becomes a map with its first map, and a map or a zone becomes the subarea of its first map, or a query that starts with that subarea. With nothing to keep, a map, a subarea or an area starts empty, and the stop shows This stop's place hasn't been picked yet. until you pick one. 0 is never put in its place: it's an ID like any other, area 0 being Amakna. Fields that name game data A field that asks for a monster, an item, a job, a subarea or any other game data has a Search by name box. Type part of a name and pick it in the list: each entry shows its ID, and the ID shows under the box once picked. A field that takes several, such as a list of monsters, keeps each one you pick. The list says "Type a name to search.", "Nothing by that name." or "The search failed." when it has nothing to show. Names are in the language picked with Language on a Game page. Fields for a map, a subarea or an area also have Pick on the world map. Click it: the button reads "Click on the world map..." and a bar on the map says what to click, with Cancel. Escape gives up too. For an area, click any square of it. A map has no name to search for: type its ID, or pick it. Steps Add a step, on a selected stop, opens the palette. It lists The Studio's blocks first, then the steps each package gives, grouped by package: the package you're editing first, marked "(this package)", then its dependencies in alphabetical order. Each entry has a line of description. Click one to add it at the end of the stop's steps. The packages offered are the one you edit and those listed in its dependencies. A package that only a dependency uses isn't offered. A dependency that gives nothing here is listed greyed out at the bottom, with the reason: Reason What to do its version in the manifest isn't an exact one Set an exact version for it in the package's Manifest card. that version isn't installed Install that version, or change the dependency to one you have. its declarations couldn't be read The package has an error. See Package errors. When the package's own declarations can't be read, the panel shows The package's own blocks couldn't be read with the error, and the palette lacks the package's own steps and conditions until it's fixed. The palette is read again each time you save, so a step newly declared in the package's code shows up once you save. The Studio's steps Step Fields What it does Fails when Wait Seconds, and Up to once turned on Waits that many seconds, or a random time between Seconds and Up to. Starts at 5 seconds. Never Wait until Until, a condition, and Give up after, in seconds, once turned on Checks the condition at once, then every second until it holds. Give up after passes first, or the condition can't be answered Play a plan Plan, another plan of the package Plays that plan here, from the start of its circuit, then carries on. Before the next step, the bot goes back to the stop's map. That plan stops on a failure Log Message Writes the message in the bot's console. Never Stop None Ends everything being played, as a normal end: this plan, and any plan that is playing it. Never An optional field shows as a switch: turn it on to set it, and turn its switch off again to remove it. Play a plan only offers the package's other plans, and says "The package has no other plan yet." when there are none. A plan played this way counts its own laps. Steps from packages A package's step shows its label, followed by the values of its arguments, such as "Gather: Wheat, Barley". Labels and descriptions are in the language the package's author wrote them in. Unfold the step to set its arguments: each is the same field as on the bot's Settings tab (see The fields), with the package's label, description and bounds, and the game data search where the package asks for game data. "Takes no argument." means there's nothing to set. An argument you haven't changed takes the package's default when the plan plays, so a plan follows the package when its author changes a default. Once you change one, Use the default puts it back. When the package's default can't be used, because it breaks the argument's own rules (a level of at least 1 would start at 0) or because the argument asks for game data and has no default, the field stays empty and the step shows Argument <argument> needs a value. until you set it. From a setting lets the bot's page set it: see Plan settings. A step's card Each step is a card with a sentence saying what it does, such as "Wait 5 s". Under it, Only if: shows its condition when it has one, and If it fails: always shows what happens when it fails, even when it's the default, Stop the plan. Click the card, or its arrow, to unfold it: its arguments or fields, Only if and If it fails. Only if is checked right before the step. False: the step is skipped, which isn't a failure. Without one, it says "Always run." Drag a card by its grip to move it, or use its arrows. The trash icon removes it, without asking. Conditions A condition is a yes or no question. They're used in a stop's Only if, a step's Only if, a Wait until, the circuit's Until, an interrupt's When, and inside other conditions. Add a condition opens the palette of conditions: The Studio's blocks first, then the conditions packages give. Condition Fields True when All of Conditions Every one of them is. It starts with one, and Add a condition adds more. Any of Conditions At least one of them is. Not Condition Its condition isn't. Time played Minutes That long has passed since the bot started the plan. In a plan played by another one, it counts from when the first plan started. Laps Laps, from 1 The circuit has been completed that many times. Time of day From, To The clock of the computer running Asterobot reads from From, included, to To, excluded. A From after To spans midnight: 22:00 to 06:00 is the night. The same time in both is never true. Chance Chance, from 0 to 100% A random draw, made again each time the condition is checked, says so. 0 is never true, 100 always is. Base gives these conditions about the character, with the labels it writes in English: Condition Arguments True when Level at least Level, from 1 The character's level is at least that one. Kamas at least Kamas It carries at least that many kamas. Life below Life, from 1 to 100% Its life is below that share of its maximum. Bags above Bags, from 1 to 100% Its bags are fuller than that share of what they can carry. In a fight None A fight is under way. Has an item Item, searched by name, and How many, 1 by default It carries at least that many of the item, worn or not. Job level at least Job, searched by name, and Level, from 1 That job is at least that level. A job the character doesn't have is level 0. On a map Map It stands on that map. In a subarea Subarea It stands in that subarea. In an area Area It stands in that area. The opposite of each is Not around it. A new condition starts with the package's defaults, and most of base's arguments have none they could use: their fields stay empty, and the condition shows Argument <argument> needs a value. until you set them. Only Kamas (0) and How many (1) can be left as they are. Each condition is a card with its sentence, such as "Between 08:00 and 20:00". Unfold it to edit its fields. The arrows button, Change the condition, replaces it with another from the palette. The cross removes it where a condition is optional: a stop's or a step's Only if, and the conditions inside All of and Any of. An interrupt's When, the circuit's Until, a Wait until and a Not always keep one: change it instead. A condition that can't answer fails, and so does the block it guards. Base's conditions fail this way when the game hasn't told something yet, such as the character's job levels: they never guess. The console then says what's missing, for example the jobs aren't known yet. When something fails Every stop and every step has If it fails: Choice Then Stop the plan The plan stops, with the error in the bot's console. This is the default. Skip it, go on to the next step (for a step), Skip it, go on to the next stop (for a stop) A line in the console, then the plan carries on. Try again Tried again up to Tries times, from 1 to 10 (2 to start with), Seconds between tries apart (5 by default). If it still fails, it stops the plan or skips, as you choose. A stop that's tried again starts over: its maps are found again and its steps run from the first. What Fails when A step A package's step reports an error. Its Only if can't be answered. A Wait until gives up, or its condition can't be answered. The plan a Play a plan step plays stops on a failure. An argument's value breaks the package's rules, for example a plan setting whose value is below the argument's minimum. A stop Its place has no map, or its maps can't be found. No trip reaches any of its maps. A trip to one of its maps fails, including a trip you stop from the bot's Map tab. Its Only if can't be answered. The whole plan, whatever If it fails says An interrupt's When can't be answered, or the plan the interrupt plays stops on a failure. The circuit's Until can't be answered. A failing step doesn't fail its stop: only the step's own If it fails applies. When the plan stops on a failure, the bot's console gets an error line naming the plan, the stop and the step, and why: base: Astrub farm › 2 Wheat field (k3f9) › wait until (w4t6) failed: its condition still didn't hold after 60 s The four characters in parentheses are the block's ID in the plan file. The Studio doesn't show them, but View as code does. With the index.js that Start with the Studio writes, a plan that stops on a failure stops the script too: the bot's page shows The behavior stopped with an error, with a text starting with unhandled Promise rejection:, followed by the same error. Click Play to start the plan again, from the start of its circuit. Interrupts An interrupt plays another plan when a condition holds, then goes back to the circuit or ends it. "When the bags are fuller than 90%, play the bank plan, then resume" is an interrupt. They're on the Interrupts tab. Add an interrupt adds one with these fields: Field What it does Name Name it (Bank when full). Shown in the bot's console. When The condition. It starts as "After 60 min of play". Run the plan Another plan of the package. Until you pick one, the interrupt has the problem No plan chosen. Then Resume where the circuit was: the bot goes back to the map it was on and runs the step it was about to run. End this plan: the plan the interrupt belongs to ends there. When another plan was playing it, that one carries on. Interrupts are checked in their order, on arriving at each map and before each step. Never during a step or a trip: a long step finishes first. The first one whose condition holds plays its plan. While that plan plays, the same interrupt isn't checked again, even from inside it, so "bags full: bank" can't start the bank plan from the bank plan. The interrupts of the plan it plays do apply. With Resume where the circuit was, the plan it plays has to make the condition false: the bank plan empties the bags. When the condition still holds right after that plan, base stops the plan rather than playing the bank plan again and again, and the console says which interrupt: base: Astrub farm › interrupt Bank when full (i7w0) is still true after its plan plans/bank.js ran: that plan must make it false, or it would run again and again A Chance in the condition doesn't count against it, since the next check draws again. The arrows move an interrupt up or down, and the trash icon removes it. An interrupt needs another plan to play: create it first with plan in Files. Plan settings A plan can have settings of its own, which a player sets on the bot's page, such as the monsters to fight or a level to reach. They're on the Settings tab. Add a setting adds one, named setting, holding a whole number, 0 by default. Field What it does Name The setting's key. Letters, digits and _, not starting with a digit, and not __proto__. It's renamed when you press Enter or leave the box, along with every argument that uses it. A name that's taken or not allowed is refused with " can't be a setting's name: it is taken, or isn't a name a script could write." Use count not used, used once or used 3 times: how many arguments take their value from it. Type bool (on or off), string (text), int (whole number), double (decimal number), array (list) or map (entries with a key). Holding For array and map: the type of what they hold. Label The name the bot's page shows. Game data For a whole number or a list of them: the game data table the numbers come from, such as monsters, items, sub_areas, areas or maps. The bot's page then offers a search by name. Minimum, Maximum For numbers. Default value The value until a player changes it on the bot's page. A setting needs one when it couldn't start at its type's zero: a whole number of at least 1 would start at 0, and a single game data ID at 0, an ID nobody picked. Without one, the field stays empty and the setting shows It needs a default value: without one, it would start at a value it can't run with. The trash icon removes a setting. The arguments that used it then show the problem Argument <argument>: the plan has no setting <name>. Use a setting Unfold a step or a condition from a package and turn on From a setting under an argument. The argument then takes its value from the plan setting with the same name and type, or from a new one made from the argument itself: its label, its bounds, its game data table, and its current value as the default, or no default when the argument has none it could use. A list then lets you pick another setting of the same type. Turn the switch off to give the argument back the package's default. Until a player sets another value on the bot's page, the argument takes the setting's default, so that default has to suit the argument: a setting that defaults to 150 can't stand for a percentage. When it doesn't, the step or condition shows Argument <argument>: the default value of setting <setting> doesn't fit: <issue>. A value set on the bot's page is checked when the step or condition runs, and one that doesn't suit the argument fails it. Only the arguments of packages' steps and conditions can take a setting. The Studio's own blocks take fixed values: a Wait's seconds can't come from a setting. Show them on the bot's page A plan's settings reach the bot's Settings tab only once the package's index.js passes them on. The Settings tab of the Studio tells you where you stand: What you see What it means These settings aren't on the bot's page yet, with Add it index.js doesn't pass them on. Add it writes what does in index.js: a line such as export { parameters } from "./plans/farm.js"; after the imports at the top, or, when index.js already passes on another plan's settings, the merge of both. A notification says "Added to index.js: save to apply it." "index.js re-exports them now: save to see these settings on the bot's page." index.js passes them on, but isn't saved yet. index.js has settings of its own index.js declares settings itself, not only plans' settings, and a second parameters would clash with them. The Studio adds nothing and shows the lines to write by hand: The editor explains them. Once saved, nothing more is shown. A package started with the Studio already passes on the settings of plans/main.js. Add it works for every other plan too, as long as index.js only gathers plans' settings: it merges the new plan's with those already there. The editor shows what it writes. On the bot's page, plan settings are package settings like any other, in the package's card on Package settings: see Package settings and actions. A value you apply there is used from the next time an argument reads it, without restarting the plan. When index.js doesn't pass the settings on, the plan uses each setting's default, and the console says so before the bot moves, in one line that names them all: base: Astrub farm: setting monsters isn't one of the package's settings, so its default is used: re-export the plan's settings from the package's entry The plans of one package share the bot's values: two plans with a setting of the same name use the same value, so they must give it the same type. When they don't, the setting says "Declared with another type by:" followed by each plan that declares it and its type, and it counts as a problem. Problems The Problems tab lists everything wrong with the plan, with a red count on the tab. Each problem says what's wrong and where: Stop 2, Interrupt 1, Setting monsters, Circuit or Plan. Click one to go there. The same sentence shows in red under the block it's about, and the list of stops counts each stop's problems. The editor's error count adds up the problems of every plan to the errors in the code. With none, the tab says "Nothing wrong with this plan." Saving is allowed with problems, since a plan is often saved half done. Base is what refuses it: when the bot plays it, base checks the whole plan, and every plan it plays, before the bot moves. Even one problem keeps the bot from moving: the console shows can't be run: after the plan's name, followed by every problem base found. Some of the problems you'll meet: Problem What to do The circuit has no stop yet. Add a stop. No plan chosen. Pick the plan for a Play a plan step or an interrupt. The plan <path> no longer exists. The file was removed. Pick another plan. Argument <argument>: <issue>. Change the value, such as a number above its maximum. Argument <argument> needs a value. Set the argument: the package's default can't be used, or there's none. Argument <argument>: the plan has no setting <name>. The setting was removed or renamed. Pick another, or turn off From a setting. Argument <argument>: the default value of setting <setting> doesn't fit: <issue>. Change the setting's Default value, or its bounds. It needs a default value: without one, it would start at a value it can't run with. Give the setting a Default value. This stop's place hasn't been picked yet. Pick the stop's map, subarea or area. The query must name a subarea, an area, a monster, a resource, coordinates or a world map: otherwise it picks every map of the game. Turn on one more field of the query. The longest wait is shorter than the shortest. Up to is below Seconds in a Wait. It needs at least one condition. An All of or Any of is empty. @asterobot:base plays this plan, but the package doesn't depend on it. Click Add base to the dependencies in the alert at the top of the panel. The setting <name> is declared with different types by the package's plans Give it the same type in every plan. Locked blocks A block the Studio can't edit is shown locked: "Read-only: made by a newer Studio, or calling something the package doesn't have", followed by the reason and the block as the file holds it. That happens to a block made by a newer version of the Studio, and to a step or condition from a package that isn't a dependency any more, that gives no blocks here, or that no longer declares that function. The Studio keeps a locked block exactly as it is and saves it unchanged. Fix the cause, such as adding or installing the dependency, or remove the block with its trash icon. A circuit made by a newer Studio says "This circuit was made by a newer Studio: it is kept as it is." A plan that can't be opened When a plan file can't be read, the Studio shows This plan can't be opened in the Studio instead of the plan, never writes over the file, and offers Open as code: Reason Cause This plan was made by a newer Studio A newer Asteroboard wrote it. Asteroboard updates on its own: reload the page once it shows Update available. See Updating. The plan's markers are missing: the file was changed by hand. Someone edited the file's code. The plan's data can't be read The plan's data in the file is broken. Part of the plan isn't what the Studio expects The plan's data has the wrong shape. Save, undo and see the code A plan is one of the package's files. Save, or Ctrl+S, saves it with the others. Unsaved and the dot next to its name in Files work as for code, and nothing asks you to save when you leave the editor: unsaved changes are lost. The editor gives every detail of saving. Undo and Redo, next to the plan's name, take back changes one at a time. While the Studio has the focus, Ctrl+Z undoes, Ctrl+Shift+Z or Ctrl+Y redoes, and Ctrl+S saves: click in the Studio first. On a Mac, use Cmd. Typing in one field, or one drag of Zone, is one change. Add it is a change to index.js, not to the plan: undo it in index.js's code. View as code shows the plan file in the code editor, with Back to the Studio above it and a reminder that changes made there by hand are lost the next time the Studio saves the plan. The Studio writes the whole file again each time you change the plan, so make your changes in the Studio. Play a plan In the editor, Run saves the package and starts it on the bot picked next to it. See Run. Or set the package on a bot and click Play, as Run a package shows. The plan waits for the character to stand on its map, checks the whole plan, then sets off. Each start begins at the start of the circuit: the plan doesn't carry on where an earlier run stopped. The bot's Console gets a line at each stop and each step, and for each interrupt, retry, skip, Log step and error: base: Astrub farm › 1 Wheat field base: Astrub farm › 1 Wheat field › wait 5 s base: Astrub farm › 1 Wheat field › wait until base: Astrub farm › 2 3 maps While the bot travels, its Map tab shows the trip, as it does for a trip you start yourself. Stopping the trip there makes the stop fail, like any trip that fails. Stop, on the bot's page, stops the script at once, wherever the plan is. When a time slot of the bot's schedule ends, the plan ends cleanly instead, within the schedule's Time to finish: the step under way finishes, a Wait or Wait until ends at once, and a trip ends once its step under way is over, so the character never stops in the middle of a map change. A Stop step ends the plan the same way, as a normal end. A One way circuit, or one that ends with Until a condition, ends the plan when it's done. The bot stays where it is. Note Coming soon. The Studio will show where a bot is on its plan while it plays. For now, follow it in the bot's Console. Plans of other packages Every package's page has a Plans card listing its plans, marketplace packages included. Each line gives the plan's name, its file and its number of stops, or can't be read. "No plan in this package." means there's none. Open shows the plan in the Studio, read-only, on a page of its own: the world map with the plan drawn on it, and the panel with nothing to change. Select stops to read them, in the list or on the map. The top of the page shows the package, the plan's file and Read-only. For a local package, Edit code opens the plan in the editor. For any package, Copy into... copies it into one of yours. When the page can't show the plan, it says why: the package's files couldn't be read, the package has no such file, the file isn't a plan, or one of the reasons in A plan that can't be opened. Copy a plan into your package Click Copy into... on the package's page or on the plan's page. The dialog is titled with the plan's file, such as Copy plans/farm.js. Pick a Package. Only your local packages are listed. With none, it says "You have no package of your own yet." Read what the copy will do. Files lists each plan copied, with the file it becomes in your package. Added to its dependencies lists the packages the plans use that your package doesn't depend on yet, or says "Nothing to add." Click Copy and open. The copy goes into your package's plans folder, with every plan it plays through interrupts and Play a plan steps. A plan whose file name is taken gets a number, such as plans/bank-2.js, and the plans that play it are changed to match. The dependencies are added at the version installed, including the package the plan came from when the plan uses that package's own steps. Both the files and the dependencies are written to your package straight away, without Save, and the editor opens on the copy, which is now yours to change. Message What it means "Not installed, to install before playing the plan:" followed by packages Packages the plans use that aren't in your library, so they can't be added as dependencies. Install them first. "Referred to but not found, left as they are:" followed by files Plans the copied plan plays that don't exist in the original package. The copy shows them as problems. "This plan can't be read." The plan file is broken, so it can't be copied. "That package's files couldn't be read." Asterobot couldn't read the package you picked. Pick it again, or another one. "The copy failed.", or Asterobot's reason The copy didn't go through. The copy's settings aren't on the bot's page until your index.js passes them on: see Plan settings. Limits A step or a condition from a package only appears when that package declares it for the Studio. If you write packages, Steps and conditions shows how. Only the package you edit and its own dependencies, at an exact version that's installed, give blocks. Interrupts are never checked during a step or a trip. The maps of a subarea, an area or a query are found when the stop comes up, from the game data of the version the bot plays, not the one the Studio shows. Time of day reads the clock of the computer running Asterobot, not the time zone of a schedule. The Studio's own blocks take fixed values only, never a setting. Stops are reached by trips, with the limits described in Travel to another map. A change made by hand to a plan file is lost the next time the Studio saves it. A marketplace package's plans can be read and copied, never edited. Where to go next Package settings and actions, to set a plan's settings on a bot Run a package Steps and conditions, to give your own functions to the Studio The editor, for what a plan file holds and how code plays it
-
0.5.1
0.5.1 - 18/10/2026✨ AjoutéCréez un bot sans écrire une seule ligne de code grâce au nouveau Studio d’Asteroboard : dessinez un parcours sur la carte du monde en définissant les étapes auxquelles votre bot doit se rendre, l’ordre dans lequel il doit les suivre et les actions à effectuer à chaque étape. Une étape peut être une carte, une zone que vous dessinez, une sous-zone, une zone ou encore des cartes que le bot trouve en cours de jeu à partir d’un monstre, d’une ressource ou de coordonnées. Le bot se déplace automatiquement d’une étape à l’autre. Rendez vos parcours intelligents grâce à des conditions qui déterminent si une étape ou une action doit être exécutée et quand le parcours doit prendre fin. Combinez-les avec All of, Any of et Not, et utilisez le temps de jeu, les tours, l’heure de la journée ou une probabilité. Avec @asterobot:base, vous pouvez également utiliser le niveau du personnage, ses kamas, ses points de vie, le contenu de son inventaire, ses objets, les niveaux de ses métiers et sa position. Les parcours continuent même en cas de problème : pour chaque étape et chaque action, choisissez d’arrêter le parcours, de passer à la suite ou de réessayer. Les interruptions permettent de lancer un autre parcours lorsqu’une condition est remplie, par exemple : « inventaire rempli à plus de 90 % : aller à la banque », puis de reprendre exactement là où le bot s’était arrêté. Des actions prédéfinies permettent d’attendre, d’attendre qu’une condition soit remplie, de lancer un autre parcours, d’écrire dans la console ou de terminer le parcours. Toutes les actions et conditions fournies par vos packages sont également disponibles dans la palette. Les actions qui interagissent avec le jeu, comme la récolte ou le combat, sont fournies par les packages, y compris les vôtres. Chaque parcours peut disposer de ses propres paramètres, configurables dans l’onglet Settings du bot, comme n’importe quel paramètre de package. Un même parcours peut ainsi être utilisé par plusieurs bots. Lancez-vous en un clic : activez Start with the Studio dans New package pour que le nouveau package exécute le parcours que vous avez créé. Consultez et copiez les parcours de n’importe quel package, y compris ceux du marketplace, depuis sa carte Plans. Intégrez vos propres fonctions au Studio : un package peut exposer ses fonctions sous forme d’actions et de conditions, avec leurs champs respectifs. Le Studio les répertorie ensuite lors de la création d’un parcours. Un paramètre de package peut désormais demander une information issue du jeu : un objet, un monstre, un métier, une sous-zone, etc. Au lieu d’un simple nombre, Asteroboard affiche alors une recherche par nom ou un sélecteur sur la carte du monde. Cette fonctionnalité est disponible dans l’onglet Settings du bot, dans les fenêtres de configuration des actions et dans le Studio. Une nouvelle page Studio dans le guide utilisateur explique l’ensemble de ces fonctionnalités, en anglais et en français. Le guide de scripting explique également comment exposer des actions et des conditions, ainsi que le fonctionnement des fichiers de parcours. Jouez avec plusieurs comptes depuis un seul ordinateur sur les serveurs monocomptes : un bot qui relaie votre client de jeu peut désormais se connecter avec son propre identifiant d’appareil (HWID), au lieu d’utiliser celui de votre ordinateur. Chaque compte apparaît ainsi comme s’il utilisait son propre ordinateur. Activez Use it when relaying my game client dans Device identifier (HWID), lors de l’ajout du bot (onglet Connection) ou ultérieurement dans sa Bot configuration. Cette option est désactivée par défaut : dans ce cas, rien ne change et la session relayée conserve le HWID de votre client de jeu. L’usurpation d’identité est maintenue pendant toute la session : le bot répond lui-même aux vérifications d’identité du serveur de jeu en utilisant ce même HWID, à la place de votre client de jeu. Un seul bot de ce type peut attendre votre client de jeu à la fois. Ankama ne précise le compte en cours de connexion qu’après l’envoi du HWID. Pour éviter d’envoyer ensuite des informations incorrectes, Asterobot interrompt la connexion si deux bots de ce type sont en attente ou si le compte appartient à un autre bot. Les journaux indiquent alors la raison de l’interruption. Un bot qui ne possède pas encore de HWID, ou qui a récupéré celui de votre ordinateur lors d’une précédente session relayée, en obtient un qui lui est propre lors de sa première connexion avec cette fonctionnalité. L’API d’Asterobot et les assistants IA connectés à Asterobot peuvent activer cette fonctionnalité pour un bot. Les scripts peuvent désormais accéder facilement aux informations du personnage grâce au nouveau module asterobot:character : niveau, kamas, énergie, points de vie, taux de remplissage de l’inventaire, état du combat, quantité d’un objet transporté et niveaux des métiers. Asterobot suit le personnage dès son entrée en jeu. Ainsi, un script lancé ou rechargé en cours de session obtient immédiatement les informations correspondant à son état actuel. Lorsqu’une pile d’objets est obtenue ou entièrement vidée pendant la session, le nombre d’objets est mis à jour à la réception du prochain inventaire complet envoyé par le jeu. La référence des scripts documente désormais character(), itemCount() et jobLevel(). Créez des IA de combat, des bots de commerce à l’hôtel de vente et des bots de boutique : les scripts reconnaissent désormais 123 messages de jeu supplémentaires par leur nom, avec leurs champs respectifs, détaillés ci-dessous. Suivez chaque action d’un combat grâce à GameActionFightEvent, notamment les sorts et les attaques à l’arme : TargetedAbility, SpellCast, AbilityRefreshInfo, AbilityRefreshInfoTeam et FightSpellCastCritical pour les coups critiques. Dégâts et soins en combat : LifePointsLost, LifePointsGain, ReduceDamages, ReflectDamages, ReflectSpell, SpellImmunity et StealKama. PA, PM et déplacements en combat : PointsVariation, DodgePointLoss, Tackled, Slide, TeleportOnSameMap, ExchangePositions, CarryCharacter, ThrowCharacter et DropCharacter. Morts, invocations et invisibilité en combat : Death, Kill, Vanish, Summons, SummonsByActor, SummonsByContextInformation, SummonContextInformation, Invisibility, InvisibleDetected et FightInvisibilityState. Glyphes, pièges et effets sur la carte de combat : MarkCells, UnmarkCells, ActivateGlyphTrap, TriggerGlyphTrap, EffectRemove, SpellRemove, ModifyEffectsDuration, ChangeLook, ChangeTeam, AddHitBox, RemoveHitBox, ExecuteScript et Staging. Bonus, temps de relance et compteurs de sorts : FightBoostAddEvent, FightBoostRemoveEvent, FightBoostSynchronizeEvent, FightRemovableEffect, FightRemovableEffectExtendedInformation, GameActionUpdateEffectTriggerCountEvent, FightEffectTriggerCount, RefreshSpellCastStateEvent, FightSpellCast, CastCountOneSomeone et FightSpellCoolDown. Ordre des tours et combattant contrôlé : TimelineRefreshEvent, Turn, TimelineFighter, AdditionalTurn et FightControlEvent. Identification des combattants et de leur emplacement : FightFighterInformation, NamedFighterInformation, FightCharacterInformation, FightMutantInformation, AIFighterInformation, MonsterFighter, TaxCollectorFighter, EntityFighterInformation, FightCharacteristics, SpawnInformation, FightStartingPositions et FightMapInformationEvent. Équipes de combat : FightTeamMemberInformation, FightTeamMemberCharacter, FightTeamMemberMonster, FightTeamMemberEntity, FightTeamMemberTaxCollector et BasicAllianceInformation. Le message FightTeamMembersInformation inclut désormais le champ alliance_relation, de type AllianceRelation. Statistiques de fin de combat, avec les dégâts, soins, boucliers, PA, PM et éliminations de chaque combattant : FightStatisticsEvent et DetailedStatistics. Hôtel de vente, de la consultation à l’achat et à la vente : ExchangeBidBuyerStartedEvent, ExchangeBidSellerStartedEvent, SellingConditions, ExchangeBidHouseTypeRequest, ExchangeTypesExchangerDescriptionForUserEvent, ExchangeBidHouseSearchRequest, ExchangeTypesItemsExchangerDescriptionForUserEvent, BidExchangerObject, ExchangeBidHouseInListUpdatedEvent, ExchangeBidHouseBuyRequest, ExchangeBidHouseBuyResultEvent, ExchangeBidHousePriceRequest, ExchangeBidPriceEvent, BidPriceForSeller, ExchangeObjectMovePricedRequest, ExchangeBidHouseItemAddedEvent, ItemToSellInBid et BidItem. Historique des prix moyens d’un objet sur le marché, jour par jour sur le dernier mois et heure par heure sur les dernières 24 heures : ObjectAveragePricesHistoryRequest, ObjectAveragePricesHistoryEvent et ObjectAveragePriceHistory. Boutiques de PNJ, avec leurs prix et limites d’achat : ExchangeNpcShopStartedEvent, ItemMinimalInformation, ItemToSellInNpcShop, ExchangeBuyRequest et ExchangeBoughtEvent. Inventaire et fenêtres d’échange : ObjectDeletedEvent est déclenché lorsqu’une pile entière quitte l’inventaire. ExchangeLeaveEvent est déclenché lorsque le serveur ferme une fenêtre d’échange. InventoryUpdateMergedInventoryTypeRequest, avec MergedInventoryType, permet d’afficher la banque ou le Havre-Sac dans une fenêtre de fabrication ou d’hôtel de vente. Sur la carte : ActorInformation, RolePlayActor, MonsterGroupActor, WaveInformation, MonsterGroupStaticInformation, MonstersInGroupAlternativeInformation, MapCoordinates, MapComplementaryAnomalyInformation, ainsi que les animations scénarisées de la carte : StagingEvent et PersistentStagingEvent. Personnage et Havre-Sac : CharacterForceSelectionEvent et CharacterForceSelectionReadyRequest lorsque le serveur sélectionne le personnage à votre place ; AlignmentExtendedInformation et AttackableStatus pour l’honneur et la possibilité d’être attaqué ; alignment_grade, alignment_quest_number et character_level dans AlignmentInformation ; enfin, HavenBagPermissionsUpdateRequest et HavenBagPermissionsUpdateEvent pour gérer les personnes autorisées à entrer dans le Havre-Sac. 🔄 ModifiéMise à jour des dépendances. 🐛 CorrigéItemMinimalInformation désignait le mauvais type de données. Il représente désormais un objet vendu dans une boutique de PNJ, avec les champs object_gid, effects et son prix dans item_to_sell_in_npc_shop. Les objets de GameActionItem sont représentés par GameActionItemObject, avec les mêmes champs qu’auparavant. Dans les scripts, findMaps() avec un identifiant égal à 0, par exemple { area: 0 } pour Amakna, renvoyait toutes les cartes du jeu au lieu de renvoyer uniquement celles de la zone concernée. Dans la référence des scripts, le lien vers asterobot:gamedata sur la page consacrée aux déplacements fonctionne de nouveau.
-
Écoutez la musique de Dofus gratuitement
Toutes les musiques de Dofus, gratuitesDofus possède certaines des musiques les plus appréciées des MMO : le thème d’Astrub, la sérénité d’Incarnam, la tension d’un boss de donjon. Asterobot est un framework de bots pour Dofus, et un bot ne joue jamais de son. Mais comme Asterobot télécharge de toute façon sa propre copie du jeu depuis les serveurs d’Ankama, il peut aussi récupérer la musique à partir des fichiers officiels du jeu, et Asteroboard peut la lire. C’est le rôle de l’onglet Music. D’où vient la musiqueDofus 3 stocke ses sons dans des banques audio intégrées aux fichiers du jeu publiés par Ankama. Asterobot ne les télécharge pas avec le reste du jeu, car un bot n’en a pas besoin. Lorsque vous le demandez, l’onglet Music récupère les quatre banques audio qui contiennent la musique, soit environ 900 Mo, en laissant de côté les autres, principalement constituées de sons de combat et d’interface, qui porteraient l’ensemble à environ 2 Go. Asterobot extrait ensuite les pistes de ces banques. Tout provient des fichiers officiels de la version de Dofus que vous avez téléchargée : ce que vous entendez est donc exactement ce que le jeu diffuse. Deux clics pour en profiterOuvrez la page d’une version du jeu depuis Game Manager, puis accédez à l’onglet Music. Cliquez sur Download. Les banques audio se téléchargent en arrière-plan, depuis les serveurs Ankama, dans la même file d’attente que les autres téléchargements, avec une barre de progression. Cliquez sur Extract the music une fois le téléchargement terminé. Le lecteur et la liste des pistes apparaissent. L’extraction de la musique ne modifie pas le reste des données du jeu, et les extractions ultérieures de la version permettent de garder la musique à jour. Un véritable lecteur de musiqueLe lecteur propose toutes les commandes attendues : lecture et pause, arrêt, piste précédente et suivante, répétition de la piste en cours, titre et album de la piste en lecture, réglage du volume et barre de progression permettant de naviguer dans la piste. La liste des pistes est organisée par albums, un par banque audio, avec le nombre de pistes de chaque album. Filtrez les pistes par titre, album ou taille, triez-les selon n’importe quelle colonne et masquez celles dont vous n’avez pas besoin. Un indicateur affiche le nombre de pistes visibles ainsi que leur taille totale. La file de lecture correspond à la liste telle qu’elle apparaît lorsque vous sélectionnez une piste : elle tient compte des filtres et du tri appliqués. Après la dernière piste, la lecture reprend depuis la première. Si plus de 3 secondes se sont écoulées depuis le début de la piste en cours, le bouton de piste précédente la relance depuis le début, comme sur la plupart des lecteurs. La musique continue pendant que vous travaillezLa musique ne s’arrête pas lorsque vous quittez l’onglet. Sur toutes les autres pages d’Asteroboard, un petit lecteur reste affiché dans la barre supérieure. Il propose les commandes de lecture et de pause, le titre de la piste, qui permet de revenir à l’onglet Music, ainsi qu’un bouton pour arrêter la musique. Vous pouvez ainsi surveiller vos bots, explorer la carte du monde ou écrire un script avec la bande originale de Dofus en arrière-plan. Asteroboard mémorise le volume et le mode répétition dans votre navigateur. La musique est diffusée depuis votre propre instance d’Asterobot vers votre navigateur : elle est donc accessible partout où Asteroboard peut être utilisé, y compris sur votre téléphone. Pourquoi intégrer cette fonctionnalité à un bot ?La page Game d’Asterobot permet d’explorer le jeu de l’intérieur : ses cartes, ses données et ses textes. La musique fait partie des fichiers du jeu, au même titre que le reste. Dès lors qu’Asterobot sait lire ces fichiers, diffuser la bande originale n’est qu’une petite étape supplémentaire. C’est également un moyen agréable de vérifier qu’une nouvelle version de Dofus a été téléchargée correctement. Pour en savoir plusMusic dans le guide Page Game Télécharger une version du jeu Télécharger Asterobot