diff --git a/README.md b/README.md index a5bf719..761ff47 100644 --- a/README.md +++ b/README.md @@ -64,18 +64,49 @@ The default quotas of all the auction houses for non trade goods items are: The sum of the percentage for these categories must always be 100, or otherwise the defaults values will be used and the modifications will not be accepted. -## Per-item listing count override (optional) - -The `mod_auctionhousebot_countOverride` table (`item`, `targetCount`) lets the bot list a -per-item quantity that mirrors a real economy instead of the uniform `DuplicatesCount`. -When an item has a row, `targetCount` is used as the maximum number of that item the bot -lists, **replacing** the global `DuplicatesCount` for that item. - -Note: because the override replaces `DuplicatesCount` for that item, an override applies -even when `DuplicatesCount` is `0` (globally "unlimited") - overridden items are then capped -at their `targetCount`. Items with no row keep the global behaviour, and an empty/absent -table is a no-op. The shipped data is derived from ChromieCraft auction liquidity -(`targetCount = min(observed_listings, 50)`). +## Merkerhood customizations + +This fork adds four behaviours on top of the stock buyer/seller bot, so the auction +house reads like a real ChromieCraft economy instead of quality-multiplier defaults. +Design detail lives in `docs/superpowers/specs/`; the Python tooling that generates the +data tables is in `tools/price-backfill/` (stdlib only, no dependencies). + +### ChromieCraft base prices + +`mod_auctionhousebot_priceOverride` (`item`, `avgPrice`, `minPrice`) is the base-price +source. The bot prioritises listing items that have an override and falls back to the +fixed defaults otherwise. The table is generated by `tools/price-backfill/backfill.py` +from ChromieCraft's live auction data, scraped from wowauctions.net's JSON endpoint keyed +by item id. Price changes that swing far from the previous overrides land in a +`reports/deviations-*.csv` worklist for manual review. See the tool README to regenerate. + +### Reagent-cost derivation + +Craftable items that never traded on ChromieCraft (so have no market price) get a price +derived from their reagents. `tools/price-backfill/derive.py` parses the recipe graph from +`Spell.dbc` (committed as `recipes.json`), prices each item recursively from its reagents' +ChromieCraft prices, falls back to vendor sell price where a reagent is unpriced, and +applies a crafting margin. Derived rows are merged (add-only) into the same priceOverride +table. + +### Per-item listing count override + +`mod_auctionhousebot_countOverride` (`item`, `targetCount`) lets the bot list a per-item +quantity that mirrors real liquidity instead of the uniform `DuplicatesCount`. When an item +has a row, `targetCount` is the maximum of that item the bot lists, **replacing** the global +`DuplicatesCount` for it (so an override applies even when `DuplicatesCount` is `0`, +"unlimited"). The cap is per auction house. Items with no row keep the global behaviour, and +an empty/absent table is a no-op. The shipped data is +`targetCount = min(observed ChromieCraft listings, 50)`. + +### Reasonable stack sizes + +Glyphs, recipes, quest items, containers, keys, and cut gems (socketable, +`GemProperties != 0`) always list as quantity 1, regardless of the item's stackable value. +Other stackables use weighted human breakpoints `{1, 5, 10, 20, full}` clamped to the +per-quality maximum, never a random 7 or 13. This is the default when +`AuctionHouseBot.DivisibleStacks = 0`; setting it to `1` keeps the older divisible-multiples +mode. ## Credits