Addon: [1.10.0] - Per-slot cast time and HasCastBar/Item inference#799
Merged
Addon: [1.10.0] - Per-slot cast time and HasCastBar/Item inference#799
Conversation
…/lifecycle fixes Per-slot cast time queue (cell 112) - populateActionbarCastTime queries GetSpellInfo / GetItemSpell per action bar slot. Encoded as slotIndex*100000 + castTimeMs, with an item-flag offset of 50000 added when the slot resolves to an item, a macro that wraps an item, or an auto-repeat action (Auto Shot, Shoot). - Lets the bot derive HasCastBar / Item routing from live game state instead of JSON declarations, including talent-modified casts (e.g. 5/5 Improved Corruption flipping Corruption to instant). - Hooked into ActionbarSlotChanged so removed/replaced slots clear stale state (publish 0 on empty slot). Per-spell cast event queue (cells 113, 114) - TimedQueue of encoded (spellId, eventCode) pairs drained one-per-tick into cell 113, plus a monotonic seq counter on cell 114 so the bot can detect repeats (same encoded value pushed twice). - PushCastEvent wired into UNIT_SPELLCAST_SENT/SUCCEEDED/FAILED and SoM_OnCastStart, plus the combat-log SPELL_CAST_FAILED branch (which carries the failure reason via select(15, ...)). - Replaces the global lastCastEvent cell as the source of truth for per-action result, since the global cell is overwrite-prone when events fire close together (pet cast, auto-shoot tick, etc.). - Layout: encoded = spellId%65536 + eventCode*65536. Codes 251/252/253 map to CAST_SENT/CAST_START/CAST_SUCCESS; codes 1..18 are direct errorList indices (BADATTACKFACING, OUT_OF_RANGE, ...). Cold-start init fix - Wrap player class/race detection in DataToColor:DetectPlayerCharacter() and re-run it from OnEnteringWorld. The addon-load-time read in Constants.lua may run before UnitClass returns valid data on a cold start, leaving every class-conditional table empty (e.g. S.spellInRangeTarget) until /reload — symptom: Pull/Combat range always false, autoattack never engages. - Re-run InitStorage on OnEnteringWorld and FushState so class-keyed tables get rebuilt against the now-known class. - Reorder OnSpellsChanged to call PopulateSpellBookInfo first so the icon->id map is fresh before InitActionBarCostQueue / range refresh read it. Without this the map can be stale if SPELLS_CHANGED hasn't fully synced yet — symptom: Warlock spell range bit never sets. Kill-credit + miss-source fixes - Clear eligibleKillCredit[destGUID] at UNIT_DIED instead of wiping the whole table on OnLeftCombat. Prevents losing eligibility for kills landed in the same encounter and keeps per-target tracking clean. - Include playerDamageMiss alongside playerDamageTakenEvents in the source-damage filter so missed/parried/dodged hits still register the attacker for combat threat tracking. Frame count bumped 114 -> 117 to accommodate cells 112, 113, 114. New DataToColor_Wrath.toc target for Wrath Classic (interface 34300). Version bumped to 1.10.0 across all toc files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ActionBarCastTimeReader (cell 112)
- Decodes the per-slot cast time the addon publishes each tick into a
fixed-size array keyed by slot index. Cast time is castTimeMs % 50000;
values >= 50000 carry the item-flag offset, which the addon sets for
true items, macros wrapping items, and auto-repeat actions (Shoot,
Auto Shot).
- Public surface: Get(KeyAction) / HasCastBar(KeyAction) / IsItem(KeyAction)
for the casting pipeline, plus GetBySlotIndex(int) so frontend views
can scan all slots without a KeyAction in hand.
- Replaces JSON-driven HasCastBar/Item declarations once consumers are
wired through (next commit). Talent-aware: a spell that becomes
instant via talents is observed as castTimeMs == 0.
CastEventReader (cells 113, 114)
- Maintains a per-spell-id event log by draining cell 113 (encoded
spellId+eventCode) gated on cell 114 (monotonic sequence). The seq
counter lets the reader distinguish a fresh push of the same encoded
value from an unchanged repeat tick, which a value-only watch would
miss.
- Public surface:
- Latest(spellId): peek the most recent event for a spell without
consuming it.
- TryConsume(spellId, out ev): peek + clear, so a stale event from a
previous attempt can't fire twice on a later cast of the same
spell.
- Sentinel event codes 251/252/253 are remapped on read back to
UI_ERROR.CAST_SENT/CAST_START/CAST_SUCCESS so consumers compare
against the same enum used by the global CastState reader.
DI wiring
- Both registered as forwarded singletons that also satisfy IReader, so
the AddonReader update loop ticks them every frame (AddAddonComponents
+ AddStartupIoC). Mirror the existing ActionBarCostReader / CooldownReader
registration pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t log Cast routing now reads the addon - HasCastBar / Item routing decisions in CastingHandler now read castTimeReader.HasCastBar(item) / castTimeReader.IsItem(item) at every call site (CastInstant strategy selection, BeforeCastDelay stop-moving guard, AfterCast GCD pad). KeyAction.HasCastBar / KeyAction.Item JSON fields are no longer consulted by the routing — a talented-instant spell now skips the cast-bar wait without the user touching JSON, and a wand/auto-shot is auto-detected as item-like via IsAutoRepeatAction. Per-spell event consumption for items - After CAST_SENT for an item / auto-repeat action, briefly wait (DoubleNetworkLatency) for either Any_AutoAttack to toggle (success signal) or UIErrorTime to advance (failure echoed via combat log). Then call castEventReader.TryConsume(item.SpellId) to read this item's most recent event without cross-spell contamination. - Closes the gap where a BADATTACKFACING was overwritten by a later pet-cast/auto-shoot success on the global CastEvent cell, masking the failure and letting the bot believe the attack landed. - Falls back to the global CastEvent cell when item.SpellId == 0 (item never fired before, or no known spell ID), with a cross-spell guard on CastSpellId. - New private static WaitForItemCastResolution helper extracted to keep CastInstant readable (mirrors existing WaitCurrentAction shape). SpellInQueue() rewritten for actual GCD-tail queueing - Old: returned true while GCD < HalfSpellQueueTimeMs, which both wasted presses before the SQW window opened and skipped the SQW window itself — the bot would never queue against the GCD boundary. - New: returns true while RemainCastMs > SQW or GCD > SQW. Inside the last SQW ms of the cast/GCD, returns false so the next press queues against the WoW SpellQueueWindow CVar window. Cast-bar wait floor - AfterCastWaitCastbar now uses Max(actual remaining, expected from cast-time reader) - SQW. A press that hasn't been observed by the cast-bar reader yet still gets the right wait floor instead of returning early on stale RemainCastMs == 0. CombatGoal: gate items during in-progress casts - Skip non-base items / auto-repeat actions while playerReader.IsCasting(). These can't queue at the server (ERR_SPELL_FAILED_ANOTHER_IN_PROGRESS) so pressing them just wastes input. Cast-time spells can still queue via SQW so they're not gated. README - HasCastBar field documented as auto-detected from GetSpellInfo. The JSON field is still parsed (back-compat) but ignored by routing. The example block updated to drop the explicit HasCastBar=true. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GoapGoalView - Highlight the currently-casting goal/key row with a left-to-right yellow gradient that grows as RemainCastMs ticks down. Filled colour matches Bootstrap's table-warning solid (#ffc107) so the row still reads as "the bot is doing this", and the empty section uses table-warning subtle (#fff3cd) so it stays visually consistent with the standard selected-row highlight. - Detection: SpellId match against playerReader.SpellBeingCast, falling through when SpellId == 0 (key never cast yet) or when not casting. - New cast-bar-row class + scoped style block forces transparent table cells so the row-level inline gradient shows through Bootstrap's per-cell --bs-table-bg. transition on background-image keeps the paint smooth at the addon's poll rate. - Helper RowClass(current, cooldown, casting) suppresses the existing table-warning/table-info paint while a row is casting so the gradient is the only visible background. SpellBookComponent - New "Action Bar" panel listing every populated slot with: slot number, icon, resolved name (via texture -> spell name lookup), cast time in ms + seconds, and a routing badge (CastInstant / CastCastbar). Rebuilt on AddonDataChanged and TextureChanged so newly-bound slots appear without a manual refresh. - Header counters: Populated / Instant / Cast Bar so the user can sanity-check at a glance that talents are being respected (e.g. an Improved Corruption Warlock should show Corruption under Instant). - Spellbook table extended with a Cast Time column. Cast time is attributed via shared-texture lookup (BuildSpellCastTimeLookup): all ranks of a spell share the same texture, so any rank that's bound to a slot lights up cast time for every rank. Spells unbound to any slot show "—" with a tooltip explaining the source. - Replaced the inline GetSortedSpells call site with a cached cachedSpells list rebuilt on hash change, so repeated re-renders during a single tick don't re-sort the spell list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l 10 Warlock_66_Demo_pet_pull - Replace HasCastBar:true with AfterCastWaitCastbar:true on cast-time spells. HasCastBar is now derived by the bot from the addon's per-slot cast time, so leaving it in is just noise; AfterCastWaitCastbar is the setting that actually changes behaviour (wait for the cast bar to finish before evaluating the next entry). - Add Interrupt + CancelOnInterrupt rules on Drain Soul, Drain Life, Health Funnel, Immolate, Incinerate, Shadow Bolt so wasted casts abort early when the precondition flips (target dies, dot already applied, pet healed, mana threshold hit, Shadow Trance proc available). - Switch Item_Healthstone (single id) to Items_Healthstone (array of all 15 healthstone item IDs across ranks/qualities). The new IntVariable- array form lets BagItem:Items_Healthstone match any rank in inventory. - Add DRAIN_STOP_HP% (90) and FUNNEL_STOP_PET_HP% (90) thresholds for the new Interrupt expressions. - New User Wait gate so the rotation pauses when the menu or chat input is open (MenuOpen || ChatInputVisible). - Drop Item:true / PressDuration on Shoot — auto-detected now, since IsAutoRepeatAction marks the slot as item-like and the bot picks the right press-duration default. Warlock_1 - Introduce IntVariables (MIN_WATER%=20, MIN_MANA_SHADOWBOLT%=40) so thresholds are tweakable in one place. Replace the magic 50% on Food/Drink with MIN_WATER%, gate Shadow Bolt on MIN_MANA_SHADOWBOLT% in both Pull and Combat. - Refine engagement: gate AutoAttack on InMeleeRange (don't spam AutoAttack from out of range), refine Approach to !MeleeSwinging (don't reposition mid-swing) and !SoftTargetDead (don't chase a corpse). TargetHealth%>20 added on Combat Shadow Bolt to stop burning mana on a dying mob. - Comment out PathFilename on the Repair / Sell vendor entries. Warlock_1_10 - New profile for Warlock at level 10. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GetSpellInfo/GetItemSpell— so cast routing tracks talents (e.g. 5/5 Improved Corruption flips Corruption to instant without a JSON edit). Item flag is derived fromIsAutoRepeatAction+ macro-wraps-item detection, which also picks up Shoot/Auto Shot withoutItem:truein JSON. JSONHasCastBar/Itemfields are still parsed for back-compat but ignored by the routing.lastCastEventcell as the source of truth for item / auto-repeat retries. Closes the gap where anERR_BADATTACKFACINGwas overwritten by a later pet-cast / auto-shoot success on the global cell and masked the failure.CastEventReader.TryConsume(spellId)reads + clears so a stale event from a previous attempt can't fire twice./reload; kill-credit cleared perUNIT_DIEDinstead of on combat exit; miss/parry/dodge damage now sources the attacker;SpellInQueuerewritten for actual GCD-tail queueing (was gating onHalfSpellQueueTimeMswhich both wasted presses and skipped the SQW window).GoapGoalViewpaints the casting row as a left→right yellow gradient that fills withRemainCastMs.SpellBookComponentgains an Action Bar panel listing every populated slot with cast time and routing badge (CastInstant / CastCastbar), and the spellbook table shows cast time per spell.DataToColor_Wrath.toc, interface 34300). Addon version bumped to 1.10.0 across all toc files (frame count 114 → 117 for the three new cells).AfterCastWaitCastbar+ Interrupt/CancelOnInterrupt rules, switched toItems_Healthstonearray. Warlock_1 introduces IntVariables for thresholds. New Warlock_1_10 profile added.Test plan
Warlock_66_Demo_pet_pulland confirm cast-time spells (Shadow Bolt, Incinerate, Drain Life, Health Funnel) route through CastCastbar with the new visualization filling the row.ERR_BADATTACKFACING/OUT_OF_RANGEretries fire (no false success masking even when a pet cast or auto-shoot tick lands between polls).PLAYER_ENTERING_WORLDfinishes (e.g. quick relog) and confirm Pull/Combat range bits set correctly without/reload.DataToColor_Wrath.tocloads and the addon emits frames.ERR_SPELL_FAILED_ANOTHER_IN_PROGRESSspam) but cast-time spells still queue via the SQW window.🤖 Generated with Claude Code