The open v2.0.29-preview section had been collecting entries as work
landed, but stopped at the terrain-seam fix; everything after it went
unrecorded. Adds the two missing sections: rendering (brightness multiply
over water, FSR3 16-bit storage, validation-layer env var), bank and guild
bank, crafting, quests, GM tools, and the two changes since.
Also narrows a comment in macos_platform.hpp -- W takes no diacritics.
SDL2 leaves text input enabled for the whole session, so AppKit routes key
events through NSTextInputContext even in normal gameplay. Holding a key
with diacritics -- W, A, S, E -- opened the accent chooser over the game
instead of repeating the key.
Register ApplePressAndHoldEnabled=NO before SDL_Init brings up
NSApplication. The registration domain is process-scoped, so the user's
saved preferences are untouched; if a global setting explicitly enables
press-and-hold, fall back to this application's own domain, which outranks
NSGlobalDomain.
Needs an Objective-C++ shim, wired into both wowee and wowee_editor since
both compile window.cpp.
Auction results carry the rolled random property separately from the item
template, so browse-tab tooltips rendered only base stats. Build an
instance-aware ItemDef from the query response plus the auction's
randomPropertyId/suffixFactor, using the same bonus folding as inventory
tooltips, so "of the ..." suffix stats are visible before bidding.
Makes the ItemDef overload of renderItemTooltip public so callers outside
InventoryScreen can use it.
Re-apply the multiplicative brightness overlay (scene*br, no white washout)
and stop it compounding through water refraction. Water refraction samples
a scene-history image captured from the final swapchain, which has the
display brightness baked in; re-applying brightness on the water each frame
fed back through that temporal capture and blew out (a multiply diverges
where the old white-lerp converged). Pass the brightness factor to the
water shader and divide it back out of the refraction sample, so refraction
sees the un-brightened scene and the display still gets a true multiply.
This also fixes the latent darkening feedback (water creeping to black).
No pass restructuring; localized to the overlay + water shader.
Brightness > 1 was implemented as a white fullscreen overlay at alpha
(br-1), so the whole image lerped toward white — desaturating and washing
everything out (fully white at max). Add a multiplicative brightness
pipeline to OverlaySystem using a dst-color blend
(result = dst*src + dst, src = br-1) so the scene is multiplied by br —
true brightening that saturates highlights but keeps color, like a real
brightness/gamma control. Darkening already used a black overlay, which is
a correct scene*br multiply, so it's unchanged.
Add a 'Max Out Character' panel to the GM command screen that detects
your class + active expansion and queues a GM command sequence: set max
level (60/70/80), learn all class spells + talents, max skills, optional
1000g, and add a class/expansion-appropriate gear kit. Commands drain one
per frame to avoid server chat-flood protection. Per-slot toggles let you
pick which parts to apply. Gear lists live in bis_gear_data.cpp — a
curated, easily-extended starter set (anchored on class legendaries);
the server validates each .additem so unknown IDs are skipped.
.gm fly on sets only the CAN_FLY movement flag, but flight physics were
gated on isPlayerFlying() which also requires FLYING (only set once
already airborne) — a chicken-and-egg that left the player unable to take
off. Drive setFlyingActive() from a new canFly() (CAN_FLY set) instead,
and ungate the descend key (X) so it works on foot, not just on a flying
mount. Space ascends, X descends, gravity off while CAN_FLY is set.
Parse each command's syntax into labeled form fields instead of an
editable raw string: #x -> numeric input, $x -> text input, a/b ->
dropdown, [word] -> optional flag checkbox. Shows a live 'Will send'
preview, defaults player/name fields to the current target when blank,
and keeps an 'Edit manually' escape hatch. Add 12 commonly-used commands
(reset level/stats/spells/talents/achievements/all, repairitems,
additemset, modify arenapoints/drunk/faction/xp/phase) and de-duplicate
the scattered reset entries.
Add a searchable GM command browser (micro-menu 'GM' button) over the
existing 195-entry kGmCommands reference. Left pane lists commands
grouped by first token (flat filtered list while searching) with a
max-permission-level filter; right pane shows syntax/description, a
security badge, and an editable command line. Send (or Enter) dispatches
the command to the server as a SAY chat message ('.' prefix, AzerothCore
convention) — the server enforces the real permission level.
- The bank 'Combine bags' (contiguous vs per-bag sections) toggle was a
function-local static, so it reset to split on every relaunch. Make it
a persisted WindowManager member (bank_combine_bags in settings.cfg),
saved on toggle and loaded at startup.
- Guild bank showed no items or slots: the grid only iterated the slots
the server sent (sparse, often just occupied ones — nothing for an
empty tab). Render a fixed 98-slot grid (14x7) and look items up by
slotId, so slots always appear and items land in the right cells.
- Right-clicking a bag item while the guild bank is open now deposits it
into the first free slot of the viewed tab (guildBankDepositFromInventory).
Bags auto-open when the guild bank opens so items are reachable, and a
hint line documents left-click withdraw / right-click deposit.
- Fix latent bug: clicking a guild bank tab only sent a query and never
updated the active tab, so withdraw/deposit always targeted tab 0. Sync
guildBankActiveTab_ from each SMSG_GUILD_BANK_LIST (server tags it).
- Add ESC-to-close for the guild bank window.
- Bank: right-clicking a bank item now withdraws it to the bags. The
bank slot renderer had left-click drag and shift-link but no
right-click handler, so right-clicks did nothing. Routes through
withdrawItem(), which now uses CMSG_AUTOSTORE_BANK_ITEM so the server
places it in any free bag slot (retail), not just the backpack.
- Guild bank: interacting with a guild-vault GameObject (type 34) now
opens it. Nothing called openGuildBank(), and openGuildBank() never
sent CMSG_GUILD_BANKER_ACTIVATE (only queried a tab), so no bank list
arrived. Detect type 34 in interactWithGameObject and send the
activate; also mark the window open when SMSG_GUILD_BANK_LIST arrives.
- Crafting: the recipe list pane is now a draggable splitter (was fixed
width, then a fixed proportion) so long recipe names can be read.
3.3.5a servers do not push collect-item objective counts (unlike kill
credit, which arrives in the quest-log update fields), so the tracker
relying solely on SMSG_QUESTUPDATE_ADD_ITEM never advanced when quest
items were looted. Reconcile item objectives against actual bag contents
on every inventory rebuild instead.
Load Spell.dbc TargetAuraState (added to every expansion layout at its
verified column) into the spell cache with getSpellTargetAuraState. The
action bar now dims abilities whose target isn't in the required aura state
(e.g. Execute below 20% health), with a tooltip naming the requirement, and
SMSG_CAST_FAILED result 111 (Target aurastate) now yields 'Target must be
below 20% health.' instead of the opaque protocol label.
Add setFactionAtWar / setFactionInactive senders (CMSG_SET_FACTION_ATWAR /
CMSG_SET_FACTION_INACTIVE) with local flag updates, plus isFactionInactive /
isFactionPeaceForced helpers and the FACTION_FLAG_INACTIVE constant. The
reputation panel's right-click menu now toggles war/peace (disabled when
peace is forced) and inactive state; inactive factions hide behind a 'Show
inactive' checkbox and dim when shown.
Load Achievement.dbc's IconID (added to the WotLK DBC layout, field 42) into
the achievement cache and resolve it through SpellIcon.dbc to the artwork.
The earned list now renders a bordered 32px icon with the name and points
beside it, replacing the gold-star glyph; a star placeholder fills the slot
while an icon streams in or when one is absent. Icon textures are lazily
BLP-loaded and cached in WindowManager with a per-frame upload cap.
Move the WoW description token resolver onto GameHandler::formatSpellDescription
and route buff/aura tooltips, the spellbook, and item Use/Equip effect lines
through it, so 'increased by $s1' etc. no longer render raw. Add the $/N;
division token used by food regen ('Restores $/5;s1 health per second').
Prefer Spell.dbc's full Description column over the short Tooltip in both the
spell_handler cache and the spellbook loader, so food tooltips include the
'become well fed and gain N Stamina and Spirit' clause instead of a bare
one-liner. The talent screen now delegates to the shared formatter.
WotLK Tooltip (139->187) and TBC Rank (136->144) / Tooltip (154->178)
layout indices assumed the wrong locale-block stride and landed on empty
columns; point them at the verified enUS strings.
Rework the talent description formatter into a real $-token resolver: it
handles $s/$o/$m/$M base points and $d durations with cross-spell
$<spellId> references (e.g. $14201d), plus $l/$g plural/gender forms,
using live spell data via GameHandler. Unresolvable tokens ($h proc chance,
$t period) are stripped cleanly instead of rendering raw, so Enrage now
reads 'a 4% damage bonus for 12 sec' rather than '$14201s1% ... $14201d'.
The talent panel read Spell.dbc's Tooltip column, which the layouts pointed
at an empty locale field, so hovering a talent showed only name and rank. Add
the correct Description column to every expansion's DBC layout (verified
against each Spell.dbc's string blocks) and read it in the talent screen,
substituting $s/$o magnitude tokens with the rank's EffectBasePoints so
descriptions read with concrete numbers. Unlearned talents show their rank-1
effect under 'Effect:'.
The Create Auction dropdown only iterated the 16-slot base backpack, hiding
every item held in an equipped bag. It now enumerates the backpack plus all
equipped bags and posts the selected item by its server GUID via the new
auctionSellItemByGuid path, so any container can be listed.
Route the unread-mail flag through a rising-edge helper that prints
'You have new mail.' and plays a notification sound once when mail arrives
(or is found waiting at login), alongside the existing minimap indicator.
Add a Sort button that orders the main bank and bank bags by quality/itemID/
stack (mirroring the backpack sort, one CMSG_SWAP_ITEM per frame), a
"Combine bags" toggle that renders every bank slot as one continuous grid,
and per-slot purchase prices from BankBagSlotPrices.dbc on the bank-bag row
(only the next slot in sequence is buyable; later ones are locked).
Reverts the emitter spawn lift, which did not help, and eases the lifespan
cap from 1.5s back to 4.5s. Cutting the life hard kept particles near the
emitter, and near the emitter is exactly where they were never visible, so
this only trims their spread rather than trying to hold them at the wick.
A particle is a point sprite carrying a single depth value, so one born
inside the mesh it belongs to is depth-rejected whole rather than partly
occluded. CHANDELIER01 puts all five candle emitters ~0.17 below the top of
the wax, so its flames were only ever seen once they had drifted metres
clear — which is exactly why shortening their life or holding them still
made them vanish, while letting them rain across the room made them
visible. Measure each emitter against the model's own vertices at load and
raise the buried ones just proud of the surface. Fixtures that already look
right have an emitter in open air and are lifted by zero.
Fires express their flame as particle emitters rather than a glow card, and
the emitter path that turns those into a light was gated on lantern-like
models — so a fireplace full of burning wood lit nothing at all and had no
light to flicker. Open flame now takes that path too, with a wider, oranger
light than a candle wick, and forges are classified as the contained fires
they are. All of it guts with the same slow rhythm as the lanterns.
WMO emissive was a flag tuned for Stormwind's lamp glass, far too bright
for a clock face, so it becomes a level instead. Level 2 keeps normal
daylight shading and adds a warm glow that seeps through the face, fading
up as the scene darkens and wavering on three detuned sines so the flame
never visibly loops. Matched on the MM_CLOCKFACE texture, so every
building sharing that face is lit the same way.
It sat near the bottom of the screen, far from the combat it describes,
and was pinned there by NoMove/NoInputs. It now follows the bottom edge of
the target frame, and the first drag latches a position that persists
across sessions; right-click sends it home.
The marks were text symbols, but the ImGui font has no code points for
skull, cross, moon and most of the others, so they rendered as '?' boxes
beside the name. Load Blizzard's UI-RaidTargetingIcon art instead and hang
it over the unit's head like the original client, with the same textures
reused at small size in the target, focus, minimap and party displays.
The server only broadcasts MSG_RAID_TARGET_UPDATE to a group, so marking
while ungrouped did nothing and the feature could not be used or tested
without a second player. Apply the mark client-side in that case, matching
the server's rule that an icon and a unit each hold one mark. Grouped
marking stays server-authoritative, and a group's full list replaces local
marks when one arrives.
Route GameHandler's raid mark getters to SocialHandler, which is where
MSG_RAID_TARGET_UPDATE stores marks — GameHandler kept a second array that
nothing ever wrote, so the target frame, nameplates, minimap and social
panel all read zeros. Fix the parse to match the wire format as well: the
full list carries only the icons that are set rather than a fixed eight,
and a single mark leads with the setter's GUID on WotLK but not on
classic/TBC, told apart by remaining size so every expansion decodes.
Re-query nearby quest giver status on kill-credit and quest-item updates
that may have made a quest turn-in-able, so the ! and ? markers change
without leaving and re-entering the area. Sweeps are coalesced behind a
one-second cooldown ticked from GameHandler::update, since one request
fans out to a packet per nearby giver and completion events arrive in
bursts.
Pin game object M2 models so the 60s unused-model reaper can't evict them
while the player is away, exempt game objects from the adaptive doodad
render distance that collapses to ~200 units in a city, and key GPU cull
results by instance ID so a respawned object can't inherit the verdict of
whatever instance held its array slot two frames earlier.
Barber cuts updated the character data and inventory preview but never
rebuilt the in-world 3D model, so the new hair/facial hair only showed
after a restart or teleport. Add a player-model-rebuild callback fired on
PLAYER_BYTES / PLAYER_BYTES_2 changes; Application re-spawns the model in
place via the same path teleport uses. Guard on an actual appearance diff
(PLAYER_BYTES_2 also carries rest state), preserve the current position,
and reset equipment dirty tracking so armor and weapons re-composite onto
the fresh model.
Keyring slots were rendered with placeholder backpack addressing
(SlotKind::BACKPACK, index -1), so keys could not be picked up, moved, or
used. Add a real SlotKind::KEYRING / HeldSource::KEYRING with correct wire
addressing (bag 0xFF, slot 86+i) wired through pickup, place, swap-source,
cancel, and right-click-use paths across all inventory view modes. Also
show at least one keyring row whenever Show Key Ring is enabled so it stays
visible (and a drop target) even when empty, instead of hiding when it
holds no keys.
A locked type-3 chest (e.g. Dead-tooth's Strongbox) is not opened by
CMSG_GAMEOBJ_USE, and casting the key's OPEN_LOCK spell via CMSG_CAST_SPELL
is rejected because the player does not know it. Open it the way the real
client does: send CMSG_USE_ITEM for the key item, targeting the chest
(TARGET_FLAG_GAMEOBJECT), so the server casts the key's on-use spell and
unlocks it. Locate the key wherever it lives (backpack, bag, or keyring)
and add GameObject-target support to UseItemPacket. Chests opened by a
known player spell (Pick Lock) still cast it; unlocked/quest containers
still use a plain CMSG_GAMEOBJ_USE.
Add an AddOns button to the character-select footer that opens a window listing
every installed addon (title, version, author, notes) with a per-addon
enable/disable checkbox. Enabled state persists to <config>/addons.cfg and is
honored by loadAllAddons (disabled addons are skipped and hidden from the Lua
VM); /reload picks up changes. Toggles apply on the next world enter, matching
retail behavior.
Relative mouse mode engaged on any button press (including left-click to select),
and the camera rotated on the slightest motion — so a click with tiny jitter
turned the view and shifted the NPC out from under the cursor, making selection
unreliable. Suppress rotation until the drag passes a 5px dead-zone, then rotate
normally; reset on each press and release.
Right-click interact/attack fired on button press with no drag detection, so
pressing RMB to rotate the view would raypick a nearby hostile unit and start
auto-attacking it. Mirror the left-click tap/drag pattern: record the press
position and only interact/attack on release when the cursor moved <5px (a tap),
treating a larger move as a camera rotate.
Pickup now removes the action from its slot so it visibly rides the cursor
instead of staying put. Fix a reference-invalidation bug in the swap where the
live slot reference was mutated before the displaced action was read, causing
the existing item to stay and the carried one to be lost. Displaced actions now
fall back into the emptied origin; cancel/off-bar paths restore or delete safely.
Add a 'Zone' filter mode to the on-screen quest tracker that shows only quests
whose zoneOrSort matches the player's current zone (getWorldStateZoneId), and
make it the default. Falls back to showing all quests when the zone isn't known
yet. Filter now cycles All / Active / Done / Zone.
Chat window resize was gated behind unlocking (locked forced NoResize); resize is
now decoupled from lock so the grips always work — locking only pins position and
blocks moving. Size persists in either state. Target frame now auto-sizes to its
widest line (name, subtitle, guild, level/classification row) with a 250px floor
instead of a fixed width that clipped the level line.
Hold left-click on a filled slot for 0.6s to lift its action onto the cursor
(a rising fill shows the charge); a quick click still casts/uses. While carried,
click another slot to swap, click the source again or empty space to cancel, or
right-click off the bar to remove. Wires up the previously dormant drag state.
Chat window size is now captured while unlocked and persisted (chat_window_w/h),
so a resized window keeps its size after locking or restart; a size constraint
keeps it from collapsing. Target frame grows to fit long names, guild tags, and
creature subtitles instead of clipping at a fixed 250px.
WoW's trade window has 7 slots; slot 6 (TRADE_SLOT_NONTRADED) holds an item
the partner can enchant/craft on without it changing hands. TRADE_SLOT_COUNT
was 6, so slot 6 was dropped in the parser and never shown. Bump to 7, add
TRADE_SLOT_NONTRADED, render it under a 'Will not be traded' separator, and
set the missing occupied flag in the slot conversion (trade items previously
never rendered).
Draw undiscovered flight masters as green diamonds so players can see
where flight paths exist before visiting them, keeping discovered nodes
gold. Filter to the player's own faction (own-faction or neutral both-
faction nodes only) so the opposite faction's flight masters and
non-flight boat/zeppelin nodes are not shown. Adds GameHandler::
isPlayerAlliance() helper.
Draw a gold diamond marker with tooltip for any visible flight master,
keyed off the live UNIT_NPC_FLAGS bit so undiscovered ones appear before
the taxi window has been opened.