Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3802abb
Update Jellypowered documentation baseline
Wishmaster117 Aug 20, 2026
ca762e2
Add bridge-first item trading and Lua 5.1 dispatch refactor
Wishmaster117 Aug 20, 2026
ddc0c24
Add chatless quest abandon and sync roadmap
Wishmaster117 Aug 20, 2026
ef5325c
Add chatless talent apply UI
Wishmaster117 Aug 21, 2026
e85b3ef
Add chatless talent spec apply UI
Wishmaster117 Aug 21, 2026
2b5ac42
Add targeted profession recipe support
Wishmaster117 Aug 22, 2026
fe2c807
Update MultiBotInventoryFrame.lua
Wishmaster117 Aug 23, 2026
363a25d
Sync SELL_VENDOR documentation
Wishmaster117 Aug 23, 2026
afaa63e
Gate bank guildbank and buy legacy fallbacks
Wishmaster117 Aug 23, 2026
f2a74c9
Guard stale bank refresh callbacks
Wishmaster117 Aug 23, 2026
b13ff79
Add exact bank and guild bank deposit requests
Wishmaster117 Aug 24, 2026
b8b2913
Update roadmap after exact bank deposit work
Wishmaster117 Aug 24, 2026
9940141
Add exact loot item rule controls and localization
Wishmaster117 Aug 24, 2026
1358019
Update roadmap and Jellypowered completion docs
Wishmaster117 Aug 24, 2026
6693b7b
Fix addon disconnect lifecycle cleanup
Wishmaster117 Aug 25, 2026
7e45703
Fix targeted crafting and self-enchant workflow
Wishmaster117 Aug 26, 2026
5883fa9
Gate Sell Grey legacy chat fallback
Wishmaster117 Aug 26, 2026
d62bb60
Fail closed on exact deposit send failure
Wishmaster117 Aug 26, 2026
d596a56
Preserve prompt item-link insertion
Wishmaster117 Aug 26, 2026
2704c68
Finalize Jellypowered v2 documentation sync
Wishmaster117 Aug 26, 2026
2045dcd
Fix targeted craft cleanup on disconnect
Wishmaster117 Aug 27, 2026
ae5cd96
Harden structured pending lifecycle
Wishmaster117 Aug 27, 2026
bd79fab
Surface quest abandon bridge failures
Wishmaster117 Aug 27, 2026
d3e0d6c
Resync inventory after exact item errors
Wishmaster117 Aug 27, 2026
c84441e
Report unavailable quest abandon bridge
Wishmaster117 Aug 27, 2026
d9bf964
Document PR73 closure technical debt
Wishmaster117 Aug 27, 2026
fafe13c
Resolve malformed quest abandon responses
Wishmaster117 Aug 27, 2026
fdce616
Harden malformed structured result lifecycle
Wishmaster117 Aug 27, 2026
f15b1d6
Clear stale recipe target selection
Wishmaster117 Aug 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,790 changes: 1,582 additions & 208 deletions Core/MultiBotComm.lua

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions Locales/MultiBotAceLocale-deDE.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@ if type(register) ~= "function" then
end

