1.0.0-release
What's new
commit 0e693d71625e3773fd58387008b00bf15f823366
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 17:24:34 2026 +0530
Dummy commit for 1.0.0 release
Carries no changes. It exists only as something to hang the 1.0.0 tag on,
so the CurseForge packager builds from a commit that means nothing else.
This supersedes f88302d, which was created for the same purpose and then
buried under four commits -- the manual move, the CurseForge project ID,
the author line and the release notes all landed after it. Tagging that
one now would ship a 1.0.0 without any of them, and without the project
ID the packager would not know where to upload.
The tree is identical to b721f7e.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit b721f7e9bcc59fc87e384b14c059b9249f0538ca
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 17:17:08 2026 +0530
Credit mundocani in the TOC, and shorten the release notes
The TOC author line uses the CurseForge handle rather than the full name,
matching how the addon is credited on the project page. The About panel
and the README credits keep "John Stephen" -- prose and a metadata field
want different registers, and both point at the same person.
The 1.0.0 release notes were unreadable: bullets up to 270 characters, so
the cell wrapped into paragraphs and the bullets stopped helping. Longest
is now 133. The change is mostly dropping the explanation and keeping the
outcome -- "Fixed the per-slot checkboxes on the character sheet, which
were invisible behind any addon drawing over the character panel" is now
"Character sheet slot checkboxes are visible again". Someone reading a
changelog wants to know what is different; the why is in the commits.
The battleground entry is split in two. It carried both the fix and the
list of newly supported maps, which is what ran it to four lines.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit a78fe7c4404be54cf374aeabbba9c83e2c69f028
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 17:13:36 2026 +0530
Add the CurseForge project ID to the TOC
X-Curse-Project-ID: 1698220, using the field name and placement the
sibling addons use rather than inventing one.
Pinned by a test. A missing ID fails the upload loudly; a mistyped one
uploads successfully to somebody else's project, which is the failure
worth catching.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 331152eaecfd8c5ad732625f507cf503196216b1
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 17:12:56 2026 +0530
Move the manual to the root, drop the rest of Documentation/
UsersManual.md now sits at the repo root. Documentation/ is gone, taking
RevisionHistory.txt, which stopped at version 5.20.3, and the six JPEGs
with it.
Deleting those JPEGs would have left the manual with five dead image
links, so its screenshots are rewired to the five new PNGs under
Media/Screenshots. Each one was opened and matched to a section rather
than guessed from the filename:
01 the outfit list (was OutfitterUI.jpg)
03 the New Outfit dialog (was NewOutfit.jpg)
02 an outfit's menu new, in Automatic switching
05 the outfit bar new
04 the icon picker new
Three sections lose their screenshot with nothing to replace it: the
character sheet's robe button, the minimap menu and QuickSlots. Those
image lines are removed rather than left broken.
The new references are absolute raw.githubusercontent.com URLs, and that
is forced rather than stylistic: the manual ships to players now that it
is at the root, and Media/ deliberately does not, so a relative link would
render on GitHub and be a broken image in every player's copy. The test
that catches exactly that mistake is updated for the new location.
Also includes your README change. The slash command table is gone from the
README, which now points at `/outfitter help` and the manual instead. That
retires the README as a command surface, so the tests that read its table
are rewritten against the manual: dispatch, in-game help and the manual
are the three surfaces checked against each other now. A new case fails if
a command table ever reappears in the README, since that would be a fourth
surface nothing watches.
One typo fixed in the line you added: "avaulable" to "available".
Package is 79 files, 3.35 MB, down from 86 and 3.70 MB.
Suite 143 passed / 0 failed; luacheck 0/0 over 43 files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit f88302de3f696cd6e1b78728d9d98985d76d70b0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 16:57:17 2026 +0530
Dummy commit to push to Curseforge
Carries no changes. It exists only as something to hang a release tag on,
so the CurseForge packager has a commit to build 1.0.0 from without that
tag landing on a commit that meant something else.
The tree is identical to 696e7a7. Everything 1.0.0 ships is already in the
history above this.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 696e7a77a4d734dcc66a3709fa662d16c433cb61
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 16:48:06 2026 +0530
Add project screenshots, kept out of the addon zip
Five PNGs under Media/Screenshots for the project listing and the
GitHub-rendered docs.
No .pkgmeta change was needed to exclude them: Media/ has been on the
ignore list since the logo went in, so anything added under it is already
out of the download. The comment there was stale about what Media/ holds
and how big it is, and now says so, along with the constraint below.
That constraint is the trap worth guarding. Documentation/ ships and
Media/ does not, so a relative image link from the user manual into
Media/ renders perfectly on GitHub and is a broken image for every player
who opens the shipped copy -- invisible to whoever writes it. A new test
walks the manual's relative links and fails if any resolves into a path
.pkgmeta excludes. Absolute URLs are deliberately not checked; those
resolve from the web wherever the manual is read.
Package is 86 files, 3.7 MB shipped against 9.9 MB kept back.
Suite 143 passed / 0 failed; luacheck 0/0 over 43 files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit ba68232c93ca22d13ce9f779147886b470300c5a
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 16:47:55 2026 +0530
Drop the version from the About heading
The yellow heading read "About Outfitter Reborn 1.0.0" directly under a
title bar already reading "Outfitter Reborn 1.0.0". It now reads "About
Outfitter Reborn"; the title bar keeps the version.
Two edits rather than one, because the version came from a format
specifier and not from the string: cAboutTitle loses its %s, and
OutfitterAbout.lua stops calling :format on it. Leaving the :format would
have worked -- Lua ignores a surplus argument when there is no specifier
-- but it would read as though a version were still being inserted.
Only English ever had that %s. All six locale files already defined
cAboutTitle without one, so the version was showing in the About heading
for English players and nobody else; this makes English match the rest
rather than making it the exception.
Also includes your README tidy: the "fuller guide" line is redundant now
that the Usage section links the manual, and the retired-features intro is
shorter.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit b2a8d4989064ee5ef07bfa1ba3de93a709681eec
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 13:57:09 2026 +0530
Fit the tab, line up the headers, and point the README at the manual
The outfit tab is back to "Outfitter". "Outfitter Reborn" overflows it, so
the tab is the one surface that keeps the short name -- reverted in the
five locales that override it as well, with a comment saying why so it is
not "fixed" back later.
The window's two headers never lined up with each other, and each was
right by its own rule. The title bar was anchored at x = -10, nudged left
to look centred in the space beside the close button; the yellow panel
heading below it centres on the frame. Ten pixels apart reads as sloppy
without being visibly wrong. Both centre on the frame now, and the reason
for the old offset is recorded in the XML rather than lost.
The white title bar text was left in place rather than removed. It is
window chrome shown on all three tabs and the only place the version
appears outside the About panel, so deleting it would leave Options and
About with no title at all. The duplication is specific to the Outfitter
tab, where the panel heading repeats the window title; that heading is the
removable one if it still reads as redundant in game.
README: Installing is replaced by Usage, a short paragraph on the actual
flow that hands off to the user manual on GitHub. Nothing is lost -- the
restart-fully warning, which is this addon's most common support issue,
has a fuller home in Documentation/UsersManual.md.
Version history highlights are now one bullet per line. Markdown will not
render a list inside a table cell, so the literal "- " before each <br>
item is the fix rather than a workaround; without it an eight-item release
row renders as a single justified paragraph.
Suite 142 passed / 0 failed; luacheck 0/0 over 43 files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit d61412968a6dff753c9a1ab9af85536a34416838
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 13:09:09 2026 +0530
Outfitter Reborn 1.0.0, for Midnight 12.1
Renames the addon in the UI, retargets it at 12.1, and replaces the user
manual, which described an addon that has not existed for years.
The rename is display only. cTitle is now "Outfitter Reborn" and every
window follows it, including all six locale files -- each of them overrode
the name, so without that non-English players would still see the old one.
Russian keeps its own word for the tab, which is a translation of the
concept rather than the product name.
cTitle was doing two jobs: the visible label AND the LibDataBroker object
key. Broker displays store their per-object settings against that key, so
renaming it would silently reset everyone's broker configuration. The
identity is now cBrokerName, which stays "Outfitter" permanently, and
three tests pin the split.
Nothing else about the addon's identity moves: the folder, Outfitter.toc,
gOutfitter_Settings and gOutfitter_GlobalSettings are all untouched, and a
test asserts the saved-variable names specifically -- renaming either one
throws away every existing user's outfits.
## Title does change, because it is the only source for the addon shelf
and the in-game AddOns list.
Version is 1.0.0 and Interface is 120100. Both are deliberate and both
have a consequence worth recording: 1.0.0 is LOWER than the 12.1.0.3 it
replaces, so updaters may not offer it to anyone already on that build,
and dropping 120007 means 12.0.7 clients will flag it out of date.
The About panel now credits both authors, and the TOC author line lists
them. The README gains a version history table in the format the sibling
addons use.
Documentation/UsersManual.html is replaced by UsersManual.md, rewritten
rather than converted. The old one named categories that no longer exist
(Complete Wardrobes, Mix-n-match, Special Occasions, against today's
Complete outfits and Accessories), used NO_ event prefixes where the addon
uses NOT_, and documented warrior stances, hunter aspects, priest
Shadowform and druid Aquatic Form, none of which the game still has. It
now covers the slot checkboxes, which it never mentioned at all, the
battleground and arena detection, the full command list and a current
scripting reference. The five existing screenshots are reused with a note
that they predate the rename.
Two more tests keep it honest: its command table must match the README's,
and every screenshot it references must exist.
Suite 142 passed / 0 failed; luacheck 0/0 over 43 files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 1539cc11aaacfc8d1a9acb438e30594adde5950d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 12:47:46 2026 +0530
Rewrite the README in plainer prose
Two edits in one: the "Working on it" section is gone, and the rest reads
less like it was generated.
The section described the test harness, which is maintainer detail in a
file aimed at players. It was also the only player-facing statement that
tests/ and Media/ do not ship; that fact now lives in CLAUDE.md and is
enforced by the packaging tests rather than asserted in prose.
The prose changes are mechanical tells, mostly mine. Thirteen em dashes
down to zero, every one of them doing a comma's or a colon's job. The
eight feature bullets were all the same `**Bold** - restatement` shape,
which is scaffolding rather than emphasis once it repeats that many times;
they are four paragraphs now, ending on a short sentence where the
interesting part runs out. The install warning was reordered so the
reassurance lands after the symptoms instead of before them, and the
credits have subjects again rather than "kept alive since by the
community".
No first person was added. This file speaks for the project, and inventing
a voice for it would be its own kind of wrong.
Command table untouched: tests/test_commands.lua reads it as a third
surface, and the suite stays at 133 passed / 0 failed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 300288adcab01108fc34d6876805a486ee253bed
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 12:22:40 2026 +0530
Close out the review: remaining findings, and regression tests
The last four findings, plus tests for every bug the earlier commit fixed.
A fix without a test is a patch, and this review's lesson was precisely
that a green suite can be worth less than it looks.
F-015: the Deprecated.lua header claimed nothing in the file touches the
live Outfitter tables. That is false and deliberately so -- preserved
bodies open `local self = Outfitter` and call live methods, because a body
with its calls rewritten is no longer the thing that was retired and could
not be revived by pasting it back. The header now says what is actually
true: nothing live calls IN, and the only names added to the live table are
Deprecated and DeprecatedFeature. Two case names that claimed more than
they checked were renamed to match.
F-021: the README documented 17 commands; the in-game help documents 21.
The four missing ones are added, the combined disable/enable row is split,
and test_commands.lua now treats the README as a third surface -- it
already checked dispatch against help in both directions, but nothing read
the README, which is how it drifted.
F-022: run-all.sh wrote the BOM-stripped copy to a fixed /tmp path that two
concurrent runs would collide on, now mktemp with a trap. run.lua listed
files with `find`, which swept untracked scratch .lua files into the
discipline checks and broke on a repo path containing a quote; now
`git ls-files`.
F-023: one DeprecatedFeature label was a feature description and another a
method name, formatted into the same sentence.
One more bug, found by the new tests rather than by the review: PlayerIsFull
had a THIRD fallback branch going the wrong way. An unreadable power type
defaulted to -1, took the `~= 0` path and reported the player full -- for
exactly the reason it could not tell. Same direction as the other two now.
New regression cases, each verified to fail against the original bug:
- the removal walk-back, driven through the real outfit stack because
RemoveOutfit returns early otherwise
- all five securable APIs, asserting none of them ever reports "full"
- PreviousManaLevel surviving a secret window
- the equipment update count: balanced pairs, an unmatched End clamping at
zero, a stranded count clearing, and the reset staying quiet when clean
Suite 133 passed / 0 failed across 23 suites; luacheck 0/0 over 43 files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 430a582a9d48eae457fda8ce0b5a276c5278eba0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 12:19:04 2026 +0530
Fix the review's correctness findings, and make three tests falsifiable
Addon bugs (F-004, F-010, F-011, F-012, F-019, and one found while fixing
them):
- RemoveOutfit's fallback walk-back used `#t` as a truth test in two
places, which is always true in Lua. The break fired after one iteration,
so the walk back through the recent-complete history has never run:
removing a Complete outfit whose predecessor was renamed or deleted left
the player wearing nothing. Now `> 0` and `== 0`.
- The same mistake at :3205 counted a BoEs header row that was not there,
overshooting the item list scroll by one. The correct spelling was eight
lines above it.
- PlayerIsFull returned true when power was unreadable, reporting the
player full and taking the dining outfit off mid-meal -- the opposite of
what its own comment says it does.
- A secret power reading wiped PreviousManaLevel, so the next real sample
read as a mana drop and could cancel the Spirit outfit with no drop.
- CheckDatabase asserted two contradictory invariants about Settings.Outfits
twelve lines apart. Outfits is now created in InitializeSettings and the
guards are gone; the two unguarded vOutfit.Items loops are guarded to
match the third, which is what a pre-6.2 saved-variable file needs to
avoid raising inside Initialize.
- An item link read at :4055 went straight into a truthiness test without
the OutfitterAPI seam -- exactly the inspection Compat.lua warns about.
Found by the rewritten discipline check below.
UpdateZone (F-003) gated on GetZoneText(), the localized name the map-ID
rebuild disowned, while everything below it is map-ID driven. Ashran and
Battle for Wintergrasp each name both an outdoor zone and a battleground
instance, and for those the refresh was skipped entirely. It now compares
instance type and map ID.
EquipmentUpdateCount (F-009) is bracketed manually at seventeen sites and
an error between Begin and End stopped equipment updates for the session,
recoverable only by /reload with nothing saying why. End now refuses to go
negative and reports an unmatched call, PlayerEnteringWorld clears a
stranded count, and /outfitter zone reports one. Deliberately NOT pcall
around the regions: that trades a visible stuck state for a swallowed error.
Three tests that could not fail (F-001, F-002, F-008):
- The preset-event whitelist carried an `^[A-Z_]+$` escape hatch that
swallowed every realistically-named event. It now checks against
tests/client_events.lua -- 1523 event names extracted from Blizzard's
published UI source rather than typed -- plus BuiltinEvents and the
addon's own outfit events. Verified by re-running the reviewer's
mutation: BOGUS_EVENT_XYZ on a live preset now fails the suite.
- run.lua recorded Ctx.initOK and no suite read it. Asserting it
immediately exposed that Initialize() had been raising the whole time on
a missing debugstack global -- so initialization was never actually
exercised. Fixed in the mock; two cases now pin both that it completes
and that it produced the state the addon assumes.
- The secret-discipline check looked for a call next to a comparison, which
is not how this codebase reads a value. It now checks the binding, with
a short lookahead for the bind-then-unsecret idiom, and carries a case
that exercises the matcher itself.
Mock fidelity (F-005, F-006, F-007, F-013): the SECRET sentinel now raises
on arithmetic, comparison, concatenation, tostring, indexing and calls
rather than only answering issecretvalue; RegisterEvent rejects events the
client does not have; item links, aura data and UnitStat can be made
secret; bit.band/bor/bxor actually mask instead of returning their first
argument. One gap is documented rather than papered over: Lua 5.1 has no
metamethod for a truthiness test, so Compat.lua's warning that even `if v`
is an inspection cannot be enforced outside a client.
F-016's locale check was filtered by a name-suffix allow-list and an escape
that passed anything already on the Outfitter table. Both are gone; the
data tables that share the `c` prefix are named explicitly.
Dead code (F-017, F-018, F-020): the orphaned VOID_DEPOSIT_MAX and a
duplicated repair block removed, InBattlegroundZone's eight-local
destructure cut to the one it reads, and two unreferenced textures dropped
from the zip via .pkgmeta. InZoneType is kept rather than retired: it has
no caller here but it is a method on the global table that a user script
can call, and retiring working API is not the same as removing dead code.
Suite 120 passed / 0 failed; luacheck 0/0 over 43 files.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit ac072fe3fc1c21fb7edfe21e867e5dea7bd909ee
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 12:06:34 2026 +0530
Record the 2026-09-16 review, and keep it out of the zip
The frozen bundle from wow-addon:review: findings, proposed changes, smoke
tests, execution plan and summary. Nothing in it is applied -- it is
evidence of what was believed on the day, and the proposals are the
reviewer's, not decisions.
Verdict was minor issues, 0 critical. The four High findings are worth
naming here because three of them are about this repo's own test harness
rather than the addon:
- The preset-event whitelist in tests/test_scripts.lua cannot fail; its
^[A-Z_]+$ escape hatch swallows every realistically-named event. Proven
by mutation, not by reading.
- tests/run.lua computes Ctx.initOK and Ctx.initError and no suite reads
them, so a raising Initialize() still passes.
- Outfitter:UpdateZone still gates on GetZoneText(), the localized name
the map-ID rebuild disowned. The zone tests cover GetCurrentZoneIDs and
never the function the client calls.
- Three bare `#t` truth tests in Outfitter.lua, which are always true in
Lua. The one at :3468 breaks RemoveOutfit's walk-back after a single
iteration, so it has never run. Verified independently before recording:
the correct `#vWarboundItems > 0` sits eight lines above the broken
`#vBoEItems` at :3205.
.pkgmeta now excludes docs/, so review, audit and test bundles stay out of
the player download. Documentation/ is NOT excluded -- that is the user
manual and it ships; the two directory names are one letter apart, which
is why the packaging test now names both.
That test also gained the half it was missing. It asserted only that three
entries ARE ignored and never the converse, so an ignore entry that should
not be there was invisible to it. It now checks both directions.
Suite at 117 passed, 0 failed; luacheck 0/0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 8ff8a26493d290b2ef76040e6383bb40d36faea9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 11:32:01 2026 +0530
Add a TGA logo and keep the artwork out of the addon zip
outfitter.logo.tga is converted from the PNG at its native 1264x1264,
32-bit uncompressed (TGA image type 2) with an opaque alpha channel added,
since the source is RGB.
None of the three logo files is referenced by any shipped file -- they are
project artwork rather than in-game textures -- so .pkgmeta now keeps the
whole Media/ directory out of the package, along with tests/, .luacheckrc
and CLAUDE.md. That is 8.6 MB of the repository that no longer lands in a
player's AddOns folder; the zip goes from 12.3 MB to 3.7 MB, most of the
saving being the TGA.
Four tests cover the manifest: that Media, tests and .luacheckrc are
ignored, that package-as names the addon, that the TOC never loads a file
.pkgmeta excludes (which would ship a half-loading addon), and that no
shipped file references Media/ -- if one ever does, excluding it would
break the addon rather than slim it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit 14eb27a56fae9aded341f88832527db4e1b71b7d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 11:31:50 2026 +0530
Add an automated test harness, and fix what it found
Three suites behind tests/run-all.sh: luac -p over every file, luacheck,
and a headless Lua suite of 116 cases. All green.
The harness is Outfitter's own -- framework, WoW mock, loader and suites.
It does not vendor the Ka0s testkit, which CLAUDE.md rules out. The mock
loads the entire TOC and builds hollow frames from the names in
Outfitter.xml, resolving $parent the way the client's parser does, so a
file that stops loading is a test failure rather than a surprise in
someone's client. Nothing rendered is covered; that needs a client.
Defects the harness found, all fixed here:
- The Spirit Regen preset never compiled. GenerateSmartUnequipScript
emitted "delay = 0.5" with no trailing newline, so it ran into the
next line as "0.5end". Every preset passing an unequip delay was
affected; Spirit Regen was the only one.
- The Resting preset declared CATEGORY rather than Category. The reader
falls back with `Category or Class or "GENERAL"`, so it had been filed
under General instead of Trade, silently. A new test rejects any preset
field name that is not one of the five known ones.
- OutfitterLDB.lua created a global `items` every time the LDB menu
opened, for want of a `local`.
- OutfitterBar.lua assigned to two undeclared globals in dead statements.
- OutfitterInventory.lua computed `local location` twice in one function
and discarded the second.
- The zone rebuild renamed three battleground description keys in English
but left the translations behind in all six locale files.
Also found and pinned rather than fixed, because the code is retired and
inert: the CHAMPFACTION preset was never valid Lua. Its condition closes
with "))) then" against an `if` that opened no parentheses, so activating
it always raised "Couldn't activate script" -- a defect that predates the
removed API it was retired for.
Libraries/MC2DebugLib/MC2DebugLib.lua ships a UTF-8 BOM. The client
accepts it; luac and Lua 5.1 reject the file outright, so the by-hand
`luac -p` loop quoted throughout this project was silently skipping it.
The loader strips it and a test pins the BOM file list.
luacheck goes from 1601 warnings to 0. Every real finding was fixed at
source; 587 whitespace-only lines and five trailing-whitespace lines were
stripped; the rest are house conventions of a 2006-era codebase, listed
in .luacheckrc by code with the reason rather than a blanket ignore.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit e887c74c724ac79b4655be5248ce05c18dbf0ec6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 10:59:16 2026 +0530
Rebuild zone detection on instance map IDs
GetCurrentZoneIDs matched localized zone names through GetMapNameByID.
That API is gone, so cZoneSpecialIDMap was commented out years ago and
every zone-triggered outfit silently stopped firing.
It now reads GetInstanceInfo: instanceType gives the generic Battleground
and Arena outfits, so a map added tomorrow still equips them, and the
instance map ID adds whatever is specific to that map. No localized string
is on the path any more, which is what rotted the old version.
cInstanceMapIDZoneIDs covers all 44 battleground and arena map IDs, taken
from Map.db2 rows with InstanceType 3 and 4 rather than from memory, and
verified against it: every ID exists and is the right type, and no BG or
arena in the game is missing. It has to carry the duplicates Blizzard
created by re-issuing maps -- Arathi Basin is four IDs, Warsong Gulch,
Eye of the Storm, Deepwind Gorge, Blade's Edge and Nagrand two each.
The addon's zone tables had also drifted apart before any of this broke.
Wintergrasp, Sewers, Gilneas and TwinPeaks had presets but no entry in
cZoneSpecialIDs, so they could never have fired; BladesEdgeArena,
NagrandArena and LordaeronArena were listed but had no preset. Both lists
are now reconciled and RingOfValor is dropped, its arena no longer being
in Map.db2 at all.
Adds outfits for the maps Outfitter never covered: Silvershard Mines,
Temple of Kotmogu, Deepwind Gorge, Seething Shore, Deephaul Ravine,
Ashran, and the twelve current arenas. Brawl maps get a map ID so they
equip the generic Battleground outfit, but no outfit of their own.
/outfitter zone reports instance type, map ID and matched zone outfits, so
a map that does not trigger can be reported as a number.
City and ArgentDawn stay retired: both are outdoor triggers needing a
uiMapID list that would go stale every expansion.
Verified with luac -p and a four-way consistency check over
cZoneSpecialIDs, cSpecialIDEvents, BuiltinEvents, PresetScripts and the
map table -- the exact drift described above. Not tested in-client.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit d976df268cef53efa36e84ce966b7b493181ecb7
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 10:46:46 2026 +0530
Add CLAUDE.md flagging this as non-Ka0s
Outfitter sits alongside the Ka0s addons but is third-party MIT code forked
from mundocani's original. The note states it must never join the Ka0s
roster or audit rotation, that the Ka0s WoW Addon Standard does not govern
it, and that LibKa0s must never be vendored in.
Also records what a sweep would otherwise have to rediscover: the mixed
per-file line endings, the secret-value seam in Compat.lua and the stuck
EquipmentUpdateCount it causes on error, live preset-script resolution, the
slot-checkbox strata requirement, and that luac -p is the only verification
available.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
commit d396f113b1e56e5d7ca76caf99d7c17749f0cbb7
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date: Wed Sep 16 10:43:34 2026 +0530
Outfitter 12.1.0.3 for retail (Midnight)
Community fork of Outfitter by John Stephen (mundocani), MIT licensed.
Original addon: https://www.curseforge.com/wow/addons/outfitter
Includes fixes for two reported problems on WoW 12.x:
- The per-slot checkboxes on the character sheet were invisible.
OutfitterSlotEnables inherits PaperDollFrame's strata, so another addon
drawing over the character panel buried them. It is now raised to DIALOG
in SelectOutfit, not OnLoad, where the frame does not exist yet.
- PlayerIsFull compared UnitHealth directly, which errors once the client
returns those as secret values. That abort also left EquipmentUpdateCount
stuck above zero, which stopped equipment updates firing. Health, power
and power type now go through OutfitterAPI:UnsecretNumber, as does the
mana read in UnitHealthOrManaChanged and the item level checks in
OutfitterItemStats.
Adds Deprecated.lua, an isolated layer holding functionality the game
removed. Each retired feature keeps its entry point, which now no-ops via
Outfitter:DeprecatedFeature; the original code is kept verbatim and
detached. Retired: void storage transfer, TankPoints, gem capture, the
spellbook icon set, banked item tooltips, CallCompanionByName, the legacy
flyout location fallback, the zone-to-outfit map, the HAS_DEBUFF,
LOW_HEALTH and Championing preset scripts, the Aspect of the Hawk spell
IDs, and 46 locale strings for mechanics that no longer exist.
Also fixes WithdrawOutfitFromVoidStorage, which was called from the outfit
menu but never defined, and TEXT(REPAIR_COST), where only the removed TEXT
wrapper was at fault.
README rewritten with credit to the original author and full slash command
and deprecation documentation.
Verified with luac -p across every file; not yet tested in-client.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011r9dNiGmVBLVbHQJCrjzbA
This mod has no additional files

