promotional bannermobile promotional banner

Loot & Baloot

Loot & Baloot — Play Saudi Baloot (بلوت) inside World of Warcraft. A four-player trick-taking card game over the party addon channel. Host with friends or play solo against bots, with full Hokm / Sun rules, melds, escalations, and SWA claims.

File Details

v3.2.14

  • R
  • May 16, 2026
  • 5.16 MB
  • 9
  • 12.0.5
  • Retail

File Name

WHEREDNGN-v3.2.14.zip

Supported Versions

  • 12.0.5

Loot & Baloot

v3.2.14 (2026-05-16)

Full Changelog Previous Releases

  • docs(CHANGELOG): add v3.2.14 release notes
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix(UI.lua): neutral status text during the non-host echo gap (F1 blocker #2)
    Codex re-review blocker #2 on localrefresh-nonhost-v3.2.14: the action
    affordance gates were correct, but UI.statusFor still returned
    "Your turn to bid" / "Your turn" whenever S.IsMyTurn() was true.
    Non-host LocalBid/LocalPlay do not advance S.s.turn locally, so during
    the echo gap the status line still looked stuck / actionable after the
    actor already bid or played.
    statusFor now mirrors the action gates:
    • PHASE_DEAL1 / PHASE_DEAL2BID: "Your turn to bid[ (round 2)]" only
      when S.IsMyTurn() AND turnKind == "bid" AND
      S.s.bids[S.s.localSeat] == nil. If IsMyTurn() but already bid →
      neutral "Bid sent — waiting for table".
    • PHASE_PLAY: "Your turn" only when S.IsMyTurn() AND
      not S.s.localPlayedThisTrick. If IsMyTurn() but already played →
      neutral "Play sent — waiting for table".
      Net.lua deferredRefresh tails (d248259) and the action-affordance
      gates (2cdecf0) are unchanged. Tests: BT.7 source pins for the two
      status guards + neutral strings. Harness 1430/0 (1426 + 4 BT.7).
      H1 11/0, H7 9/0. F2/F3/F4, SendTurn/_OnTurn, resync MSG_BIDCARD,
      contract/meld, raid-lobby, duplicate-play, safeOnPlayObserved all
      untouched. No CHANGELOG/tag/release/packaging changes.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix(UI.lua): suppress acted-seat action affordances during the echo gap (F1 blocker)
    Codex re-review blocker on localrefresh-nonhost-v3.2.14: the v3.2.14
    deferredRefresh tails are correct, but the refreshed non-host UI still
    keyed action affordances on S.IsMyTurn() alone. Non-host
    LocalBid/LocalPlay do not advance S.s.turn locally, so during the
    echo gap before the host's MSG_TURN the optimistic refresh could
    still present "your turn" controls and invite a duplicate action.
    • UI.lua bid panel: gate the bid-button block on
      S.s.bids[S.s.localSeat] == nil in addition to IsMyTurn()/turnKind
      — once this seat has bid, no bid buttons even pre-echo.
    • UI.lua hand render: isPlayable now also requires
      not S.s.localPlayedThisTrick — played cards stop looking/behaving
      playable immediately, not after the host echo.
    • UI.lua hand OnClick: hard-guard if S.s.localPlayedThisTrick then return end (belt-and-suspenders; N.LocalPlay already dedupes).
    • Net.lua: refreshed the stale deferredRefresh helper comment — it no
      longer claims "bot-dispatch only / humans inline" (v3.2.14 F1 uses
      it for the acting non-host).
    • Tests: BT.6 source pins (UI.lua not harness-loaded) for the two
      guards + the onclick hard-guard + the Net comment refresh.
      Harness 1426/0 (1422 + 4 BT.6). H1 11/0, H7 9/0. F2/F3/F4,
      SendTurn/_OnTurn, resync MSG_BIDCARD, contract/meld, raid-lobby,
      duplicate-play, safeOnPlayObserved all untouched. No CHANGELOG, no
      tag/release, no packaging changes.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix(Net.lua): immediate local refresh for the acting non-host (F1, v3.2.14)
    Stabilization checkpoint F1 (HIGH perceived-stability): addon messages
    do not loop back, so a non-host who bids/plays got NO immediate UI
    refresh — their client only redrew when the host's echo round-tripped,
    which on a throttled/dropped addon channel is the multi-second
    "I-clicked-and-it-froze" symptom. Host paths already refresh via
    _HostStepBid / _HostStepPlay (v3.2.8/9); only the non-host actor was
    left without feedback (deferred audit finding #4/#5, never fixed).
    • N.LocalBid tail: split if S.s.isHost then N._HostStepBid() end into
      host → _HostStepBid() (unchanged) / else → deferredRefresh().
    • N.LocalPlay tail: same split for _HostStepPlay() / deferredRefresh().
    • deferredRefresh() (Net.lua:142) is the existing watchdog-safe,
      next-frame refresh helper already used on host paths — pure render
      of already-applied local state, no wire/authority/turn change.
    • Bid authority, wire format, turn logic, duplicate guard,
      safeOnPlayObserved, _OnPlay, _HostStep* all UNCHANGED.
    • Tests: new BT section (17 checks) — non-host LocalBid/LocalPlay
      schedule a delay-0 deferredRefresh that fires B.UI.Refresh; host
      paths still call _HostStep* and never take the non-host branch;
      source pins for the F1 tails. Harness 1422/0 (1405 + 17). H1 11/0,
      H7 9/0.
      F2/F3/F4 from the checkpoint deliberately NOT touched. No CHANGELOG,
      no tag/release, no packaging changes.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com