local deDEValues = {
-- MB_LOOT_RULE_ITEM_I18N_V1_BEGIN
["loot.item.add"] = "Immer plündern: Gegenstand hinzufügen",
["loot.item.remove"] = "Immer plündern: Gegenstand entfernen",
["loot.item.bridge.required"] = "Exakte Beuteregeln pro Gegenstand benötigen LOOT_RULE_ITEM_V1.",
["loot.item.prompt.required"] = "Das Eingabefenster für Gegenstände ist nicht verfügbar.",
["loot.item.add.prompt"] = "Gegenstands-ID oder Link zu Immer plündern hinzufügen",
["loot.item.remove.prompt"] = "Gegenstands-ID oder Link aus Immer plündern entfernen",
["loot.item.invalid"] = "Ungültige Gegenstands-ID oder ungültiger Gegenstandslink.",
["loot.item.send.failed"] = "Die Anfrage für die Gegenstands-Beuteregel wurde nicht gesendet.",
["loot.item.result.added"] = "%s - bei %d Bot(s) hinzugefügt.",
["loot.item.result.removed"] = "%s - bei %d Bot(s) entfernt.",
["loot.item.result.already_present"] = "%s - bei %d Bot(s) bereits vorhanden.",
["loot.item.result.already_absent"] = "%s - bei %d Bot(s) bereits nicht vorhanden.",
["loot.item.result.partial"] = "%s - teilweise aktualisiert (%d/%d Bot(s)).",
["loot.item.result.ok"] = "%s - %s (%d/%d Bot(s)).",
["loot.item.result.failed"] = "%s - Beuteregel fehlgeschlagen: %s.",
["loot.item.reason.RATE_LIMIT"] = "zu viele Anfragen; bitte kurz warten",
["loot.item.reason.NO_REQUESTER_SESSION"] = "Spielersitzung nicht verfügbar",
["loot.item.reason.REQUESTER_NOT_IN_WORLD"] = "Spieler ist nicht in der Welt",
["loot.item.reason.DUPLICATE"] = "doppelte Anfrage",
["loot.item.reason.BAD_ACTION"] = "ungültige Aktion",
["loot.item.reason.INVALID_ITEM"] = "ungültiger Gegenstand",
["loot.item.reason.NO_BOTS"] = "keine geeigneten Bots",
["loot.item.reason.TOO_MANY_BOTS"] = "zu viele ausgewählte Bots",
["loot.item.reason.FORBIDDEN"] = "Bot-Steuerung nicht erlaubt",
["loot.item.reason.NO_BOT_SESSION"] = "Bot-Sitzung nicht verfügbar",
["loot.item.reason.BOT_NOT_IN_WORLD"] = "Bot ist nicht in der Welt",
["loot.item.reason.BOT_DEAD"] = "Bot ist tot",
["loot.item.reason.NO_BOT_CONTEXT"] = "Bot-KI-Kontext nicht verfügbar",
["loot.item.reason.PERSISTENCE_BUSY"] = "Persistenz ist ausgelastet; bitte kurz warten",
["loot.item.reason.FAILED"] = "Vorgang fehlgeschlagen",
-- MB_LOOT_RULE_ITEM_I18N_V1_END
-- MB_TALENT_SPEC_APPLY_I18N_V1_BEGIN
["talent.spec.apply.success"] = "Talentspezialisierung %s wurde erfolgreich auf %s angewendet.",
["talent.spec.apply.failed"] = "Talentspezialisierung %s konnte nicht auf %s angewendet werden (%s).",
-- MB_TALENT_SPEC_APPLY_I18N_V1_END
-- MB_TALENT_APPLY_I18N_V1_BEGIN
["talent.apply.success"] = "Talente wurden erfolgreich auf %s angewendet.",
["talent.apply.failed"] = "Talente konnten nicht auf %s angewendet werden (%s).",
-- MB_TALENT_APPLY_I18N_V1_END
-- MB_SELFACTION_I18N_V1_BEGIN
["selfaction.bridge_unavailable"] = "Die Bridge ist nicht verfügbar: Die SelfBot-Aktion wurde nicht gesendet.",
["selfaction.failed"] = "SelfBot-Aktion fehlgeschlagen: %s",
Expand Down Expand Up @@ -84,6 +124,30 @@ local deDEValues = {
["profession.recipes.craft.reason.CHANNELING"] = "Der Bot kanalisiert bereits einen Zauber.",
["profession.recipes.craft.reason.cast_code"] = "Der Server hat den Zauber abgelehnt (Code %s).",
["profession.recipes.craft.reason.UNKNOWN"] = "Der Server hat einen unbekannten Herstellungsfehler gemeldet.",
["profession.recipes.target.apply"] = "Anwenden",
["profession.recipes.target.unavailable"] = "Die exakte Gegenstandsauswahl über die Bridge ist nicht verfügbar.",
["profession.recipes.target.select"] = "Wähle den exakten Gegenstand im Inventar oder in der Ausrüstung des Bots aus.",
["profession.recipes.target.send_failed"] = "Die gezielte Herstellungsanfrage konnte nicht gesendet werden.",
["profession.recipes.target.pending"] = "Rezept wird auf den ausgewählten Gegenstand angewendet...",
["profession.recipes.target.wrong_bot"] = "Wähle einen Gegenstand des Bots aus, dessen Rezept geöffnet ist.",
["profession.recipes.target.exact_required"] = "Dieses Ziel muss aus der exakten Inventaransicht stammen.",
["profession.recipes.target.invalid_scope"] = "Wähle einen ausgerüsteten Gegenstand oder einen Gegenstand aus Rucksack oder ausgerüsteten Taschen.",
["profession.recipes.target.ok"] = "Das Rezept wurde auf den ausgewählten Gegenstand angewendet.",
["profession.recipes.target.err"] = "Gezielte Herstellung fehlgeschlagen: %s",
["profession.recipes.target.failed"] = "Die gezielte Herstellungsanfrage ist fehlgeschlagen.",
["profession.recipes.target.reason.BAD_TARGET_POSITION"] = "Diese Inventar- oder Ausrüstungsposition ist nicht erlaubt.",
["profession.recipes.target.reason.MISSING_TARGET_ITEM"] = "Der ausgewählte Gegenstand ist nicht mehr vorhanden.",
["profession.recipes.target.reason.TARGET_STALE"] = "Der ausgewählte Platz enthält jetzt einen anderen Gegenstand.",
["profession.recipes.target.reason.NOT_ITEM_TARGET_RECIPE"] = "Dieses Rezept akzeptiert keinen Gegenstand als Ziel.",
["profession.recipes.target.reason.INVALID_TARGET_ITEM"] = "Der ausgewählte Gegenstand ist kein gültiges Ziel für dieses Rezept.",
["profession.recipes.target.reason.REPLAY"] = "Diese gezielte Anfrage wurde bereits verarbeitet.",
["profession.recipes.target.reason.RATE_LIMIT"] = "Zu viele gezielte Herstellungsanfragen. Versuche es gleich erneut.",
["profession.recipes.target.reason.BOT_UNAVAILABLE"] = "Der Bot ist momentan nicht verfügbar.",
["profession.recipes.target.reason.BOT_DEAD"] = "Der Bot muss leben, um dieses Rezept zu verwenden.",
["profession.recipes.target.reason.FORBIDDEN"] = "Du darfst diesen Bot nicht steuern.",
["profession.recipes.target.reason.TIMEOUT"] = "Zeitüberschreitung bei der gezielten Herstellungsanfrage.",
["profession.recipes.target.reason.DISCONNECTED"] = "Die Bridge wurde getrennt, bevor die gezielte Herstellung abgeschlossen war.",
["profession.recipes.target.reason.BAD_RESPONSE"] = "Die Bridge hat eine ungültige Antwort für die gezielte Herstellung geliefert.",
["character.tab.skills"] = "Fertigkeiten",
["character.tab.reputations"] = "Ruf",
["character.tab.emblems"] = "Abzeichen",
Expand Down
64 changes: 64 additions & 0 deletions Locales/MultiBotAceLocale-enGB.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@ if type(register) ~= "function" then
end

local enGBValues = {
-- MB_LOOT_RULE_ITEM_I18N_V1_BEGIN
["loot.item.add"] = "Always loot: add item",
["loot.item.remove"] = "Always loot: remove item",
["loot.item.bridge.required"] = "Exact loot-item rules require LOOT_RULE_ITEM_V1.",
["loot.item.prompt.required"] = "Item prompt is unavailable.",
["loot.item.add.prompt"] = "Add always-loot item ID or link",
["loot.item.remove.prompt"] = "Remove always-loot item ID or link",
["loot.item.invalid"] = "Invalid item ID or item link.",
["loot.item.send.failed"] = "Loot item rule request was not sent.",
["loot.item.result.added"] = "%s - added to %d bot(s).",
["loot.item.result.removed"] = "%s - removed from %d bot(s).",
["loot.item.result.already_present"] = "%s - already present on %d bot(s).",
["loot.item.result.already_absent"] = "%s - already absent on %d bot(s).",
["loot.item.result.partial"] = "%s - partially updated (%d/%d bot(s)).",
["loot.item.result.ok"] = "%s - %s (%d/%d bot(s)).",
["loot.item.result.failed"] = "%s - loot rule failed: %s.",
["loot.item.reason.RATE_LIMIT"] = "too many requests; try again shortly",
["loot.item.reason.NO_REQUESTER_SESSION"] = "requester session unavailable",
["loot.item.reason.REQUESTER_NOT_IN_WORLD"] = "requester is not in world",
["loot.item.reason.DUPLICATE"] = "duplicate request",
["loot.item.reason.BAD_ACTION"] = "invalid action",
["loot.item.reason.INVALID_ITEM"] = "invalid item",
["loot.item.reason.NO_BOTS"] = "no eligible bots",
["loot.item.reason.TOO_MANY_BOTS"] = "too many selected bots",
["loot.item.reason.FORBIDDEN"] = "bot control forbidden",
["loot.item.reason.NO_BOT_SESSION"] = "bot session unavailable",
["loot.item.reason.BOT_NOT_IN_WORLD"] = "bot is not in world",
["loot.item.reason.BOT_DEAD"] = "bot is dead",
["loot.item.reason.NO_BOT_CONTEXT"] = "bot AI context unavailable",
["loot.item.reason.PERSISTENCE_BUSY"] = "persistence is busy; try again shortly",
["loot.item.reason.FAILED"] = "operation failed",
-- MB_LOOT_RULE_ITEM_I18N_V1_END
-- MB_TALENT_SPEC_APPLY_I18N_V1_BEGIN
["talent.spec.apply.success"] = "Talent specialization %s applied successfully to %s.",
["talent.spec.apply.failed"] = "Failed to apply talent specialization %s to %s (%s).",
-- MB_TALENT_SPEC_APPLY_I18N_V1_END
-- MB_TALENT_APPLY_I18N_V1_BEGIN
["talent.apply.success"] = "Talents applied successfully to %s.",
["talent.apply.failed"] = "Failed to apply talents to %s (%s).",
-- MB_TALENT_APPLY_I18N_V1_END
-- MB_SELFACTION_I18N_V1_BEGIN
["selfaction.bridge_unavailable"] = "The bridge is unavailable: the SelfBot action was not sent.",
["selfaction.failed"] = "SelfBot action failed: %s",
Expand Down Expand Up @@ -84,6 +124,30 @@ local enGBValues = {
["profession.recipes.craft.reason.CHANNELING"] = "The bot is already channeling a spell.",
["profession.recipes.craft.reason.cast_code"] = "The server refused the cast (code %s).",
["profession.recipes.craft.reason.UNKNOWN"] = "The server returned an unknown crafting error.",
["profession.recipes.target.apply"] = "Apply",
["profession.recipes.target.unavailable"] = "Exact item targeting via the bridge is unavailable.",
["profession.recipes.target.select"] = "Select the exact item to modify in the bot's inventory or equipment.",
["profession.recipes.target.send_failed"] = "The targeted crafting request could not be sent.",
["profession.recipes.target.pending"] = "Applying the recipe to the selected item...",
["profession.recipes.target.wrong_bot"] = "Select an item belonging to the bot whose recipe is open.",
["profession.recipes.target.exact_required"] = "This target must come from the exact inventory view.",
["profession.recipes.target.invalid_scope"] = "Choose an equipped item or an item from the backpack or equipped bags.",
["profession.recipes.target.ok"] = "The recipe was applied to the selected item.",
["profession.recipes.target.err"] = "Targeted craft failed: %s",
["profession.recipes.target.failed"] = "The targeted crafting request failed.",
["profession.recipes.target.reason.BAD_TARGET_POSITION"] = "That inventory or equipment position is not allowed.",
["profession.recipes.target.reason.MISSING_TARGET_ITEM"] = "The selected item is no longer present.",
["profession.recipes.target.reason.TARGET_STALE"] = "The selected slot now contains a different item.",
["profession.recipes.target.reason.NOT_ITEM_TARGET_RECIPE"] = "This recipe does not accept an item target.",
["profession.recipes.target.reason.INVALID_TARGET_ITEM"] = "The selected item is not a valid target for this recipe.",
["profession.recipes.target.reason.REPLAY"] = "This targeted request was already processed.",
["profession.recipes.target.reason.RATE_LIMIT"] = "Too many targeted crafting requests. Try again shortly.",
["profession.recipes.target.reason.BOT_UNAVAILABLE"] = "The bot is not available right now.",
["profession.recipes.target.reason.BOT_DEAD"] = "The bot must be alive to use this recipe.",
["profession.recipes.target.reason.FORBIDDEN"] = "You are not allowed to control this bot.",
["profession.recipes.target.reason.TIMEOUT"] = "The targeted crafting request timed out.",
["profession.recipes.target.reason.DISCONNECTED"] = "The bridge disconnected before the targeted craft completed.",
["profession.recipes.target.reason.BAD_RESPONSE"] = "The bridge returned an invalid targeted crafting response.",
["character.tab.skills"] = "Skills",
["character.tab.reputations"] = "Reputations",
["character.tab.emblems"] = "Emblems",
Expand Down
64 changes: 64 additions & 0 deletions Locales/MultiBotAceLocale-enUS.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@ if type(register) ~= "function" then
end

local enUSValues = {
-- MB_LOOT_RULE_ITEM_I18N_V1_BEGIN
["loot.item.add"] = "Always loot: add item",
["loot.item.remove"] = "Always loot: remove item",
["loot.item.bridge.required"] = "Exact loot-item rules require LOOT_RULE_ITEM_V1.",
["loot.item.prompt.required"] = "Item prompt is unavailable.",
["loot.item.add.prompt"] = "Add always-loot item ID or link",
["loot.item.remove.prompt"] = "Remove always-loot item ID or link",
["loot.item.invalid"] = "Invalid item ID or item link.",
["loot.item.send.failed"] = "Loot item rule request was not sent.",
["loot.item.result.added"] = "%s - added to %d bot(s).",
["loot.item.result.removed"] = "%s - removed from %d bot(s).",
["loot.item.result.already_present"] = "%s - already present on %d bot(s).",
["loot.item.result.already_absent"] = "%s - already absent on %d bot(s).",
["loot.item.result.partial"] = "%s - partially updated (%d/%d bot(s)).",
["loot.item.result.ok"] = "%s - %s (%d/%d bot(s)).",
["loot.item.result.failed"] = "%s - loot rule failed: %s.",
["loot.item.reason.RATE_LIMIT"] = "too many requests; try again shortly",
["loot.item.reason.NO_REQUESTER_SESSION"] = "requester session unavailable",
["loot.item.reason.REQUESTER_NOT_IN_WORLD"] = "requester is not in world",
["loot.item.reason.DUPLICATE"] = "duplicate request",
["loot.item.reason.BAD_ACTION"] = "invalid action",
["loot.item.reason.INVALID_ITEM"] = "invalid item",
["loot.item.reason.NO_BOTS"] = "no eligible bots",
["loot.item.reason.TOO_MANY_BOTS"] = "too many selected bots",
["loot.item.reason.FORBIDDEN"] = "bot control forbidden",
["loot.item.reason.NO_BOT_SESSION"] = "bot session unavailable",
["loot.item.reason.BOT_NOT_IN_WORLD"] = "bot is not in world",
["loot.item.reason.BOT_DEAD"] = "bot is dead",
["loot.item.reason.NO_BOT_CONTEXT"] = "bot AI context unavailable",
["loot.item.reason.PERSISTENCE_BUSY"] = "persistence is busy; try again shortly",
["loot.item.reason.FAILED"] = "operation failed",
-- MB_LOOT_RULE_ITEM_I18N_V1_END
-- MB_TALENT_SPEC_APPLY_I18N_V1_BEGIN
["talent.spec.apply.success"] = "Talent specialization %s applied successfully to %s.",
["talent.spec.apply.failed"] = "Failed to apply talent specialization %s to %s (%s).",
-- MB_TALENT_SPEC_APPLY_I18N_V1_END
-- MB_TALENT_APPLY_I18N_V1_BEGIN
["talent.apply.success"] = "Talents applied successfully to %s.",
["talent.apply.failed"] = "Failed to apply talents to %s (%s).",
-- MB_TALENT_APPLY_I18N_V1_END
-- MB_SELFACTION_I18N_V1_BEGIN
["selfaction.bridge_unavailable"] = "The bridge is unavailable: the SelfBot action was not sent.",
["selfaction.failed"] = "SelfBot action failed: %s",
Expand Down Expand Up @@ -84,6 +124,30 @@ local enUSValues = {
["profession.recipes.craft.reason.CHANNELING"] = "The bot is already channeling a spell.",
["profession.recipes.craft.reason.cast_code"] = "The server refused the cast (code %s).",
["profession.recipes.craft.reason.UNKNOWN"] = "The server returned an unknown crafting error.",
["profession.recipes.target.apply"] = "Apply",
["profession.recipes.target.unavailable"] = "Exact item targeting via the bridge is unavailable.",
["profession.recipes.target.select"] = "Select the exact item to modify in the bot's inventory or equipment.",
["profession.recipes.target.send_failed"] = "The targeted crafting request could not be sent.",
["profession.recipes.target.pending"] = "Applying the recipe to the selected item...",
["profession.recipes.target.wrong_bot"] = "Select an item belonging to the bot whose recipe is open.",
["profession.recipes.target.exact_required"] = "This target must come from the exact inventory view.",
["profession.recipes.target.invalid_scope"] = "Choose an equipped item or an item from the backpack or equipped bags.",
["profession.recipes.target.ok"] = "The recipe was applied to the selected item.",
["profession.recipes.target.err"] = "Targeted craft failed: %s",
["profession.recipes.target.failed"] = "The targeted crafting request failed.",
["profession.recipes.target.reason.BAD_TARGET_POSITION"] = "That inventory or equipment position is not allowed.",
["profession.recipes.target.reason.MISSING_TARGET_ITEM"] = "The selected item is no longer present.",
["profession.recipes.target.reason.TARGET_STALE"] = "The selected slot now contains a different item.",
["profession.recipes.target.reason.NOT_ITEM_TARGET_RECIPE"] = "This recipe does not accept an item target.",
["profession.recipes.target.reason.INVALID_TARGET_ITEM"] = "The selected item is not a valid target for this recipe.",
["profession.recipes.target.reason.REPLAY"] = "This targeted request was already processed.",
["profession.recipes.target.reason.RATE_LIMIT"] = "Too many targeted crafting requests. Try again shortly.",
["profession.recipes.target.reason.BOT_UNAVAILABLE"] = "The bot is not available right now.",
["profession.recipes.target.reason.BOT_DEAD"] = "The bot must be alive to use this recipe.",
["profession.recipes.target.reason.FORBIDDEN"] = "You are not allowed to control this bot.",
["profession.recipes.target.reason.TIMEOUT"] = "The targeted crafting request timed out.",
["profession.recipes.target.reason.DISCONNECTED"] = "The bridge disconnected before the targeted craft completed.",
["profession.recipes.target.reason.BAD_RESPONSE"] = "The bridge returned an invalid targeted crafting response.",
["character.tab.skills"] = "Skills",
["character.tab.reputations"] = "Reputations",
["character.tab.emblems"] = "Emblems",
Expand Down
Loading
Loading