mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-09-22 15:46:59 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 51d4c785fa | |||
| 680ddcba8a | |||
| 8d80d0663c | |||
| 8479607a13 | |||
| 23bb69d094 | |||
| b2060e0aab | |||
| 609a6bdd83 | |||
| c0c2c275eb | |||
| ab34946775 | |||
| d41703949d |
@@ -9,3 +9,7 @@
|
|||||||
tools/
|
tools/
|
||||||
LOC*.md
|
LOC*.md
|
||||||
LOCALIZATION*.md
|
LOCALIZATION*.md
|
||||||
|
|
||||||
|
# Dev tooling — Python generators, data processing scripts, scratch files
|
||||||
|
# Not part of the addon, never ship this
|
||||||
|
.tools/
|
||||||
|
|||||||
@@ -118,4 +118,9 @@
|
|||||||
<Binding name="ZPet 6" header="ZPetHeader">
|
<Binding name="ZPet 6" header="ZPetHeader">
|
||||||
zButtonPet_KeyBinding(6)
|
zButtonPet_KeyBinding(6)
|
||||||
</Binding>
|
</Binding>
|
||||||
|
|
||||||
|
<!-- ExpAmmo Action Button -->
|
||||||
|
<Binding name="ExpAmmo Action" header="ExpAmmoHeader">
|
||||||
|
MTH_EA_CastActionSpell();
|
||||||
|
</Binding>
|
||||||
</Ui>
|
</Ui>
|
||||||
+188
@@ -2,6 +2,194 @@
|
|||||||
|
|
||||||
All notable changes to MetaHunt will be documented in this file.
|
All notable changes to MetaHunt will be documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
## [1.5.0] - 2026-03-31
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Beast spawn coordinates — custom-zone remap**: Reworked 63 beast coordinate sets in the datastore. The largest changes move placeholder vanilla-zone coords onto the proper Turtle WoW custom zones for **Grim Reaches**, **Northwind**, and **Balor**, and clean up prairie beasts that were incorrectly spilling into **Thunder Bluff**.
|
||||||
|
|
||||||
|
- **Beast spawn coordinates — Stonetalon recalibration**: Recalibrated several **Stonetalon Mountains** beast spawn clusters to match the Twow updated zone bounds and improve marker placement consistency.
|
||||||
|
|
||||||
|
- **MM Widget — ClickThrough **: The whole widget is now clickable through, and ALT-drag to reposition it is thus no longer possible
|
||||||
|
|
||||||
|
- **MM Widget — clearer bottom-cell display**: The bottom cell now shows the cooldown of the current shot you would use, and only shows `USE` when that shot is ready.
|
||||||
|
|
||||||
|
- **Feed-O-Matic — NO-BUFF quarantine disabled**: The mechanism that permanently blacklisted a food item per pet family after a failed feed (no buff detected within 2.5 s) has been disabled. Foods are no longer quarantined on a no-buff timeout — the feed will simply retry without banning the item. This avoids false positives caused by server lag or client timeouts.
|
||||||
|
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **zCraft — new zButton for crafting professions**: A new `zCraft` button (Options → zButtons → zCraft) scans your spellbook and shows a child button for each crafting profession you know — Alchemy, Blacksmithing, Cooking, Disenchanting, Enchanting, Engineering, Fishing, First Aid, Herbalism, Jewelcrafting, Leatherworking, Mining (Smelting), Skinning, Survival, and Tailoring. Clicking a child opens the corresponding tradeskill window. Disabled by default.
|
||||||
|
|
||||||
|
- **zBar — unified draggable toolbar for all zButtons**: A new "zBar" tab (Options → zButtons → zBar) groups all enabled zButton bars into a single draggable anchor. Alt-drag the zBar to move the whole group together. Options: Horizontal or Vertical layout; which side children pop out (Up/Down for horizontal, Left/Right for vertical); spacing between buttons; anchor icon size; per-bar include/exclude toggle and drag-to-reorder. Disabled by default — existing layouts are untouched until you enable it.
|
||||||
|
|
||||||
|
- **zAspect / zTrack — Smart Parent**: A new "Smart Parent" checkbox in Options → zButtons → zAspect and zTrack. When enabled, the parent button automatically toggles between your 1st and 2nd spell: if the 1st is active, the parent shows the 2nd, and vice-versa. Perfect for PvP — put Track Hidden and Track Humanoids as your first two tracking spells, and the parent always shows the one you're *not* currently using. When disabled, the parent always shows the 1st spell. Enabled by default.
|
||||||
|
|
||||||
|
- **zPet — Smart Parent**: A new "Smart Parent" checkbox in Options → zButtons → zPet. When enabled, the parent button dynamically changes based on your pet's state: Revive Pet if dead, Mend Pet if hurt, Feed Pet if unhappy, or your default spell otherwise. When disabled, the parent always shows the 1st spell. Enabled by default.
|
||||||
|
|
||||||
|
- **zMounts / zCompanions — Random Parent**: A new "Random Parent" checkbox in Options → zButtons → zMounts and zCompanions. When enabled, a random child mount is picked as the parent icon on each login and after each use. Disabled by default.
|
||||||
|
|
||||||
|
- **zMounts — AQ Mount Filter**: A new "AQ Mount Filter" checkbox in Options → zButtons → zMounts. When enabled, Qiraji mounts are hidden outside AQ40, and only Qiraji mounts are shown inside AQ40. Enabled by default.
|
||||||
|
|
||||||
|
- **zAspect — NamPower support**: The Aspect button now listens to `NamPower` aura events when available, so aspect changes update faster and without the old polling delay.
|
||||||
|
|
||||||
|
- **MM Widget — NamPower support**: The widget now uses `NamPower` aura updates when available, which makes ammo proc tracking faster and more reliable. It still falls back to the old tracking method if NamPower is not installed.
|
||||||
|
|
||||||
|
- **MM Widget — keybind **: The MM Widget options panel now has a "Set Key" button. Press any key (with optional ALT/CTRL/SHIFT modifiers), or mouse button/wheel to bind the MM Widget action, turning it into a One-button rotation feature.
|
||||||
|
|
||||||
|
- **MM Widget — Quiver no-clip option**: New "Use Quiver no-clip casting" checkbox in the MM Widget options. When enabled and Quiver is installed, Aimed Shot, Steady Shot, and Multi-Shot of the Action bind are routed through Quiver's no-clip system to avoid clipping your auto-shot swing timer.
|
||||||
|
|
||||||
|
- **MM Widget — Anchor **: Since the widget is now clickable-through, a new anchor system was implemented to move the widget: toggling the anchor button in the options shows 4 drag handles (top, bottom, left, right) outside the widget edge. Any handle can be dragged to reposition the widget.
|
||||||
|
|
||||||
|
- **Hunter Book — Families stats modifiers**: The Families page now also shows `Health`, `Damage`, and `Armor` modifiers for every family. Those modifier values can be shown as raw multipliers or as `%` with a footer checkbox, and are color-coded for easier reading. Additionaly the footer recap now also shows the total number of families, and the Named/Coord counts are plugged on the new accurate server's data instead of old pfQuest data.
|
||||||
|
|
||||||
|
- **FOM — keybind**: The Feed-O-Matic "Set Key" button in options now also accepts modifiers and mouse.
|
||||||
|
|
||||||
|
- **/mth food command**: Added a new slash command to inspect Feed-O-Matic state, clear one item ban, or reset all food bans and quarantines.
|
||||||
|
|
||||||
|
- **AntiDaze — NamPower support**: Daze detection now uses NamPower's aura events when available, replacing chat-message parsing for faster and more reliable aspect cancellation.
|
||||||
|
|
||||||
|
- **Chronometer — NamPower support**: Timer bars now start and stop instantly via NamPower aura events when available. Bar durations are read directly from the NamPower aura array instead of guessed from spell data.
|
||||||
|
|
||||||
|
- **Feed-O-Matic — NamPower support**: Mount and buff detection (Shadowmeld, Feign Death, eating, etc.) now uses the NamPower aura array when available, replacing the old tooltip-scraping method.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Pet lifecycle — duplicate / ghost pets in Stable**: Reworked pet identity with GUID-based matching and fixed stable tracking so the same pet is no longer split into multiple rows after tame, rename, stable swap, or `/reload`. Old stale pets should also stop reappearing in the Stable tab as fake active/stabled entries.
|
||||||
|
|
||||||
|
- **Pet lifecycle — wrong taming info shown on old pets**: Fixed several cases where MetaHunt could invent tame data for pets that were only seen later through stable swaps or normal pet refreshes. Taming info is now only recorded from a real tame event, so old pets should no longer show fake tame location / tame date data.
|
||||||
|
|
||||||
|
- **Hunter Book — Stable tab now trusts real stable slots**: The Stable tab now shows the current pet plus the pets that are actually in your stable slots, instead of trusting stale saved slot data from older sessions.
|
||||||
|
|
||||||
|
- **Hunter Book — pet training kept on the correct pet**: Fixed cases where a pet could keep its row but lose its Training section after lifecycle repairs or row merges. Training/spellbook data now stays attached to the right pet.
|
||||||
|
|
||||||
|
- **Hunter Book — stable feed item icons**: Fixed broken food icons in the Stable tab feed summary, including cases where foods like `Roasted Quail` were showing as a red square or question mark.
|
||||||
|
|
||||||
|
- **Minimap markers moving with the player since 1.4.0**: Reworked minimap marker zone resolution and calibration so pins stay anchored to world locations again instead of sliding with player movement. The minimap path now uses exact current-zone lookup in pfQuest space, while the world map keeps the WMA-aware logic introduced for 1.18.1 zone support.
|
||||||
|
|
||||||
|
- **Chronometer — "Grow bars upward" forgotten after `/reload`**: Checking the "Grow bars upward" option and reloading the UI would revert the bars back to growing downward, even though the checkbox still appeared checked. Fixed.
|
||||||
|
|
||||||
|
- **Chronometer — bars appear below the anchor instead of above when "Grow bars upward" is enabled**: Even with "Grow bars upward" checked, the bars were still spawning a bit below the anchor and stacking upward from there, because of an existing issue in old `CandyBar` library. Fixed — bars now correctly start at the anchor and grow upward.
|
||||||
|
|
||||||
|
- **Chronometer — Aimed Shot tracker removed**: Chronometer no longer tracks Aimed Shot cooldowns. The MM Widget now owns that behavior, so Chronometer keeps its hunter timers focused on the remaining spell and proc bars.
|
||||||
|
|
||||||
|
- **MM Widget — Quiver no-clip covers Multi-Shot**: The Quiver no-clip option now explicitly includes Multi-Shot alongside Aimed Shot and Steady Shot.
|
||||||
|
|
||||||
|
- **MM Widget — stale NamPower proc state**: The widget now resyncs from the NamPower aura array after aura events, so it no longer keeps showing a proc after the debuff is gone.
|
||||||
|
|
||||||
|
- **Quiver no-clip macro — Steady Shot castbar not showing**: If you were using Quiver and its no-clip macro for your shots, the Quiver castbar for those shots would not appear with MetaHunt enabled. Fixed — the castbar now appears correctly when using the macro.
|
||||||
|
|
||||||
|
|
||||||
|
## [1.4.1] - 2026-03-24
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **zTrack**: added `Find Trees` in tracking spells.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Performance — MM Widget / ExpAmmo**: Replaced tooltip-based aura scanning (which triggered hidden tooltip rendering on every aura check) with direct texture/icon comparison via `UnitBuff`/`UnitDebuff`. Added a 150 ms throttle on `PLAYER_AURAS_CHANGED`, which fires 10–50+ times per second in combat. Lock and Load detection and ammo cycle recovery after `/reload` both updated to use the new zero-cost texture path.
|
||||||
|
|
||||||
|
- **Performance — event frame leaks**: Some addon features were registering WoW game events at load time and never unregistering them when the feature was disabled from the options, causing their `OnEvent` handlers to fire even with the option turned off. Fixed for: Auto-Strip (`PLAYER_REGEN_*`), Smart Ammo (`SPELLCAST_*`, `START/STOP_AUTOREPEAT_SPELL`), and some zButton frames (Pet, Mounts, Track, Trap, Toys). Events are now properly registered on enable and unregistered on disable.
|
||||||
|
|
||||||
|
- **Chronometer — trap effects from other hunters**: Trap effect bars (`Immolation Trap Effect`, `Explosive Trap Effect`, `Freezing Trap Effect`, `Frost Trap Aura`) were incorrectly appearing when another hunter's trap triggered on a mob you were also targeting. .
|
||||||
|
|
||||||
|
- **Version check broadcast interval**: Increased update notification broadcast cooldown from 10 minutes to 1 hour to reduce channel traffic now that the user base has grown.
|
||||||
|
|
||||||
|
- **Profile snapshot memory**: The auto `BuildSnapshot` (called on every `/reload` via `PLAYER_LOGOUT`) was deep-copying `feedomatic.legacy`, a large migration table mirroring `FOM_Cooking`, `FOM_QuestFood`, `FOM_AddedFoods` etc. These are runtime/operational blobs, not user configuration settings, and should never be included in a profile. Introduced `MTH_Profile_CopyModules` which skips `legacy` and `history` keys, reducing the snapshot allocation from ~1 MB to a few KB.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.4.0] - 2026-03-23
|
||||||
|
|
||||||
|
### TWoW 1.18.1 "Nightmares of Ursol" support
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Complete beast database overhaul**: The MTH beast datastore was reconstructed from scratch, based on a full (beasts) 1.18.1 extract from live DB, gladly provided by Twow staff (thanks @Haaxor!). The beast data should now be 100% accurate, and notably all spawn coordinates, respawn times and pet abilities learnable on all beasts in the world.
|
||||||
|
|
||||||
|
- The **Beast Lore** page of the Book now allows to filter the list by Zone. Additionally, the beast inspector has been reformatted and all meaningful beast's data is displayed nicely.
|
||||||
|
|
||||||
|
- All new and missing **Beasts Models** have been (re)scanned from MPQ game files and are viewable in the Beast Lore page, and browsable in the Family Model viewer.
|
||||||
|
|
||||||
|
- Added **MM widget** module: tracks the new 3-state of Experimental ammo cycle (Fire → Nature → Arcane), the Lock and Load procs, and has a dynamic cell that shows either Aimed Shot availability or the right shot to use following the current Experimental ammo proc if any. Lets Make MM great again.
|
||||||
|
|
||||||
|
- Added new **Moth** pet family.
|
||||||
|
|
||||||
|
- Added new **Pollen Burst** pet ability.
|
||||||
|
|
||||||
|
- Added new **Aspect of the Viper** in zAspect.
|
||||||
|
|
||||||
|
- Added new **Chronometer** timer entries for 1.18.1 spells:
|
||||||
|
- Aimed Shot cooldown tracker
|
||||||
|
- Kill Command cooldown tracker
|
||||||
|
- Lock and Load proc timer
|
||||||
|
- Scent of Blood proc timer
|
||||||
|
|
||||||
|
- Added new **Chronometer** target debuff entries for the Experimental Ammo states:
|
||||||
|
- Poisonous Ammunition: 15s armor-reduction debuff (triggered when Serpent Sting consumes the Poisonous state)
|
||||||
|
- Enchanted Ammunition: 6s magic-resist debuff (triggered when Arcane Shot consumes the Enchanted state)
|
||||||
|
|
||||||
|
- Added the **5 new craftable ammo** to the Projectiles book's page, SmartAmmo and zAmmo button:
|
||||||
|
- **Bright Wood Arrows** (Survival: Journeyman, req. 30) — 10.5 DPS
|
||||||
|
- **Shade Wood Arrows** (Survival: Expert, req. 40) — 14.5 DPS
|
||||||
|
- **Smooth Ironfeather Arrows** (Survival: Artisan, req. 50) — 17.5 DPS
|
||||||
|
- **Starfeather Arrows** (Survival: Artisan, req. 55) — 19 DPS
|
||||||
|
- **Enchanted Thorium Shells** (Engineering: Artisan, req. 55) — 19 DPS
|
||||||
|
|
||||||
|
- Added new hunter-friends NPC of **Moonwhisper Coast** to the NPC Finder Book's page:
|
||||||
|
- **Hula Swiftmane** — Horde Stable Master (66.1, 39.1)
|
||||||
|
- **Ornala** — Horde Ammo Vendor (67.3, 37.1) — sells Arrows and Slugs
|
||||||
|
- **Badel Wildlance** — Alliance Stable Master (59.0, 24.9)
|
||||||
|
- **Elendon Truebough** — Alliance Ammo Vendor (58.8, 24.5) — sells Arrows
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed **Chronometer** bars appearing from nearby players' combat events (e.g. another hunter's traps or DoTs triggering your own bars).
|
||||||
|
- Fixed the list in Families Book's page, that wasn't tall enough to display all families (wolves were hidden).
|
||||||
|
|
||||||
|
## [1.3.0] - 2026-03-19
|
||||||
|
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added a **3D Model Viewer** to the Hunter Book Beast Lore inspector panel. Clicking a beast in the list shows its in-game model.
|
||||||
|
- Added a standalone **3D Model Viewer** that is shown when cliking the model of a beast in the Beast lore. The model is rotatable with the mouse, and you can browse all models of the same pet family and shows all other beasts that share the same skin, with one-click to jump to any of them in the Beast Lore.
|
||||||
|
- Added a **Family icon** column to the Beast Lore list, replacing the text family name with the pet family icon for a more compact view.
|
||||||
|
- Added an **Attack Speed (AS)** column to the Beast Lore list.
|
||||||
|
- Added `displayId` and `skinId` fields to **all ~1000 beasts** in the MetaHunt datastore. `displayId` was scraped from the Turtle WoW DB, and `skinId` derived from it following an extraction on MPQ game files. This is what powers the model viewer and skin-grouping.
|
||||||
|
- Added per-family icons to all 19 pet families in the family data table.
|
||||||
|
- Added missing food types (`raw meat`, `raw fish`) to all pet families that accept `meat` or `fish` respectively (sourced from MPQ data).
|
||||||
|
- Added **Profile Management** panel (Options → Profiles): save the current addon configuration as a named profile and instantly load it on any character. Profiles cover all module settings (ICU, Chronometer, AutoBuy, AutoQuest, SmartAmmo, Feed-O-Matic, zButtons layout) and per-character module enabled/disabled states.
|
||||||
|
- Added automatic per-character **config snapshots** saved on every logout (`CharName-RealmName`), visible in the "Copy from Character" section — import any character's snapshot as a loadable profile in one click.
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed the pet feeding counter never incrementing: `MTH_FEED_Trace` was a no-op stub and `FOM_CORE_ATTEMPT_TRACKING_ENABLED` was `false`; both are now active.
|
||||||
|
- Fixed `FOM_AddFood` not clearing a food from `FOM_RemovedFoods` when the item belongs to the base diet list, which permanently banned it even after an explicit `/fom add`.
|
||||||
|
- Wired `FOM_ClearItemBans` into the `/fom add` command path: explicitly re-adding a food now clears it from `FOM_RemovedFoods`, FOM quarantine, and core exceptions in one step.
|
||||||
|
- Removed debug messages forgotten when releasing 1.2.
|
||||||
|
- Fixed SmartAmmo + **Quiver castbar conflict**: Quiver's castbar was disappearing when both addons were active. Root cause: MetaHunt SmartAmmo was re-installing its hooks every 0.5 seconds, constantly bumping Quiver off the top of the hook chain. Fixed by removing the repeated re-hook and adding a guard that only installs once (or when no other addon is on top).
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.0] - 2026-03-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Added keybinding text overlay on zButtons: parent and child buttons now display their bound key for the 5 bindable sets (Aspect, Track, Trap, Ammo, Pet).
|
||||||
|
- Added "Expand on Hover" option for zButton children: when enabled, hovering over the parent button automatically expands children (instead of requiring right-click).
|
||||||
|
- Added "Auto-Hide Timer" option for zButton children: a configurable 0–10 second timer that automatically collapses expanded children after the mouse leaves the button group. Timer resets while hovering any button in the group.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed SavedVariables data loss on login caused by initialization race condition overwriting persisted data.
|
||||||
|
- Fixed SavedVariables bloat by adding a migration that strips redundant default-valued keys on first load.
|
||||||
|
- Fixed six performance issues including throttling high-frequency event handlers, caching repeated `getglobal` lookups, and reducing unnecessary table allocations in hot paths.
|
||||||
|
- Cleaned up ICU module global variable leaks by properly scoping locals.
|
||||||
|
- Standardized all remaining `SetScript` handler patterns to use the WoW 1.12 `this`-based convention consistently.
|
||||||
|
|
||||||
|
|
||||||
## [1.1.0] - 2026-03-09
|
## [1.1.0] - 2026-03-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -2,6 +2,15 @@
|
|||||||
-- MetaHunt: Hunter's Toolkit Addon
|
-- MetaHunt: Hunter's Toolkit Addon
|
||||||
-- A unified addon merging FeedOMatic, Tooltips, and zhunter
|
-- A unified addon merging FeedOMatic, Tooltips, and zhunter
|
||||||
-- Modern modular architecture with legacy addon support
|
-- Modern modular architecture with legacy addon support
|
||||||
|
--
|
||||||
|
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
-- TARGET RUNTIME: LUA 5.0 (WoW 1.12 / Turtle-WoW)
|
||||||
|
-- - Max 32 upvalues per function
|
||||||
|
-- - No # operator (use table.getn)
|
||||||
|
-- - No string.gmatch (use string.gfind)
|
||||||
|
-- - NEVER validate with Lua 5.1+ tools (false passes)
|
||||||
|
-- - Errors: check Logs/FrameXML.log first
|
||||||
|
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
-- Initialize beast database after all files loaded
|
-- Initialize beast database after all files loaded
|
||||||
|
|||||||
+6
-3
@@ -1,5 +1,5 @@
|
|||||||
## Interface: 11200
|
## Interface: 11200
|
||||||
## Version: 1.1.0
|
## Version: 1.5.0
|
||||||
## Title: MetaHunt - |cff00ff00Hunter
|
## Title: MetaHunt - |cff00ff00Hunter
|
||||||
## Author: Metasploit and his Copilot ;)
|
## Author: Metasploit and his Copilot ;)
|
||||||
## Notes: Unified addon suite for huntards making old addons compatible with TurtleWoW, and adding an arsenal of never seen Hunter's utilities.
|
## Notes: Unified addon suite for huntards making old addons compatible with TurtleWoW, and adding an arsenal of never seen Hunter's utilities.
|
||||||
@@ -20,8 +20,6 @@ init\skins.xml
|
|||||||
|
|
||||||
## Load database files (DB files must come before data\init.lua)
|
## Load database files (DB files must come before data\init.lua)
|
||||||
data\ds-beasts.lua
|
data\ds-beasts.lua
|
||||||
data\ds-beasts-extra.lua
|
|
||||||
data\ds-beasts-html-enrichment.lua
|
|
||||||
data\ds-vendors.lua
|
data\ds-vendors.lua
|
||||||
data\ds-vendors-extra.lua
|
data\ds-vendors-extra.lua
|
||||||
data\ds-items.lua
|
data\ds-items.lua
|
||||||
@@ -31,12 +29,17 @@ data\ds-bags.lua
|
|||||||
data\ds-items-atlas-sources.lua
|
data\ds-items-atlas-sources.lua
|
||||||
data\ds-zones.lua
|
data\ds-zones.lua
|
||||||
data\ds-zones-fallback.lua
|
data\ds-zones-fallback.lua
|
||||||
|
data\ds-zones-wma.lua
|
||||||
data\ds-minimap-sizes.lua
|
data\ds-minimap-sizes.lua
|
||||||
data\ds-unit-coords.lua
|
data\ds-unit-coords.lua
|
||||||
data\ds-creature-coords.lua
|
data\ds-creature-coords.lua
|
||||||
data\ds-beasts-families.lua
|
data\ds-beasts-families.lua
|
||||||
|
data\ds-beasts-families-dbc.lua
|
||||||
|
data\ds-beasts-skins.lua
|
||||||
data\ds-pet-spells.lua
|
data\ds-pet-spells.lua
|
||||||
data\ds-pet-spells-trainer.lua
|
data\ds-pet-spells-trainer.lua
|
||||||
|
data\ds-hunter-spells.lua
|
||||||
|
data\ds-hunter-spells-dbc.lua
|
||||||
data\ds-racial.lua
|
data\ds-racial.lua
|
||||||
data\init.lua
|
data\init.lua
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
# MetaHunt
|
# MetaHunt
|
||||||
|
|
||||||
MetaHunt is a Turtle WoW Hunter toolkit.
|
MetaHunt is a Turtle WoW Hunter toolkit.
|
||||||
It is a modern modular addon that combines never-seen features, and improves/fixes a few old hunter add-ons.
|
It is a modern modular addon compiling brand new features, and improving a few old hunter add-ons that were broken on Twow.
|
||||||
It provides a bunch usefull tools for all huntards, wheter they are still leveling, lone-wolf, or HL raider.
|
It provides a bunch of useful tools for all huntards, wheter they are still levelling, lone-wolf, or HL raider.
|
||||||
|
|
||||||
|
### Important notes
|
||||||
|
- Altough Nampower isn't mandatory for most of the features, it is a must-have for some.
|
||||||
|
- If you were using old versions of Feed-O-Matic, ICU, zHunterMod and HunterHelper, you dont need those with MetaHunt and you should disable them to avoid conflicts.
|
||||||
|
- MetaHunt is fully compatible with Quiver and is not a replacement for it.
|
||||||
|
|
||||||
|
|
||||||
## Twow Data
|
## Twow Data
|
||||||
|
|
||||||
Metahunt ships with larges up-to-date datastores for all Turtle WOW data a hunter needs :
|
MetaHunt ships with large Turtle WOW datastores :
|
||||||
|
|
||||||
- All beasts, their location, and the abilities they can learn you
|
- 100% accurate beasts' data, their locations, and the abilities they can learn you
|
||||||
- All Pet families, their abilities and their diet
|
- All Pet families, their abilities and their diet
|
||||||
- All pet abilities ranks
|
- All pet abilities ranks
|
||||||
- All Ammo (Arrows and Bullets)
|
- All Ammo (Arrows and Bullets)
|
||||||
@@ -21,6 +27,8 @@ Metahunt ships with larges up-to-date datastores for all Turtle WOW data a hunte
|
|||||||
- Auto equip another ammo instantly during combat whenever you get out of your current ammo.
|
- Auto equip another ammo instantly during combat whenever you get out of your current ammo.
|
||||||
- Auto equip the right ammo when you swap from a box/xbow to a gun and the other way around.
|
- Auto equip the right ammo when you swap from a box/xbow to a gun and the other way around.
|
||||||
|
|
||||||
|
## MM Widget
|
||||||
|
Lets Make MM great again. Tracks the new 3-state of Experimental ammo cycle (Fire → Nature → Arcane), the Lock&Load procs, and has a dynamic cell that shows either Aimed Shot availability or the right shot to use following the current Experimental ammo proc if any.
|
||||||
|
|
||||||
## Tooltips
|
## Tooltips
|
||||||
|
|
||||||
@@ -29,7 +37,7 @@ Metahunt ships with larges up-to-date datastores for all Turtle WOW data a hunte
|
|||||||
- Vendors : Shows if a vendor sells Arrows and/or Bullets.
|
- Vendors : Shows if a vendor sells Arrows and/or Bullets.
|
||||||
- Your pet : Shows your pet's XP, loyalty, happiness and how much you fed it this session.
|
- Your pet : Shows your pet's XP, loyalty, happiness and how much you fed it this session.
|
||||||
|
|
||||||
## zBouttons
|
## zButtons
|
||||||
|
|
||||||
Old zHunterMod addon on steroids. Fully compatible with Twow, and enhanced with new functionalities
|
Old zHunterMod addon on steroids. Fully compatible with Twow, and enhanced with new functionalities
|
||||||
|
|
||||||
@@ -37,8 +45,8 @@ Old zHunterMod addon on steroids. Fully compatible with Twow, and enhanced with
|
|||||||
- zPet : Intelligent collapsible pet Bar regrouping all pet spells and providing an intelligent button that always show you the right spell to use depending on the situation
|
- zPet : Intelligent collapsible pet Bar regrouping all pet spells and providing an intelligent button that always show you the right spell to use depending on the situation
|
||||||
- zTrack: All your trackings in one collapsible bar
|
- zTrack: All your trackings in one collapsible bar
|
||||||
- zAspect: All your trackings in one collapsible bar
|
- zAspect: All your trackings in one collapsible bar
|
||||||
- zRanged : All the rnaged weampons currently in your bags to swap them fast
|
- zRanged : All the ranged weapons currently in your bags to swap them fast
|
||||||
- But also zMounts, zToys and zCompanions.
|
- But also zBar, zCrafts, zMounts, zToys and zCompanions.
|
||||||
|
|
||||||
## Feed-O-Matic
|
## Feed-O-Matic
|
||||||
|
|
||||||
@@ -59,15 +67,19 @@ Define your own simple rules for auto buy ammo and pet food when you open a vend
|
|||||||
|
|
||||||
## Auto-Quest
|
## Auto-Quest
|
||||||
|
|
||||||
Just spam SHIFT-click on the NPC to validate quests Scorpok and Thorium arrows. Addionally you can have an enhanced tooltip that display your actual Scorpok-related items when you mouseover the mobs involved.
|
Just spam SHIFT-click on the NPC to validate quests Scorpok and Thorium arrows. Additionally you can have an enhanced tooltip that display your actual Scorpok-related items when you mouseover the mobs involved.
|
||||||
|
|
||||||
|
## Beast model Viewer
|
||||||
|
|
||||||
## The book of Hunters
|
Display the model of all beasts in the world. Always know what you are going to tame exactly before running there ! You can also browse all skin models of the same pet family to find the best-looking pet according to your tastes.
|
||||||
|
|
||||||
The book of Hunters is the main GUI of Metahunt, it allows to display the data constantly collected about you and your pet, and browse the addon's data to find anything a Hunter needs.
|
## The Great Book of Huntards
|
||||||
|
|
||||||
- Browse the Metahunt datastores of NPCs (Beast, vendors, masters) and open the map to locate them like in pfQuest
|
The Book is the main GUI of MetaHunt, it allows to display the data constantly collected about you and your pet, and browse the addon's data to find anything a Hunter needs.
|
||||||
|
|
||||||
|
- Browse the MetaHunt datastores of NPCs (Beast, vendors, masters) and open the map to locate them like in pfQuest
|
||||||
- Track all info about the pet abilities that you know and don't know yet
|
- Track all info about the pet abilities that you know and don't know yet
|
||||||
- Track all info about your stabled pets
|
- Track all info about your stabled pets
|
||||||
- Keep an history of all your pets after you abandon them or if they run away.
|
- Keep an history of all your pets after you abandon them or if they run away.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+49
-7
@@ -25,16 +25,21 @@ local function AntiDaze_RegisterCombatEvents()
|
|||||||
if not AntiDazeFrame then
|
if not AntiDazeFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
|
if MTH and MTH.nampower then
|
||||||
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
|
AntiDazeFrame:RegisterEvent("DEBUFF_ADDED_SELF")
|
||||||
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
|
else
|
||||||
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
|
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
|
||||||
|
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
|
||||||
|
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
|
||||||
|
AntiDazeFrame:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function AntiDaze_UnregisterCombatEvents()
|
local function AntiDaze_UnregisterCombatEvents()
|
||||||
if not AntiDazeFrame then
|
if not AntiDazeFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
AntiDazeFrame:UnregisterEvent("DEBUFF_ADDED_SELF")
|
||||||
AntiDazeFrame:UnregisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
|
AntiDazeFrame:UnregisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
|
||||||
AntiDazeFrame:UnregisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
|
AntiDazeFrame:UnregisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
|
||||||
AntiDazeFrame:UnregisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
|
AntiDazeFrame:UnregisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
|
||||||
@@ -87,10 +92,31 @@ local function AntiDaze_ResolvePlayerFromMessage(msg)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local AntiDaze_DazeSpellIdCache = {} -- [spellId] = true/false
|
||||||
|
|
||||||
|
local function AntiDaze_IsDazeSpellId(spellId)
|
||||||
|
local cached = AntiDaze_DazeSpellIdCache[spellId]
|
||||||
|
if cached ~= nil then return cached end
|
||||||
|
if type(GetSpellRecField) ~= "function" then return false end
|
||||||
|
local name = GetSpellRecField(spellId, "name")
|
||||||
|
if name and (name == "Daze" or name == "Dazed") then
|
||||||
|
AntiDaze_DazeSpellIdCache[spellId] = true
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
AntiDaze_DazeSpellIdCache[spellId] = false
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local function AntiDaze_CancelRelevantAspect(isSelfDazed)
|
local function AntiDaze_CancelRelevantAspect(isSelfDazed)
|
||||||
local packName = _G["ZHUNTER_ASPECT_PACK"] or "Aspect of the Pack"
|
local packName = _G["ZHUNTER_ASPECT_PACK"] or "Aspect of the Pack"
|
||||||
local cheetahName = _G["ZHUNTER_ASPECT_CHEETAH"] or "Aspect of the Cheetah"
|
local cheetahName = _G["ZHUNTER_ASPECT_CHEETAH"] or "Aspect of the Cheetah"
|
||||||
|
|
||||||
|
-- Always use GetPlayerBuff + tooltip scan for cancellation.
|
||||||
|
-- The aura-array slot index from GetUnitField does NOT map 1:1
|
||||||
|
-- to the sequential buff index that CancelPlayerBuff expects
|
||||||
|
-- (empty slots create gaps), so we cannot use the NamPower
|
||||||
|
-- array for the cancel call. NamPower is still used for daze
|
||||||
|
-- DETECTION via DEBUFF_ADDED_SELF in the event handler.
|
||||||
for i = 0, 32 do
|
for i = 0, 32 do
|
||||||
if GetPlayerBuff(i, "HELPFUL") < 0 then
|
if GetPlayerBuff(i, "HELPFUL") < 0 then
|
||||||
break
|
break
|
||||||
@@ -98,7 +124,7 @@ local function AntiDaze_CancelRelevantAspect(isSelfDazed)
|
|||||||
|
|
||||||
AntiDazeTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
AntiDazeTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||||
AntiDazeTooltip:SetPlayerBuff(i, "HELPFUL")
|
AntiDazeTooltip:SetPlayerBuff(i, "HELPFUL")
|
||||||
local text = AntiDazeTooltipTextLeft1 and AntiDazeTooltipTextLeft1:GetText()
|
local text = MTH_AntiDazeProbeTextLeft1 and MTH_AntiDazeProbeTextLeft1:GetText()
|
||||||
if text == packName or (isSelfDazed and text == cheetahName) then
|
if text == packName or (isSelfDazed and text == cheetahName) then
|
||||||
CancelPlayerBuff(i)
|
CancelPlayerBuff(i)
|
||||||
return 1
|
return 1
|
||||||
@@ -112,12 +138,18 @@ local function AntiDaze_HandleSlash()
|
|||||||
AntiDaze_SetEnabled(not AntiDaze_IsEnabled())
|
AntiDaze_SetEnabled(not AntiDaze_IsEnabled())
|
||||||
end
|
end
|
||||||
|
|
||||||
AntiDazeTooltip = CreateFrame("GameTooltip", "AntiDazeTooltip", nil, "GameTooltipTemplate")
|
AntiDazeTooltip = CreateFrame("GameTooltip", "MTH_AntiDazeProbe", nil, "GameTooltipTemplate")
|
||||||
AntiDazeFrame = CreateFrame("Frame", "AntiDazeFrame")
|
AntiDazeFrame = CreateFrame("Frame", "MTH_AntiDazeEvent")
|
||||||
if AntiDazeFrame then
|
if AntiDazeFrame then
|
||||||
AntiDazeFrame:RegisterEvent("VARIABLES_LOADED")
|
AntiDazeFrame:RegisterEvent("VARIABLES_LOADED")
|
||||||
AntiDazeFrame:SetScript("OnEvent", function()
|
AntiDazeFrame:SetScript("OnEvent", function()
|
||||||
if event == "VARIABLES_LOADED" then
|
if event == "VARIABLES_LOADED" then
|
||||||
|
-- Class gate: only hunters use AntiDaze.
|
||||||
|
if MTH and MTH.IsClassGateBlocked and MTH:IsClassGateBlocked() then
|
||||||
|
AntiDazeFrame:UnregisterAllEvents()
|
||||||
|
AntiDazeFrame:SetScript("OnEvent", nil)
|
||||||
|
return
|
||||||
|
end
|
||||||
if AntiDaze_IsEnabled() then
|
if AntiDaze_IsEnabled() then
|
||||||
AntiDaze_RegisterCombatEvents()
|
AntiDaze_RegisterCombatEvents()
|
||||||
else
|
else
|
||||||
@@ -126,6 +158,16 @@ if AntiDazeFrame then
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- NamPower path: DEBUFF_ADDED_SELF fires with spellId in arg3
|
||||||
|
if event == "DEBUFF_ADDED_SELF" then
|
||||||
|
local spellId = tonumber(arg3)
|
||||||
|
if spellId and AntiDaze_IsDazeSpellId(spellId) then
|
||||||
|
AntiDaze_CancelRelevantAspect(true)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Legacy path: parse chat messages
|
||||||
local player = AntiDaze_ResolvePlayerFromMessage(arg1)
|
local player = AntiDaze_ResolvePlayerFromMessage(arg1)
|
||||||
if player then
|
if player then
|
||||||
local you = _G["ZHUNTER_YOU"] or "You"
|
local you = _G["ZHUNTER_YOU"] or "You"
|
||||||
|
|||||||
+26
-8
@@ -112,7 +112,7 @@ end
|
|||||||
|
|
||||||
local function AutoStrip_QueueDeferredRestore(reason)
|
local function AutoStrip_QueueDeferredRestore(reason)
|
||||||
if not AutoStrip_RestoreFrame then
|
if not AutoStrip_RestoreFrame then
|
||||||
AutoStrip_RestoreFrame = CreateFrame("Frame", "AutoStripRestoreFrame")
|
AutoStrip_RestoreFrame = CreateFrame("Frame", "MTH_AutoStripRestore")
|
||||||
if not AutoStrip_RestoreFrame then
|
if not AutoStrip_RestoreFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -150,6 +150,10 @@ function AutoStrip_SetAutoStripToggle(enabled, silent)
|
|||||||
if enabled then
|
if enabled then
|
||||||
saved["autostrip"] = 1
|
saved["autostrip"] = 1
|
||||||
AutoStrip_On = 1
|
AutoStrip_On = 1
|
||||||
|
if AutoStrip_Frame then
|
||||||
|
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
||||||
|
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||||
|
end
|
||||||
if AutoStripDisplay and AutoStripDisplay:IsVisible() and AutoStripDisplayAutoCast then
|
if AutoStripDisplay and AutoStripDisplay:IsVisible() and AutoStripDisplayAutoCast then
|
||||||
AutoStripDisplayAutoCast:Show()
|
AutoStripDisplayAutoCast:Show()
|
||||||
end
|
end
|
||||||
@@ -159,6 +163,10 @@ function AutoStrip_SetAutoStripToggle(enabled, silent)
|
|||||||
else
|
else
|
||||||
saved["autostrip"] = nil
|
saved["autostrip"] = nil
|
||||||
AutoStrip_On = nil
|
AutoStrip_On = nil
|
||||||
|
if AutoStrip_Frame then
|
||||||
|
AutoStrip_Frame:UnregisterEvent("PLAYER_REGEN_DISABLED")
|
||||||
|
AutoStrip_Frame:UnregisterEvent("PLAYER_REGEN_ENABLED")
|
||||||
|
end
|
||||||
if AutoStripDisplayAutoCast then
|
if AutoStripDisplayAutoCast then
|
||||||
AutoStripDisplayAutoCast:Hide()
|
AutoStripDisplayAutoCast:Hide()
|
||||||
end
|
end
|
||||||
@@ -252,11 +260,19 @@ function AutoStrip_UnequipAll(weaponsOnly)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function AutoStrip_OnEvent()
|
local function AutoStrip_OnEvent()
|
||||||
AutoStrip_Trace("OnEvent evt=" .. tostring(event or "")
|
if AutoStrip_TraceEnabled then
|
||||||
.. " runtime=" .. tostring(AutoStrip_On and 1 or 0)
|
AutoStrip_Trace("OnEvent evt=" .. tostring(event or "")
|
||||||
.. " wasInCombat=" .. tostring(AutoStrip_WasInCombat and 1 or 0)
|
.. " runtime=" .. tostring(AutoStrip_On and 1 or 0)
|
||||||
.. " playerInCombat=" .. tostring((type(UnitAffectingCombat) == "function" and UnitAffectingCombat("player")) and 1 or 0))
|
.. " wasInCombat=" .. tostring(AutoStrip_WasInCombat and 1 or 0)
|
||||||
|
.. " playerInCombat=" .. tostring((type(UnitAffectingCombat) == "function" and UnitAffectingCombat("player")) and 1 or 0))
|
||||||
|
end
|
||||||
if event == "VARIABLES_LOADED" then
|
if event == "VARIABLES_LOADED" then
|
||||||
|
-- Class gate: only hunters use AutoStrip.
|
||||||
|
if MTH and MTH.IsClassGateBlocked and MTH:IsClassGateBlocked() then
|
||||||
|
AutoStrip_Frame:UnregisterAllEvents()
|
||||||
|
AutoStrip_Frame:SetScript("OnEvent", nil)
|
||||||
|
return
|
||||||
|
end
|
||||||
local saved = AutoStrip_GetSaved()
|
local saved = AutoStrip_GetSaved()
|
||||||
AutoStrip_Trace("VARIABLES_LOADED saved.autostrip=" .. tostring(saved["autostrip"] and 1 or 0)
|
AutoStrip_Trace("VARIABLES_LOADED saved.autostrip=" .. tostring(saved["autostrip"] and 1 or 0)
|
||||||
.. " saved.display=" .. tostring(saved["display"] and 1 or 0))
|
.. " saved.display=" .. tostring(saved["display"] and 1 or 0))
|
||||||
@@ -316,11 +332,13 @@ local function AutoStrip_HandleSlash(msg)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
AutoStrip_Frame = CreateFrame("Frame", "AutoStripFrame")
|
AutoStrip_Frame = CreateFrame("Frame", "MTH_AutoStripEvent")
|
||||||
if AutoStrip_Frame then
|
if AutoStrip_Frame then
|
||||||
|
-- PLAYER_REGEN_DISABLED / PLAYER_REGEN_ENABLED are intentionally NOT registered here.
|
||||||
|
-- They are registered only when the feature is enabled via AutoStrip_SetAutoStripToggle(true),
|
||||||
|
-- and unregistered when it is disabled. This prevents any combat event overhead when the
|
||||||
|
-- feature is off.
|
||||||
AutoStrip_Frame:RegisterEvent("VARIABLES_LOADED")
|
AutoStrip_Frame:RegisterEvent("VARIABLES_LOADED")
|
||||||
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
||||||
AutoStrip_Frame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
||||||
AutoStrip_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
AutoStrip_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
AutoStrip_Frame:RegisterEvent("PLAYER_LOGOUT")
|
AutoStrip_Frame:RegisterEvent("PLAYER_LOGOUT")
|
||||||
AutoStrip_Frame:SetScript("OnEvent", AutoStrip_OnEvent)
|
AutoStrip_Frame:SetScript("OnEvent", AutoStrip_OnEvent)
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
------------------------------------------------------
|
||||||
|
-- MetaHunt: Beast Lore Scanner (removed)
|
||||||
|
------------------------------------------------------
|
||||||
|
-- This file previously contained a feature that recorded
|
||||||
|
-- unknown beasts to SavedVariables when scanned with
|
||||||
|
-- Beast Lore. The feature has been removed; the static
|
||||||
|
-- beast database (ds-beasts) is now the sole data source.
|
||||||
|
------------------------------------------------------
|
||||||
+16
-4
@@ -1,5 +1,5 @@
|
|||||||
MTH_CONST = MTH_CONST or {}
|
MTH_CONST = MTH_CONST or {}
|
||||||
MTH_CONST.version = MTH_CONST.version or "1.1.0"
|
MTH_CONST.version = MTH_CONST.version or "1.5.0"
|
||||||
|
|
||||||
MTH_CONST.WEAPON_TYPES = {
|
MTH_CONST.WEAPON_TYPES = {
|
||||||
BOWS = "Bows",
|
BOWS = "Bows",
|
||||||
@@ -24,6 +24,7 @@ MTH_CONST.AMMO = {
|
|||||||
ICETHREADED = "Ice Threaded Bullet",
|
ICETHREADED = "Ice Threaded Bullet",
|
||||||
THORIUM = "Thorium Shells",
|
THORIUM = "Thorium Shells",
|
||||||
ROCKSHARD = "Rockshard Pellets",
|
ROCKSHARD = "Rockshard Pellets",
|
||||||
|
CRAFTEDTHORIUM = "Enchanted Thorium Shells",
|
||||||
CANNONBALL = "Miniature Cannon Balls",
|
CANNONBALL = "Miniature Cannon Balls",
|
||||||
},
|
},
|
||||||
ARROWS = {
|
ARROWS = {
|
||||||
@@ -32,16 +33,19 @@ MTH_CONST.AMMO = {
|
|||||||
RAZOR = "Razor Arrow",
|
RAZOR = "Razor Arrow",
|
||||||
FEATHER = "Feathered Arrow",
|
FEATHER = "Feathered Arrow",
|
||||||
PRECISION = "Precision Arrow",
|
PRECISION = "Precision Arrow",
|
||||||
|
BRIGHT = "Bright Wood Arrows",
|
||||||
JAGGED = "Jagged Arrow",
|
JAGGED = "Jagged Arrow",
|
||||||
|
SHADE = "Shade Wood Arrows",
|
||||||
ICETHREADED = "Ice Threaded Arrow",
|
ICETHREADED = "Ice Threaded Arrow",
|
||||||
|
SMOOTH = "Smooth Ironfeather Arrows",
|
||||||
THORIUM = "Thorium Headed Arrow",
|
THORIUM = "Thorium Headed Arrow",
|
||||||
|
STAR = "Starfeather Arrows",
|
||||||
DOOMSHOT = "Doomshot",
|
DOOMSHOT = "Doomshot",
|
||||||
},
|
},
|
||||||
JUNKSHOTS = {
|
JUNKSHOTS = {
|
||||||
SERPENT = "Serpent Sting",
|
SERPENT = "Serpent Sting",
|
||||||
SCORPID = "Scorpid Sting",
|
SCORPID = "Scorpid Sting",
|
||||||
VIPER = "Viper Sting",
|
VIPER = "Viper Sting",
|
||||||
ARCANE = "Arcane Shot",
|
|
||||||
CONCUSSIVE = "Concussive Shot",
|
CONCUSSIVE = "Concussive Shot",
|
||||||
DISTRACTING = "Distracting Shot",
|
DISTRACTING = "Distracting Shot",
|
||||||
BAITED = "Baited Shot",
|
BAITED = "Baited Shot",
|
||||||
@@ -69,6 +73,7 @@ BULLETS_ICETHREADED = MTH_CONST.AMMO.BULLETS.ICETHREADED
|
|||||||
BULLETS_THORIUM = MTH_CONST.AMMO.BULLETS.THORIUM
|
BULLETS_THORIUM = MTH_CONST.AMMO.BULLETS.THORIUM
|
||||||
BULLETS_ROCKSHARD = MTH_CONST.AMMO.BULLETS.ROCKSHARD
|
BULLETS_ROCKSHARD = MTH_CONST.AMMO.BULLETS.ROCKSHARD
|
||||||
BULLETS_CANNONBALL = MTH_CONST.AMMO.BULLETS.CANNONBALL
|
BULLETS_CANNONBALL = MTH_CONST.AMMO.BULLETS.CANNONBALL
|
||||||
|
BULLETS_CRAFTEDTHORIUM = MTH_CONST.AMMO.BULLETS.CRAFTEDTHORIUM
|
||||||
|
|
||||||
ARROWS_ROUGH = MTH_CONST.AMMO.ARROWS.ROUGH
|
ARROWS_ROUGH = MTH_CONST.AMMO.ARROWS.ROUGH
|
||||||
ARROWS_SHARP = MTH_CONST.AMMO.ARROWS.SHARP
|
ARROWS_SHARP = MTH_CONST.AMMO.ARROWS.SHARP
|
||||||
@@ -77,13 +82,16 @@ ARROWS_FEATHER = MTH_CONST.AMMO.ARROWS.FEATHER
|
|||||||
ARROWS_PRECISION = MTH_CONST.AMMO.ARROWS.PRECISION
|
ARROWS_PRECISION = MTH_CONST.AMMO.ARROWS.PRECISION
|
||||||
ARROWS_JAGGED = MTH_CONST.AMMO.ARROWS.JAGGED
|
ARROWS_JAGGED = MTH_CONST.AMMO.ARROWS.JAGGED
|
||||||
ARROWS_ICETHREADED = MTH_CONST.AMMO.ARROWS.ICETHREADED
|
ARROWS_ICETHREADED = MTH_CONST.AMMO.ARROWS.ICETHREADED
|
||||||
|
ARROWS_BRIGHT = MTH_CONST.AMMO.ARROWS.BRIGHT
|
||||||
|
ARROWS_SHADE = MTH_CONST.AMMO.ARROWS.SHADE
|
||||||
|
ARROWS_SMOOTH = MTH_CONST.AMMO.ARROWS.SMOOTH
|
||||||
ARROWS_THORIUM = MTH_CONST.AMMO.ARROWS.THORIUM
|
ARROWS_THORIUM = MTH_CONST.AMMO.ARROWS.THORIUM
|
||||||
|
ARROWS_STAR = MTH_CONST.AMMO.ARROWS.STAR
|
||||||
ARROWS_DOOMSHOT = MTH_CONST.AMMO.ARROWS.DOOMSHOT
|
ARROWS_DOOMSHOT = MTH_CONST.AMMO.ARROWS.DOOMSHOT
|
||||||
|
|
||||||
JUNKSHOT_SERPENT = MTH_CONST.AMMO.JUNKSHOTS.SERPENT
|
JUNKSHOT_SERPENT = MTH_CONST.AMMO.JUNKSHOTS.SERPENT
|
||||||
JUNKSHOT_SCORPID = MTH_CONST.AMMO.JUNKSHOTS.SCORPID
|
JUNKSHOT_SCORPID = MTH_CONST.AMMO.JUNKSHOTS.SCORPID
|
||||||
JUNKSHOT_VIPER = MTH_CONST.AMMO.JUNKSHOTS.VIPER
|
JUNKSHOT_VIPER = MTH_CONST.AMMO.JUNKSHOTS.VIPER
|
||||||
JUNKSHOT_ARCANE = MTH_CONST.AMMO.JUNKSHOTS.ARCANE
|
|
||||||
JUNKSHOT_CONCUSSIVE = MTH_CONST.AMMO.JUNKSHOTS.CONCUSSIVE
|
JUNKSHOT_CONCUSSIVE = MTH_CONST.AMMO.JUNKSHOTS.CONCUSSIVE
|
||||||
JUNKSHOT_DISTRACTING = MTH_CONST.AMMO.JUNKSHOTS.DISTRACTING
|
JUNKSHOT_DISTRACTING = MTH_CONST.AMMO.JUNKSHOTS.DISTRACTING
|
||||||
JUNKSHOT_BAITED = MTH_CONST.AMMO.JUNKSHOTS.BAITED
|
JUNKSHOT_BAITED = MTH_CONST.AMMO.JUNKSHOTS.BAITED
|
||||||
@@ -105,6 +113,7 @@ MTH_AMMO_BULLETS = {
|
|||||||
BULLETS_ICETHREADED,
|
BULLETS_ICETHREADED,
|
||||||
BULLETS_THORIUM,
|
BULLETS_THORIUM,
|
||||||
BULLETS_ROCKSHARD,
|
BULLETS_ROCKSHARD,
|
||||||
|
BULLETS_CRAFTEDTHORIUM,
|
||||||
BULLETS_CANNONBALL,
|
BULLETS_CANNONBALL,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +123,13 @@ MTH_AMMO_ARROWS = {
|
|||||||
ARROWS_RAZOR,
|
ARROWS_RAZOR,
|
||||||
ARROWS_FEATHER,
|
ARROWS_FEATHER,
|
||||||
ARROWS_PRECISION,
|
ARROWS_PRECISION,
|
||||||
|
ARROWS_BRIGHT,
|
||||||
ARROWS_JAGGED,
|
ARROWS_JAGGED,
|
||||||
|
ARROWS_SHADE,
|
||||||
ARROWS_ICETHREADED,
|
ARROWS_ICETHREADED,
|
||||||
|
ARROWS_SMOOTH,
|
||||||
ARROWS_THORIUM,
|
ARROWS_THORIUM,
|
||||||
|
ARROWS_STAR,
|
||||||
ARROWS_DOOMSHOT,
|
ARROWS_DOOMSHOT,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +137,6 @@ MTH_AMMO_JUNKSHOTS = {
|
|||||||
JUNKSHOT_SERPENT,
|
JUNKSHOT_SERPENT,
|
||||||
JUNKSHOT_SCORPID,
|
JUNKSHOT_SCORPID,
|
||||||
JUNKSHOT_VIPER,
|
JUNKSHOT_VIPER,
|
||||||
JUNKSHOT_ARCANE,
|
|
||||||
JUNKSHOT_CONCUSSIVE,
|
JUNKSHOT_CONCUSSIVE,
|
||||||
JUNKSHOT_DISTRACTING,
|
JUNKSHOT_DISTRACTING,
|
||||||
JUNKSHOT_BAITED,
|
JUNKSHOT_BAITED,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ local MTH_FEED_TrackerFrame = nil
|
|||||||
local MTH_FEED_ActiveCoreAttemptId = nil
|
local MTH_FEED_ActiveCoreAttemptId = nil
|
||||||
local MTH_FEED_BootstrapFrame = nil
|
local MTH_FEED_BootstrapFrame = nil
|
||||||
local MTH_FEED_NameToItemCache = {}
|
local MTH_FEED_NameToItemCache = {}
|
||||||
|
local MTH_FEED_InvalidateDietMapCache
|
||||||
|
|
||||||
local MTH_FEED_HARDCODED_LEVEL_RULES = {
|
local MTH_FEED_HARDCODED_LEVEL_RULES = {
|
||||||
{ minPetLevel = 1, minFoodLevel = 1 },
|
{ minPetLevel = 1, minFoodLevel = 1 },
|
||||||
@@ -28,7 +29,10 @@ local MTH_FEED_HARDCODED_LEVEL_RULES = {
|
|||||||
MTH_FEED_TRACE = false
|
MTH_FEED_TRACE = false
|
||||||
|
|
||||||
local function MTH_FEED_Trace(message)
|
local function MTH_FEED_Trace(message)
|
||||||
return
|
if not MTH_FEED_TRACE then return end
|
||||||
|
if type(DEFAULT_CHAT_FRAME) == "table" and DEFAULT_CHAT_FRAME.AddMessage then
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage("|cff88aaff[MTH-FeedTrack]|r " .. tostring(message))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FEED_Now()
|
local function MTH_FEED_Now()
|
||||||
@@ -163,7 +167,7 @@ local function MTH_FEED_IndexBagFoods()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FEED_HasPetFeedBuff()
|
function MTH_FEED_HasPetFeedBuff()
|
||||||
if type(UnitBuff) ~= "function" then
|
if type(UnitBuff) ~= "function" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -460,6 +464,7 @@ local function MTH_FEED_CoreTrackerOnEvent()
|
|||||||
end
|
end
|
||||||
elseif evt == "BAG_UPDATE" then
|
elseif evt == "BAG_UPDATE" then
|
||||||
MTH_FEED_IndexBagFoods()
|
MTH_FEED_IndexBagFoods()
|
||||||
|
MTH_FEED_InvalidateDietMapCache()
|
||||||
elseif evt == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" then
|
elseif evt == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" then
|
||||||
if MTH_FEED_ActiveCoreAttemptId and MTH_FEED_HasPetFeedBuff() then
|
if MTH_FEED_ActiveCoreAttemptId and MTH_FEED_HasPetFeedBuff() then
|
||||||
MTH_FEED_Trace("Core tracker buff event confirms acceptance")
|
MTH_FEED_Trace("Core tracker buff event confirms acceptance")
|
||||||
@@ -468,7 +473,32 @@ local function MTH_FEED_CoreTrackerOnEvent()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local MTH_FEED_CoreTrackerUpdateElapsed = 0
|
||||||
|
local MTH_FEED_LastStaleCleanupAt = 0
|
||||||
|
|
||||||
local function MTH_FEED_CoreTrackerOnUpdate()
|
local function MTH_FEED_CoreTrackerOnUpdate()
|
||||||
|
MTH_FEED_CoreTrackerUpdateElapsed = MTH_FEED_CoreTrackerUpdateElapsed + (arg1 or 0)
|
||||||
|
if MTH_FEED_CoreTrackerUpdateElapsed < 0.10 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
MTH_FEED_CoreTrackerUpdateElapsed = 0
|
||||||
|
|
||||||
|
-- Periodic stale attempt cleanup (every ~30 seconds)
|
||||||
|
local now = GetTime() or 0
|
||||||
|
if (now - MTH_FEED_LastStaleCleanupAt) >= 30 then
|
||||||
|
MTH_FEED_LastStaleCleanupAt = now
|
||||||
|
if MTH_FEED_Runtime and type(MTH_FEED_Runtime.attempts) == "table" then
|
||||||
|
for id, row in pairs(MTH_FEED_Runtime.attempts) do
|
||||||
|
if type(row) == "table" then
|
||||||
|
local age = now - (tonumber(row.startedAt) or now)
|
||||||
|
if age > 10 then
|
||||||
|
MTH_FEED_Runtime.attempts[id] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local attemptId = MTH_FEED_ActiveCoreAttemptId
|
local attemptId = MTH_FEED_ActiveCoreAttemptId
|
||||||
if attemptId == nil then
|
if attemptId == nil then
|
||||||
return
|
return
|
||||||
@@ -499,7 +529,7 @@ local function MTH_FEED_EnsureTrackerFrame()
|
|||||||
if MTH_FEED_TrackerFrame then
|
if MTH_FEED_TrackerFrame then
|
||||||
return MTH_FEED_TrackerFrame
|
return MTH_FEED_TrackerFrame
|
||||||
end
|
end
|
||||||
local frame = CreateFrame("Frame", "MTH_FeedTrackingFrame")
|
local frame = CreateFrame("Frame", "MTH_FeedTracking")
|
||||||
if not frame then
|
if not frame then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -610,6 +640,7 @@ end
|
|||||||
|
|
||||||
function MTH_FEED_ReinstallCoreTracking()
|
function MTH_FEED_ReinstallCoreTracking()
|
||||||
local ok = MTH_FEED_InstallCoreHooks()
|
local ok = MTH_FEED_InstallCoreHooks()
|
||||||
|
MTH_FEED_EnsureTrackerFrame()
|
||||||
return ok and true or false
|
return ok and true or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -617,19 +648,17 @@ local function MTH_FEED_EnsureBootstrapFrame()
|
|||||||
if MTH_FEED_BootstrapFrame ~= nil then
|
if MTH_FEED_BootstrapFrame ~= nil then
|
||||||
return MTH_FEED_BootstrapFrame
|
return MTH_FEED_BootstrapFrame
|
||||||
end
|
end
|
||||||
local frame = CreateFrame("Frame", "MTH_FeedTrackingBootstrapFrame")
|
local frame = CreateFrame("Frame", "MTH_FeedTrackingBoot")
|
||||||
if not frame then
|
if not frame then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
frame:RegisterEvent("VARIABLES_LOADED")
|
frame:RegisterEvent("VARIABLES_LOADED")
|
||||||
frame:RegisterEvent("PLAYER_LOGIN")
|
frame:RegisterEvent("PLAYER_LOGIN")
|
||||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
frame:SetScript("OnEvent", function(self)
|
frame:SetScript("OnEvent", function()
|
||||||
MTH_FEED_ReinstallCoreTracking()
|
MTH_FEED_ReinstallCoreTracking()
|
||||||
if self and self.UnregisterAllEvents then
|
this:UnregisterAllEvents()
|
||||||
self:UnregisterAllEvents()
|
this:SetScript("OnEvent", nil)
|
||||||
self:SetScript("OnEvent", nil)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
MTH_FEED_BootstrapFrame = frame
|
MTH_FEED_BootstrapFrame = frame
|
||||||
return frame
|
return frame
|
||||||
@@ -826,7 +855,16 @@ local function MTH_FEED_NormalizeReason(reason, rawMessage)
|
|||||||
return "unknown"
|
return "unknown"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local MTH_FEED_DietMapCache = nil
|
||||||
|
|
||||||
|
MTH_FEED_InvalidateDietMapCache = function()
|
||||||
|
MTH_FEED_DietMapCache = nil
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_FEED_GetDietByItemIdMap()
|
local function MTH_FEED_GetDietByItemIdMap()
|
||||||
|
if MTH_FEED_DietMapCache then
|
||||||
|
return MTH_FEED_DietMapCache
|
||||||
|
end
|
||||||
local map = {}
|
local map = {}
|
||||||
if type(FOM_Foods) ~= "table" then
|
if type(FOM_Foods) ~= "table" then
|
||||||
return map
|
return map
|
||||||
@@ -841,6 +879,7 @@ local function MTH_FEED_GetDietByItemIdMap()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
MTH_FEED_DietMapCache = map
|
||||||
return map
|
return map
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1423,6 +1462,30 @@ function MTH_FEED_GetSessionFeedCount(petId)
|
|||||||
return tonumber(MTH_FEED_Runtime.sessionFeedsByPetId[petKey]) or 0
|
return tonumber(MTH_FEED_Runtime.sessionFeedsByPetId[petKey]) or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH_FEED_DebugSessionFeeds()
|
||||||
|
local pet = MTH_FEED_GetCurrentPetContext()
|
||||||
|
local petId = pet and pet.petId or "(none)"
|
||||||
|
local count = MTH_FEED_GetSessionFeedCount(petId)
|
||||||
|
local hookOk = MTH_FEED_IsCoreHookInstalled()
|
||||||
|
local frameOk = MTH_FEED_TrackerFrame ~= nil
|
||||||
|
local activeId = tostring(MTH_FEED_ActiveCoreAttemptId or "nil")
|
||||||
|
if type(DEFAULT_CHAT_FRAME) == "table" and DEFAULT_CHAT_FRAME.AddMessage then
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage("|cff88aaff[MTH-FeedTrack]|r petId=" .. tostring(petId)
|
||||||
|
.. " feeds=" .. tostring(count)
|
||||||
|
.. " hookOk=" .. tostring(hookOk)
|
||||||
|
.. " frameOk=" .. tostring(frameOk)
|
||||||
|
.. " activeAttempt=" .. activeId)
|
||||||
|
local anyFeeds = false
|
||||||
|
for k, v in pairs(MTH_FEED_Runtime.sessionFeedsByPetId) do
|
||||||
|
anyFeeds = true
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage("|cff88aaff[MTH-FeedTrack]|r session petId='" .. tostring(k) .. "' count=" .. tostring(v))
|
||||||
|
end
|
||||||
|
if not anyFeeds then
|
||||||
|
DEFAULT_CHAT_FRAME:AddMessage("|cff88aaff[MTH-FeedTrack]|r (no session feeds recorded)")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_FEED_RecordUnknownFoodCandidate(payload)
|
function MTH_FEED_RecordUnknownFoodCandidate(payload)
|
||||||
local store = MTH_FEED_EnsureStore()
|
local store = MTH_FEED_EnsureStore()
|
||||||
local itemId = payload and tonumber(payload.itemId) or nil
|
local itemId = payload and tonumber(payload.itemId) or nil
|
||||||
|
|||||||
+87
-69
@@ -1,5 +1,5 @@
|
|||||||
MTH = MTH or {
|
MTH = MTH or {
|
||||||
version = "1.1.0",
|
version = "1.5.0",
|
||||||
name = "MetaHunt",
|
name = "MetaHunt",
|
||||||
modules = {},
|
modules = {},
|
||||||
config = {},
|
config = {},
|
||||||
@@ -44,7 +44,7 @@ local function MTH_ClassGateEnsureAnnounceFrame(self)
|
|||||||
if not self or self._classGateAnnounceFrame then
|
if not self or self._classGateAnnounceFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local frame = CreateFrame("Frame", "MTH_ClassGateAnnounceFrame")
|
local frame = CreateFrame("Frame", "MTH_ClassGateAnnounce")
|
||||||
if not frame then
|
if not frame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -55,12 +55,12 @@ local function MTH_ClassGateEnsureAnnounceFrame(self)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
frame._mthElapsed = 0
|
frame._mthElapsed = 0
|
||||||
frame:SetScript("OnUpdate", function(self, elapsed)
|
frame:SetScript("OnUpdate", function()
|
||||||
self._mthElapsed = (self._mthElapsed or 0) + (elapsed or arg1 or 0)
|
this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0)
|
||||||
if self._mthElapsed < 0.5 then
|
if this._mthElapsed < 0.5 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self._mthElapsed = 0
|
this._mthElapsed = 0
|
||||||
if MTH and MTH._classGateAnnouncedChat then
|
if MTH and MTH._classGateAnnouncedChat then
|
||||||
MTH_ClassGateClearAnnounceFrame(MTH)
|
MTH_ClassGateClearAnnounceFrame(MTH)
|
||||||
return
|
return
|
||||||
@@ -192,21 +192,19 @@ end
|
|||||||
MTH:ApplyClassGate("startup")
|
MTH:ApplyClassGate("startup")
|
||||||
|
|
||||||
if not MTH._classGateLifecycleFrame then
|
if not MTH._classGateLifecycleFrame then
|
||||||
local classGateFrame = CreateFrame("Frame", "MTH_ClassGateLifecycleFrame")
|
local classGateFrame = CreateFrame("Frame", "MTH_ClassGateLifecycle")
|
||||||
if classGateFrame then
|
if classGateFrame then
|
||||||
classGateFrame:RegisterEvent("PLAYER_LOGIN")
|
classGateFrame:RegisterEvent("PLAYER_LOGIN")
|
||||||
classGateFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
classGateFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
classGateFrame:SetScript("OnEvent", function(self, eventName)
|
classGateFrame:SetScript("OnEvent", function()
|
||||||
self = self or this
|
if MTH and event == "PLAYER_LOGIN" then
|
||||||
eventName = eventName or event
|
|
||||||
if MTH and eventName == "PLAYER_LOGIN" then
|
|
||||||
MTH._classGateAnnouncedChat = nil
|
MTH._classGateAnnouncedChat = nil
|
||||||
MTH._classGateAnnounced = nil
|
MTH._classGateAnnounced = nil
|
||||||
MTH._classGateAnnouncePending = nil
|
MTH._classGateAnnouncePending = nil
|
||||||
end
|
end
|
||||||
if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate(eventName) and MTH._classGateAnnouncedChat then
|
if MTH and MTH.ApplyClassGate and MTH:ApplyClassGate(event) and MTH._classGateAnnouncedChat then
|
||||||
self:UnregisterAllEvents()
|
this:UnregisterAllEvents()
|
||||||
self:SetScript("OnEvent", nil)
|
this:SetScript("OnEvent", nil)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
MTH._classGateLifecycleFrame = classGateFrame
|
MTH._classGateLifecycleFrame = classGateFrame
|
||||||
@@ -268,15 +266,6 @@ if type(MTH_CharSavedVariables.modules) ~= "table" then
|
|||||||
MTH_CharSavedVariables.modules = {}
|
MTH_CharSavedVariables.modules = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_ModuleStateDebug(message)
|
|
||||||
local text = "[MODULE STATE] " .. tostring(message or "")
|
|
||||||
if MTH and MTH.debug and MTH.Log then
|
|
||||||
MTH:Log(text, "debug")
|
|
||||||
elseif MTH and MTH.debug and MTH.Print then
|
|
||||||
MTH:Print(text, "debug")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function MTH_IsPetUiFrameName(frameName)
|
local function MTH_IsPetUiFrameName(frameName)
|
||||||
local name = tostring(frameName or "")
|
local name = tostring(frameName or "")
|
||||||
if name == "" then
|
if name == "" then
|
||||||
@@ -425,7 +414,6 @@ end
|
|||||||
|
|
||||||
local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||||
if type(name) ~= "string" or name == "" then
|
if type(name) ~= "string" or name == "" then
|
||||||
MTH_ModuleStateDebug("read <invalid-name> fallback-default=" .. tostring(defaultEnabled and true or false))
|
|
||||||
return defaultEnabled and true or false
|
return defaultEnabled and true or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -463,7 +451,6 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
|||||||
local resolved = hardDefault and true or false
|
local resolved = hardDefault and true or false
|
||||||
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
||||||
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
|
MTH_CharSavedVariables.modules[resolvedName].enabled = resolved
|
||||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " seeded char default=" .. tostring(resolved))
|
|
||||||
return resolved
|
return resolved
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -474,7 +461,6 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
|||||||
local key = candidates[i]
|
local key = candidates[i]
|
||||||
if MTH_CharSavedVariables.moduleStates[key] ~= nil then
|
if MTH_CharSavedVariables.moduleStates[key] ~= nil then
|
||||||
local resolved = MTH_CharSavedVariables.moduleStates[key] and true or false
|
local resolved = MTH_CharSavedVariables.moduleStates[key] and true or false
|
||||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " from char.moduleStates." .. tostring(key) .. "=" .. tostring(resolved))
|
|
||||||
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
||||||
return resolved
|
return resolved
|
||||||
end
|
end
|
||||||
@@ -486,7 +472,6 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
|||||||
local key = candidates[i]
|
local key = candidates[i]
|
||||||
if MTH_SavedVariables.moduleStates[key] ~= nil then
|
if MTH_SavedVariables.moduleStates[key] ~= nil then
|
||||||
local resolved = MTH_SavedVariables.moduleStates[key] and true or false
|
local resolved = MTH_SavedVariables.moduleStates[key] and true or false
|
||||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " from moduleStates." .. tostring(key) .. "=" .. tostring(resolved))
|
|
||||||
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
||||||
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
||||||
MTH_CharSavedVariables.modules[resolvedName] = {}
|
MTH_CharSavedVariables.modules[resolvedName] = {}
|
||||||
@@ -502,7 +487,6 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
|||||||
local key = candidates[i]
|
local key = candidates[i]
|
||||||
if type(MTH_SavedVariables.modules[key]) == "table" and MTH_SavedVariables.modules[key].enabled ~= nil then
|
if type(MTH_SavedVariables.modules[key]) == "table" and MTH_SavedVariables.modules[key].enabled ~= nil then
|
||||||
local resolved = MTH_SavedVariables.modules[key].enabled and true or false
|
local resolved = MTH_SavedVariables.modules[key].enabled and true or false
|
||||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " from modules." .. tostring(key) .. ".enabled=" .. tostring(resolved))
|
|
||||||
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
||||||
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
||||||
MTH_CharSavedVariables.modules[resolvedName] = {}
|
MTH_CharSavedVariables.modules[resolvedName] = {}
|
||||||
@@ -517,7 +501,6 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
|||||||
local key = candidates[i]
|
local key = candidates[i]
|
||||||
if type(MTH_SavedVariables[key]) == "table" and MTH_SavedVariables[key].enabled ~= nil then
|
if type(MTH_SavedVariables[key]) == "table" and MTH_SavedVariables[key].enabled ~= nil then
|
||||||
local resolved = MTH_SavedVariables[key].enabled and true or false
|
local resolved = MTH_SavedVariables[key].enabled and true or false
|
||||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " from legacy-top-level." .. tostring(key) .. ".enabled=" .. tostring(resolved))
|
|
||||||
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
MTH_CharSavedVariables.moduleStates[resolvedName] = resolved
|
||||||
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
if type(MTH_CharSavedVariables.modules[resolvedName]) ~= "table" then
|
||||||
MTH_CharSavedVariables.modules[resolvedName] = {}
|
MTH_CharSavedVariables.modules[resolvedName] = {}
|
||||||
@@ -527,7 +510,6 @@ local function MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_ModuleStateDebug("read " .. tostring(name) .. " no-persisted-value fallback-default=" .. tostring(defaultEnabled and true or false))
|
|
||||||
return defaultEnabled and true or false
|
return defaultEnabled and true or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -557,7 +539,6 @@ local function MTH_SetPersistedModuleEnabled(name, enabled)
|
|||||||
enabled = enabled and true or false
|
enabled = enabled and true or false
|
||||||
MTH_CharSavedVariables.moduleStates[name] = enabled
|
MTH_CharSavedVariables.moduleStates[name] = enabled
|
||||||
MTH_CharSavedVariables.modules[name].enabled = enabled
|
MTH_CharSavedVariables.modules[name].enabled = enabled
|
||||||
MTH_ModuleStateDebug("write " .. tostring(name) .. " enabled=" .. tostring(enabled))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH:InitEventRouter()
|
function MTH:InitEventRouter()
|
||||||
@@ -565,10 +546,10 @@ function MTH:InitEventRouter()
|
|||||||
return self._eventRouter.frame
|
return self._eventRouter.frame
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame", "MTH_EventRouterFrame")
|
local frame = CreateFrame("Frame", "MTH_EventRouter")
|
||||||
frame:SetScript("OnEvent", function(self, evt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
frame:SetScript("OnEvent", function()
|
||||||
if MTH and MTH.DispatchEvent then
|
if MTH and MTH.DispatchEvent then
|
||||||
MTH:DispatchEvent(evt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
MTH:DispatchEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -628,7 +609,7 @@ function MTH:_SetModuleEventSubscriptions(name, enabled)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH:DispatchEvent(evt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
function MTH:DispatchEvent(evt, ea1, ea2, ea3, ea4, ea5, ea6, ea7, ea8, ea9)
|
||||||
for name, module in pairs(self.modules) do
|
for name, module in pairs(self.modules) do
|
||||||
if module.enabled and module.onEvent then
|
if module.enabled and module.onEvent then
|
||||||
local allow = true
|
local allow = true
|
||||||
@@ -637,11 +618,10 @@ function MTH:DispatchEvent(evt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
|||||||
end
|
end
|
||||||
if allow then
|
if allow then
|
||||||
local ok, err = pcall(function()
|
local ok, err = pcall(function()
|
||||||
module:onEvent(evt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
module:onEvent(evt, ea1, ea2, ea3, ea4, ea5, ea6, ea7, ea8, ea9)
|
||||||
end)
|
end)
|
||||||
if not ok then
|
if not ok then
|
||||||
self:Print("Module '" .. name .. "' event error on '" .. tostring(evt) .. "': " .. tostring(err))
|
MTH:Print("Module '" .. name .. "' event error on '" .. tostring(evt) .. "': " .. tostring(err), "error")
|
||||||
MTH:Print("[MTH] Module event error (" .. name .. ", " .. tostring(evt) .. "): " .. tostring(err), "error")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -672,7 +652,6 @@ function MTH:RegisterModule(name, module)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self.modules[name] then
|
if self.modules[name] then
|
||||||
if self.debug then print("|cFFFFAA00MetaHunt|r: Module '" .. name .. "' already registered") end
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -687,8 +666,6 @@ function MTH:RegisterModule(name, module)
|
|||||||
|
|
||||||
local initialEnabled = MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
local initialEnabled = MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||||
module.enabled = initialEnabled and true or false
|
module.enabled = initialEnabled and true or false
|
||||||
MTH_ModuleStateDebug("register " .. tostring(name) .. " default=" .. tostring(defaultEnabled) .. " initial=" .. tostring(module.enabled))
|
|
||||||
|
|
||||||
self.modules[name] = module
|
self.modules[name] = module
|
||||||
self:RegisterModuleEvents(name, module.events)
|
self:RegisterModuleEvents(name, module.events)
|
||||||
|
|
||||||
@@ -712,7 +689,6 @@ function MTH:RegisterModule(name, module)
|
|||||||
self:_SetModuleEventSubscriptions(name, true)
|
self:_SetModuleEventSubscriptions(name, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.debug then print("|cFF00AA00MetaHunt|r: Module '" .. name .. "' registered") end
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -777,7 +753,6 @@ function MTH:SetModuleEnabled(name, enabled)
|
|||||||
if self.SetConfig then
|
if self.SetConfig then
|
||||||
self:SetConfig(name, "enabled", enabled)
|
self:SetConfig(name, "enabled", enabled)
|
||||||
end
|
end
|
||||||
MTH_ModuleStateDebug("request " .. tostring(name) .. " no-op runtime=" .. tostring(module.enabled) .. " persisted-synced")
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -799,7 +774,6 @@ function MTH:SetModuleEnabled(name, enabled)
|
|||||||
if self.SetConfig then
|
if self.SetConfig then
|
||||||
self:SetConfig(name, "enabled", enabled)
|
self:SetConfig(name, "enabled", enabled)
|
||||||
end
|
end
|
||||||
MTH_ModuleStateDebug("request " .. tostring(name) .. " applied runtime=" .. tostring(module.enabled))
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -1038,6 +1012,12 @@ function MTH:Log(msg, severity)
|
|||||||
return chatText
|
return chatText
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH:DebugPrint(msg)
|
||||||
|
if self.debug then
|
||||||
|
self:Print("[DEBUG] " .. tostring(msg), "debug")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function MTH:Print(msg, severity)
|
function MTH:Print(msg, severity)
|
||||||
return self:Log(msg, severity)
|
return self:Log(msg, severity)
|
||||||
end
|
end
|
||||||
@@ -1086,12 +1066,6 @@ function MTH:SetMessageEnabled(key, enabled)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH:DebugPrint(msg)
|
|
||||||
if self.debug then
|
|
||||||
self:Print("[DEBUG] " .. tostring(msg), "debug")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function MTH_Log(message, severity)
|
function MTH_Log(message, severity)
|
||||||
if MTH and MTH.Log then
|
if MTH and MTH.Log then
|
||||||
return MTH:Log(message, severity)
|
return MTH:Log(message, severity)
|
||||||
@@ -1273,12 +1247,10 @@ function MTH:ApplyPersistedModuleStates(source)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local persistedEnabled = MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
local persistedEnabled = MTH_GetPersistedModuleEnabled(name, defaultEnabled)
|
||||||
MTH_ModuleStateDebug("bootstrap " .. tostring(source or "") .. " " .. tostring(name) .. " persisted=" .. tostring(persistedEnabled) .. " runtime=" .. tostring(module.enabled and true or false))
|
|
||||||
|
|
||||||
if module.enabled ~= persistedEnabled then
|
if module.enabled ~= persistedEnabled then
|
||||||
local ok, err = self:SetModuleEnabled(name, persistedEnabled)
|
local ok, err = self:SetModuleEnabled(name, persistedEnabled)
|
||||||
if not ok then
|
if not ok then
|
||||||
MTH_ModuleStateDebug("bootstrap apply failed " .. tostring(name) .. ": " .. tostring(err))
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
MTH_SetPersistedModuleEnabled(name, persistedEnabled)
|
MTH_SetPersistedModuleEnabled(name, persistedEnabled)
|
||||||
@@ -1295,24 +1267,22 @@ function MTH:EnsureModuleStateBootstrap()
|
|||||||
return self._moduleStateBootstrapFrame
|
return self._moduleStateBootstrapFrame
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame", "MTH_ModuleStateBootstrapFrame")
|
local frame = CreateFrame("Frame", "MTH_ModuleBootstrap")
|
||||||
if not frame then
|
if not frame then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
frame:RegisterEvent("VARIABLES_LOADED")
|
frame:RegisterEvent("VARIABLES_LOADED")
|
||||||
frame:SetScript("OnEvent", function(self, eventName)
|
frame:SetScript("OnEvent", function()
|
||||||
self = self or this
|
if event ~= "VARIABLES_LOADED" then
|
||||||
eventName = eventName or event
|
|
||||||
if eventName ~= "VARIABLES_LOADED" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if MTH and MTH.ApplyPersistedModuleStates then
|
if MTH and MTH.ApplyPersistedModuleStates then
|
||||||
MTH:ApplyPersistedModuleStates("VARIABLES_LOADED")
|
MTH:ApplyPersistedModuleStates("VARIABLES_LOADED")
|
||||||
end
|
end
|
||||||
if not self then return end
|
if not this then return end
|
||||||
self:UnregisterAllEvents()
|
this:UnregisterAllEvents()
|
||||||
self:SetScript("OnEvent", nil)
|
this:SetScript("OnEvent", nil)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self._moduleStateBootstrapFrame = frame
|
self._moduleStateBootstrapFrame = frame
|
||||||
@@ -1341,7 +1311,17 @@ function MTH:AnnounceLoadComplete()
|
|||||||
moduleList = table.concat(enabled, ", ")
|
moduleList = table.concat(enabled, ", ")
|
||||||
end
|
end
|
||||||
|
|
||||||
self:Print("Check ignition: OK! Version " .. tostring(self.version or "unknown") .. " loaded.")
|
local namPowerStatus = ""
|
||||||
|
if type(GetNampowerVersion) == "function" then
|
||||||
|
local maj, min = GetNampowerVersion()
|
||||||
|
maj = tonumber(maj) or 0
|
||||||
|
min = tonumber(min) or 0
|
||||||
|
if maj > 2 or (maj == 2 and min >= 40) then
|
||||||
|
namPowerStatus = " | NamPower detected"
|
||||||
|
self.nampower = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:Print("Check Ignition.... OK! Version " .. tostring(self.version or "unknown") .. " loaded." .. namPowerStatus)
|
||||||
if self:IsMessageEnabled("initModulesLoaded", false) then
|
if self:IsMessageEnabled("initModulesLoaded", false) then
|
||||||
self:Print("Modules enabled : " .. moduleList .. ".")
|
self:Print("Modules enabled : " .. moduleList .. ".")
|
||||||
end
|
end
|
||||||
@@ -1490,6 +1470,46 @@ function MTH:AnnounceLoadComplete()
|
|||||||
"Addon synced. Your threat meter just sent a stress signal.",
|
"Addon synced. Your threat meter just sent a stress signal.",
|
||||||
"Loaded cleanly. Reputation with healers currently in freefall.",
|
"Loaded cleanly. Reputation with healers currently in freefall.",
|
||||||
"Mission start: hit things from far away and deny everything in chat.",
|
"Mission start: hit things from far away and deny everything in chat.",
|
||||||
|
"Welcome back. Your pet missed you. Just kidding, it ran away.",
|
||||||
|
"MetaHunt loaded. You're still a Huntard, but now you're an organized one.",
|
||||||
|
"Aspects, traps, tracking... Don't worry, I'll handle the hard parts.",
|
||||||
|
"Oh good, another hunter who needs an addon to remember their own spells.",
|
||||||
|
"MetaHunt ready. Feign Death is not a personality trait.",
|
||||||
|
"Loaded successfully. No, I can't fix your DPS.",
|
||||||
|
"Welcome. Your pet's loyalty is higher than your raid attendance.",
|
||||||
|
"MetaHunt online. Please don't Multishot the sheep.",
|
||||||
|
"Greetings, hunter. I see you've chosen the 'easy' class and still need help.",
|
||||||
|
"All systems go. Try not to pull the entire dungeon this time.",
|
||||||
|
"MetaHunt activated. Reminder: Melee range is not your home.",
|
||||||
|
"Welcome back. Your ammo count is almost as low as your situational awareness.",
|
||||||
|
"Loaded. I'll manage your buttons since you clearly have too many.",
|
||||||
|
"MetaHunt ready. Aspect of the Cheetah in dungeons is a choice, not a strategy.",
|
||||||
|
"Oh look, a hunter that uses addons. There might be hope for you yet.",
|
||||||
|
"Welcome. No, you cannot tame that. Or that. Stop asking.",
|
||||||
|
"MetaHunt standing by. Unlike you during your last Feign Death.",
|
||||||
|
"Initialized. Fun fact: your pet has more utility than you do.",
|
||||||
|
"All buttons configured. Now if only I could configure your aim.",
|
||||||
|
"MetaHunt loaded. Growl is off, right? ...RIGHT?",
|
||||||
|
"MetaHunt loaded. Your Freezing Trap will still break early. That's on you.",
|
||||||
|
"Welcome. Aspect of the Pack is ready. Your group is not.",
|
||||||
|
"Initializing... unlike your pet, I actually come when called.",
|
||||||
|
"MetaHunt online. Remember: Hunter loot is everything. Everything.",
|
||||||
|
"Loaded. Concussive Shot the flag carrier, not the rogue vanishing.",
|
||||||
|
"Welcome back. Eyes of the Beast is not a valid boss strategy.",
|
||||||
|
"Ready. Your Aimed Shot takes longer to cast than this addon took to load.",
|
||||||
|
"MetaHunt armed. Scatter Shot into Freezing Trap — you'll get it right someday.",
|
||||||
|
"Online. Don't worry, I track your cooldowns since you clearly don't.",
|
||||||
|
"Welcome. Wing Clip and run. It's what you do best.",
|
||||||
|
"Loaded. Distracting Shot is for the boss, not for your ego.",
|
||||||
|
"MetaHunt ready. Your quiver is full but your skill bar is empty.",
|
||||||
|
"Initialized. Serpent Sting on every target doesn't make you a DoT class.",
|
||||||
|
"Welcome, hunter. Viper Sting the healer. No, the OTHER healer.",
|
||||||
|
"Ready to hunt. Mend Pet is not optional, it's a lifestyle.",
|
||||||
|
"MetaHunt loaded. Tranquilizing Shot the enrage, not the warrior.",
|
||||||
|
"Online. Rapid Fire is a cooldown, not your approach to pulling.",
|
||||||
|
"Welcome. You have 28 arrows left. Should've checked before the raid.",
|
||||||
|
"Loaded. Bestial Wrath does not make YOU immune. Learned that yet?",
|
||||||
|
"MetaHunt standing by. Dead zone? What dead zone? Oh... that dead zone.",
|
||||||
}
|
}
|
||||||
|
|
||||||
local welcomeIndex = 1
|
local welcomeIndex = 1
|
||||||
@@ -1520,24 +1540,22 @@ function MTH:EnsureLoadCompleteAnnouncement()
|
|||||||
return self._loadCompleteFrame
|
return self._loadCompleteFrame
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame", "MTH_LoadCompleteAnnounceFrame")
|
local frame = CreateFrame("Frame", "MTH_LoadAnnounce")
|
||||||
if not frame then
|
if not frame then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
frame:SetScript("OnEvent", function(self, eventName)
|
frame:SetScript("OnEvent", function()
|
||||||
self = self or this
|
if event ~= "PLAYER_ENTERING_WORLD" then
|
||||||
eventName = eventName or event
|
|
||||||
if eventName ~= "PLAYER_ENTERING_WORLD" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if MTH and MTH.AnnounceLoadComplete then
|
if MTH and MTH.AnnounceLoadComplete then
|
||||||
MTH:AnnounceLoadComplete()
|
MTH:AnnounceLoadComplete()
|
||||||
end
|
end
|
||||||
if not self then return end
|
if not this then return end
|
||||||
self:UnregisterAllEvents()
|
this:UnregisterAllEvents()
|
||||||
self:SetScript("OnEvent", nil)
|
this:SetScript("OnEvent", nil)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self._loadCompleteFrame = frame
|
self._loadCompleteFrame = frame
|
||||||
|
|||||||
@@ -623,13 +623,11 @@ function MTH_PT_ApplyScan(triggerReason)
|
|||||||
local msg = "New pet data recorded (" .. tostring(added) .. " new rank(s)): " .. detailsText .. ". Known totals for this character: " .. tostring(totalBaselines) .. " ability type(s), " .. tostring(totalRanks) .. " rank(s)."
|
local msg = "New pet data recorded (" .. tostring(added) .. " new rank(s)): " .. detailsText .. ". Known totals for this character: " .. tostring(totalBaselines) .. " ability type(s), " .. tostring(totalRanks) .. " rank(s)."
|
||||||
if MTH_PT_IsScanMessageEnabled() then
|
if MTH_PT_IsScanMessageEnabled() then
|
||||||
MTH:Print(msg)
|
MTH:Print(msg)
|
||||||
MTH:Print("INFO: " .. msg, "debug")
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local msg = "New pet data recorded (" .. tostring(added) .. " new rank(s)). Known totals for this character: " .. tostring(totalBaselines) .. " ability type(s), " .. tostring(totalRanks) .. " rank(s)."
|
local msg = "New pet data recorded (" .. tostring(added) .. " new rank(s)). Known totals for this character: " .. tostring(totalBaselines) .. " ability type(s), " .. tostring(totalRanks) .. " rank(s)."
|
||||||
if MTH_PT_IsScanMessageEnabled() then
|
if MTH_PT_IsScanMessageEnabled() then
|
||||||
MTH:Print(msg)
|
MTH:Print(msg)
|
||||||
MTH:Print("INFO: " .. msg, "debug")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -802,7 +800,7 @@ function MTH_PT_InitService()
|
|||||||
if MTH_PetTrainingFrame then
|
if MTH_PetTrainingFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
MTH_PetTrainingFrame = CreateFrame("Frame", "MTHPetTrainingScanFrame")
|
MTH_PetTrainingFrame = CreateFrame("Frame", "MTH_PetTrainingScan")
|
||||||
MTH_PetTrainingFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
MTH_PetTrainingFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
MTH_PetTrainingFrame:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
MTH_PetTrainingFrame:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||||
MTH_PetTrainingFrame:RegisterEvent("PET_TRAINING_SHOW")
|
MTH_PetTrainingFrame:RegisterEvent("PET_TRAINING_SHOW")
|
||||||
@@ -813,9 +811,8 @@ function MTH_PT_InitService()
|
|||||||
MTH_PetTrainingFrame:RegisterEvent("CRAFT_SHOW")
|
MTH_PetTrainingFrame:RegisterEvent("CRAFT_SHOW")
|
||||||
MTH_PetTrainingFrame:RegisterEvent("CRAFT_UPDATE")
|
MTH_PetTrainingFrame:RegisterEvent("CRAFT_UPDATE")
|
||||||
MTH_PetTrainingFrame:SetScript("OnEvent", MTH_PT_OnEvent)
|
MTH_PetTrainingFrame:SetScript("OnEvent", MTH_PT_OnEvent)
|
||||||
MTH_PetTrainingFrame:SetScript("OnUpdate", function(_, elapsed)
|
MTH_PetTrainingFrame:SetScript("OnUpdate", function()
|
||||||
elapsed = elapsed or arg1
|
MTH_PT_PetBookPollElapsed = (MTH_PT_PetBookPollElapsed or 0) + (arg1 or 0)
|
||||||
MTH_PT_PetBookPollElapsed = (MTH_PT_PetBookPollElapsed or 0) + (elapsed or 0)
|
|
||||||
if MTH_PT_PetBookPollElapsed < 0.20 then
|
if MTH_PT_PetBookPollElapsed < 0.20 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -861,19 +858,16 @@ function MTH_PT_InitBootstrap()
|
|||||||
end
|
end
|
||||||
frame:RegisterEvent("PET_TRAINING_SHOW")
|
frame:RegisterEvent("PET_TRAINING_SHOW")
|
||||||
frame:RegisterEvent("CRAFT_SHOW")
|
frame:RegisterEvent("CRAFT_SHOW")
|
||||||
frame:SetScript("OnEvent", function(self, evt)
|
frame:SetScript("OnEvent", function()
|
||||||
evt = evt or event
|
if event ~= "PET_TRAINING_SHOW" and event ~= "CRAFT_SHOW" then
|
||||||
if evt ~= "PET_TRAINING_SHOW" and evt ~= "CRAFT_SHOW" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
MTH_PT_InitService()
|
MTH_PT_InitService()
|
||||||
if type(MTH_PT_OnEvent) == "function" then
|
if type(MTH_PT_OnEvent) == "function" then
|
||||||
MTH_PT_OnEvent(MTH_PetTrainingFrame, evt)
|
MTH_PT_OnEvent(MTH_PetTrainingFrame, event)
|
||||||
end
|
|
||||||
if self and self.UnregisterAllEvents then
|
|
||||||
self:UnregisterAllEvents()
|
|
||||||
self:SetScript("OnEvent", nil)
|
|
||||||
end
|
end
|
||||||
|
this:UnregisterAllEvents()
|
||||||
|
this:SetScript("OnEvent", nil)
|
||||||
MTH_PT_BootstrapFrame = nil
|
MTH_PT_BootstrapFrame = nil
|
||||||
end)
|
end)
|
||||||
MTH_PT_BootstrapFrame = frame
|
MTH_PT_BootstrapFrame = frame
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
------------------------------------------------------
|
||||||
|
-- MetaHunt: Hunter Talent & Spellbook Scanner
|
||||||
|
-- Runs once on login and re-runs when spells/talents change.
|
||||||
|
--
|
||||||
|
-- Exposes:
|
||||||
|
-- MTH_HT_GetTalentRank(talentName) → currentRank (0 if unlearned)
|
||||||
|
-- MTH_HT_HasTalent(talentName) → true if rank >= 1
|
||||||
|
-- MTH_HT_GetSpellInfo(spellName) → { slot, rank, rankNum } or nil
|
||||||
|
-- MTH_HT_RescanTalents() → force re-scan of all talent tabs
|
||||||
|
-- MTH_HT_RescanSpellbook() → force re-scan of spellbook
|
||||||
|
--
|
||||||
|
-- Results cached in:
|
||||||
|
-- MTH_HT_Talents["TalentName"] = { tab, idx, rank, maxRank }
|
||||||
|
-- MTH_HT_Spells["SpellName"] = { slot, rank, rankNum }
|
||||||
|
-- (spell entry is the *highest rank* known for that name)
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
MTH_HT_Talents = {}
|
||||||
|
MTH_HT_Spells = {}
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- Talent scanner
|
||||||
|
-- Uses GetNumTalentTabs / GetNumTalents / GetTalentInfo (all vanilla 1.12)
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function MTH_HT_RescanTalents()
|
||||||
|
MTH_HT_Talents = {}
|
||||||
|
|
||||||
|
local numTabs = GetNumTalentTabs and GetNumTalentTabs() or 0
|
||||||
|
for tabIdx = 1, numTabs do
|
||||||
|
local numTalents = GetNumTalents and GetNumTalents(tabIdx) or 0
|
||||||
|
for talIdx = 1, numTalents do
|
||||||
|
local name, _, _, _, currentRank, maxRank = GetTalentInfo(tabIdx, talIdx)
|
||||||
|
if name and name ~= "" then
|
||||||
|
local existing = MTH_HT_Talents[name]
|
||||||
|
-- If the same name appears in multiple tabs (unlikely), keep highest rank.
|
||||||
|
if not existing or (tonumber(currentRank) or 0) > (existing.rank or 0) then
|
||||||
|
MTH_HT_Talents[name] = {
|
||||||
|
tab = tabIdx,
|
||||||
|
idx = talIdx,
|
||||||
|
rank = tonumber(currentRank) or 0,
|
||||||
|
maxRank = tonumber(maxRank) or 0,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- Spellbook scanner
|
||||||
|
-- Iterates all player spell tabs and caches every known spell by name.
|
||||||
|
-- Stores the highest rank found (so MTH_HT_Spells["Aimed Shot"].slot is
|
||||||
|
-- always the actionable rank the player actually has).
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local function MTH_HT_ParseRankNum(rankStr)
|
||||||
|
if not rankStr or rankStr == "" then return 0 end
|
||||||
|
local _, _, n = string.find(tostring(rankStr), "(%d+)")
|
||||||
|
return tonumber(n) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_HT_RescanSpellbook()
|
||||||
|
MTH_HT_Spells = {}
|
||||||
|
|
||||||
|
local numTabs = GetNumSpellTabs and GetNumSpellTabs() or 0
|
||||||
|
for tabIdx = 1, numTabs do
|
||||||
|
local _, _, offset, numSpells = GetSpellTabInfo(tabIdx)
|
||||||
|
for i = 1, numSpells do
|
||||||
|
local slot = offset + i
|
||||||
|
local name, rank = GetSpellName(slot, BOOKTYPE_SPELL)
|
||||||
|
if name and name ~= "" then
|
||||||
|
local rankNum = MTH_HT_ParseRankNum(rank)
|
||||||
|
local existing = MTH_HT_Spells[name]
|
||||||
|
if not existing or rankNum > (existing.rankNum or 0) then
|
||||||
|
MTH_HT_Spells[name] = {
|
||||||
|
slot = slot,
|
||||||
|
rank = rank or "",
|
||||||
|
rankNum = rankNum,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- Public accessors
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function MTH_HT_GetTalentRank(talentName)
|
||||||
|
local entry = MTH_HT_Talents[tostring(talentName or "")]
|
||||||
|
return entry and (entry.rank or 0) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_HT_HasTalent(talentName)
|
||||||
|
return MTH_HT_GetTalentRank(talentName) >= 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_HT_GetSpellInfo(spellName)
|
||||||
|
return MTH_HT_Spells[tostring(spellName or "")]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- Event-driven scanning
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local MTH_HT_Frame = CreateFrame("Frame", "MTH_HunterTalentScanFrame")
|
||||||
|
|
||||||
|
local MTH_HT_NeedTalentRescan = false
|
||||||
|
local MTH_HT_NeedSpellRescan = false
|
||||||
|
local MTH_HT_RescanDelay = 0.6 -- seconds after event before scanning
|
||||||
|
local MTH_HT_RescanElapsed = 0
|
||||||
|
|
||||||
|
MTH_HT_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
|
MTH_HT_Frame:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||||
|
MTH_HT_Frame:RegisterEvent("SPELLS_CHANGED")
|
||||||
|
MTH_HT_Frame:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||||
|
|
||||||
|
MTH_HT_Frame:SetScript("OnEvent", function()
|
||||||
|
if event == "PLAYER_ENTERING_WORLD" then
|
||||||
|
-- Immediate scan on login
|
||||||
|
MTH_HT_RescanTalents()
|
||||||
|
MTH_HT_RescanSpellbook()
|
||||||
|
if type(MTH_HT_OnScanComplete) == "function" then
|
||||||
|
MTH_HT_OnScanComplete()
|
||||||
|
end
|
||||||
|
-- Also schedule a deferred re-scan: GetTalentInfo can return stale
|
||||||
|
-- data for a brief window after PLAYER_ENTERING_WORLD on login.
|
||||||
|
MTH_HT_NeedTalentRescan = true
|
||||||
|
MTH_HT_NeedSpellRescan = true
|
||||||
|
MTH_HT_RescanElapsed = 0
|
||||||
|
this:Show() -- enable OnUpdate for the deferred pass
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- For other events, schedule a deferred rescan so we don't fire
|
||||||
|
-- multiple times if several events arrive in the same frame.
|
||||||
|
if event == "CHARACTER_POINTS_CHANGED" then
|
||||||
|
MTH_HT_NeedTalentRescan = true
|
||||||
|
end
|
||||||
|
if event == "LEARNED_SPELL_IN_TAB" or event == "SPELLS_CHANGED" then
|
||||||
|
MTH_HT_NeedSpellRescan = true
|
||||||
|
end
|
||||||
|
MTH_HT_RescanElapsed = 0
|
||||||
|
this:Show()
|
||||||
|
end)
|
||||||
|
|
||||||
|
MTH_HT_Frame:SetScript("OnUpdate", function()
|
||||||
|
MTH_HT_RescanElapsed = (MTH_HT_RescanElapsed or 0) + (arg1 or 0)
|
||||||
|
if MTH_HT_RescanElapsed < MTH_HT_RescanDelay then return end
|
||||||
|
|
||||||
|
-- Batch-flush pending scans
|
||||||
|
if MTH_HT_NeedTalentRescan then
|
||||||
|
MTH_HT_RescanTalents()
|
||||||
|
MTH_HT_NeedTalentRescan = false
|
||||||
|
end
|
||||||
|
if MTH_HT_NeedSpellRescan then
|
||||||
|
MTH_HT_RescanSpellbook()
|
||||||
|
MTH_HT_NeedSpellRescan = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Notify dependents
|
||||||
|
if type(MTH_HT_OnScanComplete) == "function" then
|
||||||
|
MTH_HT_OnScanComplete()
|
||||||
|
end
|
||||||
|
|
||||||
|
this:Hide()
|
||||||
|
MTH_HT_RescanElapsed = 0
|
||||||
|
end)
|
||||||
|
|
||||||
|
MTH_HT_Frame:Hide()
|
||||||
@@ -331,7 +331,7 @@ function MTH_PS_InitService()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_PS_Frame = CreateFrame("Frame", "MTHPetSpellbookEventFrame")
|
MTH_PS_Frame = CreateFrame("Frame", "MTH_PetSpellbookEvent")
|
||||||
MTH_PS_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
MTH_PS_Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
MTH_PS_Frame:RegisterEvent("UNIT_PET")
|
MTH_PS_Frame:RegisterEvent("UNIT_PET")
|
||||||
MTH_PS_Frame:RegisterEvent("PET_BAR_UPDATE")
|
MTH_PS_Frame:RegisterEvent("PET_BAR_UPDATE")
|
||||||
|
|||||||
+503
-145
@@ -4,6 +4,7 @@ end
|
|||||||
|
|
||||||
local MTH_PETS_SCHEMA_VERSION = 2
|
local MTH_PETS_SCHEMA_VERSION = 2
|
||||||
local MTH_PETS_CORE_HOOK_BOUNDARY_KEY = "core-pet-rename-hook"
|
local MTH_PETS_CORE_HOOK_BOUNDARY_KEY = "core-pet-rename-hook"
|
||||||
|
local MTH_ST_FULL_DEBUG_TRACE = false
|
||||||
MTH_PETS_TRACE_CONSISTENCY = false
|
MTH_PETS_TRACE_CONSISTENCY = false
|
||||||
|
|
||||||
local MTH_PetLifecycleEventFrame = nil
|
local MTH_PetLifecycleEventFrame = nil
|
||||||
@@ -24,8 +25,8 @@ local MTH_ST_Profile = {
|
|||||||
runawayMaxMs = 0,
|
runawayMaxMs = 0,
|
||||||
}
|
}
|
||||||
local MTH_ST_Trace = {
|
local MTH_ST_Trace = {
|
||||||
enabled = false,
|
enabled = MTH_ST_FULL_DEBUG_TRACE and true or false,
|
||||||
verbose = false,
|
verbose = MTH_ST_FULL_DEBUG_TRACE and true or false,
|
||||||
windowStart = 0,
|
windowStart = 0,
|
||||||
windowSeconds = 5,
|
windowSeconds = 5,
|
||||||
eventCount = 0,
|
eventCount = 0,
|
||||||
@@ -36,7 +37,7 @@ local MTH_ST_Trace = {
|
|||||||
local MTH_ST_Diag = {
|
local MTH_ST_Diag = {
|
||||||
lines = {},
|
lines = {},
|
||||||
maxLines = 200,
|
maxLines = 200,
|
||||||
chatEcho = false,
|
chatEcho = MTH_ST_FULL_DEBUG_TRACE and true or false,
|
||||||
}
|
}
|
||||||
local MTH_ST_DiagCopyFrame = nil
|
local MTH_ST_DiagCopyFrame = nil
|
||||||
local MTH_ST_PrintStableDiag
|
local MTH_ST_PrintStableDiag
|
||||||
@@ -179,7 +180,7 @@ local function MTH_ST_EnsureDiagCopyFrame()
|
|||||||
if MTH_ST_DiagCopyFrame then
|
if MTH_ST_DiagCopyFrame then
|
||||||
return MTH_ST_DiagCopyFrame
|
return MTH_ST_DiagCopyFrame
|
||||||
end
|
end
|
||||||
local frame = CreateFrame("Frame", "MTHStableDiagCopyFrame", UIParent)
|
local frame = CreateFrame("Frame", "MTH_StableDiagCopy", UIParent)
|
||||||
if not frame then
|
if not frame then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -219,11 +220,11 @@ local function MTH_ST_EnsureDiagCopyFrame()
|
|||||||
copyButton:SetHeight(24)
|
copyButton:SetHeight(24)
|
||||||
copyButton:SetText("Select All")
|
copyButton:SetText("Select All")
|
||||||
|
|
||||||
local scrollFrame = CreateFrame("ScrollFrame", "MTHStableDiagCopyScroll", frame, "UIPanelScrollFrameTemplate")
|
local scrollFrame = CreateFrame("ScrollFrame", "MTH_StableDiagScroll", frame, "UIPanelScrollFrameTemplate")
|
||||||
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -48)
|
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 16, -48)
|
||||||
scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -36, 44)
|
scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -36, 44)
|
||||||
|
|
||||||
local editBox = CreateFrame("EditBox", "MTHStableDiagCopyText", scrollFrame)
|
local editBox = CreateFrame("EditBox", "MTH_StableDiagText", scrollFrame)
|
||||||
editBox:SetMultiLine(true)
|
editBox:SetMultiLine(true)
|
||||||
editBox:SetMaxLetters(999999)
|
editBox:SetMaxLetters(999999)
|
||||||
editBox:SetFont("Fonts\\FRIZQT__.TTF", 11, "")
|
editBox:SetFont("Fonts\\FRIZQT__.TTF", 11, "")
|
||||||
@@ -255,34 +256,40 @@ local function MTH_ST_EnsureDiagCopyFrame()
|
|||||||
if UISpecialFrames then
|
if UISpecialFrames then
|
||||||
local exists = false
|
local exists = false
|
||||||
for i = 1, table.getn(UISpecialFrames) do
|
for i = 1, table.getn(UISpecialFrames) do
|
||||||
if UISpecialFrames[i] == "MTHStableDiagCopyFrame" then
|
if UISpecialFrames[i] == "MTH_StableDiagCopy" then
|
||||||
exists = true
|
exists = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not exists then
|
if not exists then
|
||||||
table.insert(UISpecialFrames, "MTHStableDiagCopyFrame")
|
table.insert(UISpecialFrames, "MTH_StableDiagCopy")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return frame
|
return frame
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_CommandStableDiag(mode)
|
function MTH_CommandStableDiag(mode)
|
||||||
|
local lowerMode = string.lower(tostring(mode or "on"))
|
||||||
MTH_ST_Diag.lines = {}
|
MTH_ST_Diag.lines = {}
|
||||||
MTH_ST_Diag.chatEcho = false
|
MTH_ST_Diag.chatEcho = (lowerMode ~= "off") and true or false
|
||||||
if MTH and MTH.Print then
|
if MTH and MTH.Print then
|
||||||
MTH:Print("Stable diagnostics are disabled.")
|
MTH:Print("Stable diagnostics chat echo " .. (MTH_ST_Diag.chatEcho and "enabled" or "disabled") .. ".", "debug")
|
||||||
end
|
end
|
||||||
return false
|
return MTH_ST_Diag.chatEcho
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_CommandStableTrace(mode)
|
function MTH_CommandStableTrace(mode)
|
||||||
MTH_ST_Trace.enabled = false
|
local lowerMode = string.lower(tostring(mode or "verbose"))
|
||||||
MTH_ST_Trace.verbose = false
|
MTH_ST_Trace.enabled = (lowerMode ~= "off") and true or false
|
||||||
if MTH and MTH.Print then
|
MTH_ST_Trace.verbose = (lowerMode == "verbose" or lowerMode == "on") and MTH_ST_Trace.enabled or false
|
||||||
MTH:Print("Stable trace is disabled.")
|
if MTH_ST_Trace.enabled then
|
||||||
|
MTH_ST_TraceResetCounters()
|
||||||
end
|
end
|
||||||
return false
|
if MTH and MTH.Print then
|
||||||
|
MTH:Print("Stable trace " .. (MTH_ST_Trace.enabled and "enabled" or "disabled")
|
||||||
|
.. " (verbose=" .. tostring(MTH_ST_Trace.verbose) .. ").", "debug")
|
||||||
|
end
|
||||||
|
return MTH_ST_Trace.enabled
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_ST_ProfileNow()
|
local function MTH_ST_ProfileNow()
|
||||||
@@ -418,18 +425,27 @@ local function MTH_ST_ProfileFlushIfDue(force)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MTH_CommandStableProfile(mode)
|
function MTH_CommandStableProfile(mode)
|
||||||
MTH_ST_Profile.enabled = false
|
local lowerMode = string.lower(tostring(mode or "off"))
|
||||||
if MTH and MTH.Print then
|
MTH_ST_Profile.enabled = (lowerMode ~= "off") and true or false
|
||||||
MTH:Print("Stable profiler is disabled.")
|
if MTH_ST_Profile.enabled then
|
||||||
|
MTH_ST_ProfileResetCounters()
|
||||||
end
|
end
|
||||||
return false
|
if MTH and MTH.Print then
|
||||||
|
MTH:Print("Stable profiler " .. (MTH_ST_Profile.enabled and "enabled" or "disabled") .. ".", "debug")
|
||||||
|
end
|
||||||
|
return MTH_ST_Profile.enabled
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_PETS_LogConsistency(line)
|
local function MTH_PETS_LogConsistency(line)
|
||||||
return
|
if not MTH_PETS_TRACE_CONSISTENCY then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if MTH and MTH.Print then
|
||||||
|
MTH:Print("[PETS] " .. tostring(line or ""), "debug")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_PETS_LogTame(line)
|
local function MTH_PETS_LogTame(_)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -816,6 +832,30 @@ local function MTH_PETS_NormalizeSystemMessageKey(rawMessage)
|
|||||||
return message
|
return message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_GetUnitGuid(unitToken)
|
||||||
|
local token = tostring(unitToken or "")
|
||||||
|
if token == "" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local getUnitGuid = (type(getglobal) == "function" and getglobal("GetUnitGUID")) or (_G and _G["GetUnitGUID"])
|
||||||
|
if type(getUnitGuid) == "function" then
|
||||||
|
local ok, guid = pcall(getUnitGuid, token)
|
||||||
|
if ok and type(guid) == "string" and guid ~= "" then
|
||||||
|
return guid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(UnitGUID) == "function" then
|
||||||
|
local ok, guid = pcall(UnitGUID, token)
|
||||||
|
if ok and type(guid) == "string" and guid ~= "" then
|
||||||
|
return guid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_PETS_IsRunawaySystemMessage(rawMessage)
|
local function MTH_PETS_IsRunawaySystemMessage(rawMessage)
|
||||||
local message = MTH_PETS_NormalizeSystemMessage(rawMessage)
|
local message = MTH_PETS_NormalizeSystemMessage(rawMessage)
|
||||||
if message == "" then
|
if message == "" then
|
||||||
@@ -856,11 +896,21 @@ local function MTH_PETS_ParseCreatureIdFromGuid(guid)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TBC-style string GUID: "Creature-realm-map-inst-?-ENTRY-spawn"
|
||||||
local _, _, creatureIdText = string.find(guidText, "^Creature%-%d+%-%d+%-%d+%-%d+%-(%d+)%-%d+$")
|
local _, _, creatureIdText = string.find(guidText, "^Creature%-%d+%-%d+%-%d+%-%d+%-(%d+)%-%d+$")
|
||||||
if creatureIdText then
|
if creatureIdText then
|
||||||
return tonumber(creatureIdText)
|
return tonumber(creatureIdText)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Vanilla/TurtleWoW hex GUID: "0xF130EEEEEECCCCCC" — entry is bits 24-47 (hex chars 7-12)
|
||||||
|
if string.sub(guidText, 1, 2) == "0x" and string.len(guidText) >= 14 then
|
||||||
|
local entryHex = string.sub(guidText, 7, 12)
|
||||||
|
local parsed = tonumber(entryHex, 16)
|
||||||
|
if parsed and parsed > 0 then
|
||||||
|
return parsed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -971,7 +1021,7 @@ local function MTH_PETS_CaptureTargetSnapshot()
|
|||||||
if MTH_PETS_IsPlaceholderPetName(targetName) then
|
if MTH_PETS_IsPlaceholderPetName(targetName) then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local targetGuid = (type(UnitGUID) == "function") and UnitGUID("target") or nil
|
local targetGuid = MTH_PETS_GetUnitGuid("target")
|
||||||
local beastId = MTH_PETS_ParseCreatureIdFromGuid(targetGuid)
|
local beastId = MTH_PETS_ParseCreatureIdFromGuid(targetGuid)
|
||||||
local targetFamily = (type(UnitCreatureFamily) == "function") and UnitCreatureFamily("target") or nil
|
local targetFamily = (type(UnitCreatureFamily) == "function") and UnitCreatureFamily("target") or nil
|
||||||
local targetLevel = (type(UnitLevel) == "function") and UnitLevel("target") or nil
|
local targetLevel = (type(UnitLevel) == "function") and UnitLevel("target") or nil
|
||||||
@@ -1185,6 +1235,22 @@ local function MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_IsTameConfirmationSource(source)
|
||||||
|
local sourceText = tostring(source or "")
|
||||||
|
return sourceText == "unit-pet-acquire" or sourceText == "refresh-current-pet"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_ResolveConfirmedTameBeastId(source, snapshot)
|
||||||
|
if not MTH_PETS_IsTameConfirmationSource(source) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local resolved = MTH_PETS_GetPendingTameBeastId(snapshot)
|
||||||
|
if resolved and resolved > 0 then
|
||||||
|
return resolved
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_PETS_MakeSignature(name, family, level)
|
local function MTH_PETS_MakeSignature(name, family, level)
|
||||||
local cleanName = MTH_PETS_SafeLower(MTH_PETS_NormalizeText(name))
|
local cleanName = MTH_PETS_SafeLower(MTH_PETS_NormalizeText(name))
|
||||||
local cleanFamily = MTH_PETS_SafeLower(MTH_PETS_NormalizeText(family))
|
local cleanFamily = MTH_PETS_SafeLower(MTH_PETS_NormalizeText(family))
|
||||||
@@ -1192,7 +1258,7 @@ local function MTH_PETS_MakeSignature(name, family, level)
|
|||||||
return cleanName .. "|" .. cleanFamily .. "|" .. tostring(numericLevel)
|
return cleanName .. "|" .. cleanFamily .. "|" .. tostring(numericLevel)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_PETS_RowHasTameRecord(row)
|
local function MTH_PETS_RowHasAnyTameMetadata(row)
|
||||||
if type(row) ~= "table" then
|
if type(row) ~= "table" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -1211,11 +1277,33 @@ local function MTH_PETS_RowHasTameRecord(row)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH_PETS_HasVerifiedTameRecord(row)
|
||||||
|
if type(row) ~= "table" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if row.tameVerified == true then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local legacyTameContext = type(row.tameContext) == "table" and row.tameContext or nil
|
||||||
|
if legacyTameContext and (legacyTameContext.name or legacyTameContext.zone or legacyTameContext.timestamp) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if type(row.events) == "table" then
|
||||||
|
for i = 1, table.getn(row.events) do
|
||||||
|
local ev = row.events[i]
|
||||||
|
if type(ev) == "table" and tostring(ev.type or "") == "pet-tamed" then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_PETS_BackfillTameMetadataFromEvents(row)
|
local function MTH_PETS_BackfillTameMetadataFromEvents(row)
|
||||||
if type(row) ~= "table" then
|
if type(row) ~= "table" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if MTH_PETS_RowHasTameRecord(row) then
|
if MTH_PETS_HasVerifiedTameRecord(row) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if type(row.events) ~= "table" then
|
if type(row.events) ~= "table" then
|
||||||
@@ -1226,7 +1314,7 @@ local function MTH_PETS_BackfillTameMetadataFromEvents(row)
|
|||||||
local stableFirstSeenAt = tonumber(row.stableFirstSeenAt) or tonumber(row.stabledAt) or 0
|
local stableFirstSeenAt = tonumber(row.stableFirstSeenAt) or tonumber(row.stabledAt) or 0
|
||||||
for i = 1, table.getn(row.events) do
|
for i = 1, table.getn(row.events) do
|
||||||
local ev = row.events[i]
|
local ev = row.events[i]
|
||||||
if type(ev) == "table" and tostring(ev.type or "") == "pet-acquired" then
|
if type(ev) == "table" and tostring(ev.type or "") == "pet-tamed" then
|
||||||
local evAt = tonumber(ev.at) or 0
|
local evAt = tonumber(ev.at) or 0
|
||||||
local timelineOk = true
|
local timelineOk = true
|
||||||
if stableFirstSeenAt > 0 and evAt > 0 and evAt > stableFirstSeenAt then
|
if stableFirstSeenAt > 0 and evAt > 0 and evAt > stableFirstSeenAt then
|
||||||
@@ -1294,12 +1382,204 @@ local function MTH_PETS_BackfillTameMetadataFromEvents(row)
|
|||||||
|
|
||||||
if changed then
|
if changed then
|
||||||
row.tameRecorded = true
|
row.tameRecorded = true
|
||||||
|
row.tameVerified = true
|
||||||
row.lastUpdated = time()
|
row.lastUpdated = time()
|
||||||
end
|
end
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_ParseNumericPetId(petId)
|
||||||
|
local _, _, numericId = string.find(tostring(petId or ""), "^pet%-(%d+)$")
|
||||||
|
return tonumber(numericId)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_GetActiveRowRepairScore(pets, petId, row)
|
||||||
|
if type(row) ~= "table" then
|
||||||
|
return -1, 0
|
||||||
|
end
|
||||||
|
local score = 0
|
||||||
|
local resolvedPetId = tostring(petId or "")
|
||||||
|
local petStore = type(pets) == "table" and pets.petStore or nil
|
||||||
|
if resolvedPetId ~= "" and tostring((pets and pets.currentPetId) or "") == resolvedPetId then
|
||||||
|
score = score + 1000000
|
||||||
|
end
|
||||||
|
if resolvedPetId ~= "" and type(petStore) == "table" and tostring(petStore.activeCurrentId or "") == resolvedPetId then
|
||||||
|
score = score + 900000
|
||||||
|
end
|
||||||
|
if tonumber(row.stableSlot) and tonumber(row.stableSlot) > 0 then
|
||||||
|
score = score + 500000
|
||||||
|
end
|
||||||
|
if type(row.guid) == "string" and row.guid ~= "" then
|
||||||
|
score = score + 100000
|
||||||
|
end
|
||||||
|
if row.tameVerified == true then
|
||||||
|
score = score + 50000
|
||||||
|
end
|
||||||
|
if row.tameRecorded == true then
|
||||||
|
score = score + 10000
|
||||||
|
end
|
||||||
|
score = score + (tonumber(row.lastSeen) or tonumber(row.lastUpdated) or 0)
|
||||||
|
return score, tonumber(MTH_PETS_ParseNumericPetId(resolvedPetId)) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_MergeActiveRows(pets, winnerId, loserId)
|
||||||
|
if type(pets) ~= "table" or type(pets.petStore) ~= "table" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local petStore = pets.petStore
|
||||||
|
local winnerRow = type(petStore.activeById) == "table" and petStore.activeById[winnerId] or nil
|
||||||
|
local loserRow = type(petStore.activeById) == "table" and petStore.activeById[loserId] or nil
|
||||||
|
if type(winnerRow) ~= "table" or type(loserRow) ~= "table" or tostring(winnerId) == tostring(loserId) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local copyIfMissingFields = {
|
||||||
|
"guid", "signature", "beastId", "name", "family", "level",
|
||||||
|
"happiness", "loyalty", "loyaltyLevel", "xp", "xpMax", "xpPercent",
|
||||||
|
"origin", "originContext", "previousName", "stableRaw", "stableInfo",
|
||||||
|
"zone", "subZone", "x", "y", "hunterLevel", "lastSource",
|
||||||
|
"tameHunterLevel", "tameZone", "tameSubZone", "tameX", "tameY",
|
||||||
|
"tameBeastId", "tameContext",
|
||||||
|
}
|
||||||
|
for i = 1, table.getn(copyIfMissingFields) do
|
||||||
|
local field = copyIfMissingFields[i]
|
||||||
|
local winnerValue = winnerRow[field]
|
||||||
|
if winnerValue == nil or winnerValue == "" then
|
||||||
|
local loserValue = loserRow[field]
|
||||||
|
if loserValue ~= nil and loserValue ~= "" then
|
||||||
|
winnerRow[field] = loserValue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(winnerRow.petSpellbook) ~= "table" and type(loserRow.petSpellbook) == "table" then
|
||||||
|
winnerRow.petSpellbook = loserRow.petSpellbook
|
||||||
|
winnerRow.lastPetSpellbookSkipAt = winnerRow.lastPetSpellbookSkipAt or loserRow.lastPetSpellbookSkipAt
|
||||||
|
winnerRow.lastPetSpellbookSkipSource = winnerRow.lastPetSpellbookSkipSource or loserRow.lastPetSpellbookSkipSource
|
||||||
|
winnerRow.lastPetSpellbookSkipReason = winnerRow.lastPetSpellbookSkipReason or loserRow.lastPetSpellbookSkipReason
|
||||||
|
end
|
||||||
|
if type(winnerRow.abilities) ~= "table" then
|
||||||
|
winnerRow.abilities = {}
|
||||||
|
end
|
||||||
|
if type(loserRow.abilities) == "table" then
|
||||||
|
for token, ability in pairs(loserRow.abilities) do
|
||||||
|
if winnerRow.abilities[token] == nil then
|
||||||
|
winnerRow.abilities[token] = ability
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(winnerRow.events) ~= "table" then
|
||||||
|
winnerRow.events = {}
|
||||||
|
end
|
||||||
|
if type(loserRow.events) == "table" then
|
||||||
|
for i = 1, table.getn(loserRow.events) do
|
||||||
|
table.insert(winnerRow.events, loserRow.events[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local winnerCreatedAt = tonumber(winnerRow.createdAt) or 0
|
||||||
|
local loserCreatedAt = tonumber(loserRow.createdAt) or 0
|
||||||
|
if winnerCreatedAt <= 0 or (loserCreatedAt > 0 and loserCreatedAt < winnerCreatedAt) then
|
||||||
|
winnerRow.createdAt = loserCreatedAt > 0 and loserCreatedAt or winnerRow.createdAt
|
||||||
|
end
|
||||||
|
local winnerFirstSeen = tonumber(winnerRow.firstSeen) or 0
|
||||||
|
local loserFirstSeen = tonumber(loserRow.firstSeen) or 0
|
||||||
|
if winnerFirstSeen <= 0 or (loserFirstSeen > 0 and loserFirstSeen < winnerFirstSeen) then
|
||||||
|
winnerRow.firstSeen = loserFirstSeen > 0 and loserFirstSeen or winnerRow.firstSeen
|
||||||
|
end
|
||||||
|
local winnerLastSeen = tonumber(winnerRow.lastSeen) or 0
|
||||||
|
local loserLastSeen = tonumber(loserRow.lastSeen) or 0
|
||||||
|
if loserLastSeen > winnerLastSeen then
|
||||||
|
winnerRow.lastSeen = loserLastSeen
|
||||||
|
end
|
||||||
|
local winnerLastUpdated = tonumber(winnerRow.lastUpdated) or 0
|
||||||
|
local loserLastUpdated = tonumber(loserRow.lastUpdated) or 0
|
||||||
|
if loserLastUpdated > winnerLastUpdated then
|
||||||
|
winnerRow.lastUpdated = loserLastUpdated
|
||||||
|
end
|
||||||
|
|
||||||
|
if winnerRow.tameVerified ~= true and loserRow.tameVerified == true then
|
||||||
|
winnerRow.tameVerified = true
|
||||||
|
winnerRow.tameRecorded = true
|
||||||
|
winnerRow.tamedAt = winnerRow.tamedAt or loserRow.tamedAt
|
||||||
|
winnerRow.tameHunterLevel = winnerRow.tameHunterLevel or loserRow.tameHunterLevel
|
||||||
|
winnerRow.tameZone = winnerRow.tameZone or loserRow.tameZone
|
||||||
|
winnerRow.tameSubZone = winnerRow.tameSubZone or loserRow.tameSubZone
|
||||||
|
winnerRow.tameX = winnerRow.tameX or loserRow.tameX
|
||||||
|
winnerRow.tameY = winnerRow.tameY or loserRow.tameY
|
||||||
|
winnerRow.tameBeastId = winnerRow.tameBeastId or loserRow.tameBeastId
|
||||||
|
end
|
||||||
|
|
||||||
|
if (winnerRow.stableSlot == nil or tonumber(winnerRow.stableSlot) == nil or tonumber(winnerRow.stableSlot) <= 0)
|
||||||
|
and tonumber(loserRow.stableSlot) and tonumber(loserRow.stableSlot) > 0 then
|
||||||
|
winnerRow.stableSlot = tonumber(loserRow.stableSlot)
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(petStore.stableSlotIndex) == "table" then
|
||||||
|
for slotNumber, mappedPetId in pairs(petStore.stableSlotIndex) do
|
||||||
|
if tostring(mappedPetId or "") == tostring(loserId) then
|
||||||
|
petStore.stableSlotIndex[slotNumber] = tostring(winnerId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if tostring(petStore.activeCurrentId or "") == tostring(loserId) then
|
||||||
|
petStore.activeCurrentId = tostring(winnerId)
|
||||||
|
end
|
||||||
|
if tostring(pets.currentPetId or "") == tostring(loserId) then
|
||||||
|
pets.currentPetId = tostring(winnerId)
|
||||||
|
end
|
||||||
|
if type(pets.currentPet) == "table" and tostring(pets.currentPet.id or "") == tostring(loserId) then
|
||||||
|
pets.currentPet.id = tostring(winnerId)
|
||||||
|
end
|
||||||
|
|
||||||
|
petStore.activeById[loserId] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_RepairActiveRowsByGuid(pets)
|
||||||
|
if type(pets) ~= "table" or type(pets.petStore) ~= "table" or type(pets.petStore.activeById) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local groupedByGuid = {}
|
||||||
|
for petId, row in pairs(pets.petStore.activeById) do
|
||||||
|
if type(row) == "table" and type(row.guid) == "string" and row.guid ~= "" then
|
||||||
|
local guid = row.guid
|
||||||
|
if type(groupedByGuid[guid]) ~= "table" then
|
||||||
|
groupedByGuid[guid] = {}
|
||||||
|
end
|
||||||
|
table.insert(groupedByGuid[guid], tostring(petId))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, petIds in pairs(groupedByGuid) do
|
||||||
|
if type(petIds) == "table" and table.getn(petIds) > 1 then
|
||||||
|
table.sort(petIds, function(a, b)
|
||||||
|
local rowA = pets.petStore.activeById[a]
|
||||||
|
local rowB = pets.petStore.activeById[b]
|
||||||
|
local scoreA, numericA = MTH_PETS_GetActiveRowRepairScore(pets, a, rowA)
|
||||||
|
local scoreB, numericB = MTH_PETS_GetActiveRowRepairScore(pets, b, rowB)
|
||||||
|
if scoreA ~= scoreB then
|
||||||
|
return scoreA > scoreB
|
||||||
|
end
|
||||||
|
if numericA ~= numericB then
|
||||||
|
return numericA < numericB
|
||||||
|
end
|
||||||
|
return tostring(a) < tostring(b)
|
||||||
|
end)
|
||||||
|
local winnerId = petIds[1]
|
||||||
|
for i = 2, table.getn(petIds) do
|
||||||
|
local loserId = petIds[i]
|
||||||
|
if pets.petStore.activeById[winnerId] and pets.petStore.activeById[loserId] then
|
||||||
|
MTH_PETS_MergeActiveRows(pets, winnerId, loserId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_PETS_EnsurePetStoreSchema(pets)
|
local function MTH_PETS_EnsurePetStoreSchema(pets)
|
||||||
if type(pets.petStore) ~= "table" then
|
if type(pets.petStore) ~= "table" then
|
||||||
pets.petStore = {}
|
pets.petStore = {}
|
||||||
@@ -1326,9 +1606,36 @@ local function MTH_PETS_EnsurePetStoreSchema(pets)
|
|||||||
if petStore.activeCurrentId == nil then
|
if petStore.activeCurrentId == nil then
|
||||||
petStore.activeCurrentId = nil
|
petStore.activeCurrentId = nil
|
||||||
end
|
end
|
||||||
|
MTH_PETS_RepairActiveRowsByGuid(pets)
|
||||||
|
petStore.signatureIndex = {}
|
||||||
|
petStore.guidIndex = {}
|
||||||
|
local highestPetNumericId = 0
|
||||||
|
|
||||||
for _, row in pairs(petStore.activeById) do
|
for petId, row in pairs(petStore.activeById) do
|
||||||
if type(row) == "table" then
|
if type(row) == "table" then
|
||||||
|
local resolvedPetId = tostring(petId)
|
||||||
|
if row.id == nil or tostring(row.id) == "" then
|
||||||
|
row.id = resolvedPetId
|
||||||
|
end
|
||||||
|
local numericPetId = MTH_PETS_ParseNumericPetId(resolvedPetId)
|
||||||
|
if numericPetId and numericPetId > highestPetNumericId then
|
||||||
|
highestPetNumericId = numericPetId
|
||||||
|
end
|
||||||
|
if row.tameVerified ~= true then
|
||||||
|
local legacyTameContext = type(row.tameContext) == "table" and row.tameContext or nil
|
||||||
|
if legacyTameContext and (legacyTameContext.name or legacyTameContext.zone or legacyTameContext.timestamp) then
|
||||||
|
row.tameVerified = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if type(row.signature) == "string" and row.signature ~= "" then
|
||||||
|
if type(petStore.signatureIndex[row.signature]) ~= "table" then
|
||||||
|
petStore.signatureIndex[row.signature] = {}
|
||||||
|
end
|
||||||
|
table.insert(petStore.signatureIndex[row.signature], resolvedPetId)
|
||||||
|
end
|
||||||
|
if type(row.guid) == "string" and row.guid ~= "" then
|
||||||
|
petStore.guidIndex[row.guid] = resolvedPetId
|
||||||
|
end
|
||||||
if row.loyaltyLevel == nil and type(row.loyalty) == "string" then
|
if row.loyaltyLevel == nil and type(row.loyalty) == "string" then
|
||||||
row.loyaltyLevel = MTH_PETS_ParseLoyaltyLevelFromText(row.loyalty)
|
row.loyaltyLevel = MTH_PETS_ParseLoyaltyLevelFromText(row.loyalty)
|
||||||
end
|
end
|
||||||
@@ -1343,9 +1650,21 @@ local function MTH_PETS_EnsurePetStoreSchema(pets)
|
|||||||
end
|
end
|
||||||
row.stableInfo.loyalty = nil
|
row.stableInfo.loyalty = nil
|
||||||
end
|
end
|
||||||
|
if row.tameVerified ~= true and MTH_PETS_RowHasAnyTameMetadata(row) then
|
||||||
|
row.tameRecorded = nil
|
||||||
|
end
|
||||||
MTH_PETS_BackfillTameMetadataFromEvents(row)
|
MTH_PETS_BackfillTameMetadataFromEvents(row)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if highestPetNumericId >= tonumber(petStore.nextId) then
|
||||||
|
petStore.nextId = highestPetNumericId + 1
|
||||||
|
end
|
||||||
|
if petStore.activeCurrentId ~= nil and petStore.activeById[tostring(petStore.activeCurrentId)] == nil then
|
||||||
|
petStore.activeCurrentId = nil
|
||||||
|
end
|
||||||
|
if pets.currentPetId ~= nil and petStore.activeById[tostring(pets.currentPetId)] == nil then
|
||||||
|
pets.currentPetId = petStore.activeCurrentId
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_PETS_EnsureCurrentPetSchema(pets)
|
local function MTH_PETS_EnsureCurrentPetSchema(pets)
|
||||||
@@ -1719,10 +2038,10 @@ local function MTH_PETS_MakeSnapshotFromLivePet()
|
|||||||
xpPercent = math.floor((xp / xpMax) * 1000 + 0.5) / 10
|
xpPercent = math.floor((xp / xpMax) * 1000 + 0.5) / 10
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local petGuid = (type(UnitGUID) == "function") and UnitGUID("pet") or nil
|
local petGuid = MTH_PETS_GetUnitGuid("pet")
|
||||||
local beastId = MTH_PETS_ParseCreatureIdFromGuid(petGuid)
|
local beastId = MTH_PETS_ParseCreatureIdFromGuid(petGuid)
|
||||||
if beastId == nil and type(UnitGUID) == "function" then
|
if beastId == nil then
|
||||||
beastId = MTH_PETS_ParseCreatureIdFromGuid(UnitGUID("target"))
|
beastId = MTH_PETS_ParseCreatureIdFromGuid(MTH_PETS_GetUnitGuid("target"))
|
||||||
end
|
end
|
||||||
local signature = MTH_PETS_MakeSignature(petName, petFamily, petLevel)
|
local signature = MTH_PETS_MakeSignature(petName, petFamily, petLevel)
|
||||||
return {
|
return {
|
||||||
@@ -1751,15 +2070,28 @@ local function MTH_PETS_SelectPetIdBySnapshot(store, snapshot, previousPetId)
|
|||||||
if previousRow.guid and snapshot.guid and previousRow.guid == snapshot.guid then
|
if previousRow.guid and snapshot.guid and previousRow.guid == snapshot.guid then
|
||||||
return previousPetId
|
return previousPetId
|
||||||
end
|
end
|
||||||
if previousRow.signature and snapshot.signature and previousRow.signature == snapshot.signature then
|
|
||||||
return previousPetId
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if snapshot.guid and store.guidIndex[snapshot.guid] and store.activeById[store.guidIndex[snapshot.guid]] then
|
if snapshot.guid and store.guidIndex[snapshot.guid] and store.activeById[store.guidIndex[snapshot.guid]] then
|
||||||
return store.guidIndex[snapshot.guid]
|
return store.guidIndex[snapshot.guid]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if snapshot.guid and snapshot.guid ~= "" then
|
||||||
|
for petId, row in pairs(store.activeById or {}) do
|
||||||
|
if type(row) == "table" and row.guid == snapshot.guid then
|
||||||
|
store.guidIndex[snapshot.guid] = tostring(petId)
|
||||||
|
return tostring(petId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if previousPetId and store.activeById[previousPetId] then
|
||||||
|
local previousRow = store.activeById[previousPetId]
|
||||||
|
if previousRow.signature and snapshot.signature and previousRow.signature == snapshot.signature then
|
||||||
|
return previousPetId
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if snapshot.signature and snapshot.signature ~= "" then
|
if snapshot.signature and snapshot.signature ~= "" then
|
||||||
local list = store.signatureIndex[snapshot.signature]
|
local list = store.signatureIndex[snapshot.signature]
|
||||||
if type(list) == "table" then
|
if type(list) == "table" then
|
||||||
@@ -1823,21 +2155,17 @@ local function MTH_PETS_ApplySnapshotToRow(row, snapshot, source, context)
|
|||||||
end
|
end
|
||||||
row.guid = snapshot.guid or row.guid
|
row.guid = snapshot.guid or row.guid
|
||||||
row.beastId = snapshot.beastId or row.beastId
|
row.beastId = snapshot.beastId or row.beastId
|
||||||
local hasPendingTame = type(MTH_PETS_LastTameAttempt) == "table"
|
local confirmedTameBeastId = MTH_PETS_ResolveConfirmedTameBeastId(source, snapshot)
|
||||||
if hasPendingTame and (row.tameBeastId == nil or tonumber(row.tameBeastId) == nil) then
|
if confirmedTameBeastId and type(context) == "table" then
|
||||||
local resolvedTameBeastId = MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
|
|
||||||
if resolvedTameBeastId and resolvedTameBeastId > 0 then
|
|
||||||
row.tameBeastId = resolvedTameBeastId
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if hasPendingTame and (source == "unit-pet-acquire" or source == "refresh-current-pet") and type(context) == "table" then
|
|
||||||
row.tameRecorded = true
|
row.tameRecorded = true
|
||||||
|
row.tameVerified = true
|
||||||
row.tamedAt = row.tamedAt or context.timestamp
|
row.tamedAt = row.tamedAt or context.timestamp
|
||||||
row.tameHunterLevel = row.tameHunterLevel or context.hunterLevel
|
row.tameHunterLevel = row.tameHunterLevel or context.hunterLevel
|
||||||
row.tameZone = row.tameZone or context.zone
|
row.tameZone = row.tameZone or context.zone
|
||||||
row.tameSubZone = row.tameSubZone or context.subZone
|
row.tameSubZone = row.tameSubZone or context.subZone
|
||||||
row.tameX = row.tameX or context.x
|
row.tameX = row.tameX or context.x
|
||||||
row.tameY = row.tameY or context.y
|
row.tameY = row.tameY or context.y
|
||||||
|
row.tameBeastId = row.tameBeastId or confirmedTameBeastId
|
||||||
end
|
end
|
||||||
row.signature = snapshot.signature
|
row.signature = snapshot.signature
|
||||||
row.lastUpdated = now
|
row.lastUpdated = now
|
||||||
@@ -1862,30 +2190,6 @@ local function MTH_PETS_ApplySnapshotToRow(row, snapshot, source, context)
|
|||||||
row.hunterLevel = context.hunterLevel or row.hunterLevel
|
row.hunterLevel = context.hunterLevel or row.hunterLevel
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not isStableScan and type(context) == "table" then
|
|
||||||
local hasTameRecord = (row.tameRecorded == true)
|
|
||||||
or tonumber(row.tamedAt) ~= nil
|
|
||||||
or tonumber(row.tameBeastId) ~= nil
|
|
||||||
or (type(row.tameZone) == "string" and row.tameZone ~= "")
|
|
||||||
if not hasTameRecord and hasPendingTame then
|
|
||||||
local sourceText = tostring(source or "")
|
|
||||||
if sourceText == "unit-pet-acquire" or sourceText == "refresh-current-pet" then
|
|
||||||
row.tameRecorded = true
|
|
||||||
row.tamedAt = row.tamedAt or context.timestamp
|
|
||||||
row.tameHunterLevel = row.tameHunterLevel or context.hunterLevel
|
|
||||||
row.tameZone = row.tameZone or context.zone
|
|
||||||
row.tameSubZone = row.tameSubZone or context.subZone
|
|
||||||
row.tameX = row.tameX or context.x
|
|
||||||
row.tameY = row.tameY or context.y
|
|
||||||
if tonumber(row.tameBeastId) == nil then
|
|
||||||
local resolvedTameBeastId = MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
|
|
||||||
if resolvedTameBeastId and resolvedTameBeastId > 0 then
|
|
||||||
row.tameBeastId = resolvedTameBeastId
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(row.abilities) ~= "table" then
|
if type(row.abilities) ~= "table" then
|
||||||
row.abilities = {}
|
row.abilities = {}
|
||||||
end
|
end
|
||||||
@@ -1954,18 +2258,6 @@ local function MTH_PETS_UpsertActivePetFromSnapshot(pets, snapshot, source, opti
|
|||||||
if created then
|
if created then
|
||||||
row.origin = source or "unknown"
|
row.origin = source or "unknown"
|
||||||
row.originContext = context
|
row.originContext = context
|
||||||
local hasPendingTame = type(MTH_PETS_LastTameAttempt) == "table"
|
|
||||||
local shouldRecordTame = hasPendingTame and (source == "unit-pet-acquire" or source == "refresh-current-pet")
|
|
||||||
if shouldRecordTame then
|
|
||||||
row.tamedAt = context.timestamp
|
|
||||||
row.tameHunterLevel = context.hunterLevel
|
|
||||||
row.tameZone = context.zone
|
|
||||||
row.tameSubZone = context.subZone
|
|
||||||
row.tameX = context.x
|
|
||||||
row.tameY = context.y
|
|
||||||
row.tameBeastId = snapshot.beastId
|
|
||||||
row.tameRecorded = true
|
|
||||||
end
|
|
||||||
if type(options) == "table" and options.stableSlot then
|
if type(options) == "table" and options.stableSlot then
|
||||||
row.origin = "stable-slot"
|
row.origin = "stable-slot"
|
||||||
end
|
end
|
||||||
@@ -2123,6 +2415,45 @@ local function MTH_PETS_RecordStableSlot(pets, slot, raw1, raw2, raw3, raw4, raw
|
|||||||
pets.updatedAt = time()
|
pets.updatedAt = time()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_PETS_ReconcileStableSlots(pets, slotCount)
|
||||||
|
if type(pets) ~= "table" or type(pets.petStore) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local petStore = pets.petStore
|
||||||
|
if type(petStore.activeById) ~= "table" or type(petStore.stableSlotIndex) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local authoritativeByPetId = {}
|
||||||
|
for slotNumber, petId in pairs(petStore.stableSlotIndex) do
|
||||||
|
local numericSlot = tonumber(slotNumber)
|
||||||
|
local mappedPetId = tostring(petId or "")
|
||||||
|
if numericSlot and numericSlot > 0 and mappedPetId ~= "" and type(petStore.activeById[mappedPetId]) == "table" then
|
||||||
|
if not slotCount or numericSlot <= slotCount then
|
||||||
|
authoritativeByPetId[mappedPetId] = numericSlot
|
||||||
|
else
|
||||||
|
petStore.stableSlotIndex[slotNumber] = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
petStore.stableSlotIndex[slotNumber] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for petId, row in pairs(petStore.activeById) do
|
||||||
|
if type(row) == "table" then
|
||||||
|
local resolvedPetId = tostring(petId)
|
||||||
|
local authoritativeSlot = authoritativeByPetId[resolvedPetId]
|
||||||
|
if authoritativeSlot then
|
||||||
|
row.stableSlot = authoritativeSlot
|
||||||
|
elseif tonumber(row.stableSlot) and tonumber(row.stableSlot) > 0 then
|
||||||
|
row.stableSlot = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pets.updatedAt = time()
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_PETS_RecordCurrentPetLearnedAbility(abilityName, rankNumber, source)
|
function MTH_PETS_RecordCurrentPetLearnedAbility(abilityName, rankNumber, source)
|
||||||
local pets = MTH_PETS_GetRootStore()
|
local pets = MTH_PETS_GetRootStore()
|
||||||
if type(pets) ~= "table" then
|
if type(pets) ~= "table" then
|
||||||
@@ -2494,15 +2825,6 @@ function MTH_PETS_GetRootStore()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local pets = MTH_CharSavedVariables.MTH_Pets
|
local pets = MTH_CharSavedVariables.MTH_Pets
|
||||||
if pets._betaFreshStoreApplied ~= 1 then
|
|
||||||
pets.petTraining = {}
|
|
||||||
pets.trainScan = {}
|
|
||||||
pets.stableScan = {}
|
|
||||||
pets.currentPet = {}
|
|
||||||
pets.petStore = {}
|
|
||||||
pets._betaFreshStoreApplied = 1
|
|
||||||
pets.updatedAt = time()
|
|
||||||
end
|
|
||||||
if type(pets.petTraining) ~= "table" then
|
if type(pets.petTraining) ~= "table" then
|
||||||
pets.petTraining = {}
|
pets.petTraining = {}
|
||||||
end
|
end
|
||||||
@@ -2519,14 +2841,52 @@ function MTH_PETS_GetRootStore()
|
|||||||
MTH_PETS_EnsureSchema(pets)
|
MTH_PETS_EnsureSchema(pets)
|
||||||
MTH_PETS_EnsurePetTrainingCompatibility(pets)
|
MTH_PETS_EnsurePetTrainingCompatibility(pets)
|
||||||
|
|
||||||
MTH_CharSavedVariables.petTraining = pets.petTraining
|
-- Migration: remove root-level duplicates that bloated SavedVariables
|
||||||
MTH_CharSavedVariables.trainScan = pets.trainScan
|
if pets._migrationCleanup ~= 2 then
|
||||||
MTH_CharSavedVariables.stableScan = pets.stableScan
|
MTH_PETS_RunSavedVarCleanup(pets)
|
||||||
MTH_CharSavedVariables.petStore = pets.petStore
|
pets._migrationCleanup = 2
|
||||||
|
end
|
||||||
|
|
||||||
return pets
|
return pets
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH_PETS_RunSavedVarCleanup(pets)
|
||||||
|
-- 1. Remove root-level duplicates (data lives inside MTH_Pets only)
|
||||||
|
if MTH_CharSavedVariables then
|
||||||
|
MTH_CharSavedVariables.petTraining = nil
|
||||||
|
MTH_CharSavedVariables.trainScan = nil
|
||||||
|
MTH_CharSavedVariables.stableScan = nil
|
||||||
|
MTH_CharSavedVariables.petStore = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 2. Purge pet-updated events (unbounded bloat)
|
||||||
|
local purged = 0
|
||||||
|
local stores = { pets.petStore and pets.petStore.activeById, pets.petStore and pets.petStore.historyById }
|
||||||
|
for _, index in ipairs(stores) do
|
||||||
|
if type(index) == "table" then
|
||||||
|
for petId, row in pairs(index) do
|
||||||
|
if type(row) == "table" and type(row.events) == "table" then
|
||||||
|
local kept = {}
|
||||||
|
for _, evt in ipairs(row.events) do
|
||||||
|
if type(evt) == "table" and evt.type ~= "pet-updated" then
|
||||||
|
table.insert(kept, evt)
|
||||||
|
else
|
||||||
|
purged = purged + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
row.events = kept
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 3. Remove stale _betaFreshStoreApplied flag
|
||||||
|
pets._betaFreshStoreApplied = nil
|
||||||
|
|
||||||
|
if purged > 0 and MTH and MTH.Print then
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_PETS_RefreshCurrentPet()
|
function MTH_PETS_RefreshCurrentPet()
|
||||||
local pets = type(MTH_PETS_GetRootStore) == "function" and MTH_PETS_GetRootStore() or nil
|
local pets = type(MTH_PETS_GetRootStore) == "function" and MTH_PETS_GetRootStore() or nil
|
||||||
if type(pets) ~= "table" then
|
if type(pets) ~= "table" then
|
||||||
@@ -2624,15 +2984,20 @@ function MTH_PETS_RefreshCurrentPet()
|
|||||||
row.events = {}
|
row.events = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local eventType = "pet-updated"
|
local eventType = nil
|
||||||
|
local confirmedTameBeastId = MTH_PETS_ResolveConfirmedTameBeastId("refresh-current-pet", snapshot)
|
||||||
if created and (not hadPetBeforeRefresh) then
|
if created and (not hadPetBeforeRefresh) then
|
||||||
eventType = "pet-acquired"
|
if confirmedTameBeastId then
|
||||||
|
eventType = "pet-tamed"
|
||||||
|
else
|
||||||
|
eventType = "pet-acquired"
|
||||||
|
end
|
||||||
|
elseif cp.id ~= nil and previousCurrentId ~= nil and cp.id ~= previousCurrentId then
|
||||||
|
eventType = "pet-swapped"
|
||||||
end
|
end
|
||||||
|
|
||||||
local shouldRecordLifecycleEvent = (eventType == "pet-acquired")
|
|
||||||
or (cp.id ~= nil and previousCurrentId ~= nil and cp.id ~= previousCurrentId)
|
|
||||||
local eventContext = nil
|
local eventContext = nil
|
||||||
if shouldRecordLifecycleEvent then
|
if eventType then
|
||||||
eventContext = MTH_PETS_CaptureContext()
|
eventContext = MTH_PETS_CaptureContext()
|
||||||
table.insert(row.events, {
|
table.insert(row.events, {
|
||||||
type = eventType,
|
type = eventType,
|
||||||
@@ -2642,26 +3007,6 @@ function MTH_PETS_RefreshCurrentPet()
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
if eventType == "pet-acquired" then
|
|
||||||
local hasTameRecord = (row.tameRecorded == true)
|
|
||||||
or (tonumber(row.tamedAt) and tonumber(row.tamedAt) > 0)
|
|
||||||
or (type(row.tameZone) == "string" and row.tameZone ~= "")
|
|
||||||
if not hasTameRecord and type(eventContext) == "table" then
|
|
||||||
row.tameRecorded = true
|
|
||||||
row.tamedAt = row.tamedAt or eventContext.timestamp or now
|
|
||||||
row.tameHunterLevel = row.tameHunterLevel or eventContext.hunterLevel
|
|
||||||
row.tameZone = row.tameZone or eventContext.zone
|
|
||||||
row.tameSubZone = row.tameSubZone or eventContext.subZone
|
|
||||||
row.tameX = row.tameX or eventContext.x
|
|
||||||
row.tameY = row.tameY or eventContext.y
|
|
||||||
if tonumber(row.tameBeastId) == nil then
|
|
||||||
local resolvedTameBeastId = MTH_PETS_ResolveTameBeastIdForRow(row, snapshot)
|
|
||||||
if resolvedTameBeastId and resolvedTameBeastId > 0 then
|
|
||||||
row.tameBeastId = resolvedTameBeastId
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if hadPendingTame and cp.id and cp.id ~= previousCurrentId then
|
if hadPendingTame and cp.id and cp.id ~= previousCurrentId then
|
||||||
@@ -3078,6 +3423,10 @@ function MTH_ST_Scan(reason)
|
|||||||
if currentPetId and type(petsRoot.petStore) == "table" and type(petsRoot.petStore.activeById) == "table" then
|
if currentPetId and type(petsRoot.petStore) == "table" and type(petsRoot.petStore.activeById) == "table" then
|
||||||
local currentRow = petsRoot.petStore.activeById[currentPetId]
|
local currentRow = petsRoot.petStore.activeById[currentPetId]
|
||||||
if type(currentRow) == "table" then
|
if type(currentRow) == "table" then
|
||||||
|
MTH_ST_PrintStableDiag("scan currentRow petId=" .. tostring(currentPetId)
|
||||||
|
.. " guid='" .. tostring(currentRow.guid or "") .. "'"
|
||||||
|
.. " signature='" .. tostring(currentRow.signature or "") .. "'"
|
||||||
|
.. " beastId='" .. tostring(currentRow.beastId or "") .. "'")
|
||||||
local currentIcon = tostring(c1 or "")
|
local currentIcon = tostring(c1 or "")
|
||||||
if currentIcon ~= "" then
|
if currentIcon ~= "" then
|
||||||
currentRow.icon = currentIcon
|
currentRow.icon = currentIcon
|
||||||
@@ -3102,6 +3451,8 @@ function MTH_ST_Scan(reason)
|
|||||||
MTH_ST_PrintStableDiag("scan slots " .. table.concat(slotDiagParts, " | "))
|
MTH_ST_PrintStableDiag("scan slots " .. table.concat(slotDiagParts, " | "))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
MTH_PETS_ReconcileStableSlots(petsRoot, slotCount)
|
||||||
|
|
||||||
MTH_PETS_MarkStableVisited(petsRoot, tostring(reason or "stable-scan"))
|
MTH_PETS_MarkStableVisited(petsRoot, tostring(reason or "stable-scan"))
|
||||||
|
|
||||||
MTH_PETS_RefreshCurrentPet()
|
MTH_PETS_RefreshCurrentPet()
|
||||||
@@ -3167,7 +3518,7 @@ end
|
|||||||
|
|
||||||
local function MTH_ST_QueueDeferredStableScan(reason, delaySeconds)
|
local function MTH_ST_QueueDeferredStableScan(reason, delaySeconds)
|
||||||
if not MTH_ST_DeferredStableScanFrame then
|
if not MTH_ST_DeferredStableScanFrame then
|
||||||
MTH_ST_DeferredStableScanFrame = CreateFrame("Frame", "MTHDeferredStableScanFrame")
|
MTH_ST_DeferredStableScanFrame = CreateFrame("Frame", "MTH_DeferredStableScan")
|
||||||
if not MTH_ST_DeferredStableScanFrame then
|
if not MTH_ST_DeferredStableScanFrame then
|
||||||
MTH_ST_TraceRecord("MTH_ST_QueueDeferredStableScan", "scan", "frame-create-failed")
|
MTH_ST_TraceRecord("MTH_ST_QueueDeferredStableScan", "scan", "frame-create-failed")
|
||||||
return false
|
return false
|
||||||
@@ -3269,10 +3620,13 @@ local function MTH_PETS_HandleUnitPetTransition(source)
|
|||||||
if type(row.events) ~= "table" then
|
if type(row.events) ~= "table" then
|
||||||
row.events = {}
|
row.events = {}
|
||||||
end
|
end
|
||||||
|
local confirmedTameBeastId = MTH_PETS_ResolveConfirmedTameBeastId(transitionSource, snapshot)
|
||||||
local eventType = (not hadPet) and "pet-acquired" or "pet-updated"
|
local eventType = (not hadPet) and "pet-acquired" or "pet-updated"
|
||||||
if eventType == "pet-updated" and source == "UNIT_PET" and MTH_ST_IsStableFrameOpen() then
|
if not hadPet and confirmedTameBeastId then
|
||||||
MTH_ST_PrintStableDiag("swap history-skip reason=stable-open")
|
eventType = "pet-tamed"
|
||||||
else
|
end
|
||||||
|
-- Only record lifecycle events (acquire, rename, abandon), not routine updates
|
||||||
|
if eventType ~= "pet-updated" then
|
||||||
table.insert(row.events, {
|
table.insert(row.events, {
|
||||||
type = eventType,
|
type = eventType,
|
||||||
source = source or transitionSource,
|
source = source or transitionSource,
|
||||||
@@ -3369,7 +3723,6 @@ end
|
|||||||
|
|
||||||
local function MTH_ST_DebugDumpLine(line)
|
local function MTH_ST_DebugDumpLine(line)
|
||||||
if MTH and MTH.Print then
|
if MTH and MTH.Print then
|
||||||
MTH:Print(tostring(line or ""), "debug")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3512,7 +3865,6 @@ function MTH_CommandPetsState()
|
|||||||
.. " petTrainingLastScan=" .. tostring(petTraining and petTraining.lastScan or 0)
|
.. " petTrainingLastScan=" .. tostring(petTraining and petTraining.lastScan or 0)
|
||||||
.. " hasCompletedPetScan=" .. tostring(petTraining and petTraining.hasCompletedPetScan or nil)
|
.. " hasCompletedPetScan=" .. tostring(petTraining and petTraining.hasCompletedPetScan or nil)
|
||||||
MTH:Print(summary)
|
MTH:Print(summary)
|
||||||
MTH:Print("[PETSSTATE] " .. summary, "debug")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_CommandPetsReset()
|
function MTH_CommandPetsReset()
|
||||||
@@ -3597,7 +3949,6 @@ function MTH_CommandPetsReset()
|
|||||||
.. " preservedHistory=" .. tostring(historyCount)
|
.. " preservedHistory=" .. tostring(historyCount)
|
||||||
.. " nextId=" .. tostring(store.nextId)
|
.. " nextId=" .. tostring(store.nextId)
|
||||||
MTH:Print(line)
|
MTH:Print(line)
|
||||||
MTH:Print("[PETSRESET] " .. line, "debug")
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3742,8 +4093,20 @@ function MTH_ST_HandleSpellcastEvent(evt, eventArg1, eventArg2)
|
|||||||
local isUnitSpellcast = (evt == "UNIT_SPELLCAST_START" or evt == "UNIT_SPELLCAST_STOP"
|
local isUnitSpellcast = (evt == "UNIT_SPELLCAST_START" or evt == "UNIT_SPELLCAST_STOP"
|
||||||
or evt == "UNIT_SPELLCAST_FAILED" or evt == "UNIT_SPELLCAST_INTERRUPTED"
|
or evt == "UNIT_SPELLCAST_FAILED" or evt == "UNIT_SPELLCAST_INTERRUPTED"
|
||||||
or evt == "UNIT_SPELLCAST_CHANNEL_START" or evt == "UNIT_SPELLCAST_CHANNEL_STOP")
|
or evt == "UNIT_SPELLCAST_CHANNEL_START" or evt == "UNIT_SPELLCAST_CHANNEL_STOP")
|
||||||
|
local isSpellcast = isUnitSpellcast
|
||||||
|
or evt == "SPELLCAST_START" or evt == "SPELLCAST_STOP"
|
||||||
|
or evt == "SPELLCAST_FAILED" or evt == "SPELLCAST_INTERRUPTED"
|
||||||
|
or evt == "SPELLCAST_CHANNEL_START" or evt == "SPELLCAST_CHANNEL_STOP"
|
||||||
|
if not isSpellcast then
|
||||||
|
return false
|
||||||
|
end
|
||||||
local castSpellName = eventArg1
|
local castSpellName = eventArg1
|
||||||
local hasPendingTame = type(MTH_PETS_LastTameAttempt) == "table"
|
local hasPendingTame = type(MTH_PETS_LastTameAttempt) == "table"
|
||||||
|
MTH_PETS_LogTame("Spellcast evt=" .. tostring(evt)
|
||||||
|
.. " arg1='" .. tostring(eventArg1 or "") .. "'"
|
||||||
|
.. " arg2='" .. tostring(eventArg2 or "") .. "'"
|
||||||
|
.. " unitCast=" .. tostring(isUnitSpellcast)
|
||||||
|
.. " pending=" .. tostring(hasPendingTame))
|
||||||
if isUnitSpellcast then
|
if isUnitSpellcast then
|
||||||
if eventArg1 ~= "player" then
|
if eventArg1 ~= "player" then
|
||||||
return true
|
return true
|
||||||
@@ -3753,9 +4116,8 @@ function MTH_ST_HandleSpellcastEvent(evt, eventArg1, eventArg2)
|
|||||||
|
|
||||||
if evt == "SPELLCAST_START" or evt == "SPELLCAST_CHANNEL_START"
|
if evt == "SPELLCAST_START" or evt == "SPELLCAST_CHANNEL_START"
|
||||||
or evt == "UNIT_SPELLCAST_START" or evt == "UNIT_SPELLCAST_CHANNEL_START" then
|
or evt == "UNIT_SPELLCAST_START" or evt == "UNIT_SPELLCAST_CHANNEL_START" then
|
||||||
if not MTH_PETS_IsTameBeastSpellName(castSpellName) then
|
-- For vanilla SPELLCAST_* events arg1 is a duration (ms), not spell name.
|
||||||
return true
|
-- Always forward to RecordTameAttempt — it has all the fallback/heuristic logic.
|
||||||
end
|
|
||||||
MTH_PETS_RecordTameAttempt(evt, castSpellName)
|
MTH_PETS_RecordTameAttempt(evt, castSpellName)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -4081,12 +4443,6 @@ local function MTH_ST_OnEvent(frame, evt, eventArg1, eventArg2)
|
|||||||
if isStableUiEvt then
|
if isStableUiEvt then
|
||||||
stableDiagStart = MTH_ST_ProfileNow()
|
stableDiagStart = MTH_ST_ProfileNow()
|
||||||
MTH_ST_PrintStableDiag("evt=" .. tostring(evt) .. " phase=begin")
|
MTH_ST_PrintStableDiag("evt=" .. tostring(evt) .. " phase=begin")
|
||||||
if MTH_ST_Trace and not MTH_ST_Trace.enabled then
|
|
||||||
MTH_ST_Trace.enabled = true
|
|
||||||
MTH_ST_Trace.verbose = false
|
|
||||||
MTH_ST_TraceResetCounters()
|
|
||||||
MTH_ST_PrintStableDiag("trace=auto-enabled")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_ST_DispatchEvent(frame, evt, eventArg1, eventArg2)
|
MTH_ST_DispatchEvent(frame, evt, eventArg1, eventArg2)
|
||||||
@@ -4120,11 +4476,17 @@ function MTH_ST_InitService()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_PetLifecycleEventFrame = CreateFrame("Frame", "MTHPetLifecycleEventFrame")
|
MTH_PetLifecycleEventFrame = CreateFrame("Frame", "MTH_PetLifecycleEvent")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
MTH_PetLifecycleEventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("UNIT_PET")
|
MTH_PetLifecycleEventFrame:RegisterEvent("UNIT_PET")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("PET_BAR_UPDATE")
|
MTH_PetLifecycleEventFrame:RegisterEvent("PET_BAR_UPDATE")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("UNIT_HAPPINESS")
|
MTH_PetLifecycleEventFrame:RegisterEvent("UNIT_HAPPINESS")
|
||||||
|
MTH_PetLifecycleEventFrame:RegisterEvent("SPELLCAST_CHANNEL_START")
|
||||||
|
MTH_PetLifecycleEventFrame:RegisterEvent("SPELLCAST_CHANNEL_STOP")
|
||||||
|
MTH_PetLifecycleEventFrame:RegisterEvent("SPELLCAST_START")
|
||||||
|
MTH_PetLifecycleEventFrame:RegisterEvent("SPELLCAST_STOP")
|
||||||
|
MTH_PetLifecycleEventFrame:RegisterEvent("SPELLCAST_FAILED")
|
||||||
|
MTH_PetLifecycleEventFrame:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
|
MTH_PetLifecycleEventFrame:RegisterEvent("CHAT_MSG_COMBAT_XP_GAIN")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("PLAYER_XP_UPDATE")
|
MTH_PetLifecycleEventFrame:RegisterEvent("PLAYER_XP_UPDATE")
|
||||||
MTH_PetLifecycleEventFrame:RegisterEvent("CHAT_MSG_SYSTEM")
|
MTH_PetLifecycleEventFrame:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||||
@@ -4141,7 +4503,6 @@ function MTH_ST_InitService()
|
|||||||
MTH_PETS_InstallCoreRenameHook()
|
MTH_PETS_InstallCoreRenameHook()
|
||||||
MTH_PETS_EmitLiveState("service:init", true)
|
MTH_PETS_EmitLiveState("service:init", true)
|
||||||
if MTH_PETS_TRACE_CONSISTENCY and MTH and MTH.Print then
|
if MTH_PETS_TRACE_CONSISTENCY and MTH and MTH.Print then
|
||||||
MTH:Print("[PETCONSIST] trace enabled", "debug")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -4153,29 +4514,26 @@ function MTH_ST_InitBootstrap()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame", "MTHPetLifecycleBootstrapFrame")
|
local frame = CreateFrame("Frame", "MTH_PetLifecycleBoot")
|
||||||
if not frame then
|
if not frame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
frame:RegisterEvent("PET_STABLE_SHOW")
|
frame:RegisterEvent("PET_STABLE_SHOW")
|
||||||
frame:RegisterEvent("PET_STABLE_UPDATE")
|
frame:RegisterEvent("PET_STABLE_UPDATE")
|
||||||
frame:SetScript("OnEvent", function(self, evt)
|
frame:SetScript("OnEvent", function()
|
||||||
evt = evt or event
|
if event ~= "PLAYER_ENTERING_WORLD" and event ~= "PET_STABLE_SHOW" and event ~= "PET_STABLE_UPDATE" then
|
||||||
if evt ~= "PLAYER_ENTERING_WORLD" and evt ~= "PET_STABLE_SHOW" and evt ~= "PET_STABLE_UPDATE" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if evt == "PET_STABLE_SHOW" or evt == "PET_STABLE_UPDATE" then
|
if event == "PET_STABLE_SHOW" or event == "PET_STABLE_UPDATE" then
|
||||||
MTH_ST_PrintStableDiag("bootstrap evt=" .. tostring(evt) .. " phase=begin")
|
MTH_ST_PrintStableDiag("bootstrap evt=" .. tostring(event) .. " phase=begin")
|
||||||
end
|
end
|
||||||
MTH_ST_InitService()
|
MTH_ST_InitService()
|
||||||
if evt == "PET_STABLE_SHOW" or evt == "PET_STABLE_UPDATE" then
|
if event == "PET_STABLE_SHOW" or event == "PET_STABLE_UPDATE" then
|
||||||
MTH_ST_PrintStableDiag("bootstrap evt=" .. tostring(evt) .. " phase=end action=no-scan")
|
MTH_ST_PrintStableDiag("bootstrap evt=" .. tostring(event) .. " phase=end action=no-scan")
|
||||||
end
|
|
||||||
if self and self.UnregisterAllEvents then
|
|
||||||
self:UnregisterAllEvents()
|
|
||||||
self:SetScript("OnEvent", nil)
|
|
||||||
end
|
end
|
||||||
|
this:UnregisterAllEvents()
|
||||||
|
this:SetScript("OnEvent", nil)
|
||||||
MTH_PetLifecycleBootstrapFrame = nil
|
MTH_PetLifecycleBootstrapFrame = nil
|
||||||
end)
|
end)
|
||||||
MTH_PetLifecycleBootstrapFrame = frame
|
MTH_PetLifecycleBootstrapFrame = frame
|
||||||
|
|||||||
+231
-9
@@ -12,7 +12,7 @@ local function MTH_PT_GetGlobal(name)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local MTH_ItemLinkCacheTooltip = nil
|
local MTH_ItemLinkCache = nil
|
||||||
|
|
||||||
local function MTH_GetQualityHexColor(quality)
|
local function MTH_GetQualityHexColor(quality)
|
||||||
local q = tonumber(quality)
|
local q = tonumber(quality)
|
||||||
@@ -34,14 +34,14 @@ function MTH_PrimeItemCache(itemId)
|
|||||||
if not id or id <= 0 then return false end
|
if not id or id <= 0 then return false end
|
||||||
if type(GetItemInfo) == "function" and GetItemInfo(id) then return true end
|
if type(GetItemInfo) == "function" and GetItemInfo(id) then return true end
|
||||||
|
|
||||||
if not MTH_ItemLinkCacheTooltip then
|
if not MTH_ItemLinkCache then
|
||||||
MTH_ItemLinkCacheTooltip = CreateFrame("GameTooltip", "MTH_ItemLinkCacheTooltip", UIParent, "GameTooltipTemplate")
|
MTH_ItemLinkCache = CreateFrame("GameTooltip", "MTH_ItemLinkCache", UIParent, "GameTooltipTemplate")
|
||||||
if not MTH_ItemLinkCacheTooltip then return false end
|
if not MTH_ItemLinkCache then return false end
|
||||||
MTH_ItemLinkCacheTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
MTH_ItemLinkCache:SetOwner(UIParent, "ANCHOR_NONE")
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_ItemLinkCacheTooltip:ClearLines()
|
MTH_ItemLinkCache:ClearLines()
|
||||||
MTH_ItemLinkCacheTooltip:SetHyperlink("item:" .. tostring(id) .. ":0:0:0")
|
MTH_ItemLinkCache:SetHyperlink("item:" .. tostring(id) .. ":0:0:0")
|
||||||
return type(GetItemInfo) == "function" and (GetItemInfo(id) ~= nil) or false
|
return type(GetItemInfo) == "function" and (GetItemInfo(id) ~= nil) or false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -312,16 +312,238 @@ function SlashCmdList.MTH(msg, editbox)
|
|||||||
local lowerMsg = string.lower(msg)
|
local lowerMsg = string.lower(msg)
|
||||||
local _, _, lowerCmd, lowerArg = string.find(lowerMsg, "^(%S+)%s*(.-)%s*$")
|
local _, _, lowerCmd, lowerArg = string.find(lowerMsg, "^(%S+)%s*(.-)%s*$")
|
||||||
if msg == "" then
|
if msg == "" then
|
||||||
MTH:Print("Available: /mth options, /mth book")
|
MTH:Print("Available: /mth options, /mth book, /mth food")
|
||||||
|
elseif lowerMsg == "err" or lowerMsg == "errors" or lowerMsg == "debug" then
|
||||||
|
if MTH_DebugFrame and MTH_DebugFrame.Toggle then
|
||||||
|
MTH_DebugFrame:Toggle()
|
||||||
|
else
|
||||||
|
MTH:Print("Debug frame is not available.")
|
||||||
|
end
|
||||||
elseif lowerMsg == "options" then
|
elseif lowerMsg == "options" then
|
||||||
MTH_CommandOptions()
|
MTH_CommandOptions()
|
||||||
elseif lowerMsg == "book" or lowerMsg == "hunterbook" then
|
elseif lowerMsg == "book" or lowerMsg == "hunterbook" then
|
||||||
MTH_CommandBook()
|
MTH_CommandBook()
|
||||||
elseif lowerMsg == "peers" or lowerMsg == "who" then
|
elseif lowerMsg == "peers" or lowerMsg == "who" then
|
||||||
MTH_CommandPeers()
|
MTH_CommandPeers()
|
||||||
|
elseif lowerMsg == "zoneinfo" then
|
||||||
|
-- Dumps all available zone data for the current zone, for adding to ds-zones / ds-minimap-sizes
|
||||||
|
pcall(SetMapToCurrentZone)
|
||||||
|
local zoneName = (type(GetRealZoneText) == "function" and GetRealZoneText()) or ""
|
||||||
|
local subZone = (type(GetSubZoneText) == "function" and GetSubZoneText()) or ""
|
||||||
|
local zoneText = (type(GetZoneText) == "function" and GetZoneText()) or ""
|
||||||
|
local areaId = nil
|
||||||
|
if type(GetCurrentMapAreaID) == "function" then
|
||||||
|
local ok, v = pcall(GetCurrentMapAreaID)
|
||||||
|
if ok then areaId = v end
|
||||||
|
end
|
||||||
|
local cx, cy = nil, nil
|
||||||
|
if type(GetPlayerMapPosition) == "function" then
|
||||||
|
local ok, x, y = pcall(GetPlayerMapPosition, "player")
|
||||||
|
if ok then cx, cy = x, y end
|
||||||
|
end
|
||||||
|
local contId = nil
|
||||||
|
if type(GetCurrentMapContinent) == "function" then
|
||||||
|
local ok, v = pcall(GetCurrentMapContinent)
|
||||||
|
if ok then contId = v end
|
||||||
|
end
|
||||||
|
MTH:Print("|cffffff00=== Zone Info ===|r")
|
||||||
|
MTH:Print("GetRealZoneText: |cffffaa00" .. tostring(zoneName) .. "|r")
|
||||||
|
MTH:Print("GetZoneText: |cffffaa00" .. tostring(zoneText) .. "|r")
|
||||||
|
MTH:Print("GetSubZoneText: |cffffaa00" .. tostring(subZone) .. "|r")
|
||||||
|
MTH:Print("AreaID (GetCurrentMapAreaID): |cff88ffff" .. tostring(areaId) .. "|r")
|
||||||
|
MTH:Print("ContinentID: |cff88ffff" .. tostring(contId) .. "|r")
|
||||||
|
if cx and cy then
|
||||||
|
MTH:Print(string.format("Player map pos: |cff88ffff%.4f, %.4f|r (display: %.1f, %.1f)", cx, cy, cx*100, cy*100))
|
||||||
|
end
|
||||||
|
-- Also check if zone is in our tables
|
||||||
|
local inZones = MTH_DS_Zones and MTH_DS_Zones[tonumber(areaId)] and "YES" or "not in MTH_DS_Zones"
|
||||||
|
local inSizes = MTH_DS_MinimapSizes and MTH_DS_MinimapSizes[tonumber(areaId)] and "YES" or "not in ds-minimap-sizes"
|
||||||
|
MTH:Print("MTH_DS_Zones entry: " .. inZones)
|
||||||
|
MTH:Print("MTH_DS_MinimapSizes entry: " .. inSizes)
|
||||||
|
elseif lowerMsg == "npcid" then
|
||||||
|
-- Print the creature entry ID of the current target, or arm a listener for next NPC interaction
|
||||||
|
local function MTH_ParseCreatureEntryFromAnyGuid(guid)
|
||||||
|
if type(guid) ~= "string" or guid == "" then return nil end
|
||||||
|
-- Format 1: TBC-style "Creature-realm-map-inst-?-ENTRY-spawn"
|
||||||
|
local _, _, id1 = string.find(guid, "^Creature%-%d+%-%d+%-%d+%-%d+%-(%d+)%-%d+$")
|
||||||
|
if id1 then return tonumber(id1) end
|
||||||
|
-- Format 2: vanilla hex "0xF130EEEEEECCCCCC" — entry is bits 24-47 = hex chars 7-12
|
||||||
|
if string.sub(guid, 1, 2) == "0x" and string.len(guid) >= 14 then
|
||||||
|
local entryHex = string.sub(guid, 7, 12) -- 24 bits = up to 16M
|
||||||
|
local parsed = tonumber(entryHex, 16)
|
||||||
|
if parsed and parsed > 0 then return parsed end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_PrintNpcId(unitToken)
|
||||||
|
unitToken = unitToken or "target"
|
||||||
|
local name = (type(UnitName) == "function") and UnitName(unitToken) or "?"
|
||||||
|
local level = (type(UnitLevel) == "function") and UnitLevel(unitToken) or "?"
|
||||||
|
-- Try UnitGUID first, then GetUnitGUID (TurtleWoW nameplate API)
|
||||||
|
local guid = nil
|
||||||
|
if type(UnitGUID) == "function" then
|
||||||
|
local ok, g = pcall(UnitGUID, unitToken)
|
||||||
|
if ok and g and g ~= "" then guid = g end
|
||||||
|
end
|
||||||
|
if (not guid or guid == "") and type(GetUnitGUID) == "function" then
|
||||||
|
local ok, g = pcall(GetUnitGUID, unitToken)
|
||||||
|
if ok and g and g ~= "" then guid = g end
|
||||||
|
end
|
||||||
|
local creatureId = MTH_ParseCreatureEntryFromAnyGuid(guid)
|
||||||
|
if creatureId then
|
||||||
|
MTH:Print(string.format("|cffffff00NPC:|r %s |cffffff00ID:|r |cff88ffff%s|r lvl: %s", tostring(name), tostring(creatureId), tostring(level)))
|
||||||
|
else
|
||||||
|
MTH:Print(string.format("|cffffff00NPC:|r %s lvl: %s |cffff8800GUID: %s|r", tostring(name), tostring(level), tostring(guid or "nil")))
|
||||||
|
MTH:Print("|cffaaaaaa(Could not parse creature ID from GUID)|r")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try current target first
|
||||||
|
local hasTarget = (type(UnitExists) == "function") and UnitExists("target")
|
||||||
|
if hasTarget then
|
||||||
|
MTH_PrintNpcId("target")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Arm a one-shot frame for MERCHANT_SHOW / TRAINER_LIST_UPDATE / GOSSIP_SHOW
|
||||||
|
if not _G["MTH_NpcIdListenerFrame"] then
|
||||||
|
local f = CreateFrame("Frame", "MTH_NpcIdListenerFrame")
|
||||||
|
f:RegisterEvent("MERCHANT_SHOW")
|
||||||
|
f:RegisterEvent("TRAINER_LIST_UPDATE")
|
||||||
|
f:RegisterEvent("GOSSIP_SHOW")
|
||||||
|
f:SetScript("OnEvent", function()
|
||||||
|
MTH_PrintNpcId("target")
|
||||||
|
this:UnregisterEvent("MERCHANT_SHOW")
|
||||||
|
this:UnregisterEvent("TRAINER_LIST_UPDATE")
|
||||||
|
this:UnregisterEvent("GOSSIP_SHOW")
|
||||||
|
_G["MTH_NpcIdListenerFrame"] = nil
|
||||||
|
end)
|
||||||
|
if not hasTarget then
|
||||||
|
MTH:Print("|cffaaffaaArmed.|r Open any vendor, trainer, or stable master to capture their ID.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif lowerCmd == "food" then
|
||||||
|
local sub = lowerArg
|
||||||
|
local function MTH_FoodItemLabel(itemId)
|
||||||
|
local id = tonumber(itemId)
|
||||||
|
if not id then return tostring(itemId) end
|
||||||
|
if type(GetItemInfo) == "function" then
|
||||||
|
local name = GetItemInfo(id)
|
||||||
|
if name and name ~= "" then
|
||||||
|
return "|cffffcc00" .. name .. "|r |cffaaaaaa(" .. id .. ")|r"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "|cffaaaaaa" .. tostring(id) .. "|r"
|
||||||
|
end
|
||||||
|
if sub == "" or sub == "status" then
|
||||||
|
-- Show quarantine and exception state
|
||||||
|
local feedStore = type(MTH_CharSavedVariables) == "table" and MTH_CharSavedVariables.feedTracking or nil
|
||||||
|
local quarantine = feedStore and feedStore.fomQuarantine and feedStore.fomQuarantine.byFamily or nil
|
||||||
|
local exceptions = feedStore and feedStore.exceptions and feedStore.exceptions.byItemId or nil
|
||||||
|
MTH:Print("|cffffff00=== Feed-O-Matic Status ===|r")
|
||||||
|
-- Quarantine
|
||||||
|
local qCount = 0
|
||||||
|
if type(quarantine) == "table" then
|
||||||
|
for family, byItem in pairs(quarantine) do
|
||||||
|
if type(byItem) == "table" then
|
||||||
|
for itemId, _ in pairs(byItem) do
|
||||||
|
qCount = qCount + 1
|
||||||
|
MTH:Print(" |cffff8800Quarantine:|r " .. MTH_FoodItemLabel(itemId) .. " (family=" .. tostring(family) .. ")")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if qCount == 0 then MTH:Print(" Quarantine: |cff00ff00empty|r") end
|
||||||
|
-- Core exceptions
|
||||||
|
local eCount = 0
|
||||||
|
if type(exceptions) == "table" then
|
||||||
|
for itemId, _ in pairs(exceptions) do
|
||||||
|
if type(itemId) == "number" then -- skip string-key dupes
|
||||||
|
eCount = eCount + 1
|
||||||
|
MTH:Print(" |cffff4444Exception block:|r " .. MTH_FoodItemLabel(itemId))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if eCount == 0 then MTH:Print(" Exception blocks: |cff00ff00none|r") end
|
||||||
|
-- FOM_RemovedFoods
|
||||||
|
local rCount = 0
|
||||||
|
if type(FOM_RemovedFoods) == "table" then
|
||||||
|
for diet, list in pairs(FOM_RemovedFoods) do
|
||||||
|
if type(list) == "table" then
|
||||||
|
for _, itemId in ipairs(list) do
|
||||||
|
rCount = rCount + 1
|
||||||
|
MTH:Print(" |cffaaaaaaRemoved food:|r " .. MTH_FoodItemLabel(itemId) .. " (diet=" .. tostring(diet) .. ")")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if rCount == 0 then MTH:Print(" Removed foods: |cff00ff00none|r") end
|
||||||
|
MTH:Print("|cffaaaaaa/mth food unban <id>|r — unban one item |cffaaaaaa/mth food reset|r — clear all bans")
|
||||||
|
elseif string.find(sub, "^unban%s") or sub == "unban" then
|
||||||
|
local _, _, itemArg = string.find(lowerArg, "^unban%s+(%S+)")
|
||||||
|
local itemId = tonumber(itemArg)
|
||||||
|
if not itemId then
|
||||||
|
MTH:Print("|cffff4444Usage:|r /mth food unban <itemId>")
|
||||||
|
MTH:Print("Example: /mth food unban 8952")
|
||||||
|
elseif type(FOM_ClearItemBans) ~= "function" then
|
||||||
|
MTH:Print("|cffff4444Error:|r Feed-O-Matic not loaded.")
|
||||||
|
else
|
||||||
|
local label = MTH_FoodItemLabel(itemId)
|
||||||
|
FOM_ClearItemBans(itemId)
|
||||||
|
MTH:Print("|cff00ff00Unbanned " .. label .. "|r — removed from quarantine, exceptions and removed-foods list.")
|
||||||
|
end
|
||||||
|
elseif sub == "reset" then
|
||||||
|
local feedStore = type(MTH_CharSavedVariables) == "table" and MTH_CharSavedVariables.feedTracking or nil
|
||||||
|
if feedStore then
|
||||||
|
if feedStore.fomQuarantine then feedStore.fomQuarantine = { byFamily = {} } end
|
||||||
|
if feedStore.exceptions then feedStore.exceptions = { byItemId = {} } end
|
||||||
|
end
|
||||||
|
if type(FOM_RemovedFoods) == "table" then
|
||||||
|
for diet, _ in pairs(FOM_RemovedFoods) do FOM_RemovedFoods[diet] = {} end
|
||||||
|
end
|
||||||
|
if type(FOM_FEED_SCAN_CACHE) ~= "nil" then FOM_FEED_SCAN_CACHE = nil end
|
||||||
|
MTH:Print("|cff00ff00All Feed-O-Matic bans and quarantines cleared.|r")
|
||||||
|
else
|
||||||
|
MTH:Print("|cffffff00/mth food|r — show quarantine/ban status")
|
||||||
|
MTH:Print("|cffffff00/mth food unban <itemId>|r — remove one item from all bans")
|
||||||
|
MTH:Print("|cffffff00/mth food reset|r — clear ALL bans and quarantines")
|
||||||
|
end
|
||||||
|
elseif lowerCmd == "zbar" and lowerArg == "debug" then
|
||||||
|
-- Dump the live state of every zBar button to chat so we can see which one is the ghost.
|
||||||
|
local p = function(s) MTH:Print("[zBar] " .. tostring(s), "debug") end
|
||||||
|
local root = (type(MTH_ZH_GetSavedRoot) == "function") and MTH_ZH_GetSavedRoot() or ZHunterMod_Saved
|
||||||
|
local zs = root and root["_zbar"]
|
||||||
|
p("=== zBar debug ===")
|
||||||
|
p("enabled=" .. tostring(zs and zs.enabled) .. " anchor=" .. tostring(getglobal("MTH_ZBar_Anchor") ~= nil))
|
||||||
|
p("direction=" .. tostring(zs and zs.direction) .. " childexpand=" .. tostring(zs and zs.childexpand) .. " childarrange=" .. tostring(zs and zs.childarrange))
|
||||||
|
local allButtons = {
|
||||||
|
"zButtonAspect","zButtonAmmo","zButtonTrack","zButtonTrap",
|
||||||
|
"zButtonPet","zButtonRanged","zButtonMounts","zButtonCompanions","zButtonToys",
|
||||||
|
}
|
||||||
|
for _, bname in ipairs(allButtons) do
|
||||||
|
local btn = getglobal(bname)
|
||||||
|
local shown = btn and btn.IsShown and btn:IsShown()
|
||||||
|
local bsaved = root and type(root[bname]) == "table" and root[bname]
|
||||||
|
local enabled = bsaved and bsaved["enabled"]
|
||||||
|
local zvis = zs and zs.visible and zs.visible[bname]
|
||||||
|
local x, y, point = "?", "?", "?"
|
||||||
|
if btn and btn.GetPoint then
|
||||||
|
local pt, _, _, bx, by = btn:GetPoint()
|
||||||
|
point = tostring(pt)
|
||||||
|
x = tostring(bx and math.floor(bx + 0.5) or "?")
|
||||||
|
y = tostring(by and math.floor(by + 0.5) or "?")
|
||||||
|
end
|
||||||
|
local bmtname = btn and tostring(btn.name) or "nil"
|
||||||
|
p(bname .. ": shown=" .. tostring(shown) ..
|
||||||
|
" enabled=" .. tostring(enabled) ..
|
||||||
|
" zbarVisible=" .. tostring(zvis) ..
|
||||||
|
" btn.name=" .. bmtname ..
|
||||||
|
" anchor=(" .. point .. " " .. x .. "," .. y .. ")")
|
||||||
|
end
|
||||||
|
p("=== end ===")
|
||||||
else
|
else
|
||||||
MTH:Print("Unknown command: " .. tostring(msg))
|
MTH:Print("Unknown command: " .. tostring(msg))
|
||||||
MTH:Print("Available: /mth options, /mth book")
|
MTH:Print("Available: /mth options, /mth book, /mth npcid, /mth food")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+7
-10
@@ -29,7 +29,7 @@ function MTH_DebugFrame:Initialize()
|
|||||||
self.initialized = true
|
self.initialized = true
|
||||||
|
|
||||||
-- Create main frame
|
-- Create main frame
|
||||||
self.frame = CreateFrame("Frame", "MTH_DebugFrameWindow", UIParent)
|
self.frame = CreateFrame("Frame", "MTH_DebugWindow", UIParent)
|
||||||
self.frame:SetWidth(800)
|
self.frame:SetWidth(800)
|
||||||
self.frame:SetHeight(400)
|
self.frame:SetHeight(400)
|
||||||
self.frame:SetPoint("CENTER", UIParent, "CENTER")
|
self.frame:SetPoint("CENTER", UIParent, "CENTER")
|
||||||
@@ -51,13 +51,13 @@ function MTH_DebugFrame:Initialize()
|
|||||||
if UISpecialFrames then
|
if UISpecialFrames then
|
||||||
local already = false
|
local already = false
|
||||||
for i = 1, table.getn(UISpecialFrames) do
|
for i = 1, table.getn(UISpecialFrames) do
|
||||||
if UISpecialFrames[i] == "MTH_DebugFrameWindow" then
|
if UISpecialFrames[i] == "MTH_DebugWindow" then
|
||||||
already = true
|
already = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not already then
|
if not already then
|
||||||
table.insert(UISpecialFrames, "MTH_DebugFrameWindow")
|
table.insert(UISpecialFrames, "MTH_DebugWindow")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ function MTH_DebugFrame:Initialize()
|
|||||||
copyButton:SetScript("OnClick", function() MTH_DebugFrame:SelectAllText() end)
|
copyButton:SetScript("OnClick", function() MTH_DebugFrame:SelectAllText() end)
|
||||||
|
|
||||||
-- Scroll frame + text content with proper vertical scrollbar
|
-- Scroll frame + text content with proper vertical scrollbar
|
||||||
self.scrollFrame = CreateFrame("ScrollFrame", "MTH_DebugScrollFrame", self.frame, "UIPanelScrollFrameTemplate")
|
self.scrollFrame = CreateFrame("ScrollFrame", "MTH_DebugScroll", self.frame, "UIPanelScrollFrameTemplate")
|
||||||
self.scrollFrame:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 15, -50)
|
self.scrollFrame:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 15, -50)
|
||||||
self.scrollFrame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT", -35, 45)
|
self.scrollFrame:SetPoint("BOTTOMRIGHT", self.frame, "BOTTOMRIGHT", -35, 45)
|
||||||
|
|
||||||
@@ -366,16 +366,13 @@ MTH_DebugFrame.UninstallHooks = MTH_DF_UninstallHooks
|
|||||||
-- Event listener for addon load
|
-- Event listener for addon load
|
||||||
local eventFrame = CreateFrame("Frame")
|
local eventFrame = CreateFrame("Frame")
|
||||||
eventFrame:RegisterEvent("ADDON_LOADED")
|
eventFrame:RegisterEvent("ADDON_LOADED")
|
||||||
eventFrame:SetScript("OnEvent", function(self, event, addonName)
|
eventFrame:SetScript("OnEvent", function()
|
||||||
if event == "ADDON_LOADED" and addonName == "MetaHunt" then
|
if event == "ADDON_LOADED" and arg1 == "MetaHunt" then
|
||||||
if MTH and MTH.GetConfig then
|
if MTH and MTH.GetConfig then
|
||||||
MTH_DF_SetGlobalCaptureEnabled(MTH:GetConfig("debug", "globalErrorCapture", false))
|
MTH_DF_SetGlobalCaptureEnabled(MTH:GetConfig("debug", "globalErrorCapture", false))
|
||||||
end
|
end
|
||||||
MTH_DF_InstallHooks()
|
MTH_DF_InstallHooks()
|
||||||
MTH_DebugFrame:Initialize()
|
MTH_DebugFrame:Initialize()
|
||||||
if MTH and MTH.Print then
|
|
||||||
local mode = MTH_DF_IsGlobalCaptureEnabled() and "legacy-global" or "safe-local"
|
|
||||||
MTH:Print("=== MetaHunt Debug Frame Initialized (" .. mode .. ") ===", "debug")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -0,0 +1,404 @@
|
|||||||
|
-- hunterbook-model-viewer.lua
|
||||||
|
-- Embeds a small 3D creature skin preview at the bottom of the Beast Lore /
|
||||||
|
-- Abilities inspector. Clicking it opens a larger draggable popup with
|
||||||
|
-- < / > navigation through all skin variants of the selected family.
|
||||||
|
--
|
||||||
|
-- Uses MTH_DS_BeastSkins[familyName] generated by .tools/generators/gen_beast_skins.py
|
||||||
|
-- Skin rendering: PlayerModel:SetUnit(CreatureDisplayInfo.ID)
|
||||||
|
|
||||||
|
local MTH_MV = {
|
||||||
|
inited = false,
|
||||||
|
family = nil,
|
||||||
|
skins = {},
|
||||||
|
index = 1,
|
||||||
|
facing = 0.6,
|
||||||
|
rotating = false,
|
||||||
|
rotateLastX = 0,
|
||||||
|
keepPopup = false,
|
||||||
|
skinBeastRows = {},
|
||||||
|
skinListEmpty = nil,
|
||||||
|
-- small preview (parented to book frame, anchored below MTH_BOOK_DetailBackdrop)
|
||||||
|
previewFrame = nil,
|
||||||
|
previewModel = nil,
|
||||||
|
-- popup
|
||||||
|
popup = nil,
|
||||||
|
popupModel = nil,
|
||||||
|
popupTitle = nil,
|
||||||
|
popupSkinLabel = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- Internal
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local function MTH_MV_ApplyModel(model, skinId)
|
||||||
|
if not model or not skinId then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
model:SetUnit(skinId)
|
||||||
|
model:SetPosition(0, 0, 0)
|
||||||
|
model:SetModelScale(1)
|
||||||
|
local useFacing = (MTH_MV.popupModel ~= nil and model == MTH_MV.popupModel)
|
||||||
|
model:SetFacing(useFacing and MTH_MV.facing or 0.6)
|
||||||
|
end
|
||||||
|
|
||||||
|
local MTH_MV_BuildSkinBeastList -- forward declaration
|
||||||
|
|
||||||
|
local function MTH_MV_DisplayCurrent()
|
||||||
|
local skin = MTH_MV.skins[MTH_MV.index]
|
||||||
|
if not skin then return end
|
||||||
|
local n = table.getn(MTH_MV.skins)
|
||||||
|
|
||||||
|
MTH_MV_ApplyModel(MTH_MV.previewModel, skin.id)
|
||||||
|
MTH_MV_ApplyModel(MTH_MV.popupModel, skin.id)
|
||||||
|
|
||||||
|
local indexStr = tostring(MTH_MV.index) .. " / " .. tostring(n)
|
||||||
|
if MTH_MV.popupSkinLabel then
|
||||||
|
MTH_MV.popupSkinLabel:SetText(indexStr .. " · " .. tostring(skin.tex or ""))
|
||||||
|
end
|
||||||
|
MTH_MV_BuildSkinBeastList(skin.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_MV_BuildSkinBeastList = function(skinId)
|
||||||
|
for i = 1, table.getn(MTH_MV.skinBeastRows) do
|
||||||
|
MTH_MV.skinBeastRows[i]:Hide()
|
||||||
|
end
|
||||||
|
if MTH_MV.skinListEmpty then MTH_MV.skinListEmpty:Hide() end
|
||||||
|
if not skinId or not MTH_DS_Beasts then return end
|
||||||
|
|
||||||
|
local matches = {}
|
||||||
|
for npcId, beast in pairs(MTH_DS_Beasts) do
|
||||||
|
if type(beast) == "table" and beast.skinId == skinId then
|
||||||
|
local nm = (MTH and MTH.GetLocalizedBeastName and MTH:GetLocalizedBeastName(npcId, beast.name)) or beast.name
|
||||||
|
table.insert(matches, { id = npcId, name = nm or "?", lvl = tostring(beast.lvl or "?") })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(matches, function(a, b) return (a.name or "") < (b.name or "") end)
|
||||||
|
|
||||||
|
local maxRows = table.getn(MTH_MV.skinBeastRows)
|
||||||
|
local shown = 0
|
||||||
|
for i = 1, table.getn(matches) do
|
||||||
|
if shown >= maxRows then break end
|
||||||
|
shown = shown + 1
|
||||||
|
local row = MTH_MV.skinBeastRows[shown]
|
||||||
|
row._npcId = matches[i].id
|
||||||
|
row.nameText:SetText(matches[i].name)
|
||||||
|
row.lvlText:SetText(matches[i].lvl)
|
||||||
|
row:Show()
|
||||||
|
end
|
||||||
|
if shown == 0 and MTH_MV.skinListEmpty then
|
||||||
|
MTH_MV.skinListEmpty:Show()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_MV_Init()
|
||||||
|
if MTH_MV.inited then return end
|
||||||
|
local backdrop = getglobal("MTH_BOOK_DetailBackdrop")
|
||||||
|
if not backdrop then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
MTH_MV.inited = true
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
-- Model preview container (sibling of inspector, full column width)
|
||||||
|
-- Hardcoded offset from book frame TOPLEFT: x=608 (right column),
|
||||||
|
-- y = -(166 inspector_top + 178 inspector_h + 6 gap) = -350
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
local bookFrame = backdrop:GetParent()
|
||||||
|
MTH_MV.previewFrame = CreateFrame("Frame", "MTH_BOOK_SkinPreview", bookFrame)
|
||||||
|
MTH_MV.previewFrame:SetWidth(136)
|
||||||
|
MTH_MV.previewFrame:SetHeight(136)
|
||||||
|
MTH_MV.previewFrame:SetPoint("TOPLEFT", bookFrame, "TOPLEFT", 608, -384)
|
||||||
|
MTH_MV.previewFrame:SetBackdrop({
|
||||||
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
||||||
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||||
|
tile = true, tileSize = 16, edgeSize = 12,
|
||||||
|
insets = {left = 3, right = 3, top = 3, bottom = 3},
|
||||||
|
})
|
||||||
|
MTH_MV.previewFrame:SetBackdropColor(0, 0, 0, 0.7)
|
||||||
|
MTH_MV.previewFrame:SetBackdropBorderColor(0.35, 0.35, 0.35, 0.8)
|
||||||
|
MTH_MV.previewFrame:Hide()
|
||||||
|
|
||||||
|
-- PlayerModel fills the inner area
|
||||||
|
MTH_MV.previewModel = CreateFrame("PlayerModel", nil, MTH_MV.previewFrame)
|
||||||
|
MTH_MV.previewModel:SetPoint("TOPLEFT", MTH_MV.previewFrame, "TOPLEFT", 3, -3)
|
||||||
|
MTH_MV.previewModel:SetPoint("BOTTOMRIGHT", MTH_MV.previewFrame, "BOTTOMRIGHT", -3, 3)
|
||||||
|
|
||||||
|
-- Invisible click overlay → opens popup
|
||||||
|
local previewBtn = CreateFrame("Button", nil, MTH_MV.previewFrame)
|
||||||
|
previewBtn:SetAllPoints(MTH_MV.previewFrame)
|
||||||
|
previewBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
|
||||||
|
previewBtn:SetScript("OnClick", function()
|
||||||
|
MTH_BOOK_ModelViewer_OpenPopup()
|
||||||
|
end)
|
||||||
|
previewBtn:SetScript("OnEnter", function()
|
||||||
|
GameTooltip:SetOwner(MTH_MV.previewFrame, "ANCHOR_LEFT")
|
||||||
|
GameTooltip:AddLine("Click to open skin viewer", 1, 1, 1)
|
||||||
|
GameTooltip:Show()
|
||||||
|
end)
|
||||||
|
previewBtn:SetScript("OnLeave", function()
|
||||||
|
GameTooltip:Hide()
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
-- Popup frame (wider: left side = model viewer, right = beast list)
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
local popup = CreateFrame("Frame", "MTH_BOOK_ModelPopup", UIParent)
|
||||||
|
popup:SetWidth(490)
|
||||||
|
popup:SetHeight(320)
|
||||||
|
popup:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||||
|
popup:SetFrameStrata("TOOLTIP")
|
||||||
|
popup:SetToplevel(true)
|
||||||
|
popup:SetMovable(true)
|
||||||
|
popup:EnableMouse(true)
|
||||||
|
popup:RegisterForDrag("LeftButton")
|
||||||
|
popup:SetScript("OnDragStart", function() this:StartMoving() end)
|
||||||
|
popup:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
|
||||||
|
popup:SetScript("OnHide", function() MTH_MV.rotating = false end)
|
||||||
|
popup:Hide()
|
||||||
|
popup:SetBackdrop({
|
||||||
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
||||||
|
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
||||||
|
tile = true, tileSize = 32, edgeSize = 32,
|
||||||
|
insets = {left = 11, right = 12, top = 12, bottom = 11},
|
||||||
|
})
|
||||||
|
popup:SetBackdropColor(0.05, 0.05, 0.08, 0.95)
|
||||||
|
|
||||||
|
-- Large model background (left side, x=20)
|
||||||
|
local modelBg = CreateFrame("Frame", nil, popup)
|
||||||
|
modelBg:SetWidth(224)
|
||||||
|
modelBg:SetHeight(226)
|
||||||
|
modelBg:SetPoint("TOPLEFT", popup, "TOPLEFT", 20, -42)
|
||||||
|
modelBg:SetBackdrop({
|
||||||
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
||||||
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||||
|
tile = true, tileSize = 16, edgeSize = 12,
|
||||||
|
insets = {left = 3, right = 3, top = 3, bottom = 3},
|
||||||
|
})
|
||||||
|
modelBg:SetBackdropColor(0, 0, 0, 0.85)
|
||||||
|
modelBg:SetBackdropBorderColor(0.35, 0.35, 0.35, 0.9)
|
||||||
|
|
||||||
|
MTH_MV.popupModel = CreateFrame("PlayerModel", "MTH_BOOK_ModelPopupModel", modelBg)
|
||||||
|
MTH_MV.popupModel:SetPoint("TOPLEFT", modelBg, "TOPLEFT", 3, -3)
|
||||||
|
MTH_MV.popupModel:SetPoint("BOTTOMRIGHT", modelBg, "BOTTOMRIGHT", -3, 3)
|
||||||
|
|
||||||
|
-- Mouse rotation: drag on the black model area rotates; outside drags the popup
|
||||||
|
MTH_MV.popupModel:EnableMouse(true)
|
||||||
|
MTH_MV.popupModel:SetScript("OnMouseDown", function()
|
||||||
|
MTH_MV.rotating = true
|
||||||
|
MTH_MV.rotateLastX = GetCursorPosition()
|
||||||
|
end)
|
||||||
|
MTH_MV.popupModel:SetScript("OnMouseUp", function()
|
||||||
|
MTH_MV.rotating = false
|
||||||
|
end)
|
||||||
|
MTH_MV.popupModel:SetScript("OnUpdate", function()
|
||||||
|
if not MTH_MV.rotating then return end
|
||||||
|
local cx = GetCursorPosition()
|
||||||
|
local dx = cx - MTH_MV.rotateLastX
|
||||||
|
MTH_MV.rotateLastX = cx
|
||||||
|
if dx ~= 0 then
|
||||||
|
MTH_MV.facing = MTH_MV.facing - dx * 0.03
|
||||||
|
MTH_MV.popupModel:SetFacing(MTH_MV.facing)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Title (family name) anchored above the model
|
||||||
|
MTH_MV.popupTitle = popup:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||||
|
MTH_MV.popupTitle:SetPoint("TOP", modelBg, "TOP", 0, 18)
|
||||||
|
MTH_MV.popupTitle:SetTextColor(1, 0.82, 0)
|
||||||
|
MTH_MV.popupTitle:SetText("Skin Viewer")
|
||||||
|
|
||||||
|
-- Close [X] button
|
||||||
|
local closeBtn = CreateFrame("Button", nil, popup)
|
||||||
|
closeBtn:SetWidth(22)
|
||||||
|
closeBtn:SetHeight(22)
|
||||||
|
closeBtn:SetPoint("TOPRIGHT", popup, "TOPRIGHT", -10, -10)
|
||||||
|
closeBtn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
|
||||||
|
local closeLbl = closeBtn:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||||
|
closeLbl:SetAllPoints(closeBtn)
|
||||||
|
closeLbl:SetText("X")
|
||||||
|
closeLbl:SetTextColor(0.9, 0.9, 0.9)
|
||||||
|
closeBtn:SetScript("OnClick", function() this:GetParent():Hide() end)
|
||||||
|
|
||||||
|
-- "Unique Appearance" badge removed (inline texture syntax unsupported in this client)
|
||||||
|
|
||||||
|
-- Nav: ◀ label ▶ (kept within the left 264px area)
|
||||||
|
local prevBtn = CreateFrame("Button", nil, popup, "UIPanelButtonTemplate")
|
||||||
|
prevBtn:SetWidth(28)
|
||||||
|
prevBtn:SetHeight(20)
|
||||||
|
prevBtn:SetPoint("BOTTOMLEFT", popup, "BOTTOMLEFT", 14, 14)
|
||||||
|
prevBtn:SetText("<")
|
||||||
|
prevBtn:SetScript("OnClick", function()
|
||||||
|
local n = table.getn(MTH_MV.skins)
|
||||||
|
if n < 1 then return end
|
||||||
|
MTH_MV.index = MTH_MV.index - 1
|
||||||
|
if MTH_MV.index < 1 then MTH_MV.index = n end
|
||||||
|
MTH_MV_DisplayCurrent()
|
||||||
|
end)
|
||||||
|
|
||||||
|
local nextBtn = CreateFrame("Button", nil, popup, "UIPanelButtonTemplate")
|
||||||
|
nextBtn:SetWidth(28)
|
||||||
|
nextBtn:SetHeight(20)
|
||||||
|
nextBtn:SetPoint("BOTTOMLEFT", popup, "BOTTOMLEFT", 222, 14)
|
||||||
|
nextBtn:SetText(">")
|
||||||
|
nextBtn:SetScript("OnClick", function()
|
||||||
|
local n = table.getn(MTH_MV.skins)
|
||||||
|
if n < 1 then return end
|
||||||
|
MTH_MV.index = MTH_MV.index + 1
|
||||||
|
if MTH_MV.index > n then MTH_MV.index = 1 end
|
||||||
|
MTH_MV_DisplayCurrent()
|
||||||
|
end)
|
||||||
|
|
||||||
|
MTH_MV.popupSkinLabel = popup:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||||
|
MTH_MV.popupSkinLabel:SetPoint("BOTTOMLEFT", prevBtn, "BOTTOMRIGHT", 4, 0)
|
||||||
|
MTH_MV.popupSkinLabel:SetPoint("BOTTOMRIGHT", nextBtn, "BOTTOMLEFT", -4, 0)
|
||||||
|
MTH_MV.popupSkinLabel:SetJustifyH("CENTER")
|
||||||
|
MTH_MV.popupSkinLabel:SetTextColor(0.9, 0.9, 0.9)
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
-- Right panel: vertical divider + beast list
|
||||||
|
-- ---------------------------------------------------------------
|
||||||
|
local divider = popup:CreateTexture(nil, "ARTWORK")
|
||||||
|
divider:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||||
|
divider:SetVertexColor(0.35, 0.35, 0.35, 0.8)
|
||||||
|
divider:SetPoint("TOPLEFT", popup, "TOPLEFT", 270, -36)
|
||||||
|
divider:SetPoint("BOTTOMLEFT", popup, "BOTTOMLEFT", 270, 12)
|
||||||
|
divider:SetWidth(1)
|
||||||
|
|
||||||
|
local listHeader = popup:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||||
|
listHeader:SetPoint("TOPLEFT", popup, "TOPLEFT", 278, -18)
|
||||||
|
listHeader:SetTextColor(1, 0.82, 0)
|
||||||
|
listHeader:SetText("Beasts with this skin")
|
||||||
|
|
||||||
|
local listSep = popup:CreateTexture(nil, "ARTWORK")
|
||||||
|
listSep:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||||
|
listSep:SetVertexColor(0.35, 0.35, 0.35, 0.6)
|
||||||
|
listSep:SetPoint("TOPLEFT", popup, "TOPLEFT", 278, -30)
|
||||||
|
listSep:SetPoint("TOPRIGHT", popup, "TOPRIGHT", -10, -30)
|
||||||
|
listSep:SetHeight(1)
|
||||||
|
|
||||||
|
MTH_MV.skinListEmpty = popup:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||||
|
MTH_MV.skinListEmpty:SetPoint("TOPLEFT", popup, "TOPLEFT", 278, -38)
|
||||||
|
MTH_MV.skinListEmpty:SetTextColor(0.5, 0.5, 0.5)
|
||||||
|
MTH_MV.skinListEmpty:SetText("\226\128\148")
|
||||||
|
MTH_MV.skinListEmpty:Hide()
|
||||||
|
|
||||||
|
-- Beast rows (14 max)
|
||||||
|
local ROW_X = 278
|
||||||
|
local ROW_START = -36
|
||||||
|
local ROW_H = 17
|
||||||
|
local MAX_ROWS = 14
|
||||||
|
for i = 1, MAX_ROWS do
|
||||||
|
local row = CreateFrame("Button", nil, popup)
|
||||||
|
row:SetPoint("TOPLEFT", popup, "TOPLEFT", ROW_X, ROW_START - (i - 1) * ROW_H)
|
||||||
|
row:SetWidth(200)
|
||||||
|
row:SetHeight(ROW_H - 1)
|
||||||
|
row._npcId = nil
|
||||||
|
|
||||||
|
local hl = row:CreateTexture(nil, "HIGHLIGHT")
|
||||||
|
hl:SetAllPoints(row)
|
||||||
|
hl:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
|
||||||
|
hl:SetBlendMode("ADD")
|
||||||
|
hl:SetAlpha(0.35)
|
||||||
|
|
||||||
|
row.nameText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
|
||||||
|
row.nameText:SetPoint("LEFT", row, "LEFT", 0, 0)
|
||||||
|
row.nameText:SetWidth(158)
|
||||||
|
row.nameText:SetJustifyH("LEFT")
|
||||||
|
|
||||||
|
row.lvlText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||||
|
row.lvlText:SetPoint("LEFT", row, "LEFT", 160, 0)
|
||||||
|
row.lvlText:SetWidth(38)
|
||||||
|
row.lvlText:SetJustifyH("LEFT")
|
||||||
|
row.lvlText:SetTextColor(0.7, 0.7, 0.7)
|
||||||
|
|
||||||
|
row:SetScript("OnClick", function()
|
||||||
|
if this._npcId and type(MTH_BOOK_JumpToBeastById) == "function" then
|
||||||
|
MTH_MV.keepPopup = true
|
||||||
|
MTH_BOOK_JumpToBeastById(this._npcId)
|
||||||
|
MTH_MV.keepPopup = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
row:Hide()
|
||||||
|
MTH_MV.skinBeastRows[i] = row
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_MV.popup = popup
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- Public API
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function MTH_BOOK_ModelViewer_SetFamily(family, skinId)
|
||||||
|
MTH_MV_Init()
|
||||||
|
if not MTH_MV.inited then return end
|
||||||
|
local skins = MTH_DS_BeastSkins and type(MTH_DS_BeastSkins) == "table" and MTH_DS_BeastSkins[family]
|
||||||
|
if not skins or table.getn(skins) == 0 then
|
||||||
|
MTH_BOOK_ModelViewer_Clear()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Filter to only skins used by at least one tameable beast
|
||||||
|
local usedSkinIds = {}
|
||||||
|
if MTH_DS_Beasts then
|
||||||
|
for _, beast in pairs(MTH_DS_Beasts) do
|
||||||
|
if type(beast) == "table" and beast.skinId then
|
||||||
|
usedSkinIds[beast.skinId] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local filteredSkins = {}
|
||||||
|
for i = 1, table.getn(skins) do
|
||||||
|
if usedSkinIds[skins[i].id] then
|
||||||
|
table.insert(filteredSkins, skins[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if table.getn(filteredSkins) == 0 then
|
||||||
|
MTH_BOOK_ModelViewer_Clear()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_MV.family = family
|
||||||
|
MTH_MV.skins = filteredSkins
|
||||||
|
MTH_MV.facing = 0.6
|
||||||
|
|
||||||
|
-- If we have a specific skinId, jump to the matching skin entry.
|
||||||
|
MTH_MV.index = 1
|
||||||
|
if skinId then
|
||||||
|
for i = 1, table.getn(filteredSkins) do
|
||||||
|
if filteredSkins[i].id == skinId then
|
||||||
|
MTH_MV.index = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if MTH_MV.popupTitle then
|
||||||
|
MTH_MV.popupTitle:SetText(tostring(family) .. " — Skins")
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_MV_DisplayCurrent()
|
||||||
|
|
||||||
|
if MTH_MV.previewFrame then MTH_MV.previewFrame:Show() end
|
||||||
|
MTH_MV_DisplayCurrent()
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_BOOK_ModelViewer_Clear()
|
||||||
|
if MTH_MV.previewFrame then MTH_MV.previewFrame:Hide() end
|
||||||
|
if not MTH_MV.keepPopup then
|
||||||
|
if MTH_MV.popup and MTH_MV.popup:IsShown() then MTH_MV.popup:Hide() end
|
||||||
|
end
|
||||||
|
MTH_MV.family = nil
|
||||||
|
MTH_MV.skins = {}
|
||||||
|
MTH_MV.index = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_BOOK_ModelViewer_OpenPopup()
|
||||||
|
MTH_MV_Init()
|
||||||
|
if not MTH_MV.popup then return end
|
||||||
|
if table.getn(MTH_MV.skins) == 0 then return end
|
||||||
|
MTH_MV.popup:Show()
|
||||||
|
MTH_MV.popup:Raise()
|
||||||
|
MTH_MV_DisplayCurrent()
|
||||||
|
end
|
||||||
@@ -2,17 +2,18 @@ if type(MTH_HUNTERBOOK_TABS) ~= "table" then MTH_HUNTERBOOK_TABS = {} end
|
|||||||
|
|
||||||
MTH_HUNTERBOOK_TABS.pets = {
|
MTH_HUNTERBOOK_TABS.pets = {
|
||||||
headerLabel = "Beasts",
|
headerLabel = "Beasts",
|
||||||
columnLabels = { "ID", "Lvl", "Family", "Name", "Abilities", "Zone", "R", "E", "U" },
|
columnLabels = { "ID", "Lvl", "Fam", "Name", "Abilities", "Zone", "R", "E", "U", "AS" },
|
||||||
columnLayout = {
|
columnLayout = {
|
||||||
{ x = 8, width = 28, align = "LEFT" },
|
{ x = 8, width = 28, align = "LEFT" },
|
||||||
{ x = 38, width = 30, align = "LEFT" },
|
{ x = 38, width = 30, align = "LEFT" },
|
||||||
{ x = 68, width = 74, align = "LEFT" },
|
{ x = 68, width = 18, align = "LEFT" },
|
||||||
{ x = 142, width = 130, align = "LEFT" },
|
{ x = 88, width = 130, align = "LEFT" },
|
||||||
{ x = 272, width = 180, align = "LEFT" },
|
{ x = 220, width = 148, align = "LEFT" },
|
||||||
{ x = 452, width = 68, align = "LEFT" },
|
{ x = 370, width = 80, align = "LEFT" },
|
||||||
{ x = 520, width = 10, align = "CENTER" },
|
{ x = 452, width = 14, align = "CENTER" },
|
||||||
{ x = 532, width = 10, align = "CENTER" },
|
{ x = 468, width = 14, align = "CENTER" },
|
||||||
{ x = 544, width = 10, align = "CENTER" },
|
{ x = 484, width = 14, align = "CENTER" },
|
||||||
|
{ x = 500, width = 54, align = "LEFT" },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,13 +29,31 @@ function MTH_BOOK_GetBeastZoneSummary(beast)
|
|||||||
return "-"
|
return "-"
|
||||||
end
|
end
|
||||||
|
|
||||||
local seen = {}
|
-- Count coords per WMA zone ID to find the dominant zone.
|
||||||
local zoneNames = {}
|
local coordCount = {}
|
||||||
for i = 1, table.getn(beast.coords) do
|
for i = 1, table.getn(beast.coords) do
|
||||||
local c = beast.coords[i]
|
local c = beast.coords[i]
|
||||||
if c and c[3] and not seen[c[3]] then
|
if c and c[3] then
|
||||||
seen[c[3]] = true
|
local zid = c[3]
|
||||||
table.insert(zoneNames, MTH_BOOK_GetZoneName(c[3]))
|
coordCount[zid] = (coordCount[zid] or 0) + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local zids = {}
|
||||||
|
for zid, _ in pairs(coordCount) do
|
||||||
|
table.insert(zids, zid)
|
||||||
|
end
|
||||||
|
-- Sort by frequency descending so the zone with most spawns is listed first.
|
||||||
|
table.sort(zids, function(a, b)
|
||||||
|
return (coordCount[a] or 0) > (coordCount[b] or 0)
|
||||||
|
end)
|
||||||
|
-- Resolve to zone names, deduplicating by name (multiple WMA IDs can resolve to the same zone).
|
||||||
|
local seenNames = {}
|
||||||
|
local zoneNames = {}
|
||||||
|
for i = 1, table.getn(zids) do
|
||||||
|
local name = MTH_BOOK_GetZoneName(zids[i])
|
||||||
|
if name and not seenNames[name] then
|
||||||
|
seenNames[name] = true
|
||||||
|
table.insert(zoneNames, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -67,6 +86,69 @@ function MTH_BOOK_SplitAbilities(text)
|
|||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local _subzoneChildCache = nil
|
||||||
|
|
||||||
|
local function MTH_BOOK_EnsureSubzoneCache()
|
||||||
|
if _subzoneChildCache then return end
|
||||||
|
_subzoneChildCache = {}
|
||||||
|
if not MTH_DS_Zones then return end
|
||||||
|
for zid, row in pairs(MTH_DS_Zones) do
|
||||||
|
local parent = row.parent
|
||||||
|
local x1 = row.x1
|
||||||
|
local y1 = row.y1
|
||||||
|
local w = row.width
|
||||||
|
local h = row.height
|
||||||
|
if parent and x1 and y1 and w and h then
|
||||||
|
local names = row.names
|
||||||
|
local name = names and (names.enUS or names[GetLocale and GetLocale() or "enUS"] or names.deDE)
|
||||||
|
if name then
|
||||||
|
if not _subzoneChildCache[parent] then
|
||||||
|
_subzoneChildCache[parent] = {}
|
||||||
|
end
|
||||||
|
table.insert(_subzoneChildCache[parent], { x1, y1, x1 + w, y1 + h, name })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_BOOK_GetBeastSubZoneSummary(beast)
|
||||||
|
if not beast or not beast.coords or table.getn(beast.coords) == 0 then return nil end
|
||||||
|
MTH_BOOK_EnsureSubzoneCache()
|
||||||
|
if not _subzoneChildCache then return nil end
|
||||||
|
|
||||||
|
local counts = {}
|
||||||
|
for i = 1, table.getn(beast.coords) do
|
||||||
|
local c = beast.coords[i]
|
||||||
|
if c then
|
||||||
|
local cx, cy, wmaId = c[1], c[2], c[3]
|
||||||
|
if cx and cy and wmaId then
|
||||||
|
local pfqId = wmaId
|
||||||
|
if type(MTH_MAP_WMA_TO_PFQ) == "table" then
|
||||||
|
pfqId = MTH_MAP_WMA_TO_PFQ[wmaId] or wmaId
|
||||||
|
end
|
||||||
|
local children = _subzoneChildCache[pfqId]
|
||||||
|
if children then
|
||||||
|
for _, sub in ipairs(children) do
|
||||||
|
if cx >= sub[1] and cx <= sub[3] and cy >= sub[2] and cy <= sub[4] then
|
||||||
|
counts[sub[5]] = (counts[sub[5]] or 0) + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local bestName, bestCount = nil, 0
|
||||||
|
for name, count in pairs(counts) do
|
||||||
|
if count > bestCount then
|
||||||
|
bestName = name
|
||||||
|
bestCount = count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return bestName
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_BOOK_HasUsableAbilities(beast)
|
function MTH_BOOK_HasUsableAbilities(beast)
|
||||||
if not beast then return false end
|
if not beast then return false end
|
||||||
local abilities = MTH_BOOK_SplitAbilities(beast.abilities)
|
local abilities = MTH_BOOK_SplitAbilities(beast.abilities)
|
||||||
@@ -231,8 +313,11 @@ function MTH_BOOK_BeastMatches(beastId, beast)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if MTH_BOOK_STATE.petInZoneOnly then
|
if MTH_BOOK_STATE.petInZoneOnly then
|
||||||
local currentZoneId = MTH_BOOK_GetCurrentZoneId()
|
-- Use the zone ID cached once per BuildResults call (avoids N calls to
|
||||||
if currentZoneId and not MTH_BOOK_BeastHasZoneId(beast, currentZoneId) then
|
-- GetCurrentZoneId which is expensive). If zone ID is nil (new/unknown
|
||||||
|
-- zone like Moonwhisper Coast), no DB entry can match — exclude all.
|
||||||
|
local currentZoneId = MTH_BOOK_STATE._cachedZoneId
|
||||||
|
if not currentZoneId or not MTH_BOOK_BeastHasZoneId(beast, currentZoneId) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -250,6 +335,12 @@ function MTH_BOOK_BeastMatches(beastId, beast)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if MTH_BOOK_STATE.petZoneFilter and MTH_BOOK_STATE.petZoneFilter ~= "all" then
|
||||||
|
if not MTH_BOOK_BeastHasZoneId(beast, MTH_BOOK_STATE.petZoneFilter) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -257,7 +348,7 @@ function MTH_BOOK_BeastSort(a, b)
|
|||||||
local beasts = MTH_DS_Beasts
|
local beasts = MTH_DS_Beasts
|
||||||
local ba = beasts and beasts[a]
|
local ba = beasts and beasts[a]
|
||||||
local bb = beasts and beasts[b]
|
local bb = beasts and beasts[b]
|
||||||
if not ba or not bb then return a < b end
|
if not ba or not bb then return tostring(a) < tostring(b) end
|
||||||
local la = MTH_BOOK_ParseLevel(ba.lvl) or 0
|
local la = MTH_BOOK_ParseLevel(ba.lvl) or 0
|
||||||
local lb = MTH_BOOK_ParseLevel(bb.lvl) or 0
|
local lb = MTH_BOOK_ParseLevel(bb.lvl) or 0
|
||||||
if la ~= lb then return la < lb end
|
if la ~= lb then return la < lb end
|
||||||
|
|||||||
+174
-25
@@ -2,18 +2,20 @@ if type(MTH_HUNTERBOOK_TABS) ~= "table" then MTH_HUNTERBOOK_TABS = {} end
|
|||||||
|
|
||||||
MTH_HUNTERBOOK_TABS.families = {
|
MTH_HUNTERBOOK_TABS.families = {
|
||||||
headerLabel = "Families",
|
headerLabel = "Families",
|
||||||
columnLabels = { "Family", "Named", "Coords", "Abilities", "Diet" },
|
columnLabels = { "Family", "Named", "Coords", "Abilities", "Diet", "HP", "dmg", "Arm" },
|
||||||
columnLayout = {
|
columnLayout = {
|
||||||
{ x = 10, width = 106, align = "LEFT" },
|
{ x = 10, width = 100, align = "LEFT" },
|
||||||
{ x = 122, width = 52, align = "LEFT" },
|
{ x = 114, width = 38, align = "LEFT" },
|
||||||
{ x = 176, width = 52, align = "LEFT" },
|
{ x = 154, width = 38, align = "LEFT" },
|
||||||
{ x = 232, width = 364, align = "LEFT" },
|
{ x = 196, width = 364, align = "LEFT" },
|
||||||
{ x = 532, width = 112, align = "LEFT" },
|
{ x = 496, width = 102, align = "LEFT" },
|
||||||
|
{ x = 602, width = 30, align = "CENTER" },
|
||||||
|
{ x = 636, width = 36, align = "CENTER" },
|
||||||
|
{ x = 674, width = 38, align = "CENTER" },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local function MTH_BOOKTAB_FamiliesTrace(message)
|
local function MTH_BOOKTAB_FamiliesTrace(message)
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_BOOKTAB_FamiliesSafeLower(value)
|
local function MTH_BOOKTAB_FamiliesSafeLower(value)
|
||||||
@@ -27,6 +29,28 @@ local function MTH_BOOKTAB_FamiliesTrim(value)
|
|||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_BOOKTAB_FormatFamilyStat(value)
|
||||||
|
local numeric = tonumber(value)
|
||||||
|
if not numeric then
|
||||||
|
return "-"
|
||||||
|
end
|
||||||
|
local colorPrefix = "|cFF4DA6FF"
|
||||||
|
if numeric < 1 then
|
||||||
|
colorPrefix = "|cFFFF4040"
|
||||||
|
elseif numeric > 1 then
|
||||||
|
colorPrefix = "|cFF40FF40"
|
||||||
|
end
|
||||||
|
local text = nil
|
||||||
|
if MTH_BOOK_STATE and MTH_BOOK_STATE.familyStatsPercent == true then
|
||||||
|
text = tostring(math.floor((numeric * 100) + 0.5)) .. "%"
|
||||||
|
return colorPrefix .. text .. "|r"
|
||||||
|
end
|
||||||
|
text = string.format("%.3f", numeric)
|
||||||
|
text = string.gsub(text, "(%..-)0+$", "%1")
|
||||||
|
text = string.gsub(text, "%.$", "")
|
||||||
|
return colorPrefix .. text .. "|r"
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_BOOKTAB_ShouldDisplayAllDiet(familyName)
|
local function MTH_BOOKTAB_ShouldDisplayAllDiet(familyName)
|
||||||
local token = MTH_BOOKTAB_FamiliesSafeLower(MTH_BOOKTAB_FamiliesTrim(familyName))
|
local token = MTH_BOOKTAB_FamiliesSafeLower(MTH_BOOKTAB_FamiliesTrim(familyName))
|
||||||
return token == "bears" or token == "boars"
|
return token == "bears" or token == "boars"
|
||||||
@@ -52,12 +76,41 @@ end
|
|||||||
function MTH_BOOKTAB_BuildFamiliesRows()
|
function MTH_BOOKTAB_BuildFamiliesRows()
|
||||||
local results = {}
|
local results = {}
|
||||||
local families = MTH_DS_Families
|
local families = MTH_DS_Families
|
||||||
|
local beasts = MTH_DS_Beasts
|
||||||
if type(families) ~= "table" then
|
if type(families) ~= "table" then
|
||||||
return results
|
return results
|
||||||
end
|
end
|
||||||
|
|
||||||
local abilityCounts = {}
|
local abilityCounts = {}
|
||||||
local canonicalMap = {}
|
local canonicalMap = {}
|
||||||
|
local familyCounts = {}
|
||||||
|
|
||||||
|
if type(beasts) == "table" then
|
||||||
|
for _, beastRow in pairs(beasts) do
|
||||||
|
if type(beastRow) == "table" then
|
||||||
|
local familyName = MTH_BOOKTAB_FamiliesTrim(beastRow.family)
|
||||||
|
if familyName ~= "" then
|
||||||
|
local counts = familyCounts[familyName]
|
||||||
|
if not counts then
|
||||||
|
counts = { named = 0, coords = 0 }
|
||||||
|
familyCounts[familyName] = counts
|
||||||
|
end
|
||||||
|
counts.named = counts.named + 1
|
||||||
|
|
||||||
|
if type(beastRow.coords) == "table" then
|
||||||
|
for coordIndex = 1, table.getn(beastRow.coords) do
|
||||||
|
local coord = beastRow.coords[coordIndex]
|
||||||
|
if type(coord) == "table" then
|
||||||
|
if coord[1] ~= nil and coord[2] ~= nil then
|
||||||
|
counts.coords = counts.coords + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, familyRow in pairs(families) do
|
for _, familyRow in pairs(families) do
|
||||||
if type(familyRow) == "table" and type(familyRow.abilities) == "table" then
|
if type(familyRow) == "table" and type(familyRow.abilities) == "table" then
|
||||||
@@ -83,6 +136,8 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
|||||||
|
|
||||||
for familyName, familyRow in pairs(families) do
|
for familyName, familyRow in pairs(families) do
|
||||||
if type(familyRow) == "table" then
|
if type(familyRow) == "table" then
|
||||||
|
local beastCounts = familyCounts[familyName] or nil
|
||||||
|
MTH_BOOKTAB_FamiliesTrace("BUILD " .. tostring(familyName) .. " icon=" .. tostring(familyRow.icon))
|
||||||
local abilities = {}
|
local abilities = {}
|
||||||
local seen = {}
|
local seen = {}
|
||||||
|
|
||||||
@@ -171,6 +226,10 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
local dietText = ""
|
local dietText = ""
|
||||||
|
local stats = type(familyRow.stats) == "table" and familyRow.stats or nil
|
||||||
|
local healthStat = stats and tonumber(stats.health) or nil
|
||||||
|
local damageStat = stats and tonumber(stats.damage) or nil
|
||||||
|
local armorStat = stats and tonumber(stats.armor) or nil
|
||||||
if MTH_BOOKTAB_ShouldDisplayAllDiet(familyName) then
|
if MTH_BOOKTAB_ShouldDisplayAllDiet(familyName) then
|
||||||
dietText = "ALL"
|
dietText = "ALL"
|
||||||
else
|
else
|
||||||
@@ -178,7 +237,8 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
|||||||
if type(familyRow.food) == "table" then
|
if type(familyRow.food) == "table" then
|
||||||
for i = 1, table.getn(familyRow.food) do
|
for i = 1, table.getn(familyRow.food) do
|
||||||
local food = MTH_BOOKTAB_FamiliesTrim(familyRow.food[i])
|
local food = MTH_BOOKTAB_FamiliesTrim(familyRow.food[i])
|
||||||
if food ~= "" then
|
local token = MTH_BOOKTAB_FamiliesSafeLower(food)
|
||||||
|
if food ~= "" and token ~= "raw fish" and token ~= "raw meat" then
|
||||||
table.insert(dietItems, string.upper(string.sub(food, 1, 1)) .. string.sub(food, 2))
|
table.insert(dietItems, string.upper(string.sub(food, 1, 1)) .. string.sub(food, 2))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -186,15 +246,22 @@ function MTH_BOOKTAB_BuildFamiliesRows()
|
|||||||
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
|
return MTH_BOOKTAB_FamiliesSafeLower(a) < MTH_BOOKTAB_FamiliesSafeLower(b)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
dietText = table.concat(dietItems, ", ")
|
dietText = table.concat(dietItems, "|")
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(results, {
|
table.insert(results, {
|
||||||
family = tostring(familyName),
|
family = tostring(familyName),
|
||||||
named = tonumber(familyRow.named) or 0,
|
icon = familyRow.icon or nil,
|
||||||
coords = tonumber(familyRow.coords) or 0,
|
named = beastCounts and (tonumber(beastCounts.named) or 0) or 0,
|
||||||
|
coords = beastCounts and (tonumber(beastCounts.coords) or 0) or 0,
|
||||||
abilities = abilities,
|
abilities = abilities,
|
||||||
dietText = dietText,
|
dietText = dietText,
|
||||||
|
healthStat = healthStat,
|
||||||
|
healthText = MTH_BOOKTAB_FormatFamilyStat(healthStat),
|
||||||
|
damageStat = damageStat,
|
||||||
|
damageText = MTH_BOOKTAB_FormatFamilyStat(damageStat),
|
||||||
|
armorStat = armorStat,
|
||||||
|
armorText = MTH_BOOKTAB_FormatFamilyStat(armorStat),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -252,31 +319,76 @@ function MTH_BOOKTAB_EnsureFamiliesUI()
|
|||||||
ui.frame:SetPoint("BOTTOMRIGHT", listParent, "BOTTOMRIGHT", -6, 6)
|
ui.frame:SetPoint("BOTTOMRIGHT", listParent, "BOTTOMRIGHT", -6, 6)
|
||||||
ui.frame:Hide()
|
ui.frame:Hide()
|
||||||
|
|
||||||
|
local statsText = getglobal("MTH_BOOK_StatsText")
|
||||||
|
local statsParent = statsText and statsText:GetParent() or nil
|
||||||
|
if statsParent then
|
||||||
|
ui.percentCheckbox = CreateFrame("CheckButton", "MTH_BOOK_FamiliesPercentCheckbox", statsParent, "UICheckButtonTemplate")
|
||||||
|
ui.percentCheckbox:SetFrameStrata(statsParent:GetFrameStrata())
|
||||||
|
ui.percentCheckbox:SetFrameLevel((statsParent:GetFrameLevel() or 0) + 20)
|
||||||
|
ui.percentCheckbox:ClearAllPoints()
|
||||||
|
if statsText then
|
||||||
|
ui.percentCheckbox:SetPoint("LEFT", statsText, "RIGHT", 260, 0)
|
||||||
|
else
|
||||||
|
ui.percentCheckbox:SetPoint("TOPLEFT", statsParent, "TOPLEFT", 538, -526)
|
||||||
|
end
|
||||||
|
ui.percentCheckbox.label = ui.percentCheckbox:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
ui.percentCheckbox.label:SetPoint("LEFT", ui.percentCheckbox, "RIGHT", 4, 0)
|
||||||
|
ui.percentCheckbox.label:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
ui.percentCheckbox.label:SetText("Show modifiers in %")
|
||||||
|
ui.percentCheckbox:SetScript("OnClick", function()
|
||||||
|
if not this then return end
|
||||||
|
MTH_BOOK_STATE.familyStatsPercent = this:GetChecked() == 1
|
||||||
|
MTH_BOOKTAB_RenderFamiliesList()
|
||||||
|
end)
|
||||||
|
ui.percentCheckbox:Hide()
|
||||||
|
end
|
||||||
|
|
||||||
ui.headerFamily = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
ui.headerFamily = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
ui.headerFamily:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 4, -2)
|
ui.headerFamily:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 4, -2)
|
||||||
ui.headerFamily:SetTextColor(1.00, 0.82, 0.00)
|
ui.headerFamily:SetTextColor(1.00, 0.82, 0.00)
|
||||||
ui.headerFamily:SetText("Family")
|
ui.headerFamily:SetText("Family")
|
||||||
|
|
||||||
ui.headerNamed = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
ui.headerNamed = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
ui.headerNamed:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 122, -2)
|
ui.headerNamed:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 114, -2)
|
||||||
ui.headerNamed:SetTextColor(1.00, 0.82, 0.00)
|
ui.headerNamed:SetTextColor(1.00, 0.82, 0.00)
|
||||||
ui.headerNamed:SetText("Named")
|
ui.headerNamed:SetText("Named")
|
||||||
|
|
||||||
ui.headerCoords = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
ui.headerCoords = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
ui.headerCoords:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 176, -2)
|
ui.headerCoords:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 154, -2)
|
||||||
ui.headerCoords:SetTextColor(1.00, 0.82, 0.00)
|
ui.headerCoords:SetTextColor(1.00, 0.82, 0.00)
|
||||||
ui.headerCoords:SetText("Coords")
|
ui.headerCoords:SetText("Coords")
|
||||||
|
|
||||||
ui.headerAbilities = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
ui.headerAbilities = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
ui.headerAbilities:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 232, -2)
|
ui.headerAbilities:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 196, -2)
|
||||||
ui.headerAbilities:SetTextColor(1.00, 0.82, 0.00)
|
ui.headerAbilities:SetTextColor(1.00, 0.82, 0.00)
|
||||||
ui.headerAbilities:SetText("Abilities")
|
ui.headerAbilities:SetText("Abilities")
|
||||||
|
|
||||||
ui.headerDiet = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
ui.headerDiet = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
ui.headerDiet:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 532, -2)
|
ui.headerDiet:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 496, -2)
|
||||||
ui.headerDiet:SetTextColor(1.00, 0.82, 0.00)
|
ui.headerDiet:SetTextColor(1.00, 0.82, 0.00)
|
||||||
ui.headerDiet:SetText("Diet")
|
ui.headerDiet:SetText("Diet")
|
||||||
|
|
||||||
|
ui.headerHP = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
ui.headerHP:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 602, -2)
|
||||||
|
ui.headerHP:SetWidth(30)
|
||||||
|
ui.headerHP:SetJustifyH("CENTER")
|
||||||
|
ui.headerHP:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
ui.headerHP:SetText("HP")
|
||||||
|
|
||||||
|
ui.headerDmg = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
ui.headerDmg:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 636, -2)
|
||||||
|
ui.headerDmg:SetWidth(36)
|
||||||
|
ui.headerDmg:SetJustifyH("CENTER")
|
||||||
|
ui.headerDmg:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
ui.headerDmg:SetText("dmg")
|
||||||
|
|
||||||
|
ui.headerArm = ui.frame:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
ui.headerArm:SetPoint("TOPLEFT", ui.frame, "TOPLEFT", 674, -2)
|
||||||
|
ui.headerArm:SetWidth(38)
|
||||||
|
ui.headerArm:SetJustifyH("CENTER")
|
||||||
|
ui.headerArm:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
ui.headerArm:SetText("Arm")
|
||||||
|
|
||||||
ui.rows = {}
|
ui.rows = {}
|
||||||
for i = 1, 28 do
|
for i = 1, 28 do
|
||||||
local row = CreateFrame("Frame", nil, ui.frame)
|
local row = CreateFrame("Frame", nil, ui.frame)
|
||||||
@@ -289,26 +401,47 @@ function MTH_BOOKTAB_EnsureFamiliesUI()
|
|||||||
row:SetPoint("TOPRIGHT", ui.rows[i - 1], "BOTTOMRIGHT", 0, -1)
|
row:SetPoint("TOPRIGHT", ui.rows[i - 1], "BOTTOMRIGHT", 0, -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
row.familyIcon = row:CreateTexture(nil, "ARTWORK")
|
||||||
|
row.familyIcon:SetPoint("LEFT", row, "LEFT", 4, 0)
|
||||||
|
row.familyIcon:SetWidth(16)
|
||||||
|
row.familyIcon:SetHeight(16)
|
||||||
|
row.familyIcon:Hide()
|
||||||
|
|
||||||
row.family = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
row.family = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
row.family:SetPoint("LEFT", row, "LEFT", 4, 0)
|
row.family:SetPoint("LEFT", row, "LEFT", 24, 0)
|
||||||
row.family:SetWidth(106)
|
row.family:SetWidth(82)
|
||||||
row.family:SetJustifyH("LEFT")
|
row.family:SetJustifyH("LEFT")
|
||||||
|
|
||||||
row.named = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
row.named = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
row.named:SetPoint("LEFT", row, "LEFT", 122, 0)
|
row.named:SetPoint("LEFT", row, "LEFT", 114, 0)
|
||||||
row.named:SetWidth(52)
|
row.named:SetWidth(38)
|
||||||
row.named:SetJustifyH("LEFT")
|
row.named:SetJustifyH("LEFT")
|
||||||
|
|
||||||
row.coords = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
row.coords = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
row.coords:SetPoint("LEFT", row, "LEFT", 176, 0)
|
row.coords:SetPoint("LEFT", row, "LEFT", 154, 0)
|
||||||
row.coords:SetWidth(52)
|
row.coords:SetWidth(38)
|
||||||
row.coords:SetJustifyH("LEFT")
|
row.coords:SetJustifyH("LEFT")
|
||||||
|
|
||||||
row.diet = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
row.diet = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
row.diet:SetPoint("LEFT", row, "LEFT", 532, 0)
|
row.diet:SetPoint("LEFT", row, "LEFT", 496, 0)
|
||||||
row.diet:SetWidth(112)
|
row.diet:SetWidth(102)
|
||||||
row.diet:SetJustifyH("LEFT")
|
row.diet:SetJustifyH("LEFT")
|
||||||
|
|
||||||
|
row.hp = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
|
row.hp:SetPoint("LEFT", row, "LEFT", 602, 0)
|
||||||
|
row.hp:SetWidth(30)
|
||||||
|
row.hp:SetJustifyH("CENTER")
|
||||||
|
|
||||||
|
row.dmg = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
|
row.dmg:SetPoint("LEFT", row, "LEFT", 636, 0)
|
||||||
|
row.dmg:SetWidth(36)
|
||||||
|
row.dmg:SetJustifyH("CENTER")
|
||||||
|
|
||||||
|
row.arm = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
|
row.arm:SetPoint("LEFT", row, "LEFT", 674, 0)
|
||||||
|
row.arm:SetWidth(38)
|
||||||
|
row.arm:SetJustifyH("CENTER")
|
||||||
|
|
||||||
row.abilityButtons = {}
|
row.abilityButtons = {}
|
||||||
for b = 1, 16 do
|
for b = 1, 16 do
|
||||||
local button = CreateFrame("Button", nil, row)
|
local button = CreateFrame("Button", nil, row)
|
||||||
@@ -372,9 +505,14 @@ function MTH_BOOKTAB_SetFamiliesUIVisible(visible)
|
|||||||
if detailParent then detailParent:Hide() end
|
if detailParent then detailParent:Hide() end
|
||||||
if detailText then detailText:Hide() end
|
if detailText then detailText:Hide() end
|
||||||
if openMapButton then openMapButton:Hide() end
|
if openMapButton then openMapButton:Hide() end
|
||||||
|
if ui.percentCheckbox then
|
||||||
|
ui.percentCheckbox:SetChecked(MTH_BOOK_STATE and MTH_BOOK_STATE.familyStatsPercent == true and 1 or nil)
|
||||||
|
ui.percentCheckbox:Show()
|
||||||
|
end
|
||||||
ui.frame:Show()
|
ui.frame:Show()
|
||||||
else
|
else
|
||||||
ui.frame:Hide()
|
ui.frame:Hide()
|
||||||
|
if ui.percentCheckbox then ui.percentCheckbox:Hide() end
|
||||||
if listParent then listParent:Show() end
|
if listParent then listParent:Show() end
|
||||||
if detailParent then detailParent:Show() end
|
if detailParent then detailParent:Show() end
|
||||||
if detailText then detailText:Show() end
|
if detailText then detailText:Show() end
|
||||||
@@ -393,12 +531,23 @@ function MTH_BOOKTAB_RenderFamiliesList()
|
|||||||
if row then
|
if row then
|
||||||
rowFrame:Show()
|
rowFrame:Show()
|
||||||
rowFrame.family:SetText(tostring(row.family or "-"))
|
rowFrame.family:SetText(tostring(row.family or "-"))
|
||||||
|
local familyIconPath = row.icon and MTH_BOOK_ResolveIconPath and MTH_BOOK_ResolveIconPath(row.icon) or nil
|
||||||
|
MTH_BOOKTAB_FamiliesTrace("RENDER " .. tostring(row.family) .. " icon=" .. tostring(row.icon) .. " path=" .. tostring(familyIconPath))
|
||||||
|
if familyIconPath then
|
||||||
|
rowFrame.familyIcon:SetTexture(familyIconPath)
|
||||||
|
rowFrame.familyIcon:Show()
|
||||||
|
else
|
||||||
|
rowFrame.familyIcon:Hide()
|
||||||
|
end
|
||||||
rowFrame.named:SetText(tostring(row.named or 0))
|
rowFrame.named:SetText(tostring(row.named or 0))
|
||||||
rowFrame.coords:SetText(tostring(row.coords or 0))
|
rowFrame.coords:SetText(tostring(row.coords or 0))
|
||||||
rowFrame.diet:SetText(tostring(row.dietText or "-"))
|
rowFrame.diet:SetText(tostring(row.dietText or "-"))
|
||||||
|
rowFrame.hp:SetText(MTH_BOOKTAB_FormatFamilyStat(row.healthStat))
|
||||||
|
rowFrame.dmg:SetText(MTH_BOOKTAB_FormatFamilyStat(row.damageStat))
|
||||||
|
rowFrame.arm:SetText(MTH_BOOKTAB_FormatFamilyStat(row.armorStat))
|
||||||
|
|
||||||
local offsetX = 232
|
local offsetX = 196
|
||||||
local abilityMaxRight = 526
|
local abilityMaxRight = 490
|
||||||
for b = 1, table.getn(rowFrame.abilityButtons) do
|
for b = 1, table.getn(rowFrame.abilityButtons) do
|
||||||
local button = rowFrame.abilityButtons[b]
|
local button = rowFrame.abilityButtons[b]
|
||||||
local ability = row.abilities and row.abilities[b] or nil
|
local ability = row.abilities and row.abilities[b] or nil
|
||||||
|
|||||||
+100
-81
@@ -140,7 +140,7 @@ function MTH_BOOK_GetResistanceShortName(nameText)
|
|||||||
if string.find(lowerName, "arcane", 1, true) then return "AR" end
|
if string.find(lowerName, "arcane", 1, true) then return "AR" end
|
||||||
if string.find(lowerName, "nature", 1, true) then return "NR" end
|
if string.find(lowerName, "nature", 1, true) then return "NR" end
|
||||||
if string.find(lowerName, "fire", 1, true) then return "FR" end
|
if string.find(lowerName, "fire", 1, true) then return "FR" end
|
||||||
if string.find(lowerName, "frost", 1, true) then return "FR" end
|
if string.find(lowerName, "frost", 1, true) then return "FrR" end
|
||||||
if string.find(lowerName, "shadow", 1, true) then return "SR" end
|
if string.find(lowerName, "shadow", 1, true) then return "SR" end
|
||||||
return tostring(nameText or "-")
|
return tostring(nameText or "-")
|
||||||
end
|
end
|
||||||
@@ -547,7 +547,75 @@ MTH_BOOK_NormalizeStableFoodLink = function(itemId, itemLink, itemName)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_BOOK_FindStableFoodBagIcon(itemId, itemName)
|
||||||
|
local getContainerNumSlots = (type(getglobal) == "function" and getglobal("GetContainerNumSlots")) or (_G and _G["GetContainerNumSlots"])
|
||||||
|
local getContainerItemLink = (type(getglobal) == "function" and getglobal("GetContainerItemLink")) or (_G and _G["GetContainerItemLink"])
|
||||||
|
local getContainerItemInfo = (type(getglobal) == "function" and getglobal("GetContainerItemInfo")) or (_G and _G["GetContainerItemInfo"])
|
||||||
|
if type(getContainerNumSlots) ~= "function" or type(getContainerItemLink) ~= "function" or type(getContainerItemInfo) ~= "function" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local wantedItemId = tonumber(itemId)
|
||||||
|
local wantedName = string.lower(tostring(itemName or ""))
|
||||||
|
for bag = 0, 4 do
|
||||||
|
local slotCount = tonumber(getContainerNumSlots(bag)) or 0
|
||||||
|
for slot = 1, slotCount do
|
||||||
|
local link = getContainerItemLink(bag, slot)
|
||||||
|
if link then
|
||||||
|
local matched = false
|
||||||
|
if wantedItemId then
|
||||||
|
local _, _, parsedId = string.find(tostring(link), "item:(%d+)")
|
||||||
|
if tonumber(parsedId) == wantedItemId then
|
||||||
|
matched = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not matched and wantedName ~= "" then
|
||||||
|
local _, _, parsedName = string.find(tostring(link), "|h%[([^%]]+)%]|h")
|
||||||
|
if parsedName and string.lower(tostring(parsedName)) == wantedName then
|
||||||
|
matched = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if matched then
|
||||||
|
local bagTexture = getContainerItemInfo(bag, slot)
|
||||||
|
if bagTexture and bagTexture ~= "" then
|
||||||
|
if type(bagTexture) == "string" and string.find(bagTexture, "\\", 1, true) then
|
||||||
|
return bagTexture
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_BOOK_ResolveStableFoodIcon(itemId, iconHint, itemName, itemLink)
|
local function MTH_BOOK_ResolveStableFoodIcon(itemId, iconHint, itemName, itemLink)
|
||||||
|
local function resolveTextureCandidate(value)
|
||||||
|
if value == nil or value == "" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if type(value) == "number" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local text = tostring(value)
|
||||||
|
if text == "" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if string.find(text, "|Hitem:", 1, true) or string.find(text, "^item:%d+") then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if string.find(text, "^table:", 1, true) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if string.find(text, "\\", 1, true) then
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
local asNumber = tonumber(text)
|
||||||
|
if asNumber then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return "Interface\\Icons\\" .. text
|
||||||
|
end
|
||||||
|
|
||||||
local linkText = tostring(itemLink or "")
|
local linkText = tostring(itemLink or "")
|
||||||
local linkItemId = nil
|
local linkItemId = nil
|
||||||
if linkText ~= "" then
|
if linkText ~= "" then
|
||||||
@@ -559,104 +627,55 @@ local function MTH_BOOK_ResolveStableFoodIcon(itemId, iconHint, itemName, itemLi
|
|||||||
|
|
||||||
local numericItemId = tonumber(itemId) or linkItemId
|
local numericItemId = tonumber(itemId) or linkItemId
|
||||||
|
|
||||||
if linkText ~= "" and type(GetItemInfo) == "function" then
|
|
||||||
local _, _, _, _, _, _, _, _, _, linkTexture = GetItemInfo(linkText)
|
|
||||||
if linkTexture and linkTexture ~= "" then
|
|
||||||
if type(linkTexture) == "number" then
|
|
||||||
return linkTexture
|
|
||||||
end
|
|
||||||
if string.find(tostring(linkTexture), "\\", 1, true) then
|
|
||||||
return tostring(linkTexture)
|
|
||||||
end
|
|
||||||
local asNumber = tonumber(tostring(linkTexture))
|
|
||||||
if asNumber then
|
|
||||||
return asNumber
|
|
||||||
end
|
|
||||||
return "Interface\\Icons\\" .. tostring(linkTexture)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(iconHint) == "number" then
|
|
||||||
return iconHint
|
|
||||||
end
|
|
||||||
|
|
||||||
local iconHintText = tostring(iconHint or "")
|
|
||||||
if iconHintText ~= "" then
|
|
||||||
local numericHint = tonumber(iconHintText)
|
|
||||||
if numericHint then
|
|
||||||
return numericHint
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local iconPath = iconHintText
|
|
||||||
if iconPath ~= "" then
|
|
||||||
if string.find(iconPath, "\\", 1, true) then
|
|
||||||
return iconPath
|
|
||||||
end
|
|
||||||
return "Interface\\Icons\\" .. iconPath
|
|
||||||
end
|
|
||||||
|
|
||||||
if numericItemId and type(GetItemInfo) == "function" then
|
if numericItemId and type(GetItemInfo) == "function" then
|
||||||
local _, _, _, _, _, _, _, _, _, infoTexture = GetItemInfo(numericItemId)
|
local _, _, _, _, _, _, _, _, _, infoTexture = GetItemInfo(numericItemId)
|
||||||
if infoTexture and infoTexture ~= "" then
|
local resolvedInfoTexture = resolveTextureCandidate(infoTexture)
|
||||||
if type(infoTexture) == "number" then
|
if resolvedInfoTexture then
|
||||||
return infoTexture
|
return resolvedInfoTexture
|
||||||
end
|
|
||||||
if string.find(tostring(infoTexture), "\\", 1, true) then
|
|
||||||
return tostring(infoTexture)
|
|
||||||
end
|
|
||||||
local asNumber = tonumber(tostring(infoTexture))
|
|
||||||
if asNumber then
|
|
||||||
return asNumber
|
|
||||||
end
|
|
||||||
return "Interface\\Icons\\" .. tostring(infoTexture)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if numericItemId and type(GetItemIcon) == "function" then
|
if numericItemId and type(GetItemIcon) == "function" then
|
||||||
local directIcon = GetItemIcon(numericItemId)
|
local directIcon = GetItemIcon(numericItemId)
|
||||||
if directIcon and directIcon ~= "" then
|
local resolvedDirectIcon = resolveTextureCandidate(directIcon)
|
||||||
if type(directIcon) == "number" then
|
if resolvedDirectIcon then
|
||||||
return directIcon
|
return resolvedDirectIcon
|
||||||
end
|
end
|
||||||
if string.find(tostring(directIcon), "\\", 1, true) then
|
end
|
||||||
return tostring(directIcon)
|
|
||||||
end
|
local resolvedHintIcon = resolveTextureCandidate(iconHint)
|
||||||
local asNumber = tonumber(tostring(directIcon))
|
if resolvedHintIcon then
|
||||||
if asNumber then
|
return resolvedHintIcon
|
||||||
return asNumber
|
end
|
||||||
end
|
|
||||||
return "Interface\\Icons\\" .. tostring(directIcon)
|
if linkText ~= "" and type(GetItemInfo) == "function" then
|
||||||
|
local _, _, _, _, _, _, _, _, _, linkTexture = GetItemInfo(linkText)
|
||||||
|
local resolvedLinkTexture = resolveTextureCandidate(linkTexture)
|
||||||
|
if resolvedLinkTexture then
|
||||||
|
return resolvedLinkTexture
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if itemName and itemName ~= "" and type(GetItemIcon) == "function" then
|
if itemName and itemName ~= "" and type(GetItemIcon) == "function" then
|
||||||
local namedIcon = GetItemIcon(itemName)
|
local namedIcon = GetItemIcon(itemName)
|
||||||
if namedIcon and namedIcon ~= "" then
|
local resolvedNamedIcon = resolveTextureCandidate(namedIcon)
|
||||||
if type(namedIcon) == "number" then
|
if resolvedNamedIcon then
|
||||||
return namedIcon
|
return resolvedNamedIcon
|
||||||
end
|
|
||||||
if string.find(tostring(namedIcon), "\\", 1, true) then
|
|
||||||
return tostring(namedIcon)
|
|
||||||
end
|
|
||||||
local asNumber = tonumber(tostring(namedIcon))
|
|
||||||
if asNumber then
|
|
||||||
return asNumber
|
|
||||||
end
|
|
||||||
return "Interface\\Icons\\" .. tostring(namedIcon)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if numericItemId and type(MTH_DS_Items) == "table" and type(MTH_DS_Items[numericItemId]) == "table" then
|
if numericItemId and type(MTH_DS_Items) == "table" and type(MTH_DS_Items[numericItemId]) == "table" then
|
||||||
local dsIcon = tostring(MTH_DS_Items[numericItemId].icon or "")
|
local resolvedDsIcon = resolveTextureCandidate(MTH_DS_Items[numericItemId].icon)
|
||||||
if dsIcon ~= "" then
|
if resolvedDsIcon then
|
||||||
if string.find(dsIcon, "\\", 1, true) then
|
return resolvedDsIcon
|
||||||
return dsIcon
|
|
||||||
end
|
|
||||||
return "Interface\\Icons\\" .. dsIcon
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local bagIcon = MTH_BOOK_FindStableFoodBagIcon(numericItemId, itemName)
|
||||||
|
if bagIcon then
|
||||||
|
return bagIcon
|
||||||
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1566,7 +1585,7 @@ function MTH_BOOKTAB_RenderStableCards()
|
|||||||
local abilitiesCount = MTH_BOOK_CountPetAbilitiesMap(row.abilities)
|
local abilitiesCount = MTH_BOOK_CountPetAbilitiesMap(row.abilities)
|
||||||
local abilitiesText = MTH_BOOK_GetStableAbilitySummary(row.abilities)
|
local abilitiesText = MTH_BOOK_GetStableAbilitySummary(row.abilities)
|
||||||
local legacyTameContext = type(row.tameContext) == "table" and row.tameContext or nil
|
local legacyTameContext = type(row.tameContext) == "table" and row.tameContext or nil
|
||||||
local hasRecordedTame = row.tameRecorded == true
|
local hasRecordedTame = type(MTH_PETS_HasVerifiedTameRecord) == "function" and MTH_PETS_HasVerifiedTameRecord(row) or (row.tameRecorded == true)
|
||||||
if not hasRecordedTame and legacyTameContext then
|
if not hasRecordedTame and legacyTameContext then
|
||||||
if legacyTameContext.name or legacyTameContext.zone or legacyTameContext.timestamp then
|
if legacyTameContext.name or legacyTameContext.zone or legacyTameContext.timestamp then
|
||||||
hasRecordedTame = true
|
hasRecordedTame = true
|
||||||
|
|||||||
+510
-116
File diff suppressed because it is too large
Load Diff
+24
-5
@@ -57,6 +57,14 @@
|
|||||||
</Anchors>
|
</Anchors>
|
||||||
</FontString>
|
</FontString>
|
||||||
|
|
||||||
|
<FontString name="$parentBeastZoneLabel" inherits="GameFontNormalSmall" text="Zone:" hidden="true">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPLEFT">
|
||||||
|
<Offset><AbsDimension x="464" y="-142"/></Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</FontString>
|
||||||
|
|
||||||
</Layer>
|
</Layer>
|
||||||
</Layers>
|
</Layers>
|
||||||
|
|
||||||
@@ -74,7 +82,7 @@
|
|||||||
</Frame>
|
</Frame>
|
||||||
|
|
||||||
<Frame name="$parentDetailBackdrop">
|
<Frame name="$parentDetailBackdrop">
|
||||||
<Size><AbsDimension x="136" y="324"/></Size>
|
<Size><AbsDimension x="136" y="155"/></Size>
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="608" y="-166"/></Offset></Anchor>
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="608" y="-166"/></Offset></Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
@@ -85,7 +93,7 @@
|
|||||||
</Backdrop>
|
</Backdrop>
|
||||||
<Frames>
|
<Frames>
|
||||||
<EditBox name="$parentDetailText" autoFocus="false" multiLine="true" text="Select an entry to view details.">
|
<EditBox name="$parentDetailText" autoFocus="false" multiLine="true" text="Select an entry to view details.">
|
||||||
<Size><AbsDimension x="120" y="306"/></Size>
|
<Size><AbsDimension x="120" y="139"/></Size>
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="8" y="-8"/></Offset></Anchor>
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="8" y="-8"/></Offset></Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
@@ -96,7 +104,7 @@
|
|||||||
<Button name="$parentOpenMapButton" inherits="UIPanelButtonTemplate" text="Open Map" hidden="true">
|
<Button name="$parentOpenMapButton" inherits="UIPanelButtonTemplate" text="Open Map" hidden="true">
|
||||||
<Size><AbsDimension x="136" y="22"/></Size>
|
<Size><AbsDimension x="136" y="22"/></Size>
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="608" y="-496"/></Offset></Anchor>
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="608" y="-524"/></Offset></Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@@ -265,7 +273,7 @@
|
|||||||
</Frame>
|
</Frame>
|
||||||
<CheckButton name="$parentPetInZoneOnly" inherits="UICheckButtonTemplate" hidden="true">
|
<CheckButton name="$parentPetInZoneOnly" inherits="UICheckButtonTemplate" hidden="true">
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="488" y="-112"/></Offset></Anchor>
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="526" y="-106"/></Offset></Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
</CheckButton>
|
</CheckButton>
|
||||||
<Button name="$parentShowAllOnMapButton" inherits="UIPanelButtonTemplate" text="Show all on map" hidden="true">
|
<Button name="$parentShowAllOnMapButton" inherits="UIPanelButtonTemplate" text="Show all on map" hidden="true">
|
||||||
@@ -298,8 +306,19 @@
|
|||||||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="232" y="-140"/></Offset></Anchor></Anchors>
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="232" y="-140"/></Offset></Anchor></Anchors>
|
||||||
</CheckButton>
|
</CheckButton>
|
||||||
<CheckButton name="$parentHideUnknown" inherits="UICheckButtonTemplate">
|
<CheckButton name="$parentHideUnknown" inherits="UICheckButtonTemplate">
|
||||||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="372" y="-140"/></Offset></Anchor></Anchors>
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="290" y="-140"/></Offset></Anchor></Anchors>
|
||||||
</CheckButton>
|
</CheckButton>
|
||||||
|
<Frame name="$parentBeastContinentDropdown" inherits="UIDropDownMenuTemplate" hidden="true">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="482" y="-136"/></Offset></Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
|
<Frame name="$parentBeastZoneDropdown" inherits="UIDropDownMenuTemplate" hidden="true">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="592" y="-136"/></Offset></Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
<Frame name="$parentListSliderBackdrop">
|
<Frame name="$parentListSliderBackdrop">
|
||||||
<Size><AbsDimension x="22" y="322"/></Size>
|
<Size><AbsDimension x="22" y="322"/></Size>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ local MTH_LOCALE_ALIASES = {
|
|||||||
enGB = "enUS",
|
enGB = "enUS",
|
||||||
esMX = "esES",
|
esMX = "esES",
|
||||||
zhTW = "zhCN",
|
zhTW = "zhCN",
|
||||||
frFR = "enUS",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local MTH_SUPPORTED_LOCALES = {
|
local MTH_SUPPORTED_LOCALES = {
|
||||||
@@ -57,6 +56,8 @@ BINDING_HEADER_ZTrackHeader = MTH_L("BINDING_HEADER_ZTrackHeader", "[MetaHunt] Z
|
|||||||
BINDING_HEADER_ZTrapHeader = MTH_L("BINDING_HEADER_ZTrapHeader", "[MetaHunt] ZTrap Buttons")
|
BINDING_HEADER_ZTrapHeader = MTH_L("BINDING_HEADER_ZTrapHeader", "[MetaHunt] ZTrap Buttons")
|
||||||
BINDING_HEADER_ZPetHeader = MTH_L("BINDING_HEADER_ZPetHeader", "[MetaHunt] ZPet Buttons")
|
BINDING_HEADER_ZPetHeader = MTH_L("BINDING_HEADER_ZPetHeader", "[MetaHunt] ZPet Buttons")
|
||||||
BINDING_HEADER_ZAmmoHeader = MTH_L("BINDING_HEADER_ZAmmoHeader", "[MetaHunt] ZAmmo Buttons")
|
BINDING_HEADER_ZAmmoHeader = MTH_L("BINDING_HEADER_ZAmmoHeader", "[MetaHunt] ZAmmo Buttons")
|
||||||
|
BINDING_HEADER_ExpAmmoHeader = MTH_L("BINDING_HEADER_ExpAmmoHeader", "[MetaHunt] MM Widget")
|
||||||
|
BINDING_NAME_EXPAMMOACTION = MTH_L("BINDING_NAME_EXPAMMOACTION", "MM Widget Action")
|
||||||
|
|
||||||
function MTH:GetLocalization(key, default)
|
function MTH:GetLocalization(key, default)
|
||||||
return MTH_L(key, default)
|
return MTH_L(key, default)
|
||||||
|
|||||||
+144
-49
@@ -5,6 +5,7 @@ MTH_Map = {
|
|||||||
activeSource = "focus",
|
activeSource = "focus",
|
||||||
providers = {},
|
providers = {},
|
||||||
nodesByZone = {},
|
nodesByZone = {},
|
||||||
|
minimapNodesByZone = {},
|
||||||
worldPins = {},
|
worldPins = {},
|
||||||
minimapPins = {},
|
minimapPins = {},
|
||||||
zoneNameToId = {},
|
zoneNameToId = {},
|
||||||
@@ -12,6 +13,7 @@ MTH_Map = {
|
|||||||
mapZoneCache = {},
|
mapZoneCache = {},
|
||||||
focusNodes = {},
|
focusNodes = {},
|
||||||
pendingZoneOpenId = nil,
|
pendingZoneOpenId = nil,
|
||||||
|
pendingZoneOpenPfqId = nil,
|
||||||
pendingZoneOpenSourceId = nil,
|
pendingZoneOpenSourceId = nil,
|
||||||
pendingZoneOpenAttempts = 0,
|
pendingZoneOpenAttempts = 0,
|
||||||
pendingZoneOpenNextAttemptAt = 0,
|
pendingZoneOpenNextAttemptAt = 0,
|
||||||
@@ -23,7 +25,7 @@ MTH_Map = {
|
|||||||
nodeRevision = 0,
|
nodeRevision = 0,
|
||||||
minimapForceRefreshInterval = 1.0,
|
minimapForceRefreshInterval = 1.0,
|
||||||
verboseMiniReasons = false,
|
verboseMiniReasons = false,
|
||||||
minimapTickActive = 0.20,
|
minimapTickActive = 0.05,
|
||||||
minimapTickIdle = 0.75,
|
minimapTickIdle = 0.75,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,11 +62,6 @@ local function MTH_Map_Mod(a, b)
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_Map_Log(msg)
|
|
||||||
if MTH and MTH.debug and MTH.Print then
|
|
||||||
MTH:Print("[MAP] " .. tostring(msg), "debug")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function MTH_Map_NormalizeName(name)
|
local function MTH_Map_NormalizeName(name)
|
||||||
if not name then return "" end
|
if not name then return "" end
|
||||||
@@ -126,16 +123,54 @@ local function MTH_Map_StripThePrefix(name)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function MTH_Map_WmaToPfq(zoneId)
|
||||||
|
if type(MTH_MAP_WMA_TO_PFQ) == "table" then
|
||||||
|
return MTH_MAP_WMA_TO_PFQ[zoneId] or zoneId
|
||||||
|
end
|
||||||
|
return zoneId
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_Map_PfqToWma(pfqId)
|
||||||
|
if type(MTH_MAP_PFQ_TO_WMA) == "table" then
|
||||||
|
return MTH_MAP_PFQ_TO_WMA[pfqId] or pfqId
|
||||||
|
end
|
||||||
|
return pfqId
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_Map_GetMinimapSizes()
|
||||||
|
if pfDB and pfDB["minimap"] and MTH_DS_MinimapSizes then
|
||||||
|
if not MTH_Map._mergedMinimapSizes then
|
||||||
|
local merged = {}
|
||||||
|
for zoneId, size in pairs(pfDB["minimap"]) do
|
||||||
|
merged[zoneId] = size
|
||||||
|
end
|
||||||
|
for zoneId, size in pairs(MTH_DS_MinimapSizes) do
|
||||||
|
if merged[zoneId] == nil then
|
||||||
|
merged[zoneId] = size
|
||||||
|
end
|
||||||
|
end
|
||||||
|
MTH_Map._mergedMinimapSizes = merged
|
||||||
|
end
|
||||||
|
return MTH_Map._mergedMinimapSizes
|
||||||
|
elseif pfDB and pfDB["minimap"] then
|
||||||
|
return pfDB["minimap"]
|
||||||
|
end
|
||||||
|
return MTH_DS_MinimapSizes or {}
|
||||||
|
end
|
||||||
|
|
||||||
local function MTH_Map_GetZoneNameById(zoneId)
|
local function MTH_Map_GetZoneNameById(zoneId)
|
||||||
local normalizedId = tonumber(zoneId) or zoneId
|
local normalizedId = tonumber(zoneId) or zoneId
|
||||||
if not normalizedId then return nil end
|
if not normalizedId then return nil end
|
||||||
|
|
||||||
if MTH_DS_ZoneNamesFallback and MTH_DS_ZoneNamesFallback[normalizedId] then
|
-- Translate WMA→pfQ first so WMA IDs don't accidentally hit wrong pfQ entries.
|
||||||
return MTH_DS_ZoneNamesFallback[normalizedId]
|
local pfqId = MTH_Map_WmaToPfq(normalizedId)
|
||||||
|
|
||||||
|
if MTH_DS_ZoneNamesFallback and MTH_DS_ZoneNamesFallback[pfqId] then
|
||||||
|
return MTH_DS_ZoneNamesFallback[pfqId]
|
||||||
end
|
end
|
||||||
|
|
||||||
if not MTH_DS_Zones then return nil end
|
if not MTH_DS_Zones then return nil end
|
||||||
local row = MTH_DS_Zones[normalizedId] or MTH_DS_Zones[tostring(normalizedId)]
|
local row = MTH_DS_Zones[pfqId] or MTH_DS_Zones[tostring(pfqId)]
|
||||||
if not row or not row.names then return nil end
|
if not row or not row.names then return nil end
|
||||||
return row.names.enUS or row.names[GetLocale()] or row.names.deDE or row.names.frFR
|
return row.names.enUS or row.names[GetLocale()] or row.names.deDE or row.names.frFR
|
||||||
end
|
end
|
||||||
@@ -327,7 +362,6 @@ function MTH_Map:BuildZoneLookup()
|
|||||||
for _ in pairs(self.zoneNameNormToId) do
|
for _ in pairs(self.zoneNameNormToId) do
|
||||||
count = count + 1
|
count = count + 1
|
||||||
end
|
end
|
||||||
MTH_Map_Log("Zone lookup rebuilt: " .. tostring(count) .. " entries")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_Map:GetMapIDByName(name)
|
function MTH_Map:GetMapIDByName(name)
|
||||||
@@ -363,6 +397,8 @@ end
|
|||||||
|
|
||||||
function MTH_Map:ResolveZoneHierarchy(zoneId)
|
function MTH_Map:ResolveZoneHierarchy(zoneId)
|
||||||
local inputId = tonumber(zoneId)
|
local inputId = tonumber(zoneId)
|
||||||
|
local pfqInputId = MTH_Map_WmaToPfq(inputId)
|
||||||
|
local inputIsWma = inputId and pfqInputId ~= inputId or false
|
||||||
local resolved = {
|
local resolved = {
|
||||||
inputId = inputId,
|
inputId = inputId,
|
||||||
zoneId = inputId,
|
zoneId = inputId,
|
||||||
@@ -376,9 +412,9 @@ function MTH_Map:ResolveZoneHierarchy(zoneId)
|
|||||||
return resolved
|
return resolved
|
||||||
end
|
end
|
||||||
|
|
||||||
local sizes = MTH_DS_MinimapSizes or (pfDB and pfDB["minimap"]) or {}
|
local sizes = MTH_Map_GetMinimapSizes()
|
||||||
local visited = {}
|
local visited = {}
|
||||||
local cursor = inputId
|
local cursor = pfqInputId
|
||||||
local depth = 0
|
local depth = 0
|
||||||
|
|
||||||
while cursor and not visited[cursor] and depth < 8 do
|
while cursor and not visited[cursor] and depth < 8 do
|
||||||
@@ -389,15 +425,17 @@ function MTH_Map:ResolveZoneHierarchy(zoneId)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local parent = tonumber(row.parent or row.continent)
|
local parent = tonumber(row.parent or row.continent)
|
||||||
|
local outputCursor = inputIsWma and MTH_Map_PfqToWma(cursor) or cursor
|
||||||
|
local outputParent = parent and (inputIsWma and MTH_Map_PfqToWma(parent) or parent) or nil
|
||||||
if parent and not resolved.continentId then
|
if parent and not resolved.continentId then
|
||||||
resolved.continentId = parent
|
resolved.continentId = outputParent
|
||||||
end
|
end
|
||||||
|
|
||||||
if parent and parent > 0 and parent ~= cursor then
|
if parent and parent > 0 and parent ~= cursor then
|
||||||
resolved.subzoneId = resolved.subzoneId or cursor
|
resolved.subzoneId = resolved.subzoneId or outputCursor
|
||||||
resolved.parentId = parent
|
resolved.parentId = outputParent
|
||||||
cursor = parent
|
cursor = parent
|
||||||
resolved.zoneId = cursor
|
resolved.zoneId = inputIsWma and MTH_Map_PfqToWma(cursor) or cursor
|
||||||
depth = depth + 1
|
depth = depth + 1
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
@@ -405,11 +443,17 @@ function MTH_Map:ResolveZoneHierarchy(zoneId)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local renderZoneId = resolved.zoneId
|
local renderZoneId = resolved.zoneId
|
||||||
|
local pfqRenderId = tonumber(cursor or pfqInputId)
|
||||||
|
local pfqParentId = resolved.parentId and MTH_Map_WmaToPfq(resolved.parentId) or nil
|
||||||
if not sizes[renderZoneId] then
|
if not sizes[renderZoneId] then
|
||||||
if sizes[inputId] then
|
if sizes[inputId] then
|
||||||
renderZoneId = inputId
|
renderZoneId = inputId
|
||||||
elseif resolved.parentId and sizes[resolved.parentId] then
|
elseif resolved.parentId and sizes[resolved.parentId] then
|
||||||
renderZoneId = resolved.parentId
|
renderZoneId = resolved.parentId
|
||||||
|
elseif pfqRenderId and sizes[pfqRenderId] then
|
||||||
|
renderZoneId = pfqRenderId
|
||||||
|
elseif pfqParentId and sizes[pfqParentId] then
|
||||||
|
renderZoneId = pfqParentId
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -418,12 +462,13 @@ function MTH_Map:ResolveZoneHierarchy(zoneId)
|
|||||||
return resolved
|
return resolved
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_Map:GetCurrentMapID()
|
function MTH_Map:GetCurrentMapID(space)
|
||||||
local continent = GetCurrentMapContinent and GetCurrentMapContinent() or nil
|
local continent = GetCurrentMapContinent and GetCurrentMapContinent() or nil
|
||||||
local zone = GetCurrentMapZone and GetCurrentMapZone() or nil
|
local zone = GetCurrentMapZone and GetCurrentMapZone() or nil
|
||||||
local zoneName = nil
|
local zoneName = nil
|
||||||
local mapId = nil
|
local mapId = nil
|
||||||
local worldMapShown = WorldMapFrame and WorldMapFrame.IsShown and WorldMapFrame:IsShown() or false
|
local worldMapShown = WorldMapFrame and WorldMapFrame.IsShown and WorldMapFrame:IsShown() or false
|
||||||
|
local preferPfq = space == "pfq"
|
||||||
|
|
||||||
if continent and zone and continent > 0 and zone > 0 and GetMapZones then
|
if continent and zone and continent > 0 and zone > 0 and GetMapZones then
|
||||||
if not self.mapZoneCache[continent] then
|
if not self.mapZoneCache[continent] then
|
||||||
@@ -434,6 +479,9 @@ function MTH_Map:GetCurrentMapID()
|
|||||||
if mapId then
|
if mapId then
|
||||||
local resolved = self:ResolveZoneHierarchy(mapId)
|
local resolved = self:ResolveZoneHierarchy(mapId)
|
||||||
local normalized = resolved.zoneId or mapId
|
local normalized = resolved.zoneId or mapId
|
||||||
|
if not preferPfq then
|
||||||
|
normalized = MTH_Map_PfqToWma(normalized)
|
||||||
|
end
|
||||||
self.lastMapContext = string.format("continent=%s zone=%s mapZone='%s' real=nil mapId=%s normalized=%s", tostring(continent), tostring(zone), tostring(zoneName), tostring(mapId), tostring(normalized))
|
self.lastMapContext = string.format("continent=%s zone=%s mapZone='%s' real=nil mapId=%s normalized=%s", tostring(continent), tostring(zone), tostring(zoneName), tostring(mapId), tostring(normalized))
|
||||||
return normalized
|
return normalized
|
||||||
end
|
end
|
||||||
@@ -449,6 +497,9 @@ function MTH_Map:GetCurrentMapID()
|
|||||||
mapId = self:GetMapIDByName(real)
|
mapId = self:GetMapIDByName(real)
|
||||||
local resolved = self:ResolveZoneHierarchy(mapId)
|
local resolved = self:ResolveZoneHierarchy(mapId)
|
||||||
local normalized = resolved.zoneId or mapId
|
local normalized = resolved.zoneId or mapId
|
||||||
|
if not preferPfq then
|
||||||
|
normalized = MTH_Map_PfqToWma(normalized)
|
||||||
|
end
|
||||||
self.lastMapContext = string.format("continent=%s zone=%s mapZone='%s' real='%s' mapId=%s normalized=%s", tostring(continent), tostring(zone), tostring(zoneName), tostring(real), tostring(mapId), tostring(normalized))
|
self.lastMapContext = string.format("continent=%s zone=%s mapZone='%s' real='%s' mapId=%s normalized=%s", tostring(continent), tostring(zone), tostring(zoneName), tostring(real), tostring(mapId), tostring(normalized))
|
||||||
return normalized
|
return normalized
|
||||||
end
|
end
|
||||||
@@ -458,6 +509,30 @@ function MTH_Map:GetCurrentMapID()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH_Map:GetCurrentMinimapMapID()
|
||||||
|
local realZoneName = GetRealZoneText and GetRealZoneText() or nil
|
||||||
|
if realZoneName and realZoneName ~= "" then
|
||||||
|
local mapId = self:GetMapIDByName(realZoneName)
|
||||||
|
if mapId then
|
||||||
|
return mapId
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local continent = GetCurrentMapContinent and GetCurrentMapContinent() or nil
|
||||||
|
local zone = GetCurrentMapZone and GetCurrentMapZone() or nil
|
||||||
|
if continent and zone and continent > 0 and zone > 0 and GetMapZones then
|
||||||
|
if not self.mapZoneCache[continent] then
|
||||||
|
self.mapZoneCache[continent] = { GetMapZones(continent) }
|
||||||
|
end
|
||||||
|
local zoneName = self.mapZoneCache[continent][zone]
|
||||||
|
if zoneName and zoneName ~= "" then
|
||||||
|
return self:GetMapIDByName(zoneName)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_Map:RegisterProvider(key, provider)
|
function MTH_Map:RegisterProvider(key, provider)
|
||||||
if not key or type(key) ~= "string" then return false end
|
if not key or type(key) ~= "string" then return false end
|
||||||
if type(provider) ~= "table" or type(provider.buildNodes) ~= "function" then return false end
|
if type(provider) ~= "table" or type(provider.buildNodes) ~= "function" then return false end
|
||||||
@@ -467,6 +542,7 @@ end
|
|||||||
|
|
||||||
local function MTH_Map_ClearPendingZoneOpen()
|
local function MTH_Map_ClearPendingZoneOpen()
|
||||||
MTH_Map.pendingZoneOpenId = nil
|
MTH_Map.pendingZoneOpenId = nil
|
||||||
|
MTH_Map.pendingZoneOpenPfqId = nil
|
||||||
MTH_Map.pendingZoneOpenSourceId = nil
|
MTH_Map.pendingZoneOpenSourceId = nil
|
||||||
MTH_Map.pendingZoneOpenAttempts = 0
|
MTH_Map.pendingZoneOpenAttempts = 0
|
||||||
MTH_Map.pendingZoneOpenNextAttemptAt = 0
|
MTH_Map.pendingZoneOpenNextAttemptAt = 0
|
||||||
@@ -532,8 +608,12 @@ end
|
|||||||
function MTH_Map:OpenWorldMapForZone(zoneId)
|
function MTH_Map:OpenWorldMapForZone(zoneId)
|
||||||
local zid = tonumber(zoneId)
|
local zid = tonumber(zoneId)
|
||||||
if not zid then return false end
|
if not zid then return false end
|
||||||
local resolved = self:ResolveZoneHierarchy(zid)
|
-- Translate WMA ID → pfQ so game map APIs (pfMap, SetMapZoom) work correctly.
|
||||||
local targetZoneId = tonumber(resolved.zoneId or zid) or zid
|
local pfqZid = (type(MTH_MAP_WMA_TO_PFQ) == "table" and MTH_MAP_WMA_TO_PFQ[zid]) or zid
|
||||||
|
local resolved = self:ResolveZoneHierarchy(pfqZid)
|
||||||
|
local targetZoneId = tonumber(resolved.zoneId or pfqZid) or pfqZid
|
||||||
|
-- WMA ID of this zone, for comparing against GetCurrentMapID() which returns WMA IDs.
|
||||||
|
local targetWmaId = (type(MTH_MAP_PFQ_TO_WMA) == "table" and MTH_MAP_PFQ_TO_WMA[targetZoneId]) or zid
|
||||||
|
|
||||||
if ToggleWorldMap then
|
if ToggleWorldMap then
|
||||||
if not WorldMapFrame or not WorldMapFrame:IsShown() then
|
if not WorldMapFrame or not WorldMapFrame:IsShown() then
|
||||||
@@ -546,34 +626,39 @@ function MTH_Map:OpenWorldMapForZone(zoneId)
|
|||||||
if pfMap and pfMap.SetMapByID then
|
if pfMap and pfMap.SetMapByID then
|
||||||
pfMap:SetMapByID(targetZoneId)
|
pfMap:SetMapByID(targetZoneId)
|
||||||
local currentAfterPF = self:GetCurrentMapID()
|
local currentAfterPF = self:GetCurrentMapID()
|
||||||
if tonumber(currentAfterPF) == tonumber(targetZoneId) then
|
if tonumber(currentAfterPF) == tonumber(targetWmaId) then
|
||||||
MTH_Map_ClearPendingZoneOpen()
|
MTH_Map_ClearPendingZoneOpen()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local zoomApplied = MTH_Map_ApplyWorldMapZone(targetZoneId, zid)
|
local zoomApplied = MTH_Map_ApplyWorldMapZone(zid, zid)
|
||||||
if zoomApplied then
|
if zoomApplied then
|
||||||
local currentAfterZoom = self:GetCurrentMapID()
|
local currentAfterZoom = self:GetCurrentMapID()
|
||||||
if tonumber(currentAfterZoom) == tonumber(targetZoneId) then
|
if tonumber(currentAfterZoom) == tonumber(targetWmaId) then
|
||||||
MTH_Map_ClearPendingZoneOpen()
|
MTH_Map_ClearPendingZoneOpen()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local nowMapId = self:GetCurrentMapID()
|
local nowMapId = self:GetCurrentMapID()
|
||||||
if tonumber(nowMapId) == tonumber(targetZoneId) then
|
if tonumber(nowMapId) == tonumber(targetWmaId) then
|
||||||
MTH_Map_ClearPendingZoneOpen()
|
MTH_Map_ClearPendingZoneOpen()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
self.pendingZoneOpenId = targetZoneId
|
self.pendingZoneOpenId = targetWmaId
|
||||||
self.pendingZoneOpenSourceId = zid
|
self.pendingZoneOpenPfqId = targetZoneId
|
||||||
|
self.pendingZoneOpenSourceId = pfqZid
|
||||||
self.pendingZoneOpenAttempts = 8
|
self.pendingZoneOpenAttempts = 8
|
||||||
self.pendingZoneOpenNextAttemptAt = (GetTime and GetTime() or 0) + 0.25
|
self.pendingZoneOpenNextAttemptAt = (GetTime and GetTime() or 0) + 0.25
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH_Map:GetFamilyColor(family)
|
||||||
|
return MTH_Map_GetFamilyColor(family)
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_Map:FocusBeast(beastId, beast)
|
function MTH_Map:FocusBeast(beastId, beast)
|
||||||
local id = tonumber(beastId)
|
local id = tonumber(beastId)
|
||||||
if not id then return false end
|
if not id then return false end
|
||||||
@@ -864,6 +949,7 @@ end
|
|||||||
function MTH_Map:RebuildNodes()
|
function MTH_Map:RebuildNodes()
|
||||||
self:BuildZoneLookup()
|
self:BuildZoneLookup()
|
||||||
self.nodesByZone = {}
|
self.nodesByZone = {}
|
||||||
|
self.minimapNodesByZone = {}
|
||||||
self.nodeRevision = (tonumber(self.nodeRevision) or 0) + 1
|
self.nodeRevision = (tonumber(self.nodeRevision) or 0) + 1
|
||||||
self._lastWorldRenderKey = nil
|
self._lastWorldRenderKey = nil
|
||||||
self._lastMiniState = nil
|
self._lastMiniState = nil
|
||||||
@@ -877,20 +963,26 @@ function MTH_Map:RebuildNodes()
|
|||||||
local node = allNodes[i]
|
local node = allNodes[i]
|
||||||
if node and node.zoneId then
|
if node and node.zoneId then
|
||||||
local sourceZoneId = tonumber(node.zoneId)
|
local sourceZoneId = tonumber(node.zoneId)
|
||||||
local resolved = self:ResolveZoneHierarchy(sourceZoneId)
|
local worldResolved = self:ResolveZoneHierarchy(sourceZoneId)
|
||||||
local zoneId = tonumber(resolved.zoneId or sourceZoneId)
|
local worldZoneId = tonumber(worldResolved.zoneId or sourceZoneId)
|
||||||
if zoneId then
|
local pfqSourceZoneId = MTH_Map_WmaToPfq(sourceZoneId)
|
||||||
|
local minimapZoneId = tonumber(pfqSourceZoneId)
|
||||||
|
if worldZoneId then
|
||||||
node.sourceZoneId = sourceZoneId
|
node.sourceZoneId = sourceZoneId
|
||||||
node.zoneId = zoneId
|
node.zoneId = worldZoneId
|
||||||
node.parentZoneId = resolved.parentId
|
node.parentZoneId = worldResolved.parentId
|
||||||
node.subzoneId = resolved.subzoneId
|
node.subzoneId = worldResolved.subzoneId
|
||||||
if not self.nodesByZone[zoneId] then self.nodesByZone[zoneId] = {} end
|
node.minimapZoneId = minimapZoneId
|
||||||
table.insert(self.nodesByZone[zoneId], node)
|
if not self.nodesByZone[worldZoneId] then self.nodesByZone[worldZoneId] = {} end
|
||||||
|
table.insert(self.nodesByZone[worldZoneId], node)
|
||||||
|
if minimapZoneId then
|
||||||
|
if not self.minimapNodesByZone[minimapZoneId] then self.minimapNodesByZone[minimapZoneId] = {} end
|
||||||
|
table.insert(self.minimapNodesByZone[minimapZoneId], node)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_Map_Log("Rebuilt nodes for source '" .. tostring(self.activeSource) .. "'")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_Map:UpdateWorldMap()
|
function MTH_Map:UpdateWorldMap()
|
||||||
@@ -975,8 +1067,8 @@ function MTH_Map:UpdateMinimap()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local mapId = self:GetCurrentMapID()
|
local mapId = self:GetCurrentMinimapMapID()
|
||||||
local nodes = mapId and self.nodesByZone[mapId] or nil
|
local nodes = mapId and self.minimapNodesByZone[mapId] or nil
|
||||||
if not mapId or not nodes then
|
if not mapId or not nodes then
|
||||||
self.lastMiniReason = "no-mapid-or-nodes"
|
self.lastMiniReason = "no-mapid-or-nodes"
|
||||||
self._lastMiniState = nil
|
self._lastMiniState = nil
|
||||||
@@ -1009,16 +1101,18 @@ function MTH_Map:UpdateMinimap()
|
|||||||
and miniState.zoom == zoom
|
and miniState.zoom == zoom
|
||||||
and miniState.nodeRevision == (self.nodeRevision or 0)
|
and miniState.nodeRevision == (self.nodeRevision or 0)
|
||||||
then
|
then
|
||||||
local dx = math.abs((xPlayer or 0) - (miniState.xPlayer or 0))
|
if xPlayer == miniState.xPlayer and yPlayer == miniState.yPlayer and now < (miniState.nextForceAt or 0) then
|
||||||
local dy = math.abs((yPlayer or 0) - (miniState.yPlayer or 0))
|
self.lastMiniReason = self.verboseMiniReasons and "throttled-still" or "throttle"
|
||||||
if dx < 0.05 and dy < 0.05 and now < (miniState.nextForceAt or 0) then
|
|
||||||
self.lastMiniReason = self.verboseMiniReasons and "throttled-small-move" or "throttle"
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local minimapSizes = MTH_DS_MinimapSizes or (pfDB and pfDB["minimap"])
|
local minimapSizes = MTH_Map_GetMinimapSizes()
|
||||||
local mapSize = minimapSizes and minimapSizes[mapId]
|
local mapSize = minimapSizes and minimapSizes[mapId]
|
||||||
|
if not mapSize then
|
||||||
|
local wmaId = MTH_Map_PfqToWma(mapId)
|
||||||
|
mapSize = wmaId and minimapSizes and minimapSizes[wmaId]
|
||||||
|
end
|
||||||
if not mapSize then
|
if not mapSize then
|
||||||
self.lastMiniReason = self.verboseMiniReasons and "missing-minimap-size" or "missing-size"
|
self.lastMiniReason = self.verboseMiniReasons and "missing-minimap-size" or "missing-size"
|
||||||
self._lastMiniState = nil
|
self._lastMiniState = nil
|
||||||
@@ -1227,7 +1321,6 @@ function MTH_Map:RegisterDefaultProviders()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if unresolvedCount > 0 then
|
if unresolvedCount > 0 then
|
||||||
MTH_Map_Log("drops source: " .. tostring(unresolvedCount) .. " drop-creature links have no loaded coordinates (sample IDs: " .. table.concat(unresolvedSamples, ", ") .. ")")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
@@ -1244,7 +1337,7 @@ function MTH_Map:Init()
|
|||||||
self.nodesByZone = self.nodesByZone or {}
|
self.nodesByZone = self.nodesByZone or {}
|
||||||
|
|
||||||
if not self.controller then
|
if not self.controller then
|
||||||
self.controller = CreateFrame("Frame", "MTHMapController", UIParent)
|
self.controller = CreateFrame("Frame", "MTH_MapController", UIParent)
|
||||||
self.controller:RegisterEvent("PLAYER_ENTERING_WORLD")
|
self.controller:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
self.controller:RegisterEvent("ZONE_CHANGED")
|
self.controller:RegisterEvent("ZONE_CHANGED")
|
||||||
self.controller:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
self.controller:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
||||||
@@ -1253,6 +1346,9 @@ function MTH_Map:Init()
|
|||||||
|
|
||||||
self.controller:SetScript("OnEvent", function(frame, eventName)
|
self.controller:SetScript("OnEvent", function(frame, eventName)
|
||||||
eventName = eventName or event
|
eventName = eventName or event
|
||||||
|
if eventName == "WORLD_MAP_UPDATE" and MTH_Map._syncingMapContext then
|
||||||
|
return
|
||||||
|
end
|
||||||
if eventName == "PLAYER_ENTERING_WORLD" or eventName == "ZONE_CHANGED" or eventName == "ZONE_CHANGED_NEW_AREA" or eventName == "MINIMAP_ZONE_CHANGED" then
|
if eventName == "PLAYER_ENTERING_WORLD" or eventName == "ZONE_CHANGED" or eventName == "ZONE_CHANGED_NEW_AREA" or eventName == "MINIMAP_ZONE_CHANGED" then
|
||||||
if SetMapToCurrentZone and (not WorldMapFrame or not WorldMapFrame:IsShown()) then
|
if SetMapToCurrentZone and (not WorldMapFrame or not WorldMapFrame:IsShown()) then
|
||||||
SetMapToCurrentZone()
|
SetMapToCurrentZone()
|
||||||
@@ -1274,9 +1370,9 @@ function MTH_Map:Init()
|
|||||||
|
|
||||||
if WorldMapFrame and WorldMapFrame:IsShown() then
|
if WorldMapFrame and WorldMapFrame:IsShown() then
|
||||||
if pfMap and pfMap.SetMapByID then
|
if pfMap and pfMap.SetMapByID then
|
||||||
pfMap:SetMapByID(MTH_Map.pendingZoneOpenId)
|
pfMap:SetMapByID(MTH_Map.pendingZoneOpenPfqId or MTH_Map.pendingZoneOpenId)
|
||||||
end
|
end
|
||||||
MTH_Map_ApplyWorldMapZone(MTH_Map.pendingZoneOpenId, MTH_Map.pendingZoneOpenSourceId)
|
MTH_Map_ApplyWorldMapZone(MTH_Map.pendingZoneOpenId or MTH_Map.pendingZoneOpenPfqId, MTH_Map.pendingZoneOpenId or MTH_Map.pendingZoneOpenPfqId)
|
||||||
local nowMapId = MTH_Map:GetCurrentMapID()
|
local nowMapId = MTH_Map:GetCurrentMapID()
|
||||||
if tonumber(nowMapId) == tonumber(MTH_Map.pendingZoneOpenId) then
|
if tonumber(nowMapId) == tonumber(MTH_Map.pendingZoneOpenId) then
|
||||||
MTH_Map_ClearPendingZoneOpen()
|
MTH_Map_ClearPendingZoneOpen()
|
||||||
@@ -1295,15 +1391,15 @@ function MTH_Map:Init()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if MTH_Map.enabled and MTH_Map.showMinimap then
|
if MTH_Map.enabled and MTH_Map.showMinimap then
|
||||||
local mapId = MTH_Map:GetCurrentMapID()
|
local mapId = MTH_Map:GetCurrentMinimapMapID()
|
||||||
if not mapId and (frame._mthMapRecoverAt or 0) <= now then
|
if not mapId and (frame._mthMapRecoverAt or 0) <= now then
|
||||||
frame._mthMapRecoverAt = now + 2.0
|
frame._mthMapRecoverAt = now + 2.0
|
||||||
if SetMapToCurrentZone and (not WorldMapFrame or not WorldMapFrame:IsShown()) then
|
if SetMapToCurrentZone and (not WorldMapFrame or not WorldMapFrame:IsShown()) then
|
||||||
SetMapToCurrentZone()
|
SetMapToCurrentZone()
|
||||||
mapId = MTH_Map:GetCurrentMapID()
|
mapId = MTH_Map:GetCurrentMinimapMapID()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local nodes = mapId and MTH_Map.nodesByZone and MTH_Map.nodesByZone[mapId] or nil
|
local nodes = mapId and MTH_Map.minimapNodesByZone and MTH_Map.minimapNodesByZone[mapId] or nil
|
||||||
local hasNodes = nodes and table.getn(nodes) > 0
|
local hasNodes = nodes and table.getn(nodes) > 0
|
||||||
frame._mthTick = now + (hasNodes and (tonumber(MTH_Map.minimapTickActive) or 0.20) or (tonumber(MTH_Map.minimapTickIdle) or 0.75))
|
frame._mthTick = now + (hasNodes and (tonumber(MTH_Map.minimapTickActive) or 0.20) or (tonumber(MTH_Map.minimapTickIdle) or 0.75))
|
||||||
if hasNodes then
|
if hasNodes then
|
||||||
@@ -1318,5 +1414,4 @@ function MTH_Map:Init()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_Map_Log("Map system initialized")
|
|
||||||
end
|
end
|
||||||
|
|||||||
+29
-26
@@ -1,5 +1,13 @@
|
|||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
-- MetaHunt Minimap Button
|
-- MetaHunt Minimap Button
|
||||||
|
--
|
||||||
|
-- NOTE: The namespace table is MTH_MinimapButton (a plain Lua table).
|
||||||
|
-- The actual UI frame is named "MTH_MinimapBtn" to avoid a global
|
||||||
|
-- collision — CreateFrame("...", "MTH_MinimapButton", ...) would
|
||||||
|
-- OVERWRITE the namespace table with the frame object, orphaning
|
||||||
|
-- all methods and .frame/.icon references. pfUI iterates Minimap
|
||||||
|
-- children by name and calls _G[name]:GetHeight(); if the global is
|
||||||
|
-- a plain {} table instead of a frame, that call crashes.
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
if not MTH_MinimapButton then
|
if not MTH_MinimapButton then
|
||||||
@@ -84,7 +92,9 @@ function MTH_MinimapButton:Initialize()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local button = CreateFrame("Button", "MTH_MinimapButtonFrame", Minimap)
|
-- Frame name is MTH_MinimapBtn (NOT "MTH_MinimapButton") to avoid
|
||||||
|
-- overwriting the namespace table in _G.
|
||||||
|
local button = CreateFrame("Button", "MTH_MinimapBtn", Minimap)
|
||||||
if not button then
|
if not button then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -114,10 +124,9 @@ function MTH_MinimapButton:Initialize()
|
|||||||
highlight:SetHeight(31)
|
highlight:SetHeight(31)
|
||||||
highlight:SetPoint("CENTER", button, "CENTER", 0, 0)
|
highlight:SetPoint("CENTER", button, "CENTER", 0, 0)
|
||||||
|
|
||||||
button:SetScript("OnEnter", function(self)
|
button:SetScript("OnEnter", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
GameTooltip:SetOwner(this, "ANCHOR_LEFT")
|
||||||
GameTooltip:SetOwner(self, "ANCHOR_LEFT")
|
|
||||||
GameTooltip:SetText(MTH_MB_L("MINIMAP_TITLE", "MetaHunt"), 1, 0.82, 0)
|
GameTooltip:SetText(MTH_MB_L("MINIMAP_TITLE", "MetaHunt"), 1, 0.82, 0)
|
||||||
GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_LEFT_CLICK", "Left-Click: Open Hunter Book"), 1, 1, 1)
|
GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_LEFT_CLICK", "Left-Click: Open Hunter Book"), 1, 1, 1)
|
||||||
GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_RIGHT_CLICK", "Right-Click: Open MetaHunt Options"), 1, 1, 1)
|
GameTooltip:AddLine(MTH_MB_L("MINIMAP_HINT_RIGHT_CLICK", "Right-Click: Open MetaHunt Options"), 1, 1, 1)
|
||||||
@@ -129,25 +138,23 @@ function MTH_MinimapButton:Initialize()
|
|||||||
GameTooltip:Hide()
|
GameTooltip:Hide()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
button:SetScript("OnDragStart", function(self)
|
button:SetScript("OnDragStart", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
this.dragging = 1
|
||||||
self.dragging = 1
|
this:SetScript("OnUpdate", function()
|
||||||
self:SetScript("OnUpdate", function()
|
|
||||||
MTH_MB_UpdateDragPosition()
|
MTH_MB_UpdateDragPosition()
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
button:SetScript("OnDragStop", function(self)
|
button:SetScript("OnDragStop", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
this.dragging = nil
|
||||||
self.dragging = nil
|
this:SetScript("OnUpdate", nil)
|
||||||
self:SetScript("OnUpdate", nil)
|
|
||||||
MTH_MB_UpdateDragPosition()
|
MTH_MB_UpdateDragPosition()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
button:SetScript("OnClick", function(_, mouseButton)
|
button:SetScript("OnClick", function()
|
||||||
mouseButton = mouseButton or arg1
|
local mouseButton = arg1
|
||||||
if mouseButton == "RightButton" then
|
if mouseButton == "RightButton" then
|
||||||
if type(MTH_OpenOptions) == "function" then
|
if type(MTH_OpenOptions) == "function" then
|
||||||
MTH_OpenOptions("General")
|
MTH_OpenOptions("General")
|
||||||
@@ -167,16 +174,12 @@ function MTH_MinimapButton:Initialize()
|
|||||||
MTH_MB_UpdatePosition()
|
MTH_MB_UpdatePosition()
|
||||||
end
|
end
|
||||||
|
|
||||||
local loader = CreateFrame("Frame", "MTH_MinimapButtonLoader")
|
local loader = CreateFrame("Frame", "MTH_MinimapLoader")
|
||||||
loader:RegisterEvent("ADDON_LOADED")
|
loader:RegisterEvent("ADDON_LOADED")
|
||||||
loader:SetScript("OnEvent", function(self, eventName, addonName)
|
loader:SetScript("OnEvent", function()
|
||||||
eventName = eventName or event
|
if event == "ADDON_LOADED" and arg1 == "MetaHunt" then
|
||||||
addonName = addonName or arg1
|
|
||||||
if eventName == "ADDON_LOADED" and addonName == "MetaHunt" then
|
|
||||||
MTH_MinimapButton:Initialize()
|
MTH_MinimapButton:Initialize()
|
||||||
if self and self.UnregisterAllEvents then
|
this:UnregisterAllEvents()
|
||||||
self:UnregisterAllEvents()
|
this:SetScript("OnEvent", nil)
|
||||||
self:SetScript("OnEvent", nil)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|||||||
+30
-40
@@ -657,28 +657,25 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
|
|||||||
row.suffix:SetText("Stacks")
|
row.suffix:SetText("Stacks")
|
||||||
|
|
||||||
if row.check then
|
if row.check then
|
||||||
row.check:SetScript("OnClick", function(self)
|
row.check:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if not self or MTH_AB_STATE.syncing then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
MTH_AB_SetRuleEnabled(store, subtype, index, MTH_AB_IsChecked(self))
|
MTH_AB_SetRuleEnabled(store, subtype, index, MTH_AB_IsChecked(this))
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
row.qty:SetScript("OnEnterPressed", function(self)
|
row.qty:SetScript("OnEnterPressed", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
MTH_AB_SetRuleStacks(store, subtype, index, self:GetText())
|
MTH_AB_SetRuleStacks(store, subtype, index, this:GetText())
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
self:ClearFocus()
|
this:ClearFocus()
|
||||||
end)
|
end)
|
||||||
row.qty:SetScript("OnEditFocusLost", function(self)
|
row.qty:SetScript("OnEditFocusLost", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
MTH_AB_SetRuleStacks(store, subtype, index, self:GetText())
|
MTH_AB_SetRuleStacks(store, subtype, index, this:GetText())
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -715,11 +712,10 @@ local function MTH_AB_BuildUI(container)
|
|||||||
|
|
||||||
controls.moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", -30)
|
controls.moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", -30)
|
||||||
if controls.moduleEnabled then
|
if controls.moduleEnabled then
|
||||||
controls.moduleEnabled:SetScript("OnClick", function(self)
|
controls.moduleEnabled:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if not self or MTH_AB_STATE.syncing then return end
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(self))
|
local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this))
|
||||||
if not ok and MTH and MTH.Print then
|
if not ok and MTH and MTH.Print then
|
||||||
MTH:Print("Failed to change Auto Buy state: " .. tostring(err), "error")
|
MTH:Print("Failed to change Auto Buy state: " .. tostring(err), "error")
|
||||||
end
|
end
|
||||||
@@ -730,11 +726,10 @@ local function MTH_AB_BuildUI(container)
|
|||||||
|
|
||||||
controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74)
|
controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74)
|
||||||
if controls.projectilesEnabled then
|
if controls.projectilesEnabled then
|
||||||
controls.projectilesEnabled:SetScript("OnClick", function(self)
|
controls.projectilesEnabled:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if not self or MTH_AB_STATE.syncing then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.projectiles.enabled = MTH_AB_IsChecked(self)
|
store.projectiles.enabled = MTH_AB_IsChecked(this)
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -769,11 +764,10 @@ local function MTH_AB_BuildUI(container)
|
|||||||
|
|
||||||
controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X)
|
controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X)
|
||||||
if controls.petFoodEnabled then
|
if controls.petFoodEnabled then
|
||||||
controls.petFoodEnabled:SetScript("OnClick", function(self)
|
controls.petFoodEnabled:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if not self or MTH_AB_STATE.syncing then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.petFood.enabled = MTH_AB_IsChecked(self)
|
store.petFood.enabled = MTH_AB_IsChecked(this)
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -791,19 +785,17 @@ local function MTH_AB_BuildUI(container)
|
|||||||
controls.petFoodQty:SetHeight(20)
|
controls.petFoodQty:SetHeight(20)
|
||||||
controls.petFoodQty:SetNumeric(true)
|
controls.petFoodQty:SetNumeric(true)
|
||||||
controls.petFoodQty:SetAutoFocus(false)
|
controls.petFoodQty:SetAutoFocus(false)
|
||||||
controls.petFoodQty:SetScript("OnEnterPressed", function(self)
|
controls.petFoodQty:SetScript("OnEnterPressed", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
MTH_AB_SetPetFoodStacks(store, self:GetText())
|
MTH_AB_SetPetFoodStacks(store, this:GetText())
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
self:ClearFocus()
|
this:ClearFocus()
|
||||||
end)
|
end)
|
||||||
controls.petFoodQty:SetScript("OnEditFocusLost", function(self)
|
controls.petFoodQty:SetScript("OnEditFocusLost", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
MTH_AB_SetPetFoodStacks(store, self:GetText())
|
MTH_AB_SetPetFoodStacks(store, this:GetText())
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -816,9 +808,8 @@ local function MTH_AB_BuildUI(container)
|
|||||||
|
|
||||||
controls.petFoodScopeCurrent = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", -376, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
|
controls.petFoodScopeCurrent = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", -376, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
|
||||||
if controls.petFoodScopeCurrent then
|
if controls.petFoodScopeCurrent then
|
||||||
controls.petFoodScopeCurrent:SetScript("OnClick", function(self)
|
controls.petFoodScopeCurrent:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if not self or MTH_AB_STATE.syncing then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.petFood.scope = "current"
|
store.petFood.scope = "current"
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
@@ -827,9 +818,8 @@ local function MTH_AB_BuildUI(container)
|
|||||||
|
|
||||||
controls.petFoodScopeAll = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", -402, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
|
controls.petFoodScopeAll = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", -402, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
|
||||||
if controls.petFoodScopeAll then
|
if controls.petFoodScopeAll then
|
||||||
controls.petFoodScopeAll:SetScript("OnClick", function(self)
|
controls.petFoodScopeAll:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if not self or MTH_AB_STATE.syncing then return end
|
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.petFood.scope = "all"
|
store.petFood.scope = "all"
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
|
|||||||
+10
-14
@@ -72,10 +72,9 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
local moduleToggle = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", -70, 20)
|
local moduleToggle = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", -70, 20)
|
||||||
if moduleToggle then
|
if moduleToggle then
|
||||||
moduleToggle:SetChecked(moduleEnabled and true or false)
|
moduleToggle:SetChecked(moduleEnabled and true or false)
|
||||||
moduleToggle:SetScript("OnClick", function(self)
|
moduleToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
local enabled = MTH_AQ_IsChecked(self)
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
local ok, err = MTH:SetModuleEnabled("autoquest", enabled)
|
local ok, err = MTH:SetModuleEnabled("autoquest", enabled)
|
||||||
if not ok and MTH and MTH.Print then
|
if not ok and MTH and MTH.Print then
|
||||||
@@ -84,7 +83,7 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
end
|
end
|
||||||
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") or nil
|
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") or nil
|
||||||
local actual = (type(module) == "table" and module.enabled ~= nil) and (module.enabled and true or false) or enabled
|
local actual = (type(module) == "table" and module.enabled ~= nil) and (module.enabled and true or false) or enabled
|
||||||
self:SetChecked(actual and true or false)
|
this:SetChecked(actual and true or false)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -151,9 +150,8 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
store.scorpokDrazial and true or false
|
store.scorpokDrazial and true or false
|
||||||
)
|
)
|
||||||
if scorpokToggle then
|
if scorpokToggle then
|
||||||
scorpokToggle:SetScript("OnClick", function(self)
|
scorpokToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
local enabled = MTH_AQ_IsChecked(self)
|
|
||||||
store.scorpokDrazial = enabled and true or false
|
store.scorpokDrazial = enabled and true or false
|
||||||
if MTH and MTH.GetModuleCharSavedVariables then
|
if MTH and MTH.GetModuleCharSavedVariables then
|
||||||
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
||||||
@@ -176,9 +174,8 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
store.scorpokTooltip and true or false
|
store.scorpokTooltip and true or false
|
||||||
)
|
)
|
||||||
if tooltipToggle then
|
if tooltipToggle then
|
||||||
tooltipToggle:SetScript("OnClick", function(self)
|
tooltipToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
local enabled = MTH_AQ_IsChecked(self)
|
|
||||||
store.scorpokTooltip = enabled and true or false
|
store.scorpokTooltip = enabled and true or false
|
||||||
if MTH and MTH.GetModuleCharSavedVariables then
|
if MTH and MTH.GetModuleCharSavedVariables then
|
||||||
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
||||||
@@ -212,9 +209,8 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
store.arrowsForSissies and true or false
|
store.arrowsForSissies and true or false
|
||||||
)
|
)
|
||||||
if sissiesToggle then
|
if sissiesToggle then
|
||||||
sissiesToggle:SetScript("OnClick", function(self)
|
sissiesToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
local enabled = MTH_AQ_IsChecked(self)
|
|
||||||
store.arrowsForSissies = enabled and true or false
|
store.arrowsForSissies = enabled and true or false
|
||||||
if MTH and MTH.GetModuleCharSavedVariables then
|
if MTH and MTH.GetModuleCharSavedVariables then
|
||||||
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
||||||
|
|||||||
+37
-40
@@ -252,8 +252,14 @@ local function MTH_CHRON_ApplyLiveProfile(profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
engine.profile = profile
|
engine.profile = profile
|
||||||
if engine.SetCandyBarGroupGrowth then
|
if engine.SetCandyBarGroupGrowth and engine.SetCandyBarGroupPoint and engine.anchor then
|
||||||
engine:SetCandyBarGroupGrowth("MTHChronometer", profile.growup and true or false)
|
local growup = profile.growup and true or false
|
||||||
|
if growup then
|
||||||
|
engine:SetCandyBarGroupPoint("MTHChronometer", "BOTTOM", engine.anchor, "TOP", 0, 0)
|
||||||
|
else
|
||||||
|
engine:SetCandyBarGroupPoint("MTHChronometer", "TOP", engine.anchor, "BOTTOM", 0, 0)
|
||||||
|
end
|
||||||
|
engine:SetCandyBarGroupGrowth("MTHChronometer", growup)
|
||||||
end
|
end
|
||||||
if engine.SetCandyBarGroupVerticalSpacing then
|
if engine.SetCandyBarGroupVerticalSpacing then
|
||||||
engine:SetCandyBarGroupVerticalSpacing("MTHChronometer", profile.spacing or 0)
|
engine:SetCandyBarGroupVerticalSpacing("MTHChronometer", profile.spacing or 0)
|
||||||
@@ -326,13 +332,12 @@ local function MTH_CHRON_MakeInput(parent, name, x, y, width, height, value, onA
|
|||||||
edit:SetHeight(height or 20)
|
edit:SetHeight(height or 20)
|
||||||
edit:SetAutoFocus(false)
|
edit:SetAutoFocus(false)
|
||||||
edit:SetText(tostring(value or ""))
|
edit:SetText(tostring(value or ""))
|
||||||
edit:SetScript("OnEnterPressed", function(self)
|
edit:SetScript("OnEnterPressed", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if type(onAccept) == "function" then
|
if type(onAccept) == "function" then
|
||||||
onAccept(self:GetText() or "")
|
onAccept(this:GetText() or "")
|
||||||
end
|
end
|
||||||
self:ClearFocus()
|
this:ClearFocus()
|
||||||
end)
|
end)
|
||||||
return edit
|
return edit
|
||||||
end
|
end
|
||||||
@@ -385,16 +390,15 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
|
|||||||
local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX)
|
local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX)
|
||||||
if check then
|
if check then
|
||||||
check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false)
|
check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false)
|
||||||
check:SetScript("OnClick", function(self)
|
check:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
|
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
|
||||||
if currentlyDisabled then
|
if currentlyDisabled then
|
||||||
profile.disabledSpells[bucket][timerName] = nil
|
profile.disabledSpells[bucket][timerName] = nil
|
||||||
self:SetChecked(true)
|
this:SetChecked(true)
|
||||||
else
|
else
|
||||||
profile.disabledSpells[bucket][timerName] = {}
|
profile.disabledSpells[bucket][timerName] = {}
|
||||||
self:SetChecked(nil)
|
this:SetChecked(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
@@ -470,10 +474,9 @@ function MTH_SetupChronometerOptions(tabKey)
|
|||||||
if moduleCheck then
|
if moduleCheck then
|
||||||
local module = MTH and MTH:GetModule("chronometer")
|
local module = MTH and MTH:GetModule("chronometer")
|
||||||
moduleCheck:SetChecked(module and module.enabled and true or false)
|
moduleCheck:SetChecked(module and module.enabled and true or false)
|
||||||
moduleCheck:SetScript("OnClick", function(self)
|
moduleCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local enabled = MTH_CHRON_IsChecked(this)
|
||||||
local enabled = MTH_CHRON_IsChecked(self)
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
MTH:SetModuleEnabled("chronometer", enabled)
|
MTH:SetModuleEnabled("chronometer", enabled)
|
||||||
end
|
end
|
||||||
@@ -495,40 +498,36 @@ function MTH_SetupChronometerOptions(tabKey)
|
|||||||
local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154)
|
local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154)
|
||||||
if killCheck then
|
if killCheck then
|
||||||
killCheck:SetChecked(profile.fadeonkill and true or false)
|
killCheck:SetChecked(profile.fadeonkill and true or false)
|
||||||
killCheck:SetScript("OnClick", function(self)
|
killCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
profile.fadeonkill = MTH_CHRON_IsChecked(this)
|
||||||
profile.fadeonkill = MTH_CHRON_IsChecked(self)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179)
|
local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179)
|
||||||
if fadeCheck then
|
if fadeCheck then
|
||||||
fadeCheck:SetChecked(profile.fadeonfade and true or false)
|
fadeCheck:SetChecked(profile.fadeonfade and true or false)
|
||||||
fadeCheck:SetScript("OnClick", function(self)
|
fadeCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
profile.fadeonfade = MTH_CHRON_IsChecked(this)
|
||||||
profile.fadeonfade = MTH_CHRON_IsChecked(self)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local selfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerSelfBars", "Show self bars", -204)
|
local selfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerSelfBars", "Show self bars", -204)
|
||||||
if selfCheck then
|
if selfCheck then
|
||||||
selfCheck:SetChecked(profile.selfbars and true or false)
|
selfCheck:SetChecked(profile.selfbars and true or false)
|
||||||
selfCheck:SetScript("OnClick", function(self)
|
selfCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
profile.selfbars = MTH_CHRON_IsChecked(this)
|
||||||
profile.selfbars = MTH_CHRON_IsChecked(self)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local onlySelfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerOnlySelf", "Only self target", -229)
|
local onlySelfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerOnlySelf", "Only self target", -229)
|
||||||
if onlySelfCheck then
|
if onlySelfCheck then
|
||||||
onlySelfCheck:SetChecked(profile.onlyself and true or false)
|
onlySelfCheck:SetChecked(profile.onlyself and true or false)
|
||||||
onlySelfCheck:SetScript("OnClick", function(self)
|
onlySelfCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
profile.onlyself = MTH_CHRON_IsChecked(this)
|
||||||
profile.onlyself = MTH_CHRON_IsChecked(self)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
elseif section == "bar" then
|
elseif section == "bar" then
|
||||||
@@ -610,10 +609,9 @@ function MTH_SetupChronometerOptions(tabKey)
|
|||||||
local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438)
|
local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438)
|
||||||
if growCheck then
|
if growCheck then
|
||||||
growCheck:SetChecked(profile.growup and true or false)
|
growCheck:SetChecked(profile.growup and true or false)
|
||||||
growCheck:SetScript("OnClick", function(self)
|
growCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
profile.growup = MTH_CHRON_IsChecked(this)
|
||||||
profile.growup = MTH_CHRON_IsChecked(self)
|
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -621,10 +619,9 @@ function MTH_SetupChronometerOptions(tabKey)
|
|||||||
local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463)
|
local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463)
|
||||||
if reverseCheck then
|
if reverseCheck then
|
||||||
reverseCheck:SetChecked(profile.reverse and true or false)
|
reverseCheck:SetChecked(profile.reverse and true or false)
|
||||||
reverseCheck:SetScript("OnClick", function(self)
|
reverseCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
profile.reverse = MTH_CHRON_IsChecked(this)
|
||||||
profile.reverse = MTH_CHRON_IsChecked(self)
|
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,370 @@
|
|||||||
|
------------------------------------------------------
|
||||||
|
-- MetaHunt: Experimental Ammunition Options Panel
|
||||||
|
-- TWoW 1.18.1 — "Nightmares of Ursol"
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_Ready()
|
||||||
|
return type(MTH_GetFrame) == "function"
|
||||||
|
and type(MTH_CreateCheckbox) == "function"
|
||||||
|
and type(MTH_CreateSlider) == "function"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_GetCfg()
|
||||||
|
if type(MTH_SavedVariables) ~= "table" then return {} end
|
||||||
|
if type(MTH_SavedVariables.modules) ~= "table" then return {} end
|
||||||
|
return MTH_SavedVariables.modules["expammo"] or {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local MTH_EA_OPT_built = false
|
||||||
|
local MTH_EA_OPT_STATE = { bindStatus = nil, bindButton = nil, captureFrame = nil }
|
||||||
|
|
||||||
|
-- ── Layout constants ──────────────────────────────────────────
|
||||||
|
-- Two equal columns separated by a gutter. Values are offsets from the
|
||||||
|
-- container TOPLEFT corner (positive X right, negative Y down).
|
||||||
|
local OPT_L = 20 -- left column X
|
||||||
|
local OPT_R = 300 -- right column X
|
||||||
|
local OPT_CW = 255 -- column width (used for text wrapping and sliders)
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_GetBindText()
|
||||||
|
if not GetBindingKey then return "Unbound" end
|
||||||
|
local k1, k2 = GetBindingKey("EXPAMMO ACTION")
|
||||||
|
if not k1 and not k2 then return "Unbound" end
|
||||||
|
if k1 and k2 then return k1 .. " / " .. k2 end
|
||||||
|
return k1 or k2 or "Unbound"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_UpdateBindStatus()
|
||||||
|
local bs = MTH_EA_OPT_STATE.bindStatus
|
||||||
|
if not bs then return end
|
||||||
|
bs:SetText("Key: " .. MTH_EA_OPT_GetBindText())
|
||||||
|
end
|
||||||
|
|
||||||
|
-- key must already be the full chord string (e.g. "ALT-F", "BUTTON3", "MOUSEWHEELUP")
|
||||||
|
local function MTH_EA_OPT_SaveBinding(key)
|
||||||
|
if not SetBinding or not SaveBindings or not GetBindingKey then return end
|
||||||
|
local old1, old2 = GetBindingKey("EXPAMMO ACTION")
|
||||||
|
if old1 then SetBinding(old1) end
|
||||||
|
if old2 then SetBinding(old2) end
|
||||||
|
if key and key ~= "" then
|
||||||
|
SetBinding(key, "EXPAMMO ACTION")
|
||||||
|
end
|
||||||
|
local bs = 1
|
||||||
|
if GetCurrentBindingSet then bs = GetCurrentBindingSet() or 1 end
|
||||||
|
SaveBindings(bs)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_GetPrefix()
|
||||||
|
return string.format("%s%s%s",
|
||||||
|
(IsAltKeyDown and IsAltKeyDown() and "ALT-" or ""),
|
||||||
|
(IsControlKeyDown and IsControlKeyDown() and "CTRL-" or ""),
|
||||||
|
(IsShiftKeyDown and IsShiftKeyDown() and "SHIFT-" or ""))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_StopCapture()
|
||||||
|
if MTH_EA_OPT_STATE.captureFrame then
|
||||||
|
MTH_EA_OPT_STATE.captureFrame:Hide()
|
||||||
|
end
|
||||||
|
local bb = MTH_EA_OPT_STATE.bindButton
|
||||||
|
if bb then bb:SetText("Set Key") end
|
||||||
|
MTH_EA_OPT_UpdateBindStatus()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_MakeCaptureFrame()
|
||||||
|
local f = CreateFrame("Frame", "MTH_ExpAmmoBindCapture", UIParent)
|
||||||
|
f:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||||
|
f:SetAllPoints(UIParent)
|
||||||
|
f:EnableKeyboard(true)
|
||||||
|
f:EnableMouse(true)
|
||||||
|
f:EnableMouseWheel(true)
|
||||||
|
f:Hide()
|
||||||
|
local bg = f:CreateTexture(nil, "BACKGROUND")
|
||||||
|
bg:SetAllPoints(f)
|
||||||
|
bg:SetTexture(0, 0, 0, 0.5)
|
||||||
|
local lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||||
|
lbl:SetPoint("CENTER", f, "CENTER", 0, 0)
|
||||||
|
lbl:SetText("|cffffff00Press a key, mouse button, or scroll wheel|r\n|cffaaaaaa(ESC to cancel)|r")
|
||||||
|
f:SetScript("OnKeyUp", function()
|
||||||
|
local key = arg1
|
||||||
|
if not key or key == "" then return end
|
||||||
|
if key == "ESCAPE" then MTH_EA_OPT_StopCapture() return end
|
||||||
|
if key == "UNKNOWN" or key == "PRINTSCREEN" then return end
|
||||||
|
if key == "ALT" or key == "CTRL" or key == "SHIFT" then return end
|
||||||
|
MTH_EA_OPT_SaveBinding(MTH_EA_OPT_GetPrefix() .. key)
|
||||||
|
MTH_EA_OPT_StopCapture()
|
||||||
|
end)
|
||||||
|
f:SetScript("OnMouseUp", function()
|
||||||
|
local btmap = { LeftButton="BUTTON1", RightButton="BUTTON2", MiddleButton="BUTTON3", Button4="BUTTON4", Button5="BUTTON5" }
|
||||||
|
local mapped = btmap[arg1]
|
||||||
|
if not mapped then return end
|
||||||
|
local prefix = MTH_EA_OPT_GetPrefix()
|
||||||
|
if prefix == "" and (mapped == "BUTTON1" or mapped == "BUTTON2") then return end
|
||||||
|
MTH_EA_OPT_SaveBinding(prefix .. mapped)
|
||||||
|
MTH_EA_OPT_StopCapture()
|
||||||
|
end)
|
||||||
|
f:SetScript("OnMouseWheel", function()
|
||||||
|
local wheelkey = (arg1 == 1 and "MOUSEWHEELUP") or (arg1 == -1 and "MOUSEWHEELDOWN") or nil
|
||||||
|
if not wheelkey then return end
|
||||||
|
MTH_EA_OPT_SaveBinding(MTH_EA_OPT_GetPrefix() .. wheelkey)
|
||||||
|
MTH_EA_OPT_StopCapture()
|
||||||
|
end)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_StartCapture()
|
||||||
|
if not MTH_EA_OPT_STATE.captureFrame then
|
||||||
|
MTH_EA_OPT_STATE.captureFrame = MTH_EA_OPT_MakeCaptureFrame()
|
||||||
|
end
|
||||||
|
MTH_EA_OPT_STATE.captureFrame:Show()
|
||||||
|
local bb = MTH_EA_OPT_STATE.bindButton
|
||||||
|
if bb then bb:SetText("Press key...") end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: checkbox anchored to a given X column
|
||||||
|
local function MTH_EA_OPT_CB(container, name, label, yOff, xOff, isChecked, onClick)
|
||||||
|
local cb = MTH_CreateCheckbox(container, name, label, yOff, xOff or OPT_L)
|
||||||
|
if cb then
|
||||||
|
cb:SetChecked(isChecked and 1 or 0)
|
||||||
|
cb:SetScript("OnClick", function()
|
||||||
|
local v = this:GetChecked()
|
||||||
|
onClick(v == 1 or v == true)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
return cb
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: section header label
|
||||||
|
local function MTH_EA_OPT_Header(container, text, yOff, xOff)
|
||||||
|
local fs = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||||
|
fs:SetPoint("TOPLEFT", container, "TOPLEFT", xOff or OPT_L, yOff)
|
||||||
|
fs:SetText("|cffff9900" .. text .. "|r")
|
||||||
|
return fs
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Helper: small descriptive text
|
||||||
|
local function MTH_EA_OPT_Tip(container, text, yOff, xOff, r, g, b)
|
||||||
|
local fs = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
fs:SetPoint("TOPLEFT", container, "TOPLEFT", xOff or OPT_L, yOff)
|
||||||
|
fs:SetWidth(OPT_CW)
|
||||||
|
fs:SetJustifyH("LEFT")
|
||||||
|
fs:SetTextColor(r or 0.6, g or 0.6, b or 0.6)
|
||||||
|
fs:SetText(text)
|
||||||
|
return fs
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Enable or disable a list of widgets (supports Frames/Buttons and FontStrings)
|
||||||
|
local function MTH_EA_OPT_SetGroupEnabled(widgets, enabled)
|
||||||
|
for _, w in ipairs(widgets) do
|
||||||
|
if w then
|
||||||
|
if w.Enable and w.Disable then
|
||||||
|
-- Frame / Button / CheckButton
|
||||||
|
if enabled then w:Enable() else w:Disable() end
|
||||||
|
end
|
||||||
|
-- Dim all (including FontStrings and frames) via alpha
|
||||||
|
if w.SetAlpha then
|
||||||
|
w:SetAlpha(enabled and 1.0 or 0.35)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_EA_OPT_BuildUI(container)
|
||||||
|
if MTH_EA_OPT_built then return end
|
||||||
|
MTH_EA_OPT_built = true
|
||||||
|
|
||||||
|
local cfg = MTH_EA_OPT_GetCfg()
|
||||||
|
local showHint = cfg.showHint ~= false
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- Title
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
local title = container:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge")
|
||||||
|
title:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L, -16)
|
||||||
|
title:SetText("MM Widget — Experimental Ammunition Tracker")
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- LEFT COLUMN
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- ── Module ──────────────────────────────────────────────
|
||||||
|
MTH_EA_OPT_Header(container, "Module", -46)
|
||||||
|
|
||||||
|
local moduleEnabled = true
|
||||||
|
if MTH and MTH.IsModuleEnabled then
|
||||||
|
moduleEnabled = MTH:IsModuleEnabled("expammo", true) and true or false
|
||||||
|
end
|
||||||
|
MTH_EA_OPT_CB(container, "MTH_ExpAmmoModuleCB",
|
||||||
|
"Enable MM Widget module",
|
||||||
|
-66, OPT_L, moduleEnabled,
|
||||||
|
function(v)
|
||||||
|
if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("expammo", v) end
|
||||||
|
if MTH_ExpAmmo then MTH_ExpAmmo.SetEnabled(v) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- ── Tracker Visibility ───────────────────────────────────
|
||||||
|
MTH_EA_OPT_Header(container, "Tracker Visibility", -100)
|
||||||
|
|
||||||
|
MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowLnLCB",
|
||||||
|
"Show Lock and Load cell (top)",
|
||||||
|
-120, OPT_L, cfg.showLnL ~= false,
|
||||||
|
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(v) end end)
|
||||||
|
|
||||||
|
-- "Show action hint cell" also gates the right column
|
||||||
|
local rightGroup = {} -- filled below; toggled when this CB changes
|
||||||
|
local showHintCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowHintCB",
|
||||||
|
"Show action hint cell (bottom)",
|
||||||
|
-144, OPT_L, showHint,
|
||||||
|
function(v)
|
||||||
|
if MTH_ExpAmmo then MTH_ExpAmmo.SetShowHint(v) end
|
||||||
|
MTH_EA_OPT_SetGroupEnabled(rightGroup, v)
|
||||||
|
end)
|
||||||
|
|
||||||
|
MTH_EA_OPT_CB(container, "MTH_ExpAmmoHideOOCCB",
|
||||||
|
"Hide widget when out of combat",
|
||||||
|
-168, OPT_L, cfg.hideOOC == true,
|
||||||
|
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetHideOOC(v) end end)
|
||||||
|
|
||||||
|
-- ── Appearance ───────────────────────────────────────────
|
||||||
|
MTH_EA_OPT_Header(container, "Appearance", -202)
|
||||||
|
|
||||||
|
local sizeSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellSizeSlider",
|
||||||
|
"Cell Size (px)", 20, 80, 4, -222)
|
||||||
|
if sizeSlider then
|
||||||
|
sizeSlider:ClearAllPoints()
|
||||||
|
sizeSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 5, -222)
|
||||||
|
sizeSlider:SetWidth(OPT_CW - 10)
|
||||||
|
sizeSlider:SetValue(math.max(20, math.min(80, cfg.cellSize or 40)))
|
||||||
|
sizeSlider.onChange = function(val)
|
||||||
|
if MTH_ExpAmmo then MTH_ExpAmmo.SetCellSize(val) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local gapSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellGapSlider",
|
||||||
|
"Cell Spacing (px)", 0, 20, 1, -286)
|
||||||
|
if gapSlider then
|
||||||
|
gapSlider:ClearAllPoints()
|
||||||
|
gapSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 5, -286)
|
||||||
|
gapSlider:SetWidth(OPT_CW - 10)
|
||||||
|
gapSlider:SetValue(math.max(0, math.min(20, cfg.cellGap or 2)))
|
||||||
|
gapSlider.onChange = function(val)
|
||||||
|
if MTH_ExpAmmo then MTH_ExpAmmo.SetCellGap(val) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_EA_OPT_CB(container, "MTH_ExpAmmoBigCDCB",
|
||||||
|
"Large cooldown numbers (centered in cell)",
|
||||||
|
-350, OPT_L, cfg.bigCD == true,
|
||||||
|
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBigCD(v) end end)
|
||||||
|
|
||||||
|
-- ── Position ─────────────────────────────────────────────
|
||||||
|
MTH_EA_OPT_Header(container, "Position", -390)
|
||||||
|
|
||||||
|
local anchorButton = MTH_CreateActionButton(container, "MTH_ExpAmmoToggleAnchor",
|
||||||
|
"Toggle Anchor", OPT_L, -410, 130, 22, function()
|
||||||
|
if MTH_ExpAmmo then MTH_ExpAmmo.ToggleAnchor() end
|
||||||
|
end)
|
||||||
|
if anchorButton then anchorButton:Show() end
|
||||||
|
|
||||||
|
MTH_EA_OPT_Tip(container,
|
||||||
|
"Shows 4 drag handles around the widget (top / bottom / left / right). Drag any one to reposition it.",
|
||||||
|
-436, OPT_L)
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- RIGHT COLUMN — Action Hint Cell (keybind + casting)
|
||||||
|
-- All widgets here are greyed out when the bottom cell is hidden.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Vertical divider line
|
||||||
|
local divider = container:CreateTexture(nil, "BACKGROUND")
|
||||||
|
divider:SetTexture(0.3, 0.3, 0.3, 0.6)
|
||||||
|
divider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R - 10, -46)
|
||||||
|
divider:SetPoint("BOTTOMLEFT", container, "TOPLEFT", OPT_R - 10, -530)
|
||||||
|
divider:SetWidth(1)
|
||||||
|
|
||||||
|
-- Column title
|
||||||
|
local rTitle = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
|
||||||
|
rTitle:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -46)
|
||||||
|
rTitle:SetText("|cffff9900" .. "Action Hint Cell" .. "|r")
|
||||||
|
table.insert(rightGroup, rTitle)
|
||||||
|
|
||||||
|
|
||||||
|
local rSubtitle = MTH_EA_OPT_Tip(container,
|
||||||
|
"Options below apply to the bottom cell only.\n Disable \"Show action hint cell\" to hide the cell and these controls.",
|
||||||
|
-64, OPT_R, 1.00, 1.00, 1.00)
|
||||||
|
if rSubtitle then rSubtitle:SetWidth(290) end
|
||||||
|
table.insert(rightGroup, rSubtitle)
|
||||||
|
|
||||||
|
local rNamPowerTip = MTH_EA_OPT_Tip(container,
|
||||||
|
"Notes:\n - You need NAMPOWER for this to work reliably.\n - Aimed/Steady/Multi/Arcane Shots SHOULD BE on your action bars.",
|
||||||
|
-100, OPT_R, 0.35, 0.65, 1.00)
|
||||||
|
if rNamPowerTip then rNamPowerTip:SetWidth(290) end
|
||||||
|
table.insert(rightGroup, rNamPowerTip)
|
||||||
|
|
||||||
|
-- ── Keybind ──────────────────────────────────────────────
|
||||||
|
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Keybind", -182, OPT_R))
|
||||||
|
|
||||||
|
local bindTip = MTH_EA_OPT_Tip(container,
|
||||||
|
"One key to rule them all.\n Aimed Shot when ready, Steady Shot while Aimed is on cooldown,\n consume-spell (Multi / Serpent / Arcane) when proc is up.",
|
||||||
|
-200, OPT_R, 0.65, 0.65, 0.65)
|
||||||
|
if bindTip then bindTip:SetWidth(290) end
|
||||||
|
table.insert(rightGroup, bindTip)
|
||||||
|
|
||||||
|
local bindStatus = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -248)
|
||||||
|
bindStatus:SetText("Key: " .. MTH_EA_OPT_GetBindText())
|
||||||
|
MTH_EA_OPT_STATE.bindStatus = bindStatus
|
||||||
|
table.insert(rightGroup, bindStatus)
|
||||||
|
|
||||||
|
local bindButton = CreateFrame("Button", "MTH_ExpAmmoBindButton", container, "UIPanelButtonTemplate")
|
||||||
|
bindButton:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -264)
|
||||||
|
bindButton:SetWidth(90)
|
||||||
|
bindButton:SetHeight(22)
|
||||||
|
bindButton:SetText("Set Key")
|
||||||
|
bindButton:EnableKeyboard(false)
|
||||||
|
bindButton:SetScript("OnClick", function()
|
||||||
|
if MTH_EA_OPT_STATE.captureFrame and MTH_EA_OPT_STATE.captureFrame:IsShown() then
|
||||||
|
MTH_EA_OPT_StopCapture()
|
||||||
|
else
|
||||||
|
MTH_EA_OPT_StartCapture()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
MTH_EA_OPT_STATE.bindButton = bindButton
|
||||||
|
table.insert(rightGroup, bindButton)
|
||||||
|
|
||||||
|
local clearButton = CreateFrame("Button", "MTH_ExpAmmoBindClear", container, "UIPanelButtonTemplate")
|
||||||
|
clearButton:SetPoint("LEFT", bindButton, "RIGHT", 6, 0)
|
||||||
|
clearButton:SetWidth(70)
|
||||||
|
clearButton:SetHeight(22)
|
||||||
|
clearButton:SetText("Clear")
|
||||||
|
clearButton:SetScript("OnClick", function()
|
||||||
|
MTH_EA_OPT_SaveBinding(nil)
|
||||||
|
end)
|
||||||
|
table.insert(rightGroup, clearButton)
|
||||||
|
|
||||||
|
-- ── Casting ──────────────────────────────────────────────
|
||||||
|
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Casting", -304, OPT_R))
|
||||||
|
|
||||||
|
local quiverCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoQuiverNoClipCB",
|
||||||
|
"Use Quiver no-clip casting",
|
||||||
|
-324, OPT_R, cfg.useQuiverNoClip == true,
|
||||||
|
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetUseQuiverNoClip(v) end end)
|
||||||
|
table.insert(rightGroup, quiverCB)
|
||||||
|
|
||||||
|
local quiverTip = MTH_EA_OPT_Tip(container,
|
||||||
|
"|cff4d9cffRequires the Quiver addon.|r \n Routes Aimed/Steady/Multi cast through Quiver.CastNoClip \n to avoid clipping your auto-shot swing timer",
|
||||||
|
-350, OPT_R, 1, 1, 1)
|
||||||
|
if quiverTip then quiverTip:SetWidth(290) end
|
||||||
|
table.insert(rightGroup, quiverTip)
|
||||||
|
|
||||||
|
-- Apply initial enabled state
|
||||||
|
MTH_EA_OPT_SetGroupEnabled(rightGroup, showHint)
|
||||||
|
end
|
||||||
|
|
||||||
|
function MTH_SetupExpAmmoOptions()
|
||||||
|
if not MTH_EA_OPT_Ready() then return end
|
||||||
|
local container = MTH_GetFrame("MetaHuntOptionsExpAmmo")
|
||||||
|
if not container then return end
|
||||||
|
local ok, err = pcall(MTH_EA_OPT_BuildUI, container)
|
||||||
|
if not ok and MTH and MTH.Print then
|
||||||
|
MTH:Print("[MTH ExpAmmo OPTIONS] " .. tostring(err), "error")
|
||||||
|
end
|
||||||
|
end
|
||||||
+80
-64
@@ -10,7 +10,7 @@ local MTH_FOM_STATE = {
|
|||||||
bindStatus = nil,
|
bindStatus = nil,
|
||||||
bindButton = nil,
|
bindButton = nil,
|
||||||
bindClearButton = nil,
|
bindClearButton = nil,
|
||||||
bindingCapture = false,
|
captureFrame = nil,
|
||||||
ctrl = {},
|
ctrl = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,43 +93,79 @@ local function MTH_FOM_UpdateBindingStatus()
|
|||||||
if not bindStatus or not bindStatus.SetText then
|
if not bindStatus or not bindStatus.SetText then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if MTH_FOM_STATE.bindingCapture then
|
bindStatus:SetText(string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
|
||||||
bindStatus:SetText(MTH_FOM_L("FOM_BIND_STATUS_PROMPT", "Feed key: press a key... (ESC to clear)"))
|
|
||||||
else
|
|
||||||
bindStatus:SetText(string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FOM_StopBindingCapture()
|
local function MTH_FOM_StopBindingCapture()
|
||||||
MTH_FOM_STATE.bindingCapture = false
|
if MTH_FOM_STATE.captureFrame then
|
||||||
|
MTH_FOM_STATE.captureFrame:Hide()
|
||||||
|
end
|
||||||
if MTH_FOM_STATE.bindButton then
|
if MTH_FOM_STATE.bindButton then
|
||||||
if MTH_FOM_STATE.bindButton.SetPropagateKeyboardInput then
|
|
||||||
MTH_FOM_STATE.bindButton:SetPropagateKeyboardInput(true)
|
|
||||||
end
|
|
||||||
MTH_FOM_STATE.bindButton:EnableKeyboard(false)
|
|
||||||
MTH_FOM_STATE.bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"))
|
MTH_FOM_STATE.bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"))
|
||||||
end
|
end
|
||||||
MTH_FOM_UpdateBindingStatus()
|
MTH_FOM_UpdateBindingStatus()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FOM_StartBindingCapture()
|
local function MTH_FOM_BuildBindingChord(key)
|
||||||
MTH_FOM_STATE.bindingCapture = true
|
return string.format("%s%s%s%s",
|
||||||
if MTH_FOM_STATE.bindButton then
|
(IsAltKeyDown and IsAltKeyDown() and "ALT-" or ""),
|
||||||
MTH_FOM_STATE.bindButton:SetText(MTH_FOM_L("FOM_BIND_PRESS_KEY", "Press key..."))
|
(IsControlKeyDown and IsControlKeyDown() and "CTRL-" or ""),
|
||||||
MTH_FOM_STATE.bindButton:EnableKeyboard(true)
|
(IsShiftKeyDown and IsShiftKeyDown() and "SHIFT-" or ""),
|
||||||
if MTH_FOM_STATE.bindButton.SetPropagateKeyboardInput then
|
key)
|
||||||
MTH_FOM_STATE.bindButton:SetPropagateKeyboardInput(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
MTH_FOM_UpdateBindingStatus()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FOM_BuildBindingChord(key)
|
local function MTH_FOM_MakeCaptureFrame()
|
||||||
local chord = ""
|
local f = CreateFrame("Frame", "MTH_FOMBindCapture", UIParent)
|
||||||
if IsControlKeyDown and IsControlKeyDown() and key ~= "LCTRL" and key ~= "RCTRL" then chord = chord .. "CTRL-" end
|
f:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||||
if IsAltKeyDown and IsAltKeyDown() and key ~= "LALT" and key ~= "RALT" then chord = chord .. "ALT-" end
|
f:SetAllPoints(UIParent)
|
||||||
if IsShiftKeyDown and IsShiftKeyDown() and key ~= "LSHIFT" and key ~= "RSHIFT" then chord = chord .. "SHIFT-" end
|
f:EnableKeyboard(true)
|
||||||
return chord .. key
|
f:EnableMouse(true)
|
||||||
|
f:EnableMouseWheel(true)
|
||||||
|
f:Hide()
|
||||||
|
local bg = f:CreateTexture(nil, "BACKGROUND")
|
||||||
|
bg:SetAllPoints(f)
|
||||||
|
bg:SetTexture(0, 0, 0, 0.5)
|
||||||
|
local lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||||
|
lbl:SetPoint("CENTER", f, "CENTER", 0, 0)
|
||||||
|
lbl:SetText("|cffffff00Press a key, mouse button, or scroll wheel|r\n|cffaaaaaa(ESC to cancel)|r")
|
||||||
|
f:SetScript("OnKeyUp", function()
|
||||||
|
local key = arg1
|
||||||
|
if not key or key == "" then return end
|
||||||
|
if key == "ESCAPE" then MTH_FOM_StopBindingCapture() return end
|
||||||
|
if key == "UNKNOWN" or key == "PRINTSCREEN" then return end
|
||||||
|
if key == "ALT" or key == "CTRL" or key == "SHIFT" then return end
|
||||||
|
MTH_FOM_SaveBinding(MTH_FOM_BuildBindingChord(key))
|
||||||
|
MTH_FOM_StopBindingCapture()
|
||||||
|
end)
|
||||||
|
f:SetScript("OnMouseUp", function()
|
||||||
|
local btmap = { LeftButton="BUTTON1", RightButton="BUTTON2", MiddleButton="BUTTON3", Button4="BUTTON4", Button5="BUTTON5" }
|
||||||
|
local mapped = btmap[arg1]
|
||||||
|
if not mapped then return end
|
||||||
|
local prefix = string.format("%s%s%s",
|
||||||
|
(IsAltKeyDown and IsAltKeyDown() and "ALT-" or ""),
|
||||||
|
(IsControlKeyDown and IsControlKeyDown() and "CTRL-" or ""),
|
||||||
|
(IsShiftKeyDown and IsShiftKeyDown() and "SHIFT-" or ""))
|
||||||
|
if prefix == "" and (mapped == "BUTTON1" or mapped == "BUTTON2") then return end
|
||||||
|
MTH_FOM_SaveBinding(prefix .. mapped)
|
||||||
|
MTH_FOM_StopBindingCapture()
|
||||||
|
end)
|
||||||
|
f:SetScript("OnMouseWheel", function()
|
||||||
|
local wheelkey = (arg1 == 1 and "MOUSEWHEELUP") or (arg1 == -1 and "MOUSEWHEELDOWN") or nil
|
||||||
|
if not wheelkey then return end
|
||||||
|
MTH_FOM_SaveBinding(MTH_FOM_BuildBindingChord(wheelkey))
|
||||||
|
MTH_FOM_StopBindingCapture()
|
||||||
|
end)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_FOM_StartBindingCapture()
|
||||||
|
if not MTH_FOM_STATE.captureFrame then
|
||||||
|
MTH_FOM_STATE.captureFrame = MTH_FOM_MakeCaptureFrame()
|
||||||
|
end
|
||||||
|
MTH_FOM_STATE.captureFrame:Show()
|
||||||
|
if MTH_FOM_STATE.bindButton then
|
||||||
|
MTH_FOM_STATE.bindButton:SetText(MTH_FOM_L("FOM_BIND_PRESS_KEY", "Press key..."))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FOM_SaveBinding(key)
|
local function MTH_FOM_SaveBinding(key)
|
||||||
@@ -226,10 +262,9 @@ function MTH_SetupFeedOMaticOptions()
|
|||||||
|
|
||||||
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsFeedOMaticEnabled", MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), -32 + yAdjust)
|
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsFeedOMaticEnabled", MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), -32 + yAdjust)
|
||||||
if moduleCheck then
|
if moduleCheck then
|
||||||
moduleCheck:SetScript("OnClick", function(self)
|
moduleCheck:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local enabled = this:GetChecked() == 1
|
||||||
local enabled = self:GetChecked() == 1
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
local ok, err = MTH:SetModuleEnabled("feedomatic", enabled)
|
local ok, err = MTH:SetModuleEnabled("feedomatic", enabled)
|
||||||
if not ok and MTH and MTH.Print then
|
if not ok and MTH and MTH.Print then
|
||||||
@@ -255,31 +290,13 @@ function MTH_SetupFeedOMaticOptions()
|
|||||||
bindButton:SetWidth(90)
|
bindButton:SetWidth(90)
|
||||||
bindButton:SetHeight(22)
|
bindButton:SetHeight(22)
|
||||||
bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"))
|
bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"))
|
||||||
bindButton:EnableKeyboard(false)
|
|
||||||
bindButton:SetScript("OnClick", function()
|
bindButton:SetScript("OnClick", function()
|
||||||
if MTH_FOM_STATE.bindingCapture then
|
if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then
|
||||||
MTH_FOM_StopBindingCapture()
|
MTH_FOM_StopBindingCapture()
|
||||||
else
|
else
|
||||||
MTH_FOM_StartBindingCapture()
|
MTH_FOM_StartBindingCapture()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
bindButton:SetScript("OnKeyDown", function(_, key)
|
|
||||||
if not MTH_FOM_STATE.bindingCapture then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
key = key or arg1
|
|
||||||
if not key or key == "" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if key == "ESCAPE" then
|
|
||||||
MTH_FOM_SaveBinding(nil)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if key == "UNKNOWN" or key == "PRINTSCREEN" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
MTH_FOM_SaveBinding(MTH_FOM_BuildBindingChord(key))
|
|
||||||
end)
|
|
||||||
MTH_FOM_STATE.bindButton = bindButton
|
MTH_FOM_STATE.bindButton = bindButton
|
||||||
|
|
||||||
local bindClearButton = CreateFrame("Button", "MetaHuntOptionsFOMBindClearButton", container, "UIPanelButtonTemplate")
|
local bindClearButton = CreateFrame("Button", "MetaHuntOptionsFOMBindClearButton", container, "UIPanelButtonTemplate")
|
||||||
@@ -305,10 +322,10 @@ function MTH_SetupFeedOMaticOptions()
|
|||||||
MTH_FOM_STATE.ctrl.PreferHigherQuality = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMPreferQuality", FOM_OptionsButtonText and FOM_OptionsButtonText["PreferHigherQuality"] or MTH_FOM_L("FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"), -220 + yAdjust)
|
MTH_FOM_STATE.ctrl.PreferHigherQuality = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMPreferQuality", FOM_OptionsButtonText and FOM_OptionsButtonText["PreferHigherQuality"] or MTH_FOM_L("FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"), -220 + yAdjust)
|
||||||
MTH_FOM_STATE.ctrl.Fallback = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMFallback", FOM_OptionsButtonText and FOM_OptionsButtonText["Fallback"] or MTH_FOM_L("FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"), -245 + yAdjust)
|
MTH_FOM_STATE.ctrl.Fallback = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMFallback", FOM_OptionsButtonText and FOM_OptionsButtonText["Fallback"] or MTH_FOM_L("FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"), -245 + yAdjust)
|
||||||
|
|
||||||
if MTH_FOM_STATE.ctrl.AvoidQuestFood then MTH_FOM_STATE.ctrl.AvoidQuestFood:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.AvoidQuestFood = self:GetChecked() == 1 end) end
|
if MTH_FOM_STATE.ctrl.AvoidQuestFood then MTH_FOM_STATE.ctrl.AvoidQuestFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end) end
|
||||||
if MTH_FOM_STATE.ctrl.AvoidBonusFood then MTH_FOM_STATE.ctrl.AvoidBonusFood:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.AvoidBonusFood = self:GetChecked() == 1 end) end
|
if MTH_FOM_STATE.ctrl.AvoidBonusFood then MTH_FOM_STATE.ctrl.AvoidBonusFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end) end
|
||||||
if MTH_FOM_STATE.ctrl.PreferHigherQuality then MTH_FOM_STATE.ctrl.PreferHigherQuality:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.PreferHigherQuality = self:GetChecked() == 1 end) end
|
if MTH_FOM_STATE.ctrl.PreferHigherQuality then MTH_FOM_STATE.ctrl.PreferHigherQuality:SetScript("OnClick", function() if not this then return end FOM_Config.PreferHigherQuality = this:GetChecked() == 1 end) end
|
||||||
if MTH_FOM_STATE.ctrl.Fallback then MTH_FOM_STATE.ctrl.Fallback:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.Fallback = self:GetChecked() == 1 end) end
|
if MTH_FOM_STATE.ctrl.Fallback then MTH_FOM_STATE.ctrl.Fallback:SetScript("OnClick", function() if not this then return end FOM_Config.Fallback = this:GetChecked() == 1 end) end
|
||||||
|
|
||||||
local keepOpenLabel = container:CreateFontString("MetaHuntOptionsFOMKeepOpenLabel", "ARTWORK", "GameFontNormalSmall")
|
local keepOpenLabel = container:CreateFontString("MetaHuntOptionsFOMKeepOpenLabel", "ARTWORK", "GameFontNormalSmall")
|
||||||
keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust)
|
keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust)
|
||||||
@@ -320,14 +337,13 @@ function MTH_SetupFeedOMaticOptions()
|
|||||||
keepOpen:SetHeight(20)
|
keepOpen:SetHeight(20)
|
||||||
keepOpen:SetNumeric(true)
|
keepOpen:SetNumeric(true)
|
||||||
keepOpen:SetAutoFocus(false)
|
keepOpen:SetAutoFocus(false)
|
||||||
keepOpen:SetScript("OnTextChanged", function(self)
|
keepOpen:SetScript("OnTextChanged", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local value = tonumber(this:GetText()) or 0
|
||||||
local value = tonumber(self:GetText()) or 0
|
|
||||||
FOM_Config.KeepOpenSlots = value
|
FOM_Config.KeepOpenSlots = value
|
||||||
end)
|
end)
|
||||||
keepOpen:SetScript("OnEnterPressed", function(self) self = self or this if self then self:ClearFocus() end end)
|
keepOpen:SetScript("OnEnterPressed", function() if this then this:ClearFocus() end end)
|
||||||
keepOpen:SetScript("OnEscapePressed", function(self) self = self or this if self then self:ClearFocus() end end)
|
keepOpen:SetScript("OnEscapePressed", function() if this then this:ClearFocus() end end)
|
||||||
MTH_FOM_STATE.keepOpenEdit = keepOpen
|
MTH_FOM_STATE.keepOpenEdit = keepOpen
|
||||||
|
|
||||||
local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight")
|
local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight")
|
||||||
@@ -356,10 +372,10 @@ function MTH_SetupFeedOMaticOptions()
|
|||||||
MTH_FOM_STATE.ctrl.AudioWarningBell = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarningBell", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarningBell"] or MTH_FOM_L("FOM_LABEL_USE_BELL_SOUND", "Use bell sound"), -403 + yAdjust, rightColumnX)
|
MTH_FOM_STATE.ctrl.AudioWarningBell = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarningBell", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarningBell"] or MTH_FOM_L("FOM_LABEL_USE_BELL_SOUND", "Use bell sound"), -403 + yAdjust, rightColumnX)
|
||||||
MTH_FOM_STATE.ctrl.TextWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMTextWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["TextWarning"] or MTH_FOM_L("FOM_LABEL_SHOW_TEXT", "Show text"), -428 + yAdjust, rightColumnX)
|
MTH_FOM_STATE.ctrl.TextWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMTextWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["TextWarning"] or MTH_FOM_L("FOM_LABEL_SHOW_TEXT", "Show text"), -428 + yAdjust, rightColumnX)
|
||||||
MTH_FOM_STATE.ctrl.IconWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMIconWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["IconWarning"] or MTH_FOM_L("FOM_LABEL_FLASH_ICON", "Flash icon"), -453 + yAdjust, rightColumnX)
|
MTH_FOM_STATE.ctrl.IconWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMIconWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["IconWarning"] or MTH_FOM_L("FOM_LABEL_FLASH_ICON", "Flash icon"), -453 + yAdjust, rightColumnX)
|
||||||
if MTH_FOM_STATE.ctrl.AudioWarning then MTH_FOM_STATE.ctrl.AudioWarning:SetScript("OnClick", function(self) self = self or this if not self then return end if self:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end) end
|
if MTH_FOM_STATE.ctrl.AudioWarning then MTH_FOM_STATE.ctrl.AudioWarning:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end) end
|
||||||
if MTH_FOM_STATE.ctrl.AudioWarningBell then MTH_FOM_STATE.ctrl.AudioWarningBell:SetScript("OnClick", function(self) self = self or this if not self then return end if self:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end) end
|
if MTH_FOM_STATE.ctrl.AudioWarningBell then MTH_FOM_STATE.ctrl.AudioWarningBell:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end) end
|
||||||
if MTH_FOM_STATE.ctrl.TextWarning then MTH_FOM_STATE.ctrl.TextWarning:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.TextWarning = self:GetChecked() == 1 end) end
|
if MTH_FOM_STATE.ctrl.TextWarning then MTH_FOM_STATE.ctrl.TextWarning:SetScript("OnClick", function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end) end
|
||||||
if MTH_FOM_STATE.ctrl.IconWarning then MTH_FOM_STATE.ctrl.IconWarning:SetScript("OnClick", function(self) self = self or this if not self then return end FOM_Config.IconWarning = self:GetChecked() == 1 end) end
|
if MTH_FOM_STATE.ctrl.IconWarning then MTH_FOM_STATE.ctrl.IconWarning:SetScript("OnClick", function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end) end
|
||||||
|
|
||||||
local cookHeader = container:CreateFontString("MetaHuntOptionsFOMCookingHeader", "ARTWORK", "GameFontHighlight")
|
local cookHeader = container:CreateFontString("MetaHuntOptionsFOMCookingHeader", "ARTWORK", "GameFontHighlight")
|
||||||
cookHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -62 + yAdjust)
|
cookHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -62 + yAdjust)
|
||||||
|
|||||||
+24
-32
@@ -297,11 +297,10 @@ local function MTH_ICU_BuildUI(container)
|
|||||||
|
|
||||||
local moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsICUModuleEnabled", "Enable ICU module", -72, MTH_ICU_LAYOUT.LEFT_X)
|
local moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsICUModuleEnabled", "Enable ICU module", -72, MTH_ICU_LAYOUT.LEFT_X)
|
||||||
if moduleEnabled then
|
if moduleEnabled then
|
||||||
moduleEnabled:SetScript("OnClick", function(self)
|
moduleEnabled:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
local ok, err = MTH:SetModuleEnabled("icu", self:GetChecked() == 1)
|
local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1)
|
||||||
if not ok and MTH and MTH.Print then
|
if not ok and MTH and MTH.Print then
|
||||||
MTH:Print("Failed to change ICU module state: " .. tostring(err), "error")
|
MTH:Print("Failed to change ICU module state: " .. tostring(err), "error")
|
||||||
end
|
end
|
||||||
@@ -313,11 +312,10 @@ local function MTH_ICU_BuildUI(container)
|
|||||||
|
|
||||||
local mouseOver = MTH_CreateCheckbox(container, "MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", -98, MTH_ICU_LAYOUT.LEFT_X)
|
local mouseOver = MTH_CreateCheckbox(container, "MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", -98, MTH_ICU_LAYOUT.LEFT_X)
|
||||||
if mouseOver then
|
if mouseOver then
|
||||||
mouseOver:SetScript("OnClick", function(self)
|
mouseOver:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.mouseOver = self:GetChecked() == 1 and true or false
|
store.mouseOver = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end)
|
||||||
MTH_ICU_OPT_STATE.controls.mouseOver = mouseOver
|
MTH_ICU_OPT_STATE.controls.mouseOver = mouseOver
|
||||||
end
|
end
|
||||||
@@ -346,11 +344,10 @@ local function MTH_ICU_BuildUI(container)
|
|||||||
|
|
||||||
local expandUp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUExpandUp", "Expand Up", -301, MTH_ICU_LAYOUT.LEFT_X + 132)
|
local expandUp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUExpandUp", "Expand Up", -301, MTH_ICU_LAYOUT.LEFT_X + 132)
|
||||||
if expandUp then
|
if expandUp then
|
||||||
expandUp:SetScript("OnClick", function(self)
|
expandUp:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.EXPAND_UP = self:GetChecked() == 1 and true or false
|
store.EXPAND_UP = this:GetChecked() == 1 and true or false
|
||||||
if type(ICU_SetPoints) == "function" then
|
if type(ICU_SetPoints) == "function" then
|
||||||
ICU_SetPoints()
|
ICU_SetPoints()
|
||||||
end
|
end
|
||||||
@@ -360,44 +357,40 @@ local function MTH_ICU_BuildUI(container)
|
|||||||
|
|
||||||
local showGuild = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowGuild", "Show player guild names", -344, MTH_ICU_LAYOUT.LEFT_X)
|
local showGuild = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowGuild", "Show player guild names", -344, MTH_ICU_LAYOUT.LEFT_X)
|
||||||
if showGuild then
|
if showGuild then
|
||||||
showGuild:SetScript("OnClick", function(self)
|
showGuild:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.SHOW_GUILD_NAME = self:GetChecked() == 1 and true or false
|
store.SHOW_GUILD_NAME = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end)
|
||||||
MTH_ICU_OPT_STATE.controls.showGuildName = showGuild
|
MTH_ICU_OPT_STATE.controls.showGuildName = showGuild
|
||||||
end
|
end
|
||||||
|
|
||||||
local showClass = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowClass", "Show player class", -368, MTH_ICU_LAYOUT.LEFT_X)
|
local showClass = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowClass", "Show player class", -368, MTH_ICU_LAYOUT.LEFT_X)
|
||||||
if showClass then
|
if showClass then
|
||||||
showClass:SetScript("OnClick", function(self)
|
showClass:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.SHOW_PLAYER_CLASS = self:GetChecked() == 1 and true or false
|
store.SHOW_PLAYER_CLASS = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end)
|
||||||
MTH_ICU_OPT_STATE.controls.showPlayerClass = showClass
|
MTH_ICU_OPT_STATE.controls.showPlayerClass = showClass
|
||||||
end
|
end
|
||||||
|
|
||||||
local showRace = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowRace", "Show player race", -392, MTH_ICU_LAYOUT.LEFT_X)
|
local showRace = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowRace", "Show player race", -392, MTH_ICU_LAYOUT.LEFT_X)
|
||||||
if showRace then
|
if showRace then
|
||||||
showRace:SetScript("OnClick", function(self)
|
showRace:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.SHOW_PLAYER_RACE = self:GetChecked() == 1 and true or false
|
store.SHOW_PLAYER_RACE = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end)
|
||||||
MTH_ICU_OPT_STATE.controls.showPlayerRace = showRace
|
MTH_ICU_OPT_STATE.controls.showPlayerRace = showRace
|
||||||
end
|
end
|
||||||
|
|
||||||
local showTitles = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", -416, MTH_ICU_LAYOUT.LEFT_X)
|
local showTitles = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", -416, MTH_ICU_LAYOUT.LEFT_X)
|
||||||
if showTitles then
|
if showTitles then
|
||||||
showTitles:SetScript("OnClick", function(self)
|
showTitles:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.SHOW_CUSTOM_TITLES = self:GetChecked() == 1 and true or false
|
store.SHOW_CUSTOM_TITLES = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end)
|
||||||
MTH_ICU_OPT_STATE.controls.showCustomTitles = showTitles
|
MTH_ICU_OPT_STATE.controls.showCustomTitles = showTitles
|
||||||
end
|
end
|
||||||
@@ -410,11 +403,10 @@ local function MTH_ICU_BuildUI(container)
|
|||||||
|
|
||||||
local reactionOnlyPvp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", -200, MTH_ICU_LAYOUT.RIGHT_X)
|
local reactionOnlyPvp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", -200, MTH_ICU_LAYOUT.RIGHT_X)
|
||||||
if reactionOnlyPvp then
|
if reactionOnlyPvp then
|
||||||
reactionOnlyPvp:SetScript("OnClick", function(self)
|
reactionOnlyPvp:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.REACTION_ONLY_PVP_PLAYERS = self:GetChecked() == 1 and true or false
|
store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end)
|
||||||
MTH_ICU_OPT_STATE.controls.reactionOnlyPvp = reactionOnlyPvp
|
MTH_ICU_OPT_STATE.controls.reactionOnlyPvp = reactionOnlyPvp
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,403 @@
|
|||||||
|
------------------------------------------------------
|
||||||
|
-- MetaHunt Profile Management Options Panel
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
local MAX_PROFILE_ROWS = 15
|
||||||
|
local MAX_CHAR_ROWS = 10
|
||||||
|
local ROW_H = 26
|
||||||
|
|
||||||
|
-- Row pools — anonymous frames created once against scroll content, reused each refresh
|
||||||
|
local gProfileRows = {} -- [i] = { frame, nameText, infoText, loadBtn, delBtn }
|
||||||
|
local gCharRows = {} -- [i] = { frame, nameText, infoText, copyBtn }
|
||||||
|
|
||||||
|
-- Static element refs created once
|
||||||
|
local gActiveLabel = nil
|
||||||
|
local gSetupDone = false
|
||||||
|
|
||||||
|
-- Pending confirmations — globals so StaticPopup OnAccept can read them
|
||||||
|
MTH_PROFILE_PENDING_LOAD = nil
|
||||||
|
MTH_PROFILE_PENDING_DELETE = nil
|
||||||
|
MTH_PROFILE_PENDING_SAVE = nil
|
||||||
|
|
||||||
|
-- ── Static popup dialogs ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
StaticPopupDialogs["MTH_PROFILE_LOAD_CONFIRM"] = {
|
||||||
|
text = "Load profile \"%s\"?\n\nCurrent settings will be replaced.\nThe UI will reload to apply all changes.",
|
||||||
|
button1 = "Load & Reload",
|
||||||
|
button2 = "Cancel",
|
||||||
|
OnAccept = function()
|
||||||
|
if MTH_PROFILE_PENDING_LOAD then
|
||||||
|
local ok, err = MTH_Profile_Load(MTH_PROFILE_PENDING_LOAD)
|
||||||
|
MTH_PROFILE_PENDING_LOAD = nil
|
||||||
|
if ok then
|
||||||
|
ReloadUI()
|
||||||
|
elseif MTH and MTH.Print then
|
||||||
|
MTH:Print("Profile load failed: " .. tostring(err), "error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
timeout = 0, whileDead = 0, hideOnEscape = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticPopupDialogs["MTH_PROFILE_DELETE_CONFIRM"] = {
|
||||||
|
text = "Delete profile \"%s\"?\n\nThis cannot be undone.",
|
||||||
|
button1 = "Delete",
|
||||||
|
button2 = "Cancel",
|
||||||
|
OnAccept = function()
|
||||||
|
if MTH_PROFILE_PENDING_DELETE then
|
||||||
|
MTH_Profile_Delete(MTH_PROFILE_PENDING_DELETE)
|
||||||
|
MTH_PROFILE_PENDING_DELETE = nil
|
||||||
|
MTH_SetupProfilesOptions()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
timeout = 0, whileDead = 0, hideOnEscape = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticPopupDialogs["MTH_PROFILE_SAVE_CONFIRM"] = {
|
||||||
|
text = "Profile \"%s\" already exists.\nOverwrite with current settings?",
|
||||||
|
button1 = "Overwrite",
|
||||||
|
button2 = "Cancel",
|
||||||
|
OnAccept = function()
|
||||||
|
if MTH_PROFILE_PENDING_SAVE then
|
||||||
|
MTH_Profile_Save(MTH_PROFILE_PENDING_SAVE)
|
||||||
|
MTH_PROFILE_PENDING_SAVE = nil
|
||||||
|
MTH_SetupProfilesOptions()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
timeout = 0, whileDead = 0, hideOnEscape = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- ── internal helpers ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
local function PROF_TrimString(s)
|
||||||
|
if type(s) ~= "string" then return "" end
|
||||||
|
return string.gsub(s, "^%s*(.-)%s*$", "%1")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function PROF_DoSave(rawName)
|
||||||
|
local name = PROF_TrimString(rawName)
|
||||||
|
if string.len(name) == 0 then
|
||||||
|
if MTH and MTH.Print then MTH:Print("Enter a profile name first.", "error") end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if string.len(name) > 50 then
|
||||||
|
if MTH and MTH.Print then MTH:Print("Profile name too long (50 chars max).", "error") end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local existing = type(MTH_SavedVariables) == "table"
|
||||||
|
and type(MTH_SavedVariables.profiles) == "table"
|
||||||
|
and MTH_SavedVariables.profiles[name] ~= nil
|
||||||
|
if existing then
|
||||||
|
MTH_PROFILE_PENDING_SAVE = name
|
||||||
|
StaticPopup_Show("MTH_PROFILE_SAVE_CONFIRM", name)
|
||||||
|
else
|
||||||
|
MTH_Profile_Save(name)
|
||||||
|
if MTH and MTH.Print then MTH:Print("Profile saved: " .. name) end
|
||||||
|
MTH_SetupProfilesOptions()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ── scroll frames + row pool creation (idempotent) ────────────────────────
|
||||||
|
|
||||||
|
local function PROF_EnsureScrollFrames(container)
|
||||||
|
if not MTH_GetFrame("MetaHuntOptionsProfilesScroll") then
|
||||||
|
local sf = CreateFrame("ScrollFrame", "MetaHuntOptionsProfilesScroll", container, "UIPanelScrollFrameTemplate")
|
||||||
|
local sc = CreateFrame("Frame", "MetaHuntOptionsProfilesContent", sf)
|
||||||
|
sc:SetWidth(510)
|
||||||
|
sc:SetHeight(MAX_PROFILE_ROWS * ROW_H + 4)
|
||||||
|
sf:SetScrollChild(sc)
|
||||||
|
end
|
||||||
|
if not MTH_GetFrame("MetaHuntOptionsCharScroll") then
|
||||||
|
local csf = CreateFrame("ScrollFrame", "MetaHuntOptionsCharScroll", container, "UIPanelScrollFrameTemplate")
|
||||||
|
local csc = CreateFrame("Frame", "MetaHuntOptionsCharContent", csf)
|
||||||
|
csc:SetWidth(510)
|
||||||
|
csc:SetHeight(MAX_CHAR_ROWS * ROW_H + 4)
|
||||||
|
csf:SetScrollChild(csc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function PROF_EnsureProfileRows()
|
||||||
|
local sc = MTH_GetFrame("MetaHuntOptionsProfilesContent")
|
||||||
|
if not sc then return end
|
||||||
|
for i = 1, MAX_PROFILE_ROWS do
|
||||||
|
if not gProfileRows[i] then
|
||||||
|
local row = CreateFrame("Frame", nil, sc)
|
||||||
|
row:SetHeight(ROW_H)
|
||||||
|
row:SetWidth(510)
|
||||||
|
row:SetPoint("TOPLEFT", sc, "TOPLEFT", 0, -(i - 1) * ROW_H)
|
||||||
|
|
||||||
|
local nameText = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
|
nameText:SetPoint("LEFT", row, "LEFT", 4, 2)
|
||||||
|
nameText:SetWidth(210)
|
||||||
|
nameText:SetJustifyH("LEFT")
|
||||||
|
|
||||||
|
local infoText = row:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
infoText:SetPoint("LEFT", row, "LEFT", 218, 2)
|
||||||
|
infoText:SetWidth(155)
|
||||||
|
infoText:SetJustifyH("LEFT")
|
||||||
|
infoText:SetTextColor(0.55, 0.55, 0.55)
|
||||||
|
|
||||||
|
local loadBtn = CreateFrame("Button", nil, row, "UIPanelButtonTemplate")
|
||||||
|
loadBtn:SetWidth(58)
|
||||||
|
loadBtn:SetHeight(20)
|
||||||
|
loadBtn:SetPoint("RIGHT", row, "RIGHT", -62, 0)
|
||||||
|
loadBtn:SetText("Load")
|
||||||
|
|
||||||
|
local delBtn = CreateFrame("Button", nil, row, "UIPanelButtonTemplate")
|
||||||
|
delBtn:SetWidth(58)
|
||||||
|
delBtn:SetHeight(20)
|
||||||
|
delBtn:SetPoint("RIGHT", row, "RIGHT", 0, 0)
|
||||||
|
delBtn:SetText("Delete")
|
||||||
|
|
||||||
|
gProfileRows[i] = { frame = row, nameText = nameText, infoText = infoText, loadBtn = loadBtn, delBtn = delBtn }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function PROF_EnsureCharRows()
|
||||||
|
local csc = MTH_GetFrame("MetaHuntOptionsCharContent")
|
||||||
|
if not csc then return end
|
||||||
|
for i = 1, MAX_CHAR_ROWS do
|
||||||
|
if not gCharRows[i] then
|
||||||
|
local row = CreateFrame("Frame", nil, csc)
|
||||||
|
row:SetHeight(ROW_H)
|
||||||
|
row:SetWidth(510)
|
||||||
|
row:SetPoint("TOPLEFT", csc, "TOPLEFT", 0, -(i - 1) * ROW_H)
|
||||||
|
|
||||||
|
local nameText = row:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
||||||
|
nameText:SetPoint("LEFT", row, "LEFT", 4, 2)
|
||||||
|
nameText:SetWidth(250)
|
||||||
|
nameText:SetJustifyH("LEFT")
|
||||||
|
nameText:SetTextColor(0.70, 0.85, 1.00)
|
||||||
|
|
||||||
|
local infoText = row:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
infoText:SetPoint("LEFT", row, "LEFT", 258, 2)
|
||||||
|
infoText:SetWidth(120)
|
||||||
|
infoText:SetJustifyH("LEFT")
|
||||||
|
infoText:SetTextColor(0.55, 0.55, 0.55)
|
||||||
|
|
||||||
|
local copyBtn = CreateFrame("Button", nil, row, "UIPanelButtonTemplate")
|
||||||
|
copyBtn:SetWidth(80)
|
||||||
|
copyBtn:SetHeight(20)
|
||||||
|
copyBtn:SetPoint("RIGHT", row, "RIGHT", 0, 0)
|
||||||
|
copyBtn:SetText("Import")
|
||||||
|
|
||||||
|
gCharRows[i] = { frame = row, nameText = nameText, infoText = infoText, copyBtn = copyBtn }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ── dynamic refresh functions ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
local function PROF_RefreshActive()
|
||||||
|
if not gActiveLabel then return end
|
||||||
|
local active = type(MTH_Profile_GetActive) == "function" and MTH_Profile_GetActive()
|
||||||
|
if active then
|
||||||
|
gActiveLabel:SetText("Active: |cffffd200" .. active .. "|r")
|
||||||
|
gActiveLabel:SetTextColor(0.90, 0.90, 0.90)
|
||||||
|
else
|
||||||
|
gActiveLabel:SetText("Active: |cff888888Custom (unsaved)|r")
|
||||||
|
gActiveLabel:SetTextColor(0.90, 0.90, 0.90)
|
||||||
|
end
|
||||||
|
gActiveLabel:Show()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function PROF_RefreshProfileList()
|
||||||
|
PROF_EnsureProfileRows()
|
||||||
|
local profiles = type(MTH_Profile_GetList) == "function" and MTH_Profile_GetList() or {}
|
||||||
|
local active = type(MTH_Profile_GetActive) == "function" and MTH_Profile_GetActive()
|
||||||
|
local n = table.getn(profiles)
|
||||||
|
|
||||||
|
local sc = MTH_GetFrame("MetaHuntOptionsProfilesContent")
|
||||||
|
if sc then
|
||||||
|
sc:SetHeight(math.max(n * ROW_H + 4, ROW_H))
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, MAX_PROFILE_ROWS do
|
||||||
|
local row = gProfileRows[i]
|
||||||
|
if not row then break end
|
||||||
|
local name = profiles[i]
|
||||||
|
if name then
|
||||||
|
-- Name (with active indicator)
|
||||||
|
if name == active then
|
||||||
|
row.nameText:SetText(name .. " |cff00cc44[active]|r")
|
||||||
|
else
|
||||||
|
row.nameText:SetText(name)
|
||||||
|
end
|
||||||
|
-- Info: date saved by who
|
||||||
|
local p = type(MTH_SavedVariables) == "table"
|
||||||
|
and type(MTH_SavedVariables.profiles) == "table"
|
||||||
|
and MTH_SavedVariables.profiles[name]
|
||||||
|
local info = ""
|
||||||
|
if type(p) == "table" then
|
||||||
|
if p.savedAt and p.savedAt ~= "" then
|
||||||
|
info = p.savedAt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
row.infoText:SetText(info)
|
||||||
|
-- Wire buttons (SetScript replaces previous handler each refresh)
|
||||||
|
local rowName = name
|
||||||
|
row.loadBtn:SetScript("OnClick", function()
|
||||||
|
MTH_PROFILE_PENDING_LOAD = rowName
|
||||||
|
StaticPopup_Show("MTH_PROFILE_LOAD_CONFIRM", rowName)
|
||||||
|
end)
|
||||||
|
row.delBtn:SetScript("OnClick", function()
|
||||||
|
MTH_PROFILE_PENDING_DELETE = rowName
|
||||||
|
StaticPopup_Show("MTH_PROFILE_DELETE_CONFIRM", rowName)
|
||||||
|
end)
|
||||||
|
row.frame:Show()
|
||||||
|
row.loadBtn:Show()
|
||||||
|
row.delBtn:Show()
|
||||||
|
else
|
||||||
|
row.frame:Hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function PROF_RefreshCharList()
|
||||||
|
PROF_EnsureCharRows()
|
||||||
|
local chars = type(MTH_Profile_GetCharList) == "function" and MTH_Profile_GetCharList() or {}
|
||||||
|
local n = table.getn(chars)
|
||||||
|
|
||||||
|
local csc = MTH_GetFrame("MetaHuntOptionsCharContent")
|
||||||
|
if csc then
|
||||||
|
csc:SetHeight(math.max(n * ROW_H + 4, ROW_H))
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, MAX_CHAR_ROWS do
|
||||||
|
local row = gCharRows[i]
|
||||||
|
if not row then break end
|
||||||
|
local charKey = chars[i]
|
||||||
|
if charKey then
|
||||||
|
local snap = type(MTH_SavedVariables) == "table"
|
||||||
|
and type(MTH_SavedVariables.charSnapshots) == "table"
|
||||||
|
and MTH_SavedVariables.charSnapshots[charKey]
|
||||||
|
local info = (type(snap) == "table" and snap.savedAt) and snap.savedAt or ""
|
||||||
|
row.nameText:SetText(charKey)
|
||||||
|
row.infoText:SetText(info)
|
||||||
|
local ck = charKey
|
||||||
|
row.copyBtn:SetScript("OnClick", function()
|
||||||
|
local ok, pName = MTH_Profile_CopyFromChar(ck)
|
||||||
|
if ok then
|
||||||
|
MTH_SetupProfilesOptions()
|
||||||
|
if MTH and MTH.Print then
|
||||||
|
MTH:Print('Imported "' .. ck .. '" as profile "' .. tostring(pName) .. '".')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
row.frame:Show()
|
||||||
|
row.copyBtn:Show()
|
||||||
|
else
|
||||||
|
row.frame:Hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ── main setup (static elements created once, dynamic lists refreshed every call) ──
|
||||||
|
|
||||||
|
function MTH_SetupProfilesOptions()
|
||||||
|
local container = MTH_GetFrame("MetaHuntOptionsProfiles")
|
||||||
|
if not container then return end
|
||||||
|
|
||||||
|
if not gSetupDone then
|
||||||
|
-- Title
|
||||||
|
local title = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||||
|
title:SetPoint("TOPLEFT", container, "TOPLEFT", 6, -6)
|
||||||
|
title:SetText("Profiles")
|
||||||
|
title:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
|
||||||
|
-- Active profile indicator
|
||||||
|
gActiveLabel = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
gActiveLabel:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -4)
|
||||||
|
gActiveLabel:SetWidth(540)
|
||||||
|
gActiveLabel:SetJustifyH("LEFT")
|
||||||
|
|
||||||
|
-- ── Save As section ───────────────────────────────────────────────
|
||||||
|
local saveHdr = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||||
|
saveHdr:SetPoint("TOPLEFT", gActiveLabel, "BOTTOMLEFT", 0, -10)
|
||||||
|
saveHdr:SetText("Save current settings as:")
|
||||||
|
saveHdr:SetTextColor(0.90, 0.90, 0.90)
|
||||||
|
|
||||||
|
local eb = CreateFrame("EditBox", "MTH_ProfileNameInput", container, "InputBoxTemplate")
|
||||||
|
eb:SetWidth(240)
|
||||||
|
eb:SetHeight(20)
|
||||||
|
eb:SetMaxLetters(50)
|
||||||
|
eb:SetAutoFocus(false)
|
||||||
|
eb:SetPoint("TOPLEFT", saveHdr, "BOTTOMLEFT", 2, -6)
|
||||||
|
eb:SetScript("OnEnterPressed", function()
|
||||||
|
PROF_DoSave(this:GetText())
|
||||||
|
this:SetText("")
|
||||||
|
this:ClearFocus()
|
||||||
|
end)
|
||||||
|
eb:SetScript("OnEscapePressed", function()
|
||||||
|
this:SetText("")
|
||||||
|
this:ClearFocus()
|
||||||
|
end)
|
||||||
|
|
||||||
|
local saveBtn = CreateFrame("Button", "MTH_ProfileSaveBtn", container, "UIPanelButtonTemplate")
|
||||||
|
saveBtn:SetWidth(70)
|
||||||
|
saveBtn:SetHeight(20)
|
||||||
|
saveBtn:SetPoint("LEFT", eb, "RIGHT", 6, 0)
|
||||||
|
saveBtn:SetText("Save")
|
||||||
|
saveBtn:SetScript("OnClick", function()
|
||||||
|
local box = MTH_GetFrame("MTH_ProfileNameInput")
|
||||||
|
if box then
|
||||||
|
PROF_DoSave(box:GetText())
|
||||||
|
box:SetText("")
|
||||||
|
box:ClearFocus()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- ── Saved Profiles section ────────────────────────────────────────
|
||||||
|
local profHdr = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||||
|
profHdr:SetPoint("TOPLEFT", eb, "BOTTOMLEFT", -2, -12)
|
||||||
|
profHdr:SetText("Saved Profiles")
|
||||||
|
profHdr:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
|
||||||
|
local rule1 = container:CreateTexture(nil, "ARTWORK")
|
||||||
|
rule1:SetPoint("TOPLEFT", profHdr, "BOTTOMLEFT", 0, -3)
|
||||||
|
rule1:SetWidth(540)
|
||||||
|
rule1:SetHeight(1)
|
||||||
|
rule1:SetTexture(0.30, 0.30, 0.30, 0.80)
|
||||||
|
|
||||||
|
PROF_EnsureScrollFrames(container)
|
||||||
|
|
||||||
|
local sf = MTH_GetFrame("MetaHuntOptionsProfilesScroll")
|
||||||
|
sf:SetPoint("TOPLEFT", rule1, "BOTTOMLEFT", 0, -4)
|
||||||
|
sf:SetWidth(530)
|
||||||
|
sf:SetHeight(170)
|
||||||
|
sf:Show()
|
||||||
|
|
||||||
|
-- ── Copy from Character section ───────────────────────────────────
|
||||||
|
local charHdr = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||||
|
charHdr:SetPoint("TOPLEFT", sf, "BOTTOMLEFT", 0, -10)
|
||||||
|
charHdr:SetText("Copy from Character")
|
||||||
|
charHdr:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
|
||||||
|
local charNote = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
charNote:SetPoint("TOPLEFT", charHdr, "BOTTOMLEFT", 0, -2)
|
||||||
|
charNote:SetWidth(540)
|
||||||
|
charNote:SetJustifyH("LEFT")
|
||||||
|
charNote:SetText("Snapshots are saved automatically on logout. Click Import to create a profile from one.")
|
||||||
|
charNote:SetTextColor(0.60, 0.60, 0.60)
|
||||||
|
|
||||||
|
local rule2 = container:CreateTexture(nil, "ARTWORK")
|
||||||
|
rule2:SetPoint("TOPLEFT", charNote, "BOTTOMLEFT", 0, -3)
|
||||||
|
rule2:SetWidth(540)
|
||||||
|
rule2:SetHeight(1)
|
||||||
|
rule2:SetTexture(0.30, 0.30, 0.30, 0.80)
|
||||||
|
|
||||||
|
local csf = MTH_GetFrame("MetaHuntOptionsCharScroll")
|
||||||
|
csf:SetPoint("TOPLEFT", rule2, "BOTTOMLEFT", 0, -4)
|
||||||
|
csf:SetWidth(530)
|
||||||
|
csf:SetHeight(140)
|
||||||
|
csf:Show()
|
||||||
|
|
||||||
|
gSetupDone = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Refresh dynamic content every time the panel is opened
|
||||||
|
PROF_RefreshActive()
|
||||||
|
PROF_RefreshProfileList()
|
||||||
|
PROF_RefreshCharList()
|
||||||
|
end
|
||||||
+24
-2
@@ -3,8 +3,8 @@ local MTH_OPTIONS_SETUP = {} -- Track which frames have been set up
|
|||||||
MTH_OPTIONS_CONST = MTH_OPTIONS_CONST or {}
|
MTH_OPTIONS_CONST = MTH_OPTIONS_CONST or {}
|
||||||
MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH = MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH or 120
|
MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH = MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH or 120
|
||||||
MTH_OPTIONS_CONST.WINDOW_PADDING = MTH_OPTIONS_CONST.WINDOW_PADDING or 12
|
MTH_OPTIONS_CONST.WINDOW_PADDING = MTH_OPTIONS_CONST.WINDOW_PADDING or 12
|
||||||
MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -72
|
MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -58
|
||||||
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 540
|
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 566
|
||||||
MTH_OPTIONS_CONST.CLOSE_BTN_SIZE = MTH_OPTIONS_CONST.CLOSE_BTN_SIZE or 22
|
MTH_OPTIONS_CONST.CLOSE_BTN_SIZE = MTH_OPTIONS_CONST.CLOSE_BTN_SIZE or 22
|
||||||
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X or -8
|
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X or -8
|
||||||
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y or -8
|
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y or -8
|
||||||
@@ -117,6 +117,11 @@ function MTH_SelectOptionsTab(tabKey)
|
|||||||
MTH_SetupGeneralOptions()
|
MTH_SetupGeneralOptions()
|
||||||
MTH_OPTIONS_SETUP["General"] = true
|
MTH_OPTIONS_SETUP["General"] = true
|
||||||
end
|
end
|
||||||
|
elseif tabKey == "Profiles" then
|
||||||
|
if type(MTH_SetupProfilesOptions) == "function" then
|
||||||
|
MTH_SetupProfilesOptions()
|
||||||
|
MTH_OPTIONS_SETUP["Profiles"] = true
|
||||||
|
end
|
||||||
elseif tabKey == "Messages" then
|
elseif tabKey == "Messages" then
|
||||||
if not MTH_OPTIONS_SETUP["Messages"] then
|
if not MTH_OPTIONS_SETUP["Messages"] then
|
||||||
if type(MTH_SetupMessagesOptions) == "function" then
|
if type(MTH_SetupMessagesOptions) == "function" then
|
||||||
@@ -128,6 +133,11 @@ function MTH_SelectOptionsTab(tabKey)
|
|||||||
MTH_SetupMessagesOptions()
|
MTH_SetupMessagesOptions()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
elseif tabKey == "ZBar" then
|
||||||
|
if type(MTH_SetupZBarOptions) == "function" then
|
||||||
|
MTH_SetupZBarOptions()
|
||||||
|
MTH_OPTIONS_SETUP["ZBar"] = true
|
||||||
|
end
|
||||||
elseif tabKey == "Pet" then
|
elseif tabKey == "Pet" then
|
||||||
if not MTH_OPTIONS_SETUP["Pet"] then
|
if not MTH_OPTIONS_SETUP["Pet"] then
|
||||||
MTH_SetupPetOptions()
|
MTH_SetupPetOptions()
|
||||||
@@ -177,6 +187,11 @@ function MTH_SelectOptionsTab(tabKey)
|
|||||||
MTH_SetupToysOptions()
|
MTH_SetupToysOptions()
|
||||||
MTH_OPTIONS_SETUP["Toys"] = true
|
MTH_OPTIONS_SETUP["Toys"] = true
|
||||||
end
|
end
|
||||||
|
elseif tabKey == "Craft" then
|
||||||
|
if not MTH_OPTIONS_SETUP["Craft"] then
|
||||||
|
MTH_SetupCraftOptions()
|
||||||
|
MTH_OPTIONS_SETUP["Craft"] = true
|
||||||
|
end
|
||||||
elseif tabKey == "SmartAmmo" then
|
elseif tabKey == "SmartAmmo" then
|
||||||
if not MTH_OPTIONS_SETUP["SmartAmmo"] then
|
if not MTH_OPTIONS_SETUP["SmartAmmo"] then
|
||||||
MTH_SetupSmartAmmoOptions()
|
MTH_SetupSmartAmmoOptions()
|
||||||
@@ -200,6 +215,13 @@ function MTH_SelectOptionsTab(tabKey)
|
|||||||
MTH_SetupAutoQuestOptions()
|
MTH_SetupAutoQuestOptions()
|
||||||
MTH_OPTIONS_SETUP["AutoQuest"] = true
|
MTH_OPTIONS_SETUP["AutoQuest"] = true
|
||||||
end
|
end
|
||||||
|
elseif tabKey == "ExpAmmo" then
|
||||||
|
if not MTH_OPTIONS_SETUP["ExpAmmo"] then
|
||||||
|
if type(MTH_SetupExpAmmoOptions) == "function" then
|
||||||
|
MTH_SetupExpAmmoOptions()
|
||||||
|
MTH_OPTIONS_SETUP["ExpAmmo"] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
elseif tabKey == "ICU" then
|
elseif tabKey == "ICU" then
|
||||||
if type(MTH_SetupICUOptions) == "function" then
|
if type(MTH_SetupICUOptions) == "function" then
|
||||||
MTH_SetupICUOptions()
|
MTH_SetupICUOptions()
|
||||||
|
|||||||
+13
-5
@@ -1,4 +1,4 @@
|
|||||||
MTH_OPTIONS_TREE_STATE = MTH_OPTIONS_TREE_STATE or { zButtons = true, chronometer = true }
|
MTH_OPTIONS_TREE_STATE = MTH_OPTIONS_TREE_STATE or { zButtons = false, chronometer = false }
|
||||||
MTH_OPTIONS_TREE_BUTTONS = MTH_OPTIONS_TREE_BUTTONS or {}
|
MTH_OPTIONS_TREE_BUTTONS = MTH_OPTIONS_TREE_BUTTONS or {}
|
||||||
MTH_OPTIONS_STATE = MTH_OPTIONS_STATE or {}
|
MTH_OPTIONS_STATE = MTH_OPTIONS_STATE or {}
|
||||||
if MTH_OPTIONS_STATE.activeTab == nil and MTH_OPTIONS_ACTIVE_TAB ~= nil then
|
if MTH_OPTIONS_STATE.activeTab == nil and MTH_OPTIONS_ACTIVE_TAB ~= nil then
|
||||||
@@ -27,9 +27,11 @@ MTH_OPTIONS_CONST = MTH_OPTIONS_CONST or {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
|
MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
|
||||||
{ key = "General", label = "General", frame = "MetaHuntOptionsGeneral" },
|
{ key = "General", label = "General", frame = "MetaHuntOptionsGeneral" },
|
||||||
|
{ key = "Profiles", label = "Profiles", frame = "MetaHuntOptionsProfiles" },
|
||||||
{ key = "Messages", label = "Messages", frame = "MetaHuntOptionsMessages" },
|
{ key = "Messages", label = "Messages", frame = "MetaHuntOptionsMessages" },
|
||||||
{ key = "Pet", label = "ZPet", frame = "MetaHuntOptionsPet" },
|
{ key = "ZBar", label = "zBar", frame = "MetaHuntOptionsZBar" },
|
||||||
|
{ key = "Pet", label = "ZPet", frame = "MetaHuntOptionsPet" },
|
||||||
{ key = "Track", label = "ZTrack", frame = "MetaHuntOptionsTrack" },
|
{ key = "Track", label = "ZTrack", frame = "MetaHuntOptionsTrack" },
|
||||||
{ key = "Aspect", label = "ZAspect", frame = "MetaHuntOptionsAspect" },
|
{ key = "Aspect", label = "ZAspect", frame = "MetaHuntOptionsAspect" },
|
||||||
{ key = "Trap", label = "ZTrap", frame = "MetaHuntOptionsTrap" },
|
{ key = "Trap", label = "ZTrap", frame = "MetaHuntOptionsTrap" },
|
||||||
@@ -38,11 +40,13 @@ MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
|
|||||||
{ key = "Mounts", label = "ZMounts", frame = "MetaHuntOptionsMounts" },
|
{ key = "Mounts", label = "ZMounts", frame = "MetaHuntOptionsMounts" },
|
||||||
{ key = "Companions", label = "ZCompanions", frame = "MetaHuntOptionsCompanions" },
|
{ key = "Companions", label = "ZCompanions", frame = "MetaHuntOptionsCompanions" },
|
||||||
{ key = "Toys", label = "ZToys", frame = "MetaHuntOptionsToys" },
|
{ key = "Toys", label = "ZToys", frame = "MetaHuntOptionsToys" },
|
||||||
|
{ key = "Craft", label = "ZCraft", frame = "MetaHuntOptionsCraft" },
|
||||||
{ key = "SmartAmmo", label = "Smart Ammo", frame = "MetaHuntOptionsSmartAmmo" },
|
{ key = "SmartAmmo", label = "Smart Ammo", frame = "MetaHuntOptionsSmartAmmo" },
|
||||||
{ key = "FeedOMatic", label = "FeedOMatic", frame = "MetaHuntOptionsFeedOMatic" },
|
{ key = "FeedOMatic", label = "FeedOMatic", frame = "MetaHuntOptionsFeedOMatic" },
|
||||||
{ key = "AutoBuy", label = "Auto Buy", frame = "MetaHuntOptionsAutoBuy" },
|
{ key = "AutoBuy", label = "Auto Buy", frame = "MetaHuntOptionsAutoBuy" },
|
||||||
{ key = "AutoQuest", label = "Auto Quest", frame = "MetaHuntOptionsAutoQuest" },
|
{ key = "AutoQuest", label = "Auto Quest", frame = "MetaHuntOptionsAutoQuest" },
|
||||||
{ key = "ICU", label = "ICU", frame = "MetaHuntOptionsICU" },
|
{ key = "ICU", label = "ICU", frame = "MetaHuntOptionsICU" },
|
||||||
|
{ key = "ExpAmmo", label = "MM Widget", frame = "MetaHuntOptionsExpAmmo" },
|
||||||
{ key = "ChronometerGeneral", label = "General", frame = "MetaHuntOptionsChronometer" },
|
{ key = "ChronometerGeneral", label = "General", frame = "MetaHuntOptionsChronometer" },
|
||||||
{ key = "ChronometerBar", label = "Bar", frame = "MetaHuntOptionsChronometer" },
|
{ key = "ChronometerBar", label = "Bar", frame = "MetaHuntOptionsChronometer" },
|
||||||
{ key = "ChronometerClassSpells", label = "Hunter Spells", frame = "MetaHuntOptionsChronometer" },
|
{ key = "ChronometerClassSpells", label = "Hunter Spells", frame = "MetaHuntOptionsChronometer" },
|
||||||
@@ -52,17 +56,20 @@ MTH_OPTIONS_TABS = MTH_OPTIONS_TABS or {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MTH_OPTIONS_TREE = MTH_OPTIONS_TREE or {
|
MTH_OPTIONS_TREE = MTH_OPTIONS_TREE or {
|
||||||
{ label = "General", key = "General" },
|
{ label = "General", key = "General" },
|
||||||
|
{ label = "Profiles", key = "Profiles" },
|
||||||
{ label = "Messages", key = "Messages" },
|
{ label = "Messages", key = "Messages" },
|
||||||
{ label = "Auto Buy", key = "AutoBuy" },
|
{ label = "Auto Buy", key = "AutoBuy" },
|
||||||
{ label = "Auto Quest", key = "AutoQuest" },
|
{ label = "Auto Quest", key = "AutoQuest" },
|
||||||
{ label = "Feed-O-Matic", key = "FeedOMatic" },
|
{ label = "Feed-O-Matic", key = "FeedOMatic" },
|
||||||
{ label = "ICU", key = "ICU" },
|
{ label = "ICU", key = "ICU" },
|
||||||
|
{ label = "MM Widget", key = "ExpAmmo" },
|
||||||
{
|
{
|
||||||
label = "zButtons",
|
label = "zButtons",
|
||||||
node = "zButtons",
|
node = "zButtons",
|
||||||
children = {
|
children = {
|
||||||
{ label = "zAmmo", key = "Ammo" },
|
{ label = "zBar", key = "ZBar" },
|
||||||
|
{ label = "zAmmo", key = "Ammo" },
|
||||||
{ label = "zPet", key = "Pet" },
|
{ label = "zPet", key = "Pet" },
|
||||||
{ label = "zAspect", key = "Aspect" },
|
{ label = "zAspect", key = "Aspect" },
|
||||||
{ label = "zTrack", key = "Track" },
|
{ label = "zTrack", key = "Track" },
|
||||||
@@ -71,6 +78,7 @@ MTH_OPTIONS_TREE = MTH_OPTIONS_TREE or {
|
|||||||
{ label = "zMounts", key = "Mounts" },
|
{ label = "zMounts", key = "Mounts" },
|
||||||
{ label = "zCompanions", key = "Companions" },
|
{ label = "zCompanions", key = "Companions" },
|
||||||
{ label = "zToys", key = "Toys" },
|
{ label = "zToys", key = "Toys" },
|
||||||
|
{ label = "zCraft", key = "Craft" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+606
-140
@@ -37,7 +37,9 @@ local function MTH_RebuildSpellOrder(buttonName, buttonObj, itemList, maxButtons
|
|||||||
for i = 1, maxButtons do
|
for i = 1, maxButtons do
|
||||||
local spellIndex = ZHunterMod_Saved[buttonName]["spells"][i]
|
local spellIndex = ZHunterMod_Saved[buttonName]["spells"][i]
|
||||||
if spellIndex and visible[spellIndex] ~= false then
|
if spellIndex and visible[spellIndex] ~= false then
|
||||||
info[infoIndex] = itemList[spellIndex]
|
-- String-based lists (zCraft) store names directly; numeric lists index into itemList
|
||||||
|
local name = (type(spellIndex) == "number") and itemList[spellIndex] or spellIndex
|
||||||
|
info[infoIndex] = name
|
||||||
infoIndex = infoIndex + 1
|
infoIndex = infoIndex + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -108,34 +110,34 @@ local function MTH_SetButtonEnabledState(buttonName, buttonObj, enabled)
|
|||||||
ZHunterMod_Saved[buttonName]["enabled"] = enabled and true or false
|
ZHunterMod_Saved[buttonName]["enabled"] = enabled and true or false
|
||||||
|
|
||||||
local resolvedButtonObj = buttonObj or getglobal(buttonName)
|
local resolvedButtonObj = buttonObj or getglobal(buttonName)
|
||||||
if not resolvedButtonObj then return end
|
if resolvedButtonObj then
|
||||||
|
if not enabled then
|
||||||
if not enabled then
|
if resolvedButtonObj.Hide then resolvedButtonObj:Hide() end
|
||||||
if resolvedButtonObj.Hide then
|
if resolvedButtonObj.count and resolvedButtonObj.name then
|
||||||
resolvedButtonObj:Hide()
|
for i = 1, resolvedButtonObj.count do
|
||||||
end
|
local child = getglobal(resolvedButtonObj.name .. i)
|
||||||
if resolvedButtonObj.count and resolvedButtonObj.name then
|
if child and child.Hide then child:Hide() end
|
||||||
for i = 1, resolvedButtonObj.count do
|
|
||||||
local child = getglobal(resolvedButtonObj.name .. i)
|
|
||||||
if child and child.Hide then
|
|
||||||
child:Hide()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
elseif ZHunterMod_Saved[buttonName]["parent"] and ZHunterMod_Saved[buttonName]["parent"]["hide"] then
|
||||||
|
if resolvedButtonObj.Hide then resolvedButtonObj:Hide() end
|
||||||
|
else
|
||||||
|
if resolvedButtonObj.Show then resolvedButtonObj:Show() end
|
||||||
|
MTH_RefreshButtonGeometry(buttonName, resolvedButtonObj)
|
||||||
end
|
end
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
-- If zBar is active, re-apply its layout so this button is included/excluded.
|
||||||
if ZHunterMod_Saved[buttonName]["parent"] and ZHunterMod_Saved[buttonName]["parent"]["hide"] then
|
-- When re-enabling a button, also un-exclude it from the bar so it appears
|
||||||
if resolvedButtonObj.Hide then
|
-- in the bar rather than as a standalone button.
|
||||||
resolvedButtonObj:Hide()
|
if type(MTH_ZBar_GetSaved) == "function" then
|
||||||
|
local zs = MTH_ZBar_GetSaved()
|
||||||
|
if enabled and zs.visible[buttonName] == false then
|
||||||
|
zs.visible[buttonName] = true
|
||||||
|
end
|
||||||
|
if zs.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
end
|
end
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if resolvedButtonObj.Show then
|
|
||||||
resolvedButtonObj:Show()
|
|
||||||
end
|
|
||||||
MTH_RefreshButtonGeometry(buttonName, resolvedButtonObj)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_GetButtonItemList(buttonName)
|
local function MTH_GetButtonItemList(buttonName)
|
||||||
@@ -170,7 +172,7 @@ local function MTH_GetButtonItemList(buttonName)
|
|||||||
if rangedList and table.getn(rangedList) > 0 then
|
if rangedList and table.getn(rangedList) > 0 then
|
||||||
return rangedList
|
return rangedList
|
||||||
end
|
end
|
||||||
elseif buttonName == "zButtonMounts" or buttonName == "zButtonCompanions" or buttonName == "zButtonToys" then
|
elseif buttonName == "zButtonMounts" or buttonName == "zButtonCompanions" or buttonName == "zButtonToys" or buttonName == "zButtonCraft" then
|
||||||
if ZHunterMod_Saved and ZHunterMod_Saved[buttonName] and ZHunterMod_Saved[buttonName]["spells"] then
|
if ZHunterMod_Saved and ZHunterMod_Saved[buttonName] and ZHunterMod_Saved[buttonName]["spells"] then
|
||||||
return ZHunterMod_Saved[buttonName]["spells"]
|
return ZHunterMod_Saved[buttonName]["spells"]
|
||||||
end
|
end
|
||||||
@@ -195,15 +197,15 @@ local function MTH_EnsureAmmoOptionsWatcher()
|
|||||||
if MTH_AmmoOptionsWatcher then
|
if MTH_AmmoOptionsWatcher then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
MTH_AmmoOptionsWatcher = CreateFrame("Frame", "MTHAmmoOptionsWatcherFrame")
|
MTH_AmmoOptionsWatcher = CreateFrame("Frame", "MTH_AmmoOptionsWatcher")
|
||||||
if not MTH_AmmoOptionsWatcher then
|
if not MTH_AmmoOptionsWatcher then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
MTH_AmmoOptionsWatcher:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
MTH_AmmoOptionsWatcher:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||||
MTH_AmmoOptionsWatcher:RegisterEvent("BAG_UPDATE")
|
MTH_AmmoOptionsWatcher:RegisterEvent("BAG_UPDATE")
|
||||||
MTH_AmmoOptionsWatcher:SetScript("OnEvent", function(_, eventName, unit)
|
MTH_AmmoOptionsWatcher:SetScript("OnEvent", function()
|
||||||
eventName = eventName or event
|
local eventName = event
|
||||||
unit = unit or arg1
|
local unit = arg1
|
||||||
if eventName == "UNIT_INVENTORY_CHANGED" and unit and unit ~= "player" then
|
if eventName == "UNIT_INVENTORY_CHANGED" and unit and unit ~= "player" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -212,7 +214,7 @@ local function MTH_EnsureAmmoOptionsWatcher()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_ZB_GetDefaultEnabled(buttonName)
|
local function MTH_ZB_GetDefaultEnabled(buttonName)
|
||||||
if buttonName == "zButtonMounts" or buttonName == "zButtonCompanions" or buttonName == "zButtonToys" or buttonName == "zButtonRanged" then
|
if buttonName == "zButtonMounts" or buttonName == "zButtonCompanions" or buttonName == "zButtonToys" or buttonName == "zButtonCraft" or buttonName == "zButtonRanged" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
@@ -247,6 +249,16 @@ local function MTH_ZB_EnsureButtonOptionDefaults(buttonName)
|
|||||||
end
|
end
|
||||||
saved["children"]["hideonclick"] = saved["children"]["hideonclick"] and true or false
|
saved["children"]["hideonclick"] = saved["children"]["hideonclick"] and true or false
|
||||||
|
|
||||||
|
if saved["children"]["expandonhover"] == nil then
|
||||||
|
saved["children"]["expandonhover"] = false
|
||||||
|
end
|
||||||
|
saved["children"]["expandonhover"] = saved["children"]["expandonhover"] and true or false
|
||||||
|
|
||||||
|
if saved["children"]["fadetimer"] == nil then
|
||||||
|
saved["children"]["fadetimer"] = 0
|
||||||
|
end
|
||||||
|
saved["children"]["fadetimer"] = tonumber(saved["children"]["fadetimer"]) or 0
|
||||||
|
|
||||||
if type(saved["parent"]) ~= "table" then
|
if type(saved["parent"]) ~= "table" then
|
||||||
saved["parent"] = {}
|
saved["parent"] = {}
|
||||||
end
|
end
|
||||||
@@ -259,6 +271,27 @@ local function MTH_ZB_EnsureButtonOptionDefaults(buttonName)
|
|||||||
end
|
end
|
||||||
saved["parent"]["circle"] = saved["parent"]["circle"] and true or false
|
saved["parent"]["circle"] = saved["parent"]["circle"] and true or false
|
||||||
|
|
||||||
|
if buttonName == "zButtonAspect" or buttonName == "zButtonTrack" or buttonName == "zButtonPet" then
|
||||||
|
if saved["parent"]["smart"] == nil then
|
||||||
|
saved["parent"]["smart"] = true
|
||||||
|
end
|
||||||
|
saved["parent"]["smart"] = saved["parent"]["smart"] and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
if buttonName == "zButtonMounts" or buttonName == "zButtonCompanions" then
|
||||||
|
if saved["parent"]["random"] == nil then
|
||||||
|
saved["parent"]["random"] = false
|
||||||
|
end
|
||||||
|
saved["parent"]["random"] = saved["parent"]["random"] and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
if buttonName == "zButtonMounts" then
|
||||||
|
if saved["parent"]["aqfilter"] == nil then
|
||||||
|
saved["parent"]["aqfilter"] = true
|
||||||
|
end
|
||||||
|
saved["parent"]["aqfilter"] = saved["parent"]["aqfilter"] and true or false
|
||||||
|
end
|
||||||
|
|
||||||
if saved["firstbutton"] ~= "LEFT" and saved["firstbutton"] ~= "RIGHT" then
|
if saved["firstbutton"] ~= "LEFT" and saved["firstbutton"] ~= "RIGHT" then
|
||||||
saved["firstbutton"] = "RIGHT"
|
saved["firstbutton"] = "RIGHT"
|
||||||
end
|
end
|
||||||
@@ -333,16 +366,24 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
enableButton:SetChecked(enabledValue and true or false)
|
enableButton:SetChecked(enabledValue and true or false)
|
||||||
enableButton.buttonName = buttonName
|
enableButton.buttonName = buttonName
|
||||||
enableButton.buttonObj = buttonObj
|
enableButton.buttonObj = buttonObj
|
||||||
enableButton:SetScript("OnClick", function(self)
|
enableButton:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = MTH_ZB_IsChecked(this)
|
||||||
local checked = MTH_ZB_IsChecked(self)
|
MTH_SetButtonEnabledState(this.buttonName, this.buttonObj, checked)
|
||||||
MTH_SetButtonEnabledState(self.buttonName, self.buttonObj, checked)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local parentSection = MTH_ZB_EnsureSection(containerName.."ParentSection", MTH_ZB_L("ZB_SECTION_PARENT_BUTTON", "Parent Button"), -52, 116)
|
local parentSectionHeight = 116
|
||||||
local childrenSection = MTH_ZB_EnsureSection(containerName.."ChildrenSection", MTH_ZB_L("ZB_SECTION_CHILDREN_BUTTONS", "Children Buttons"), -184, 235)
|
if buttonName == "zButtonAspect" or buttonName == "zButtonTrack" or buttonName == "zButtonPet" then
|
||||||
|
parentSectionHeight = 200
|
||||||
|
elseif buttonName == "zButtonMounts" then
|
||||||
|
parentSectionHeight = 225
|
||||||
|
elseif buttonName == "zButtonCompanions" then
|
||||||
|
parentSectionHeight = 196
|
||||||
|
end
|
||||||
|
local childrenSectionY = -52 - parentSectionHeight - 16
|
||||||
|
local parentSection = MTH_ZB_EnsureSection(containerName.."ParentSection", MTH_ZB_L("ZB_SECTION_PARENT_BUTTON", "Parent Button"), -52, parentSectionHeight)
|
||||||
|
local childrenSection = MTH_ZB_EnsureSection(containerName.."ChildrenSection", MTH_ZB_L("ZB_SECTION_CHILDREN_BUTTONS", "Children Buttons"), childrenSectionY, 290)
|
||||||
|
|
||||||
local parentYOffset = -18
|
local parentYOffset = -18
|
||||||
local childrenYOffset = -18
|
local childrenYOffset = -18
|
||||||
@@ -392,16 +433,15 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
expandLeft:SetChecked(saved["firstbutton"] == "LEFT")
|
expandLeft:SetChecked(saved["firstbutton"] == "LEFT")
|
||||||
expandLeft.buttonName = buttonName
|
expandLeft.buttonName = buttonName
|
||||||
expandLeft.buttonObj = buttonObj
|
expandLeft.buttonObj = buttonObj
|
||||||
expandLeft:SetScript("OnClick", function(self)
|
expandLeft:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = MTH_ZB_IsChecked(this)
|
||||||
local checked = MTH_ZB_IsChecked(self)
|
local btnName = this.buttonName
|
||||||
local btnName = self.buttonName
|
|
||||||
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
|
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
|
||||||
ZHunterMod_Saved[btnName]["firstbutton"] = checked and "LEFT" or "RIGHT"
|
ZHunterMod_Saved[btnName]["firstbutton"] = checked and "LEFT" or "RIGHT"
|
||||||
ZHunterMod_Saved[btnName]["horizontal"] = checked and 1 or nil
|
ZHunterMod_Saved[btnName]["horizontal"] = checked and 1 or nil
|
||||||
ZHunterMod_Saved[btnName]["vertical"] = checked and 1 or nil
|
ZHunterMod_Saved[btnName]["vertical"] = checked and 1 or nil
|
||||||
MTH_RefreshButtonGeometry(btnName, self.buttonObj)
|
MTH_RefreshButtonGeometry(btnName, this.buttonObj)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
childrenYOffset = childrenYOffset - 30
|
childrenYOffset = childrenYOffset - 30
|
||||||
@@ -414,17 +454,64 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
if hideClick.buttonObj then
|
if hideClick.buttonObj then
|
||||||
hideClick.buttonObj.hideonclick = saved["children"]["hideonclick"] and true or false
|
hideClick.buttonObj.hideonclick = saved["children"]["hideonclick"] and true or false
|
||||||
end
|
end
|
||||||
hideClick:SetScript("OnClick", function(self)
|
hideClick:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = MTH_ZB_IsChecked(this)
|
||||||
local checked = MTH_ZB_IsChecked(self)
|
ZHunterMod_Saved[this.buttonName]["children"]["hideonclick"] = checked
|
||||||
ZHunterMod_Saved[self.buttonName]["children"]["hideonclick"] = checked
|
local btnObj = this.buttonObj or getglobal(this.buttonName)
|
||||||
local btnObj = self.buttonObj or getglobal(self.buttonName)
|
|
||||||
if btnObj then btnObj.hideonclick = checked end
|
if btnObj then btnObj.hideonclick = checked end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
childrenYOffset = childrenYOffset - 25
|
childrenYOffset = childrenYOffset - 25
|
||||||
|
|
||||||
|
local expandOnHover = MTH_CreateCheckbox(childrenSection or container, containerName.."ExpandOnHover", MTH_ZB_L("ZB_LABEL_EXPAND_ON_HOVER", "Expand on Hover"), childrenYOffset)
|
||||||
|
if expandOnHover then
|
||||||
|
expandOnHover:SetChecked(saved["children"]["expandonhover"])
|
||||||
|
expandOnHover.buttonName = buttonName
|
||||||
|
expandOnHover.buttonObj = buttonObj
|
||||||
|
expandOnHover:SetScript("OnClick", function()
|
||||||
|
if not this then return end
|
||||||
|
local checked = MTH_ZB_IsChecked(this)
|
||||||
|
local btnName = this.buttonName
|
||||||
|
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
|
||||||
|
if not ZHunterMod_Saved[btnName]["children"] then
|
||||||
|
ZHunterMod_Saved[btnName]["children"] = {}
|
||||||
|
end
|
||||||
|
ZHunterMod_Saved[btnName]["children"]["expandonhover"] = checked
|
||||||
|
local btnObj = this.buttonObj or getglobal(btnName)
|
||||||
|
if btnObj then btnObj.expandonhover = checked end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
childrenYOffset = childrenYOffset - 40
|
||||||
|
|
||||||
|
local fadeTimer = MTH_CreateSlider(childrenSection or container, containerName.."FadeTimer", MTH_ZB_L("ZB_LABEL_AUTO_HIDE_TIMER", "Auto-Hide Timer (seconds)"), 0, 10, 1, childrenYOffset)
|
||||||
|
if fadeTimer then
|
||||||
|
fadeTimer:SetWidth(leftWidth - 40)
|
||||||
|
fadeTimer:SetValue(saved["children"]["fadetimer"] or 0)
|
||||||
|
fadeTimer.buttonName = buttonName
|
||||||
|
fadeTimer.buttonObj = buttonObj
|
||||||
|
fadeTimer.onChange = function(val, slider)
|
||||||
|
local frame = slider or fadeTimer
|
||||||
|
local btnName = frame and frame.buttonName
|
||||||
|
if not btnName or not (ZHunterMod_Saved and ZHunterMod_Saved[btnName]) then return end
|
||||||
|
if not ZHunterMod_Saved[btnName]["children"] then
|
||||||
|
ZHunterMod_Saved[btnName]["children"] = {}
|
||||||
|
end
|
||||||
|
local secs = math.floor((val or 0) + 0.5)
|
||||||
|
ZHunterMod_Saved[btnName]["children"]["fadetimer"] = secs
|
||||||
|
local btnObj = frame.buttonObj or getglobal(btnName)
|
||||||
|
if btnObj then
|
||||||
|
btnObj.fadetimer = secs
|
||||||
|
if secs <= 0 then
|
||||||
|
ZSpellButton_StopFadeTimer(btnObj)
|
||||||
|
elseif btnObj.children and btnObj.children:IsVisible() then
|
||||||
|
ZSpellButton_StartFadeTimer(btnObj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
childrenYOffset = childrenYOffset - 40
|
||||||
|
|
||||||
local showTooltip = MTH_CreateCheckbox(childrenSection or container, containerName.."ShowTooltip", MTH_ZB_L("ZB_LABEL_SHOW_TOOLTIP", "Show Tooltip"), childrenYOffset)
|
local showTooltip = MTH_CreateCheckbox(childrenSection or container, containerName.."ShowTooltip", MTH_ZB_L("ZB_LABEL_SHOW_TOOLTIP", "Show Tooltip"), childrenYOffset)
|
||||||
if showTooltip then
|
if showTooltip then
|
||||||
showTooltip:SetChecked(saved["tooltip"])
|
showTooltip:SetChecked(saved["tooltip"])
|
||||||
@@ -433,16 +520,15 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
if showTooltip.buttonObj then
|
if showTooltip.buttonObj then
|
||||||
showTooltip.buttonObj.tooltip = saved["tooltip"] and true or false
|
showTooltip.buttonObj.tooltip = saved["tooltip"] and true or false
|
||||||
end
|
end
|
||||||
showTooltip:SetScript("OnClick", function(self)
|
showTooltip:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = MTH_ZB_IsChecked(this)
|
||||||
local checked = MTH_ZB_IsChecked(self)
|
ZHunterMod_Saved[this.buttonName]["tooltip"] = checked
|
||||||
ZHunterMod_Saved[self.buttonName]["tooltip"] = checked
|
local btnObj = this.buttonObj or getglobal(this.buttonName)
|
||||||
local btnObj = self.buttonObj or getglobal(self.buttonName)
|
|
||||||
if btnObj then btnObj.tooltip = checked end
|
if btnObj then btnObj.tooltip = checked end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
childrenYOffset = childrenYOffset - 25
|
childrenYOffset = childrenYOffset - 20
|
||||||
|
|
||||||
if buttonName == "zButtonAmmo" then
|
if buttonName == "zButtonAmmo" then
|
||||||
local showAmmoName = MTH_CreateCheckbox(childrenSection or container, containerName.."ShowAmmoName", MTH_ZB_L("ZB_LABEL_SHOW_AMMO_NAME", "Show ammo name"), childrenYOffset)
|
local showAmmoName = MTH_CreateCheckbox(childrenSection or container, containerName.."ShowAmmoName", MTH_ZB_L("ZB_LABEL_SHOW_AMMO_NAME", "Show ammo name"), childrenYOffset)
|
||||||
@@ -451,13 +537,12 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
showAmmoName.buttonName = buttonName
|
showAmmoName.buttonName = buttonName
|
||||||
showAmmoName.buttonObj = buttonObj
|
showAmmoName.buttonObj = buttonObj
|
||||||
showAmmoName.maxButtons = maxButtons
|
showAmmoName.maxButtons = maxButtons
|
||||||
showAmmoName:SetScript("OnClick", function(self)
|
showAmmoName:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = MTH_ZB_IsChecked(this)
|
||||||
local checked = MTH_ZB_IsChecked(self)
|
local btnName = this.buttonName
|
||||||
local btnName = self.buttonName
|
|
||||||
ZHunterMod_Saved[btnName]["showammoname"] = checked
|
ZHunterMod_Saved[btnName]["showammoname"] = checked
|
||||||
local btnObj = self.buttonObj or getglobal(btnName)
|
local btnObj = this.buttonObj or getglobal(btnName)
|
||||||
if btnObj then
|
if btnObj then
|
||||||
for i = 1, (btnObj.count or 0) do
|
for i = 1, (btnObj.count or 0) do
|
||||||
local child = getglobal(btnName..i)
|
local child = getglobal(btnName..i)
|
||||||
@@ -471,9 +556,9 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
childrenYOffset = childrenYOffset - 35
|
childrenYOffset = childrenYOffset - 25
|
||||||
else
|
else
|
||||||
childrenYOffset = childrenYOffset - 35
|
childrenYOffset = childrenYOffset - 25
|
||||||
end
|
end
|
||||||
|
|
||||||
local mainSize = MTH_CreateSlider(parentSection or container, containerName.."MainButtonSize", MTH_ZB_L("ZB_LABEL_BUTTON_SIZE", "Button Size"), 10, 100, 1, parentYOffset)
|
local mainSize = MTH_CreateSlider(parentSection or container, containerName.."MainButtonSize", MTH_ZB_L("ZB_LABEL_BUTTON_SIZE", "Button Size"), 10, 100, 1, parentYOffset)
|
||||||
@@ -506,13 +591,12 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
hideButton:SetChecked(saved["parent"]["hide"])
|
hideButton:SetChecked(saved["parent"]["hide"])
|
||||||
hideButton.buttonName = buttonName
|
hideButton.buttonName = buttonName
|
||||||
hideButton.buttonObj = buttonObj
|
hideButton.buttonObj = buttonObj
|
||||||
hideButton:SetScript("OnClick", function(self)
|
hideButton:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = this:GetChecked() == 1
|
||||||
local checked = self:GetChecked() == 1
|
ZHunterMod_Saved[this.buttonName]["parent"]["hide"] = checked
|
||||||
ZHunterMod_Saved[self.buttonName]["parent"]["hide"] = checked
|
if this.buttonObj then
|
||||||
if self.buttonObj then
|
if checked then this.buttonObj:Hide() else this.buttonObj:Show() end
|
||||||
if checked then self.buttonObj:Hide() else self.buttonObj:Show() end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -523,17 +607,108 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
useCircle:SetChecked(saved["parent"]["circle"])
|
useCircle:SetChecked(saved["parent"]["circle"])
|
||||||
useCircle.buttonName = buttonName
|
useCircle.buttonName = buttonName
|
||||||
useCircle.buttonObj = buttonObj
|
useCircle.buttonObj = buttonObj
|
||||||
useCircle:SetScript("OnClick", function(self)
|
useCircle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = this:GetChecked() == 1
|
||||||
local checked = self:GetChecked() == 1
|
ZHunterMod_Saved[this.buttonName]["parent"]["circle"] = checked
|
||||||
ZHunterMod_Saved[self.buttonName]["parent"]["circle"] = checked
|
if this.buttonObj and this.buttonObj.circle then
|
||||||
if self.buttonObj and self.buttonObj.circle then
|
if checked then this.buttonObj.circle:Show() else this.buttonObj.circle:Hide() end
|
||||||
if checked then self.buttonObj.circle:Show() else self.buttonObj.circle:Hide() end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Smart Parent: Aspect/Track/Pet
|
||||||
|
if buttonName == "zButtonAspect" or buttonName == "zButtonTrack" or buttonName == "zButtonPet" then
|
||||||
|
parentYOffset = parentYOffset - 25
|
||||||
|
local smartParent = MTH_CreateCheckbox(parentSection or container, containerName.."SmartParent", MTH_ZB_L("ZB_LABEL_SMART_PARENT", "Smart Parent"), parentYOffset)
|
||||||
|
if smartParent then
|
||||||
|
smartParent:SetChecked(saved["parent"]["smart"])
|
||||||
|
smartParent.buttonName = buttonName
|
||||||
|
smartParent.buttonObj = buttonObj
|
||||||
|
smartParent:SetScript("OnClick", function()
|
||||||
|
if not this then return end
|
||||||
|
local checked = this:GetChecked() == 1
|
||||||
|
ZHunterMod_Saved[this.buttonName]["parent"]["smart"] = checked
|
||||||
|
local btn = this.buttonObj or getglobal(this.buttonName)
|
||||||
|
if btn then
|
||||||
|
if not checked then
|
||||||
|
local firstChild = getglobal(this.buttonName .. "1")
|
||||||
|
if firstChild and firstChild.id then
|
||||||
|
btn.id = firstChild.id
|
||||||
|
ZSpellButton_UpdateButton(btn)
|
||||||
|
ZSpellButton_UpdateCooldown(btn)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local setupFunc = getglobal(this.buttonName .. "_SetupSizeAndPosition")
|
||||||
|
if type(setupFunc) == "function" then
|
||||||
|
setupFunc()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
local smartDescText
|
||||||
|
if buttonName == "zButtonAspect" then
|
||||||
|
smartDescText = "When ON, the parent toggles between your 1st and 2nd aspect. If the 1st is active, the parent shows the 2nd and vice-versa. Useful for quickly swapping between two aspects in combat. When OFF, the parent always shows the 1st aspect."
|
||||||
|
elseif buttonName == "zButtonTrack" then
|
||||||
|
smartDescText = "When ON, the parent toggles between your 1st and 2nd tracking. If the 1st is active, the parent shows the 2nd and vice-versa. Great for PvP to swap between Track Hidden and Track Humanoids. When OFF, the parent always shows the 1st tracking."
|
||||||
|
elseif buttonName == "zButtonPet" then
|
||||||
|
smartDescText = "When ON, the parent dynamically changes based on your pet state: Revive if dead, Mend if hurt, Feed if unhappy, or your default spell otherwise. When OFF, the parent always shows the 1st spell."
|
||||||
|
else
|
||||||
|
smartDescText = "Dynamically swap the parent icon based on context."
|
||||||
|
end
|
||||||
|
local smartDesc = (parentSection or container):CreateFontString(containerName.."SmartParentDesc", "ARTWORK", "GameFontNormalSmall")
|
||||||
|
smartDesc:SetPoint("TOPLEFT", parentSection or container, "TOPLEFT", 40, parentYOffset - 24)
|
||||||
|
smartDesc:SetWidth(leftWidth - 50)
|
||||||
|
smartDesc:SetJustifyH("LEFT")
|
||||||
|
smartDesc:SetText(smartDescText)
|
||||||
|
smartDesc:SetTextColor(0.5, 0.7, 1.0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Random Parent: Mounts/Companions
|
||||||
|
if buttonName == "zButtonMounts" or buttonName == "zButtonCompanions" then
|
||||||
|
parentYOffset = parentYOffset - 25
|
||||||
|
local randomParent = MTH_CreateCheckbox(parentSection or container, containerName.."RandomParent", MTH_ZB_L("ZB_LABEL_RANDOM_PARENT", "Random Parent"), parentYOffset)
|
||||||
|
if randomParent then
|
||||||
|
randomParent:SetChecked(saved["parent"]["random"])
|
||||||
|
randomParent.buttonName = buttonName
|
||||||
|
randomParent.buttonObj = buttonObj
|
||||||
|
randomParent:SetScript("OnClick", function()
|
||||||
|
if not this then return end
|
||||||
|
local checked = this:GetChecked() == 1
|
||||||
|
ZHunterMod_Saved[this.buttonName]["parent"]["random"] = checked
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
local randomDesc = (parentSection or container):CreateFontString(containerName.."RandomParentDesc", "ARTWORK", "GameFontNormalSmall")
|
||||||
|
randomDesc:SetPoint("TOPLEFT", parentSection or container, "TOPLEFT", 40, parentYOffset - 24)
|
||||||
|
randomDesc:SetWidth(leftWidth - 50)
|
||||||
|
randomDesc:SetJustifyH("LEFT")
|
||||||
|
randomDesc:SetText(MTH_ZB_L("ZB_DESC_RANDOM_PARENT", "Pick a random child as parent on each login and after each use."))
|
||||||
|
randomDesc:SetTextColor(0.5, 0.7, 1.0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- AQ Mount Filter: Mounts only
|
||||||
|
if buttonName == "zButtonMounts" then
|
||||||
|
parentYOffset = parentYOffset - 45
|
||||||
|
local aqFilter = MTH_CreateCheckbox(parentSection or container, containerName.."AQFilter", MTH_ZB_L("ZB_LABEL_AQ_FILTER", "AQ Mount Filter"), parentYOffset)
|
||||||
|
if aqFilter then
|
||||||
|
aqFilter:SetChecked(saved["parent"]["aqfilter"])
|
||||||
|
aqFilter.buttonName = buttonName
|
||||||
|
aqFilter.buttonObj = buttonObj
|
||||||
|
aqFilter:SetScript("OnClick", function()
|
||||||
|
if not this then return end
|
||||||
|
local checked = this:GetChecked() == 1
|
||||||
|
ZHunterMod_Saved[this.buttonName]["parent"]["aqfilter"] = checked
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
local aqDesc = (parentSection or container):CreateFontString(containerName.."AQFilterDesc", "ARTWORK", "GameFontNormalSmall")
|
||||||
|
aqDesc:SetPoint("TOPLEFT", parentSection or container, "TOPLEFT", 40, parentYOffset - 24)
|
||||||
|
aqDesc:SetWidth(leftWidth - 50)
|
||||||
|
aqDesc:SetJustifyH("LEFT")
|
||||||
|
aqDesc:SetText(MTH_ZB_L("ZB_DESC_AQ_FILTER", "Hide Qiraji mounts outside AQ40. Show only Qiraji inside."))
|
||||||
|
aqDesc:SetTextColor(0.5, 0.7, 1.0)
|
||||||
|
end
|
||||||
|
|
||||||
MTH_SetButtonEnabledState(buttonName, buttonObj, saved["enabled"] and true or false)
|
MTH_SetButtonEnabledState(buttonName, buttonObj, saved["enabled"] and true or false)
|
||||||
|
|
||||||
local advHeader = container:CreateFontString(containerName.."AdvHeader", "ARTWORK", "GameFontHighlight")
|
local advHeader = container:CreateFontString(containerName.."AdvHeader", "ARTWORK", "GameFontHighlight")
|
||||||
@@ -587,17 +762,16 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
showText:SetText("")
|
showText:SetText("")
|
||||||
end
|
end
|
||||||
showToggle:SetChecked(ZHunterMod_Saved[buttonName]["visible"][showToggle.spellIndex] ~= false)
|
showToggle:SetChecked(ZHunterMod_Saved[buttonName]["visible"][showToggle.spellIndex] ~= false)
|
||||||
showToggle:SetScript("OnClick", function(self)
|
showToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local checked = this:GetChecked() == 1
|
||||||
local checked = self:GetChecked() == 1
|
local btnName = this.buttonName
|
||||||
local btnName = self.buttonName
|
local visibleIndex = this.spellIndex
|
||||||
local visibleIndex = self.spellIndex
|
|
||||||
if not ZHunterMod_Saved[btnName]["visible"] then
|
if not ZHunterMod_Saved[btnName]["visible"] then
|
||||||
ZHunterMod_Saved[btnName]["visible"] = {}
|
ZHunterMod_Saved[btnName]["visible"] = {}
|
||||||
end
|
end
|
||||||
ZHunterMod_Saved[btnName]["visible"][visibleIndex] = checked
|
ZHunterMod_Saved[btnName]["visible"][visibleIndex] = checked
|
||||||
MTH_RefreshButtonLayout(btnName, self.buttonObj, self.itemList, self.maxButtons)
|
MTH_RefreshButtonLayout(btnName, this.buttonObj, this.itemList, this.maxButtons)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -612,18 +786,17 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
downBtn.buttonObj = buttonObj
|
downBtn.buttonObj = buttonObj
|
||||||
downBtn.itemList = itemList
|
downBtn.itemList = itemList
|
||||||
downBtn.maxButtons = maxButtons
|
downBtn.maxButtons = maxButtons
|
||||||
downBtn:SetScript("OnClick", function(self)
|
downBtn:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local idx = this.spellIndex
|
||||||
local idx = self.spellIndex
|
local btnName = this.buttonName
|
||||||
local btnName = self.buttonName
|
local contName = this.containerName
|
||||||
local contName = self.containerName
|
local maxBtns = this.maxButtons
|
||||||
local maxBtns = self.maxButtons
|
|
||||||
if idx < maxBtns then
|
if idx < maxBtns then
|
||||||
local temp = ZHunterMod_Saved[btnName]["spells"][idx+1]
|
local temp = ZHunterMod_Saved[btnName]["spells"][idx+1]
|
||||||
ZHunterMod_Saved[btnName]["spells"][idx+1] = ZHunterMod_Saved[btnName]["spells"][idx]
|
ZHunterMod_Saved[btnName]["spells"][idx+1] = ZHunterMod_Saved[btnName]["spells"][idx]
|
||||||
ZHunterMod_Saved[btnName]["spells"][idx] = temp
|
ZHunterMod_Saved[btnName]["spells"][idx] = temp
|
||||||
MTH_RebuildSpellOrder(btnName, self.buttonObj, self.itemList, self.maxButtons)
|
MTH_RebuildSpellOrder(btnName, this.buttonObj, this.itemList, this.maxButtons)
|
||||||
local tabName = gsub(contName, "MetaHuntOptions", "")
|
local tabName = gsub(contName, "MetaHuntOptions", "")
|
||||||
MTH_ZB_RefreshTab(tabName)
|
MTH_ZB_RefreshTab(tabName)
|
||||||
end
|
end
|
||||||
@@ -640,17 +813,16 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
upBtn.buttonObj = buttonObj
|
upBtn.buttonObj = buttonObj
|
||||||
upBtn.itemList = itemList
|
upBtn.itemList = itemList
|
||||||
upBtn.maxButtons = maxButtons
|
upBtn.maxButtons = maxButtons
|
||||||
upBtn:SetScript("OnClick", function(self)
|
upBtn:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
local idx = this.spellIndex
|
||||||
local idx = self.spellIndex
|
local btnName = this.buttonName
|
||||||
local btnName = self.buttonName
|
local contName = this.containerName
|
||||||
local contName = self.containerName
|
|
||||||
if idx > 1 then
|
if idx > 1 then
|
||||||
local temp = ZHunterMod_Saved[btnName]["spells"][idx-1]
|
local temp = ZHunterMod_Saved[btnName]["spells"][idx-1]
|
||||||
ZHunterMod_Saved[btnName]["spells"][idx-1] = ZHunterMod_Saved[btnName]["spells"][idx]
|
ZHunterMod_Saved[btnName]["spells"][idx-1] = ZHunterMod_Saved[btnName]["spells"][idx]
|
||||||
ZHunterMod_Saved[btnName]["spells"][idx] = temp
|
ZHunterMod_Saved[btnName]["spells"][idx] = temp
|
||||||
MTH_RebuildSpellOrder(btnName, self.buttonObj, self.itemList, self.maxButtons)
|
MTH_RebuildSpellOrder(btnName, this.buttonObj, this.itemList, this.maxButtons)
|
||||||
local tabName = gsub(contName, "MetaHuntOptions", "")
|
local tabName = gsub(contName, "MetaHuntOptions", "")
|
||||||
MTH_ZB_RefreshTab(tabName)
|
MTH_ZB_RefreshTab(tabName)
|
||||||
end
|
end
|
||||||
@@ -666,6 +838,303 @@ local function MTH_SetupButtonOptions(containerName, buttonName, displayName, ma
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
-- zBar options
|
||||||
|
-- ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
|
||||||
|
function MTH_SetupZBarOptions()
|
||||||
|
if not MTH_ZBUTTONS_READY then return end
|
||||||
|
local container = MTH_GetFrame("MetaHuntOptionsZBar")
|
||||||
|
if not container then return end
|
||||||
|
MTH_ClearContainer(container)
|
||||||
|
|
||||||
|
if type(MTH_ZBar_GetSaved) ~= "function" then
|
||||||
|
local err = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
||||||
|
err:SetPoint("CENTER", container, "CENTER", 0, 0)
|
||||||
|
err:SetText("zBar module not loaded")
|
||||||
|
err:SetTextColor(1, 0.5, 0.5)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local s = MTH_ZBar_GetSaved()
|
||||||
|
local containerWidth = container:GetWidth() or 500
|
||||||
|
local leftWidth = 260
|
||||||
|
local rightX = leftWidth + 44
|
||||||
|
local rightWidth = containerWidth - rightX - 12
|
||||||
|
|
||||||
|
-- ===== Enable checkbox =====
|
||||||
|
local enableBtn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarEnable",
|
||||||
|
"Enable zBar — group all zButtons into a single draggable bar", -8)
|
||||||
|
if enableBtn then
|
||||||
|
enableBtn:SetChecked(s.enabled and true or false)
|
||||||
|
enableBtn:SetScript("OnClick", function()
|
||||||
|
if type(MTH_ZBar_SetEnabled) == "function" then
|
||||||
|
MTH_ZBar_SetEnabled(this:GetChecked() == 1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Direction header =====
|
||||||
|
local dirLabel = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
|
||||||
|
dirLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 16, -46)
|
||||||
|
dirLabel:SetText("Bar Direction")
|
||||||
|
|
||||||
|
-- ===== Horizontal radio =====
|
||||||
|
local horizBtn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarHoriz",
|
||||||
|
"Horizontal (side by side)", -64)
|
||||||
|
if horizBtn then
|
||||||
|
horizBtn:SetChecked(s.direction ~= "VERTICAL")
|
||||||
|
horizBtn:SetScript("OnClick", function()
|
||||||
|
if this:GetChecked() == 1 then
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.direction = "HORIZONTAL"
|
||||||
|
-- Auto-correct childexpand to a valid side for a horizontal bar
|
||||||
|
if sv.childexpand ~= "TOP" and sv.childexpand ~= "BOTTOM" then
|
||||||
|
sv.childexpand = "BOTTOM"
|
||||||
|
end
|
||||||
|
local v = getglobal("MetaHuntOptionsZBarVert")
|
||||||
|
if v then v:SetChecked(false) end
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
|
end
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
else
|
||||||
|
this:SetChecked(true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Vertical radio =====
|
||||||
|
local vertBtn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarVert",
|
||||||
|
"Vertical (stacked)", -90)
|
||||||
|
if vertBtn then
|
||||||
|
vertBtn:SetChecked(s.direction == "VERTICAL")
|
||||||
|
vertBtn:SetScript("OnClick", function()
|
||||||
|
if this:GetChecked() == 1 then
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.direction = "VERTICAL"
|
||||||
|
-- Auto-correct childexpand to a valid side for a vertical bar
|
||||||
|
if sv.childexpand ~= "LEFT" and sv.childexpand ~= "RIGHT" then
|
||||||
|
sv.childexpand = "RIGHT"
|
||||||
|
end
|
||||||
|
local h = getglobal("MetaHuntOptionsZBarHoriz")
|
||||||
|
if h then h:SetChecked(false) end
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
|
end
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
else
|
||||||
|
this:SetChecked(true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Children expand side (contextual to bar direction) =====
|
||||||
|
local expandLbl = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
|
||||||
|
expandLbl:SetPoint("TOPLEFT", container, "TOPLEFT", 16, -120)
|
||||||
|
if s.direction == "VERTICAL" then
|
||||||
|
expandLbl:SetText("Children expand side (Vertical bar):")
|
||||||
|
else
|
||||||
|
expandLbl:SetText("Children expand side (Horizontal bar):")
|
||||||
|
end
|
||||||
|
|
||||||
|
local exp1Val, exp2Val, exp1Lbl, exp2Lbl
|
||||||
|
if s.direction == "VERTICAL" then
|
||||||
|
exp1Val = "LEFT" ; exp1Lbl = "Left"
|
||||||
|
exp2Val = "RIGHT" ; exp2Lbl = "Right"
|
||||||
|
else
|
||||||
|
exp1Val = "TOP" ; exp1Lbl = "Top (above)"
|
||||||
|
exp2Val = "BOTTOM" ; exp2Lbl = "Bottom (below)"
|
||||||
|
end
|
||||||
|
|
||||||
|
local exp1Btn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarExp1", exp1Lbl, -138, 30)
|
||||||
|
if exp1Btn then
|
||||||
|
exp1Btn:SetChecked(s.childexpand == exp1Val)
|
||||||
|
exp1Btn.zbarVal = exp1Val
|
||||||
|
exp1Btn:SetScript("OnClick", function()
|
||||||
|
if this:GetChecked() == 1 then
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.childexpand = this.zbarVal
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then MTH_ZBar_ApplyLayout() end
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
else
|
||||||
|
this:SetChecked(true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local exp2Btn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarExp2", exp2Lbl, -164, 30)
|
||||||
|
if exp2Btn then
|
||||||
|
exp2Btn:SetChecked(s.childexpand == exp2Val)
|
||||||
|
exp2Btn.zbarVal = exp2Val
|
||||||
|
exp2Btn:SetScript("OnClick", function()
|
||||||
|
if this:GetChecked() == 1 then
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.childexpand = this.zbarVal
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then MTH_ZBar_ApplyLayout() end
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
else
|
||||||
|
this:SetChecked(true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Children layout (how children #2+ are arranged relative to #1) =====
|
||||||
|
local arrLbl = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
|
||||||
|
arrLbl:SetPoint("TOPLEFT", container, "TOPLEFT", 16, -196)
|
||||||
|
arrLbl:SetText("Children layout:")
|
||||||
|
|
||||||
|
local arrVBtn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarArrV",
|
||||||
|
"Vertical (stacked column)", -214, 30)
|
||||||
|
if arrVBtn then
|
||||||
|
arrVBtn:SetChecked((s.childarrange or "VERTICAL") == "VERTICAL")
|
||||||
|
arrVBtn:SetScript("OnClick", function()
|
||||||
|
if this:GetChecked() == 1 then
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.childarrange = "VERTICAL"
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then MTH_ZBar_ApplyLayout() end
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
else
|
||||||
|
this:SetChecked(true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local arrHBtn = MTH_CreateCheckbox(container, "MetaHuntOptionsZBarArrH",
|
||||||
|
"Horizontal (side-by-side row)", -240, 30)
|
||||||
|
if arrHBtn then
|
||||||
|
arrHBtn:SetChecked((s.childarrange or "VERTICAL") == "HORIZONTAL")
|
||||||
|
arrHBtn:SetScript("OnClick", function()
|
||||||
|
if this:GetChecked() == 1 then
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.childarrange = "HORIZONTAL"
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then MTH_ZBar_ApplyLayout() end
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
else
|
||||||
|
this:SetChecked(true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Spacing slider =====
|
||||||
|
local spacingSlider = MTH_CreateSlider(container, "MetaHuntOptionsZBarSpacing",
|
||||||
|
"Spacing (px)", 0, 30, 1, -300)
|
||||||
|
if spacingSlider then
|
||||||
|
spacingSlider:SetWidth(leftWidth - 40)
|
||||||
|
spacingSlider:SetValue(tonumber(s.spacing) or 4)
|
||||||
|
spacingSlider.onChange = function(val)
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.spacing = math.floor((tonumber(val) or 4) + 0.5)
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Button size slider =====
|
||||||
|
local sizeSlider = MTH_CreateSlider(container, "MetaHuntOptionsZBarSize",
|
||||||
|
"Button Size", 10, 100, 1, -360)
|
||||||
|
if sizeSlider then
|
||||||
|
sizeSlider:SetWidth(leftWidth - 40)
|
||||||
|
sizeSlider:SetValue(tonumber(s.size) or 36)
|
||||||
|
sizeSlider.onChange = function(val)
|
||||||
|
if type(MTH_ZBar_SetSize) == "function" then
|
||||||
|
MTH_ZBar_SetSize(val)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== Right column: Bar Order =====
|
||||||
|
local orderHeader = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
|
||||||
|
orderHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightX, -10)
|
||||||
|
orderHeader:SetText("Bar Order")
|
||||||
|
|
||||||
|
local LABELS = MTH_ZBar_GetAllButtonLabels()
|
||||||
|
local numBars = table.getn(s.order)
|
||||||
|
local listY = -35
|
||||||
|
local downX = rightX + 28
|
||||||
|
local upX = downX + 22
|
||||||
|
local labelX = upX + 26
|
||||||
|
local labelWidth = rightWidth - (labelX - rightX) - 8
|
||||||
|
if labelWidth < 80 then labelWidth = 80 end
|
||||||
|
|
||||||
|
for i = 1, numBars do
|
||||||
|
local buttonName = s.order[i]
|
||||||
|
local displayName = (LABELS and LABELS[buttonName]) or buttonName
|
||||||
|
|
||||||
|
-- Include/exclude visibility toggle
|
||||||
|
local toggleName = "MetaHuntOptionsZBarToggle" .. i
|
||||||
|
local showToggle = CreateFrame("CheckButton", toggleName, container, "UICheckButtonTemplate")
|
||||||
|
if showToggle then
|
||||||
|
showToggle:ClearAllPoints()
|
||||||
|
showToggle:SetPoint("TOPLEFT", container, "TOPLEFT", rightX, listY + 2)
|
||||||
|
local tText = getglobal(toggleName .. "Text")
|
||||||
|
if tText then tText:SetText("") end
|
||||||
|
showToggle:SetChecked(s.visible[buttonName] ~= false)
|
||||||
|
showToggle.zbarName = buttonName
|
||||||
|
showToggle:SetScript("OnClick", function()
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
sv.visible[this.zbarName] = (this:GetChecked() == 1)
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Move Down (-)
|
||||||
|
local downBtn = CreateFrame("Button", nil, container, "UIPanelButtonTemplate")
|
||||||
|
downBtn:SetPoint("TOPLEFT", container, "TOPLEFT", downX, listY)
|
||||||
|
downBtn:SetWidth(20)
|
||||||
|
downBtn:SetHeight(20)
|
||||||
|
downBtn:SetText("-")
|
||||||
|
downBtn.zbarIndex = i
|
||||||
|
downBtn:SetScript("OnClick", function()
|
||||||
|
local idx = this.zbarIndex
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
local tot = table.getn(sv.order)
|
||||||
|
if idx < tot then
|
||||||
|
local tmp = sv.order[idx + 1]
|
||||||
|
sv.order[idx + 1] = sv.order[idx]
|
||||||
|
sv.order[idx] = tmp
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Move Up (+)
|
||||||
|
local upBtn = CreateFrame("Button", nil, container, "UIPanelButtonTemplate")
|
||||||
|
upBtn:SetPoint("TOPLEFT", container, "TOPLEFT", upX, listY)
|
||||||
|
upBtn:SetWidth(20)
|
||||||
|
upBtn:SetHeight(20)
|
||||||
|
upBtn:SetText("+")
|
||||||
|
upBtn.zbarIndex = i
|
||||||
|
upBtn:SetScript("OnClick", function()
|
||||||
|
local idx = this.zbarIndex
|
||||||
|
local sv = MTH_ZBar_GetSaved()
|
||||||
|
if idx > 1 then
|
||||||
|
local tmp = sv.order[idx - 1]
|
||||||
|
sv.order[idx - 1] = sv.order[idx]
|
||||||
|
sv.order[idx] = tmp
|
||||||
|
MTH_ResetAndSelectOptionsTab("ZBar")
|
||||||
|
if sv.enabled and type(MTH_ZBar_ApplyLayout) == "function" then
|
||||||
|
MTH_ZBar_ApplyLayout()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Bar name label
|
||||||
|
local lbl = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
lbl:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, listY)
|
||||||
|
lbl:SetText(displayName)
|
||||||
|
lbl:SetWidth(labelWidth)
|
||||||
|
lbl:SetJustifyH("LEFT")
|
||||||
|
|
||||||
|
listY = listY - 25
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_SetupPetOptions()
|
function MTH_SetupPetOptions()
|
||||||
if not MTH_ZBUTTONS_READY then return end
|
if not MTH_ZBUTTONS_READY then return end
|
||||||
MTH_SetupButtonOptions("MetaHuntOptionsPet", "zButtonPet", "ZPet", 10)
|
MTH_SetupButtonOptions("MetaHuntOptionsPet", "zButtonPet", "ZPet", 10)
|
||||||
@@ -725,6 +1194,13 @@ function MTH_SetupToysOptions()
|
|||||||
MTH_SetupButtonOptions("MetaHuntOptionsToys", "zButtonToys", "ZToys", maxButtons)
|
MTH_SetupButtonOptions("MetaHuntOptionsToys", "zButtonToys", "ZToys", maxButtons)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MTH_SetupCraftOptions()
|
||||||
|
if not MTH_ZBUTTONS_READY then return end
|
||||||
|
local itemList = MTH_GetButtonItemList("zButtonCraft")
|
||||||
|
local maxButtons = itemList and table.getn(itemList) or 1
|
||||||
|
MTH_SetupButtonOptions("MetaHuntOptionsCraft", "zButtonCraft", "ZCraft", maxButtons)
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_SetupSmartAmmoOptions()
|
function MTH_SetupSmartAmmoOptions()
|
||||||
if not MTH_ZBUTTONS_READY then return end
|
if not MTH_ZBUTTONS_READY then return end
|
||||||
local container = MTH_GetFrame("MetaHuntOptionsSmartAmmo")
|
local container = MTH_GetFrame("MetaHuntOptionsSmartAmmo")
|
||||||
@@ -749,11 +1225,10 @@ function MTH_SetupSmartAmmoOptions()
|
|||||||
end
|
end
|
||||||
if moduleToggle then
|
if moduleToggle then
|
||||||
moduleToggle:SetChecked(moduleEnabled)
|
moduleToggle:SetChecked(moduleEnabled)
|
||||||
moduleToggle:SetScript("OnClick", function(self)
|
moduleToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
MTH:SetModuleEnabled("smartammo", MTH_ZB_IsChecked(self))
|
MTH:SetModuleEnabled("smartammo", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
MTH_SetupSmartAmmoOptions()
|
MTH_SetupSmartAmmoOptions()
|
||||||
end)
|
end)
|
||||||
@@ -766,11 +1241,10 @@ function MTH_SetupSmartAmmoOptions()
|
|||||||
if not moduleEnabled then
|
if not moduleEnabled then
|
||||||
smartToggle:Disable()
|
smartToggle:Disable()
|
||||||
end
|
end
|
||||||
smartToggle:SetScript("OnClick", function(self)
|
smartToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if type(MTHSmartAmmo_SetSmartEnabled) == "function" then
|
if type(MTHSmartAmmo_SetSmartEnabled) == "function" then
|
||||||
MTHSmartAmmo_SetSmartEnabled(MTH_ZB_IsChecked(self) and 1 or nil)
|
MTHSmartAmmo_SetSmartEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -785,11 +1259,10 @@ function MTH_SetupSmartAmmoOptions()
|
|||||||
if not moduleEnabled then
|
if not moduleEnabled then
|
||||||
reloadToggle:Disable()
|
reloadToggle:Disable()
|
||||||
end
|
end
|
||||||
reloadToggle:SetScript("OnClick", function(self)
|
reloadToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
|
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
|
||||||
MTHSmartAmmo_SetReloadEnabled(MTH_ZB_IsChecked(self) and 1 or nil)
|
MTHSmartAmmo_SetReloadEnabled(MTH_ZB_IsChecked(this) and 1 or nil)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -825,11 +1298,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local initModulesToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitModules", "Init : modules loaded", -36)
|
local initModulesToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitModules", "Init : modules loaded", -36)
|
||||||
if initModulesToggle then
|
if initModulesToggle then
|
||||||
initModulesToggle:SetChecked(msgSettings.initModulesLoaded and true or false)
|
initModulesToggle:SetChecked(msgSettings.initModulesLoaded and true or false)
|
||||||
initModulesToggle:SetScript("OnClick", function(self)
|
initModulesToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("initModulesLoaded", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("initModulesLoaded", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -837,11 +1309,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local initWelcomeToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitWelcome", "Init : Sarcastic welcome message", -64)
|
local initWelcomeToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesInitWelcome", "Init : Sarcastic welcome message", -64)
|
||||||
if initWelcomeToggle then
|
if initWelcomeToggle then
|
||||||
initWelcomeToggle:SetChecked(msgSettings.initSarcasticWelcome ~= false)
|
initWelcomeToggle:SetChecked(msgSettings.initSarcasticWelcome ~= false)
|
||||||
initWelcomeToggle:SetScript("OnClick", function(self)
|
initWelcomeToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("initSarcasticWelcome", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("initSarcasticWelcome", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -849,11 +1320,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local petHungryToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetHungry", "Pet is hungry (spam)", -92)
|
local petHungryToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetHungry", "Pet is hungry (spam)", -92)
|
||||||
if petHungryToggle then
|
if petHungryToggle then
|
||||||
petHungryToggle:SetChecked(msgSettings.petHungry and true or false)
|
petHungryToggle:SetChecked(msgSettings.petHungry and true or false)
|
||||||
petHungryToggle:SetScript("OnClick", function(self)
|
petHungryToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("petHungry", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("petHungry", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -861,11 +1331,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local beastTrainingScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesBeastTrainingScan", "Beasttraining scan", -120)
|
local beastTrainingScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesBeastTrainingScan", "Beasttraining scan", -120)
|
||||||
if beastTrainingScanToggle then
|
if beastTrainingScanToggle then
|
||||||
beastTrainingScanToggle:SetChecked(msgSettings.beastTrainingScan ~= false)
|
beastTrainingScanToggle:SetChecked(msgSettings.beastTrainingScan ~= false)
|
||||||
beastTrainingScanToggle:SetScript("OnClick", function(self)
|
beastTrainingScanToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("beastTrainingScan", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("beastTrainingScan", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -873,11 +1342,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local spellbookScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesSpellbookScan", "Spellbook scan", -148)
|
local spellbookScanToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesSpellbookScan", "Spellbook scan", -148)
|
||||||
if spellbookScanToggle then
|
if spellbookScanToggle then
|
||||||
spellbookScanToggle:SetChecked(msgSettings.spellbookScan and true or false)
|
spellbookScanToggle:SetChecked(msgSettings.spellbookScan and true or false)
|
||||||
spellbookScanToggle:SetScript("OnClick", function(self)
|
spellbookScanToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("spellbookScan", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("spellbookScan", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -885,11 +1353,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local petRanAwayToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetRanAway", "Pet ran away", -176)
|
local petRanAwayToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesPetRanAway", "Pet ran away", -176)
|
||||||
if petRanAwayToggle then
|
if petRanAwayToggle then
|
||||||
petRanAwayToggle:SetChecked(msgSettings.petRanAway ~= false)
|
petRanAwayToggle:SetChecked(msgSettings.petRanAway ~= false)
|
||||||
petRanAwayToggle:SetScript("OnClick", function(self)
|
petRanAwayToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("petRanAway", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("petRanAway", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -897,11 +1364,10 @@ function MTH_SetupMessagesOptions()
|
|||||||
local mapMarkersToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesMapMarkers", "Map markers", -204)
|
local mapMarkersToggle = MTH_CreateCheckbox(section, "MetaHuntMessagesMapMarkers", "Map markers", -204)
|
||||||
if mapMarkersToggle then
|
if mapMarkersToggle then
|
||||||
mapMarkersToggle:SetChecked(msgSettings.mapMarkers ~= false)
|
mapMarkersToggle:SetChecked(msgSettings.mapMarkers ~= false)
|
||||||
mapMarkersToggle:SetScript("OnClick", function(self)
|
mapMarkersToggle:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if MTH and MTH.SetMessageEnabled then
|
if MTH and MTH.SetMessageEnabled then
|
||||||
MTH:SetMessageEnabled("mapMarkers", MTH_ZB_IsChecked(self))
|
MTH:SetMessageEnabled("mapMarkers", MTH_ZB_IsChecked(this))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -1057,7 +1523,7 @@ function MTH_SetupGeneralOptions()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
ensureHelpText(smartAmmoSection, "MetaHuntGeneralSmartAmmoReloadHelp", "Falls back to any available ammo when preferred ammo is missing.", -154)
|
ensureHelpText(smartAmmoSection, "MetaHuntGeneralSmartAmmoReloadHelp", "Falls back to any available ammo when equipped ammo is out of stock.", -154)
|
||||||
|
|
||||||
local weaponSwapEnabled = type(MTHSmartAmmo_GetWeaponSwapEnabled) == "function" and MTHSmartAmmo_GetWeaponSwapEnabled() and true or false
|
local weaponSwapEnabled = type(MTHSmartAmmo_GetWeaponSwapEnabled) == "function" and MTHSmartAmmo_GetWeaponSwapEnabled() and true or false
|
||||||
local weaponSwapToggle = ensureCheckbox(smartAmmoSection, "MetaHuntGeneralSmartAmmoWeaponSwapToggle", "Enable Weapon-Swap Auto Ammo", -180, weaponSwapEnabled)
|
local weaponSwapToggle = ensureCheckbox(smartAmmoSection, "MetaHuntGeneralSmartAmmoWeaponSwapToggle", "Enable Weapon-Swap Auto Ammo", -180, weaponSwapEnabled)
|
||||||
|
|||||||
+3
-3
@@ -68,9 +68,9 @@ function MTH_CreateSlider(parent, name, label, minVal, maxVal, step, yOffset)
|
|||||||
if lowLabel then lowLabel:Hide() end
|
if lowLabel then lowLabel:Hide() end
|
||||||
if highLabel then highLabel:Hide() end
|
if highLabel then highLabel:Hide() end
|
||||||
|
|
||||||
slider:SetScript("OnValueChanged", function(self, newValue)
|
slider:SetScript("OnValueChanged", function()
|
||||||
local activeSlider = self or this or slider
|
local activeSlider = this or this or slider
|
||||||
local current = tonumber(newValue)
|
local current = tonumber(arg1)
|
||||||
if not current and activeSlider and activeSlider.GetValue then
|
if not current and activeSlider and activeSlider.GetValue then
|
||||||
current = tonumber(activeSlider:GetValue())
|
current = tonumber(activeSlider:GetValue())
|
||||||
end
|
end
|
||||||
|
|||||||
+6
-3
@@ -46,12 +46,12 @@
|
|||||||
<Frames>
|
<Frames>
|
||||||
<Frame name="$parentNav" enableMouse="true">
|
<Frame name="$parentNav" enableMouse="true">
|
||||||
<Size>
|
<Size>
|
||||||
<AbsDimension x="120" y="540"/>
|
<AbsDimension x="120" y="566"/>
|
||||||
</Size>
|
</Size>
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="TOPLEFT">
|
<Anchor point="TOPLEFT">
|
||||||
<Offset>
|
<Offset>
|
||||||
<AbsDimension x="12" y="-72"/>
|
<AbsDimension x="12" y="-58"/>
|
||||||
</Offset>
|
</Offset>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
@@ -64,8 +64,9 @@
|
|||||||
</Backdrop>
|
</Backdrop>
|
||||||
</Frame>
|
</Frame>
|
||||||
|
|
||||||
<!-- Content Areas -->
|
<Frame name="$parentZBar" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentGeneral" hidden="true" enableMouse="true"/>
|
<Frame name="$parentGeneral" hidden="true" enableMouse="true"/>
|
||||||
|
<Frame name="$parentProfiles" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentMessages" hidden="true" enableMouse="true"/>
|
<Frame name="$parentMessages" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentPet" hidden="true" enableMouse="true"/>
|
<Frame name="$parentPet" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentTrack" hidden="true" enableMouse="true"/>
|
<Frame name="$parentTrack" hidden="true" enableMouse="true"/>
|
||||||
@@ -76,11 +77,13 @@
|
|||||||
<Frame name="$parentMounts" hidden="true" enableMouse="true"/>
|
<Frame name="$parentMounts" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentCompanions" hidden="true" enableMouse="true"/>
|
<Frame name="$parentCompanions" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentToys" hidden="true" enableMouse="true"/>
|
<Frame name="$parentToys" hidden="true" enableMouse="true"/>
|
||||||
|
<Frame name="$parentCraft" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentSmartAmmo" hidden="true" enableMouse="true"/>
|
<Frame name="$parentSmartAmmo" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentFeedOMatic" hidden="true" enableMouse="true"/>
|
<Frame name="$parentFeedOMatic" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentAutoBuy" hidden="true" enableMouse="true"/>
|
<Frame name="$parentAutoBuy" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentAutoQuest" hidden="true" enableMouse="true"/>
|
<Frame name="$parentAutoQuest" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentICU" hidden="true" enableMouse="true"/>
|
<Frame name="$parentICU" hidden="true" enableMouse="true"/>
|
||||||
|
<Frame name="$parentExpAmmo" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentChronometer" hidden="true" enableMouse="true"/>
|
<Frame name="$parentChronometer" hidden="true" enableMouse="true"/>
|
||||||
<Frame name="$parentCredits" hidden="true" enableMouse="true"/>
|
<Frame name="$parentCredits" hidden="true" enableMouse="true"/>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ function MTH_ST_LifecycleService:HandleEvent(evt, eventArg1, eventArg2)
|
|||||||
if type(MTH_ST_HandlePlayerEnteringWorld) == "function" and MTH_ST_HandlePlayerEnteringWorld(evt) then
|
if type(MTH_ST_HandlePlayerEnteringWorld) == "function" and MTH_ST_HandlePlayerEnteringWorld(evt) then
|
||||||
return true, "lifecycle-enter-world"
|
return true, "lifecycle-enter-world"
|
||||||
end
|
end
|
||||||
|
if type(MTH_ST_HandleSpellcastEvent) == "function" and MTH_ST_HandleSpellcastEvent(evt, eventArg1, eventArg2) then
|
||||||
|
return true, "lifecycle-spellcast"
|
||||||
|
end
|
||||||
if type(MTH_ST_HandleUnitPetEvent) == "function" and MTH_ST_HandleUnitPetEvent(evt, eventArg1) then
|
if type(MTH_ST_HandleUnitPetEvent) == "function" and MTH_ST_HandleUnitPetEvent(evt, eventArg1) then
|
||||||
if evt == "UNIT_PET" then
|
if evt == "UNIT_PET" then
|
||||||
if eventArg1 == "player" then
|
if eventArg1 == "player" then
|
||||||
|
|||||||
+226
@@ -0,0 +1,226 @@
|
|||||||
|
------------------------------------------------------
|
||||||
|
-- MetaHunt Profile System
|
||||||
|
-- Captures:
|
||||||
|
-- MTH_SavedVariables.modules (account-wide option values, e.g. feedomatic)
|
||||||
|
-- MTH_CharSavedVariables.modules (per-char option values: ICU, Chronometer,
|
||||||
|
-- AutoBuy, AutoQuest, SmartAmmo, tooltips...)
|
||||||
|
-- MTH_CharSavedVariables.moduleStates (enabled/disabled per char)
|
||||||
|
-- ZHunterMod_Saved / MTH_CharSavedVariables.modules.zhunter (zButtons layout)
|
||||||
|
-- Auto-snapshots current character on PLAYER_LOGOUT into
|
||||||
|
-- MTH_SavedVariables.charSnapshots["CharName-RealmName"]
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
local function MTH_Profile_DeepCopy(orig)
|
||||||
|
if type(orig) ~= "table" then return orig end
|
||||||
|
local copy = {}
|
||||||
|
for k, v in orig do
|
||||||
|
copy[MTH_Profile_DeepCopy(k)] = MTH_Profile_DeepCopy(v)
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Shallow-copy a module's saved data, skipping keys that hold large operational
|
||||||
|
-- blobs (e.g. feedomatic's "legacy" table which mirrors FOM_Cooking, FOM_QuestFood
|
||||||
|
-- etc.) — those are runtime migration artifacts, not user configuration settings.
|
||||||
|
local MTH_PROFILE_SKIP_KEYS = { legacy = true, history = true }
|
||||||
|
|
||||||
|
local function MTH_Profile_CopyModules(src)
|
||||||
|
if type(src) ~= "table" then return {} end
|
||||||
|
local out = {}
|
||||||
|
for modName, modData in src do
|
||||||
|
if type(modData) == "table" then
|
||||||
|
local modCopy = {}
|
||||||
|
for k, v in modData do
|
||||||
|
if not MTH_PROFILE_SKIP_KEYS[k] then
|
||||||
|
modCopy[MTH_Profile_DeepCopy(k)] = MTH_Profile_DeepCopy(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
out[modName] = modCopy
|
||||||
|
else
|
||||||
|
out[modName] = modData
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_Profile_EnsureStore()
|
||||||
|
if type(MTH_SavedVariables) ~= "table" then
|
||||||
|
MTH_SavedVariables = {}
|
||||||
|
end
|
||||||
|
if type(MTH_SavedVariables.profiles) ~= "table" then
|
||||||
|
MTH_SavedVariables.profiles = {}
|
||||||
|
end
|
||||||
|
if type(MTH_SavedVariables.charSnapshots) ~= "table" then
|
||||||
|
MTH_SavedVariables.charSnapshots = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_Profile_GetCharKey()
|
||||||
|
local name = (type(UnitName) == "function") and UnitName("player") or "Unknown"
|
||||||
|
local realm = (type(GetRealmName) == "function") and GetRealmName() or "Unknown"
|
||||||
|
name = (name and name ~= "") and name or "Unknown"
|
||||||
|
realm = (realm and realm ~= "") and realm or "Unknown"
|
||||||
|
return name .. "-" .. realm
|
||||||
|
end
|
||||||
|
|
||||||
|
local function MTH_Profile_BuildSnapshot()
|
||||||
|
local snap = {}
|
||||||
|
snap.savedBy = MTH_Profile_GetCharKey()
|
||||||
|
snap.savedAt = (type(date) == "function") and date("%Y-%m-%d %H:%M") or ""
|
||||||
|
|
||||||
|
-- Account-wide module option values (e.g. feedomatic)
|
||||||
|
snap.config = (type(MTH_SavedVariables) == "table"
|
||||||
|
and type(MTH_SavedVariables.modules) == "table")
|
||||||
|
and MTH_Profile_CopyModules(MTH_SavedVariables.modules)
|
||||||
|
or {}
|
||||||
|
|
||||||
|
-- Per-character module option values (ICU, Chronometer, AutoBuy, SmartAmmo, etc.)
|
||||||
|
snap.charConfig = (type(MTH_CharSavedVariables) == "table"
|
||||||
|
and type(MTH_CharSavedVariables.modules) == "table")
|
||||||
|
and MTH_Profile_CopyModules(MTH_CharSavedVariables.modules)
|
||||||
|
or {}
|
||||||
|
|
||||||
|
-- Per-character module enabled/disabled states
|
||||||
|
snap.moduleStates = (type(MTH_CharSavedVariables) == "table"
|
||||||
|
and type(MTH_CharSavedVariables.moduleStates) == "table")
|
||||||
|
and MTH_Profile_DeepCopy(MTH_CharSavedVariables.moduleStates)
|
||||||
|
or {}
|
||||||
|
|
||||||
|
-- zButtons config — kept as dedicated key for clarity
|
||||||
|
-- (also lives in charConfig.zhunter but we keep it explicit)
|
||||||
|
local zh = nil
|
||||||
|
if type(MTH_CharSavedVariables) == "table"
|
||||||
|
and type(MTH_CharSavedVariables.modules) == "table"
|
||||||
|
and type(MTH_CharSavedVariables.modules.zhunter) == "table"
|
||||||
|
then
|
||||||
|
zh = MTH_CharSavedVariables.modules.zhunter
|
||||||
|
elseif type(ZHunterMod_Saved) == "table" then
|
||||||
|
zh = ZHunterMod_Saved
|
||||||
|
end
|
||||||
|
snap.zhunter = zh and MTH_Profile_DeepCopy(zh) or {}
|
||||||
|
|
||||||
|
return snap
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Save current settings as a named profile
|
||||||
|
function MTH_Profile_Save(name)
|
||||||
|
if type(name) ~= "string" or string.len(name) == 0 then
|
||||||
|
return false, "invalid name"
|
||||||
|
end
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
MTH_SavedVariables.profiles[name] = MTH_Profile_BuildSnapshot()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Delete a named profile
|
||||||
|
function MTH_Profile_Delete(name)
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
if MTH_SavedVariables.profiles[name] == nil then return false end
|
||||||
|
MTH_SavedVariables.profiles[name] = nil
|
||||||
|
if type(MTH_CharSavedVariables) == "table"
|
||||||
|
and MTH_CharSavedVariables.activeProfile == name
|
||||||
|
then
|
||||||
|
MTH_CharSavedVariables.activeProfile = nil
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply a profile to SavedVariables; a /reload is required for changes to take full effect
|
||||||
|
function MTH_Profile_Load(name)
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
local p = MTH_SavedVariables.profiles[name]
|
||||||
|
if type(p) ~= "table" then return false, "profile not found" end
|
||||||
|
|
||||||
|
if type(MTH_CharSavedVariables) ~= "table" then MTH_CharSavedVariables = {} end
|
||||||
|
if type(MTH_CharSavedVariables.modules) ~= "table" then MTH_CharSavedVariables.modules = {} end
|
||||||
|
|
||||||
|
-- Apply account-wide module option values (e.g. feedomatic)
|
||||||
|
if type(p.config) == "table" then
|
||||||
|
if type(MTH_SavedVariables.modules) ~= "table" then
|
||||||
|
MTH_SavedVariables.modules = {}
|
||||||
|
end
|
||||||
|
for modName, modData in p.config do
|
||||||
|
MTH_SavedVariables.modules[modName] = MTH_Profile_DeepCopy(modData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply per-character module option values (ICU, Chronometer, AutoBuy, SmartAmmo, etc.)
|
||||||
|
if type(p.charConfig) == "table" then
|
||||||
|
for modName, modData in p.charConfig do
|
||||||
|
MTH_CharSavedVariables.modules[modName] = MTH_Profile_DeepCopy(modData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply module enabled/disabled
|
||||||
|
if type(p.moduleStates) == "table" then
|
||||||
|
if type(MTH_CharSavedVariables.moduleStates) ~= "table" then
|
||||||
|
MTH_CharSavedVariables.moduleStates = {}
|
||||||
|
end
|
||||||
|
for k, v in p.moduleStates do
|
||||||
|
MTH_CharSavedVariables.moduleStates[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply zButtons (also written into charConfig.zhunter above, but keep explicit)
|
||||||
|
if type(p.zhunter) == "table" then
|
||||||
|
ZHunterMod_Saved = MTH_Profile_DeepCopy(p.zhunter)
|
||||||
|
MTH_CharSavedVariables.modules.zhunter = ZHunterMod_Saved
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_CharSavedVariables.activeProfile = name
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a named profile from another character's auto-snapshot
|
||||||
|
-- profileName defaults to charKey if not provided
|
||||||
|
function MTH_Profile_CopyFromChar(charKey, profileName)
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
local snap = MTH_SavedVariables.charSnapshots[charKey]
|
||||||
|
if type(snap) ~= "table" then
|
||||||
|
return false, "no snapshot for " .. tostring(charKey)
|
||||||
|
end
|
||||||
|
local name = (type(profileName) == "string" and string.len(profileName) > 0)
|
||||||
|
and profileName or charKey
|
||||||
|
MTH_SavedVariables.profiles[name] = MTH_Profile_DeepCopy(snap)
|
||||||
|
return true, name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return sorted list of profile names
|
||||||
|
function MTH_Profile_GetList()
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
local list = {}
|
||||||
|
for name, _ in MTH_SavedVariables.profiles do
|
||||||
|
table.insert(list, name)
|
||||||
|
end
|
||||||
|
table.sort(list)
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return sorted list of character snapshot keys
|
||||||
|
function MTH_Profile_GetCharList()
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
local list = {}
|
||||||
|
for charKey, _ in MTH_SavedVariables.charSnapshots do
|
||||||
|
table.insert(list, charKey)
|
||||||
|
end
|
||||||
|
table.sort(list)
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the active profile name for the current character, or nil
|
||||||
|
function MTH_Profile_GetActive()
|
||||||
|
if type(MTH_CharSavedVariables) == "table" then
|
||||||
|
return MTH_CharSavedVariables.activeProfile
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Auto-snapshot on logout so other characters can import this config
|
||||||
|
local MTH_ProfileEventFrame = CreateFrame("Frame", "MTH_ProfileEventFrame")
|
||||||
|
MTH_ProfileEventFrame:RegisterEvent("PLAYER_LOGOUT")
|
||||||
|
MTH_ProfileEventFrame:SetScript("OnEvent", function()
|
||||||
|
if event == "PLAYER_LOGOUT" then
|
||||||
|
MTH_Profile_EnsureStore()
|
||||||
|
MTH_SavedVariables.charSnapshots[MTH_Profile_GetCharKey()] = MTH_Profile_BuildSnapshot()
|
||||||
|
end
|
||||||
|
end)
|
||||||
+7
-8
@@ -65,11 +65,10 @@ local function MTH_UIR_CreateControl(frame, key, option, context, x, y, width)
|
|||||||
checkButton:SetPoint("TOPLEFT", frame, "TOPLEFT", x, y + 2)
|
checkButton:SetPoint("TOPLEFT", frame, "TOPLEFT", x, y + 2)
|
||||||
checkButton:SetChecked(MTH_UI.ResolveValue(option.get, context) and 1 or nil)
|
checkButton:SetChecked(MTH_UI.ResolveValue(option.get, context) and 1 or nil)
|
||||||
MTH_UIR_SetCheckboxLabel(checkButton, optionName or "")
|
MTH_UIR_SetCheckboxLabel(checkButton, optionName or "")
|
||||||
checkButton:SetScript("OnClick", function(self)
|
checkButton:SetScript("OnClick", function()
|
||||||
self = self or this
|
if not this then return end
|
||||||
if not self then return end
|
|
||||||
if option.set then
|
if option.set then
|
||||||
option.set(context, self:GetChecked() == 1)
|
option.set(context, this:GetChecked() == 1)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
if MTH_UI.ResolveValue(option.disabled, context) then
|
if MTH_UI.ResolveValue(option.disabled, context) then
|
||||||
@@ -100,8 +99,8 @@ local function MTH_UIR_CreateControl(frame, key, option, context, x, y, width)
|
|||||||
text:SetText(optionName or "Run")
|
text:SetText(optionName or "Run")
|
||||||
text:SetTextColor(1.00, 0.82, 0.00)
|
text:SetTextColor(1.00, 0.82, 0.00)
|
||||||
|
|
||||||
button:SetScript("OnEnter", function(self) self = self or this if self then self:SetBackdropBorderColor(0.6, 0.6, 0.6) end end)
|
button:SetScript("OnEnter", function() if this then this:SetBackdropBorderColor(0.6, 0.6, 0.6) end end)
|
||||||
button:SetScript("OnLeave", function(self) self = self or this if self then self:SetBackdropBorderColor(0.4, 0.4, 0.4) end end)
|
button:SetScript("OnLeave", function() if this then this:SetBackdropBorderColor(0.4, 0.4, 0.4) end end)
|
||||||
button:SetScript("OnClick", function()
|
button:SetScript("OnClick", function()
|
||||||
if option.func then
|
if option.func then
|
||||||
option.func(context)
|
option.func(context)
|
||||||
@@ -139,8 +138,8 @@ local function MTH_UIR_CreateControl(frame, key, option, context, x, y, width)
|
|||||||
text:SetText(tostring(currentValue or "Choose"))
|
text:SetText(tostring(currentValue or "Choose"))
|
||||||
text:SetTextColor(0.90, 0.90, 0.90)
|
text:SetTextColor(0.90, 0.90, 0.90)
|
||||||
|
|
||||||
button:SetScript("OnEnter", function(self) self = self or this if self then self:SetBackdropBorderColor(0.6, 0.6, 0.6) end end)
|
button:SetScript("OnEnter", function() if this then this:SetBackdropBorderColor(0.6, 0.6, 0.6) end end)
|
||||||
button:SetScript("OnLeave", function(self) self = self or this if self then self:SetBackdropBorderColor(0.4, 0.4, 0.4) end end)
|
button:SetScript("OnLeave", function() if this then this:SetBackdropBorderColor(0.4, 0.4, 0.4) end end)
|
||||||
button:SetScript("OnClick", function()
|
button:SetScript("OnClick", function()
|
||||||
if option.onClick then
|
if option.onClick then
|
||||||
option.onClick(context, option)
|
option.onClick(context, option)
|
||||||
|
|||||||
+10
-4
@@ -6,10 +6,11 @@ VC.abbrev = "MTH"
|
|||||||
VC.channelName = "LFT"
|
VC.channelName = "LFT"
|
||||||
VC.updateUrl = "https://github.com/DuvelCorp/MetaHunt"
|
VC.updateUrl = "https://github.com/DuvelCorp/MetaHunt"
|
||||||
VC.nextPublishAt = nil
|
VC.nextPublishAt = nil
|
||||||
|
VC.lastPublishedAt = nil
|
||||||
VC.joinAt = nil
|
VC.joinAt = nil
|
||||||
VC.notified = false
|
VC.notified = false
|
||||||
VC._invalidVersionWarned = false
|
VC._invalidVersionWarned = false
|
||||||
VC.maxPersistedPeers = 200
|
VC.maxPersistedPeers = 10000
|
||||||
VC.seenPeers = VC.seenPeers or {}
|
VC.seenPeers = VC.seenPeers or {}
|
||||||
|
|
||||||
local function VC_GetTimeNow()
|
local function VC_GetTimeNow()
|
||||||
@@ -140,7 +141,7 @@ end
|
|||||||
function VC:PrunePersistedPeers(limit)
|
function VC:PrunePersistedPeers(limit)
|
||||||
local maxCount = tonumber(limit) or tonumber(self.maxPersistedPeers) or 200
|
local maxCount = tonumber(limit) or tonumber(self.maxPersistedPeers) or 200
|
||||||
if maxCount <= 0 then
|
if maxCount <= 0 then
|
||||||
maxCount = 200
|
maxCount = 10000
|
||||||
end
|
end
|
||||||
if type(self.seenPeers) ~= "table" then
|
if type(self.seenPeers) ~= "table" then
|
||||||
return
|
return
|
||||||
@@ -219,7 +220,11 @@ function VC:GetTrackedPeers()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function VC:ResetPublishDelay()
|
function VC:ResetPublishDelay()
|
||||||
self.nextPublishAt = VC_GetTimeNow() + math.random(10, 20)
|
local now = VC_GetTimeNow()
|
||||||
|
if self.lastPublishedAt and (now - self.lastPublishedAt) < 3600 then
|
||||||
|
return -- 1-hour cooldown between publishes
|
||||||
|
end
|
||||||
|
self.nextPublishAt = now + math.random(10, 20)
|
||||||
end
|
end
|
||||||
|
|
||||||
function VC:ShouldPublish()
|
function VC:ShouldPublish()
|
||||||
@@ -247,6 +252,7 @@ function VC:TryPublish()
|
|||||||
end
|
end
|
||||||
local payload = self.abbrev .. ":" .. tostring(localVersionNumber) .. ":v"
|
local payload = self.abbrev .. ":" .. tostring(localVersionNumber) .. ":v"
|
||||||
SendChatMessage(payload, "CHANNEL", nil, tostring(channelId))
|
SendChatMessage(payload, "CHANNEL", nil, tostring(channelId))
|
||||||
|
self.lastPublishedAt = VC_GetTimeNow()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -305,7 +311,7 @@ function VC:HandleRemoteMessage(message, author, channelLabel)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not VC.frame then
|
if not VC.frame then
|
||||||
local frame = CreateFrame("Frame", "MTHVersionCheckFrame", UIParent)
|
local frame = CreateFrame("Frame", "MTH_VersionCheck", UIParent)
|
||||||
if frame then
|
if frame then
|
||||||
VC.frame = frame
|
VC.frame = frame
|
||||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,329 @@
|
|||||||
|
-- MetaHunt: Beast family DBC enrichment (scales, food validation)
|
||||||
|
-- AUTO-GENERATED by .tools — do not edit by hand.
|
||||||
|
-- Source DBC(s): CreatureFamily.dbc, ItemPetFood.dbc
|
||||||
|
-- Generated: 2026-03-20 13:57 UTC
|
||||||
|
|
||||||
|
if not MTH_DS_Families then return end
|
||||||
|
|
||||||
|
-- DBC ID=1 PetFoodMask=208 scale=[0.70-1.00]
|
||||||
|
if MTH_DS_Families["Wolves"] then
|
||||||
|
MTH_DS_Families["Wolves"]["dbcId"] = 1
|
||||||
|
MTH_DS_Families["Wolves"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Wolves"]["maxScale"] = 1.0
|
||||||
|
MTH_DS_Families["Wolves"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Wolves"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Wolves"]["foodMask"] = 208
|
||||||
|
MTH_DS_Families["Wolves"]["foodDbc"] = {
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=2 PetFoodMask=209 scale=[0.70-1.10]
|
||||||
|
if MTH_DS_Families["Cats"] then
|
||||||
|
MTH_DS_Families["Cats"]["dbcId"] = 2
|
||||||
|
MTH_DS_Families["Cats"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Cats"]["maxScale"] = 1.1
|
||||||
|
MTH_DS_Families["Cats"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Cats"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Cats"]["foodMask"] = 209
|
||||||
|
MTH_DS_Families["Cats"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=3 PetFoodMask=203 scale=[0.40-0.60]
|
||||||
|
if MTH_DS_Families["Spiders"] then
|
||||||
|
MTH_DS_Families["Spiders"]["dbcId"] = 3
|
||||||
|
MTH_DS_Families["Spiders"]["minScale"] = 0.4
|
||||||
|
MTH_DS_Families["Spiders"]["maxScale"] = 0.6
|
||||||
|
MTH_DS_Families["Spiders"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Spiders"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Spiders"]["foodMask"] = 203
|
||||||
|
MTH_DS_Families["Spiders"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"fish",
|
||||||
|
"bread",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=4 PetFoodMask=210 scale=[0.60-1.00]
|
||||||
|
if MTH_DS_Families["Bears"] then
|
||||||
|
MTH_DS_Families["Bears"]["dbcId"] = 4
|
||||||
|
MTH_DS_Families["Bears"]["minScale"] = 0.6
|
||||||
|
MTH_DS_Families["Bears"]["maxScale"] = 1.0
|
||||||
|
MTH_DS_Families["Bears"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Bears"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Bears"]["foodMask"] = 210
|
||||||
|
MTH_DS_Families["Bears"]["foodDbc"] = {
|
||||||
|
"bread",
|
||||||
|
"cheese",
|
||||||
|
"fish",
|
||||||
|
"fruit",
|
||||||
|
"fungus",
|
||||||
|
"meat",
|
||||||
|
"raw fish",
|
||||||
|
"raw meat",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=5 PetFoodMask=211 scale=[0.60-1.00]
|
||||||
|
if MTH_DS_Families["Boars"] then
|
||||||
|
MTH_DS_Families["Boars"]["dbcId"] = 5
|
||||||
|
MTH_DS_Families["Boars"]["minScale"] = 0.6
|
||||||
|
MTH_DS_Families["Boars"]["maxScale"] = 1.0
|
||||||
|
MTH_DS_Families["Boars"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Boars"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Boars"]["foodMask"] = 211
|
||||||
|
MTH_DS_Families["Boars"]["foodDbc"] = {
|
||||||
|
"bread",
|
||||||
|
"cheese",
|
||||||
|
"fish",
|
||||||
|
"fruit",
|
||||||
|
"fungus",
|
||||||
|
"meat",
|
||||||
|
"raw fish",
|
||||||
|
"raw meat",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=6 PetFoodMask=212 scale=[0.40-0.60]
|
||||||
|
if MTH_DS_Families["Crocolisks"] then
|
||||||
|
MTH_DS_Families["Crocolisks"]["dbcId"] = 6
|
||||||
|
MTH_DS_Families["Crocolisks"]["minScale"] = 0.4
|
||||||
|
MTH_DS_Families["Crocolisks"]["maxScale"] = 0.6
|
||||||
|
MTH_DS_Families["Crocolisks"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Crocolisks"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Crocolisks"]["foodMask"] = 212
|
||||||
|
MTH_DS_Families["Crocolisks"]["foodDbc"] = {
|
||||||
|
"cheese",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=7 PetFoodMask=213 scale=[0.50-0.90]
|
||||||
|
if MTH_DS_Families["Carrion Birds"] then
|
||||||
|
MTH_DS_Families["Carrion Birds"]["dbcId"] = 7
|
||||||
|
MTH_DS_Families["Carrion Birds"]["minScale"] = 0.5
|
||||||
|
MTH_DS_Families["Carrion Birds"]["maxScale"] = 0.9
|
||||||
|
MTH_DS_Families["Carrion Birds"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Carrion Birds"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Carrion Birds"]["foodMask"] = 213
|
||||||
|
MTH_DS_Families["Carrion Birds"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"cheese",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=8 PetFoodMask=214 scale=[0.70-1.40]
|
||||||
|
if MTH_DS_Families["Crabs"] then
|
||||||
|
MTH_DS_Families["Crabs"]["dbcId"] = 8
|
||||||
|
MTH_DS_Families["Crabs"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Crabs"]["maxScale"] = 1.4
|
||||||
|
MTH_DS_Families["Crabs"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Crabs"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Crabs"]["foodMask"] = 214
|
||||||
|
MTH_DS_Families["Crabs"]["foodDbc"] = {
|
||||||
|
"fish",
|
||||||
|
"cheese",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=9 PetFoodMask=215 scale=[0.70-1.00]
|
||||||
|
if MTH_DS_Families["Gorillas"] then
|
||||||
|
MTH_DS_Families["Gorillas"]["dbcId"] = 9
|
||||||
|
MTH_DS_Families["Gorillas"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Gorillas"]["maxScale"] = 1.0
|
||||||
|
MTH_DS_Families["Gorillas"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Gorillas"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Gorillas"]["foodMask"] = 215
|
||||||
|
MTH_DS_Families["Gorillas"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"fish",
|
||||||
|
"cheese",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=11 PetFoodMask=217 scale=[0.50-0.80]
|
||||||
|
if MTH_DS_Families["Raptors"] then
|
||||||
|
MTH_DS_Families["Raptors"]["dbcId"] = 11
|
||||||
|
MTH_DS_Families["Raptors"]["minScale"] = 0.5
|
||||||
|
MTH_DS_Families["Raptors"]["maxScale"] = 0.8
|
||||||
|
MTH_DS_Families["Raptors"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Raptors"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Raptors"]["foodMask"] = 217
|
||||||
|
MTH_DS_Families["Raptors"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"bread",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=12 PetFoodMask=218 scale=[0.50-0.80]
|
||||||
|
if MTH_DS_Families["Tallstriders"] then
|
||||||
|
MTH_DS_Families["Tallstriders"]["dbcId"] = 12
|
||||||
|
MTH_DS_Families["Tallstriders"]["minScale"] = 0.5
|
||||||
|
MTH_DS_Families["Tallstriders"]["maxScale"] = 0.8
|
||||||
|
MTH_DS_Families["Tallstriders"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Tallstriders"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Tallstriders"]["foodMask"] = 218
|
||||||
|
MTH_DS_Families["Tallstriders"]["foodDbc"] = {
|
||||||
|
"fish",
|
||||||
|
"bread",
|
||||||
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=20 PetFoodMask=236 scale=[0.70-1.00]
|
||||||
|
if MTH_DS_Families["Scorpids"] then
|
||||||
|
MTH_DS_Families["Scorpids"]["dbcId"] = 20
|
||||||
|
MTH_DS_Families["Scorpids"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Scorpids"]["maxScale"] = 1.0
|
||||||
|
MTH_DS_Families["Scorpids"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Scorpids"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Scorpids"]["foodMask"] = 236
|
||||||
|
MTH_DS_Families["Scorpids"]["foodDbc"] = {
|
||||||
|
"cheese",
|
||||||
|
"bread",
|
||||||
|
"fruit",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=21 PetFoodMask=251 scale=[0.50-0.80]
|
||||||
|
if MTH_DS_Families["Turtles"] then
|
||||||
|
MTH_DS_Families["Turtles"]["dbcId"] = 21
|
||||||
|
MTH_DS_Families["Turtles"]["minScale"] = 0.5
|
||||||
|
MTH_DS_Families["Turtles"]["maxScale"] = 0.8
|
||||||
|
MTH_DS_Families["Turtles"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Turtles"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Turtles"]["foodMask"] = 251
|
||||||
|
MTH_DS_Families["Turtles"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"fish",
|
||||||
|
"bread",
|
||||||
|
"fungus",
|
||||||
|
"fruit",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=24 PetFoodMask=653 scale=[0.40-0.70]
|
||||||
|
if MTH_DS_Families["Bats"] then
|
||||||
|
MTH_DS_Families["Bats"]["dbcId"] = 24
|
||||||
|
MTH_DS_Families["Bats"]["minScale"] = 0.4
|
||||||
|
MTH_DS_Families["Bats"]["maxScale"] = 0.7
|
||||||
|
MTH_DS_Families["Bats"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Bats"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Bats"]["foodMask"] = 653
|
||||||
|
MTH_DS_Families["Bats"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"cheese",
|
||||||
|
"bread",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=25 PetFoodMask=654 scale=[0.70-0.90]
|
||||||
|
if MTH_DS_Families["Hyenas"] then
|
||||||
|
MTH_DS_Families["Hyenas"]["dbcId"] = 25
|
||||||
|
MTH_DS_Families["Hyenas"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Hyenas"]["maxScale"] = 0.9
|
||||||
|
MTH_DS_Families["Hyenas"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Hyenas"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Hyenas"]["foodMask"] = 654
|
||||||
|
MTH_DS_Families["Hyenas"]["foodDbc"] = {
|
||||||
|
"fish",
|
||||||
|
"cheese",
|
||||||
|
"bread",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=26 PetFoodMask=655 scale=[0.50-0.80]
|
||||||
|
if MTH_DS_Families["Owls"] then
|
||||||
|
MTH_DS_Families["Owls"]["dbcId"] = 26
|
||||||
|
MTH_DS_Families["Owls"]["minScale"] = 0.5
|
||||||
|
MTH_DS_Families["Owls"]["maxScale"] = 0.8
|
||||||
|
MTH_DS_Families["Owls"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Owls"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Owls"]["foodMask"] = 655
|
||||||
|
MTH_DS_Families["Owls"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"fish",
|
||||||
|
"cheese",
|
||||||
|
"bread",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=27 PetFoodMask=656 scale=[0.50-0.70]
|
||||||
|
if MTH_DS_Families["Wind Serpents"] then
|
||||||
|
MTH_DS_Families["Wind Serpents"]["dbcId"] = 27
|
||||||
|
MTH_DS_Families["Wind Serpents"]["minScale"] = 0.5
|
||||||
|
MTH_DS_Families["Wind Serpents"]["maxScale"] = 0.7
|
||||||
|
MTH_DS_Families["Wind Serpents"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Wind Serpents"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Wind Serpents"]["foodMask"] = 656
|
||||||
|
MTH_DS_Families["Wind Serpents"]["foodDbc"] = {
|
||||||
|
"fungus",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=35 PetFoodMask=1009 scale=[0.60-0.80]
|
||||||
|
if MTH_DS_Families["Serpents"] then
|
||||||
|
MTH_DS_Families["Serpents"]["dbcId"] = 35
|
||||||
|
MTH_DS_Families["Serpents"]["minScale"] = 0.6
|
||||||
|
MTH_DS_Families["Serpents"]["maxScale"] = 0.8
|
||||||
|
MTH_DS_Families["Serpents"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Serpents"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Serpents"]["foodMask"] = 1009
|
||||||
|
MTH_DS_Families["Serpents"]["foodDbc"] = {
|
||||||
|
"meat",
|
||||||
|
"fungus",
|
||||||
|
"fruit",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DBC ID=36 PetFoodMask=1010 scale=[0.70-0.90]
|
||||||
|
if MTH_DS_Families["Foxes"] then
|
||||||
|
MTH_DS_Families["Foxes"]["dbcId"] = 36
|
||||||
|
MTH_DS_Families["Foxes"]["minScale"] = 0.7
|
||||||
|
MTH_DS_Families["Foxes"]["maxScale"] = 0.9
|
||||||
|
MTH_DS_Families["Foxes"]["minScaleLevel"] = 1
|
||||||
|
MTH_DS_Families["Foxes"]["maxScaleLevel"] = 60
|
||||||
|
MTH_DS_Families["Foxes"]["foodMask"] = 1010
|
||||||
|
MTH_DS_Families["Foxes"]["foodDbc"] = {
|
||||||
|
"fish",
|
||||||
|
"fungus",
|
||||||
|
"fruit",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
|
}
|
||||||
|
end
|
||||||
@@ -6,8 +6,10 @@ if not MTH_DS then MTH_DS = {} end
|
|||||||
|
|
||||||
MTH_DS_Families = {
|
MTH_DS_Families = {
|
||||||
["Bats"] = {
|
["Bats"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Bat",
|
||||||
["named"] = 20,
|
["named"] = 20,
|
||||||
["coords"] = 18,
|
["coords"] = 18,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1, ["damage"] = 1.07 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"fruit",
|
"fruit",
|
||||||
"fungus",
|
"fungus",
|
||||||
@@ -21,8 +23,10 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Bears"] = {
|
["Bears"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Bear",
|
||||||
["named"] = 45,
|
["named"] = 45,
|
||||||
["coords"] = 45,
|
["coords"] = 45,
|
||||||
|
["stats"] = { ["health"] = 1.08, ["armor"] = 1.05, ["damage"] = 0.91 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fish",
|
"fish",
|
||||||
@@ -30,6 +34,8 @@ MTH_DS_Families = {
|
|||||||
"cheese",
|
"cheese",
|
||||||
"fruit",
|
"fruit",
|
||||||
"fungus",
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -40,8 +46,10 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Boars"] = {
|
["Boars"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Boar",
|
||||||
["named"] = 45,
|
["named"] = 45,
|
||||||
["coords"] = 87,
|
["coords"] = 87,
|
||||||
|
["stats"] = { ["health"] = 1.04, ["armor"] = 1.09, ["damage"] = 0.9 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fish",
|
"fish",
|
||||||
@@ -49,6 +57,8 @@ MTH_DS_Families = {
|
|||||||
"cheese",
|
"cheese",
|
||||||
"fruit",
|
"fruit",
|
||||||
"fungus",
|
"fungus",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -59,10 +69,13 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Carrion Birds"] = {
|
["Carrion Birds"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Vulture",
|
||||||
["named"] = 36,
|
["named"] = 36,
|
||||||
["coords"] = 101,
|
["coords"] = 101,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1.05, ["damage"] = 1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -74,11 +87,15 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Cats"] = {
|
["Cats"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Cat",
|
||||||
["named"] = 85,
|
["named"] = 85,
|
||||||
["coords"] = 88,
|
["coords"] = 88,
|
||||||
|
["stats"] = { ["health"] = 0.98, ["armor"] = 1, ["damage"] = 1.1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fish",
|
"fish",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -90,13 +107,16 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Crabs"] = {
|
["Crabs"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Crab",
|
||||||
["named"] = 32,
|
["named"] = 32,
|
||||||
["coords"] = 74,
|
["coords"] = 74,
|
||||||
|
["stats"] = { ["health"] = 0.96, ["armor"] = 1.13, ["damage"] = 0.95 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"fruit",
|
"fruit",
|
||||||
"fish",
|
"fish",
|
||||||
"fungus",
|
"fungus",
|
||||||
"bread",
|
"bread",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bubble Barrier",
|
"Bubble Barrier",
|
||||||
@@ -106,11 +126,15 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Crocolisks"] = {
|
["Crocolisks"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Crocolisk",
|
||||||
["named"] = 27,
|
["named"] = 27,
|
||||||
["coords"] = 71,
|
["coords"] = 71,
|
||||||
|
["stats"] = { ["health"] = 0.95, ["armor"] = 1.1, ["damage"] = 1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fish",
|
"fish",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -120,11 +144,14 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Foxes"] = {
|
["Foxes"] = {
|
||||||
|
["icon"] = "ability_hunter_aspectofthefox",
|
||||||
["named"] = 9,
|
["named"] = 9,
|
||||||
["coords"] = 51,
|
["coords"] = 51,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1, ["damage"] = 1.07 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fruit",
|
"fruit",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -135,8 +162,10 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Gorillas"] = {
|
["Gorillas"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Gorilla",
|
||||||
["named"] = 24,
|
["named"] = 24,
|
||||||
["coords"] = 117,
|
["coords"] = 117,
|
||||||
|
["stats"] = { ["health"] = 1.04, ["armor"] = 1, ["damage"] = 1.02 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"fruit",
|
"fruit",
|
||||||
"fungus",
|
"fungus",
|
||||||
@@ -149,11 +178,14 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Hyenas"] = {
|
["Hyenas"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Hyena",
|
||||||
["named"] = 26,
|
["named"] = 26,
|
||||||
["coords"] = 36,
|
["coords"] = 36,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1.05, ["damage"] = 1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fruit",
|
"fruit",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -164,10 +196,13 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Owls"] = {
|
["Owls"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Owl",
|
||||||
["named"] = 16,
|
["named"] = 16,
|
||||||
["coords"] = 59,
|
["coords"] = 59,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1, ["damage"] = 1.07 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Claw",
|
"Claw",
|
||||||
@@ -178,10 +213,13 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Raptors"] = {
|
["Raptors"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Raptor",
|
||||||
["named"] = 51,
|
["named"] = 51,
|
||||||
["coords"] = 115,
|
["coords"] = 115,
|
||||||
|
["stats"] = { ["health"] = 0.95, ["armor"] = 1.03, ["damage"] = 1.1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -193,10 +231,13 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Scorpids"] = {
|
["Scorpids"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Scorpid",
|
||||||
["named"] = 38,
|
["named"] = 38,
|
||||||
["coords"] = 36,
|
["coords"] = 36,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1.1, ["damage"] = 0.94 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Claw",
|
"Claw",
|
||||||
@@ -205,12 +246,16 @@ MTH_DS_Families = {
|
|||||||
"Scorpid Poison",
|
"Scorpid Poison",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Serpents (Cobra)"] = {
|
["Serpents"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Serpent1",
|
||||||
["named"] = 10,
|
["named"] = 10,
|
||||||
["coords"] = 13,
|
["coords"] = 13,
|
||||||
|
["stats"] = { ["health"] = 1.03, ["armor"] = 1.03, ["damage"] = 1.135 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
"fish",
|
"fish",
|
||||||
|
"raw meat",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -220,10 +265,13 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Spiders"] = {
|
["Spiders"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Spider",
|
||||||
["named"] = 91,
|
["named"] = 91,
|
||||||
["coords"] = 213,
|
["coords"] = 213,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1, ["damage"] = 1.07 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -233,8 +281,10 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Tallstriders"] = {
|
["Tallstriders"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_TallStrider",
|
||||||
["named"] = 15,
|
["named"] = 15,
|
||||||
["coords"] = 112,
|
["coords"] = 112,
|
||||||
|
["stats"] = { ["health"] = 1.05, ["armor"] = 1, ["damage"] = 1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"fruit",
|
"fruit",
|
||||||
"fungus",
|
"fungus",
|
||||||
@@ -249,12 +299,15 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Turtles"] = {
|
["Turtles"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Turtle",
|
||||||
["named"] = 25,
|
["named"] = 25,
|
||||||
["coords"] = 42,
|
["coords"] = 42,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1.13, ["damage"] = 0.9 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"fruit",
|
"fruit",
|
||||||
"fish",
|
"fish",
|
||||||
"fungus",
|
"fungus",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -264,12 +317,15 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Wind Serpents"] = {
|
["Wind Serpents"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_WindSerpent",
|
||||||
["named"] = 27,
|
["named"] = 27,
|
||||||
["coords"] = 42,
|
["coords"] = 42,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1, ["damage"] = 1.07 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"fish",
|
"fish",
|
||||||
"cheese",
|
"cheese",
|
||||||
"bread",
|
"bread",
|
||||||
|
"raw fish",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -280,10 +336,13 @@ MTH_DS_Families = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
["Wolves"] = {
|
["Wolves"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Wolf",
|
||||||
["named"] = 81,
|
["named"] = 81,
|
||||||
["coords"] = 99,
|
["coords"] = 99,
|
||||||
|
["stats"] = { ["health"] = 1, ["armor"] = 1.05, ["damage"] = 1 },
|
||||||
["food"] = {
|
["food"] = {
|
||||||
"meat",
|
"meat",
|
||||||
|
"raw meat",
|
||||||
},
|
},
|
||||||
["abilities"] = {
|
["abilities"] = {
|
||||||
"Bite",
|
"Bite",
|
||||||
@@ -293,4 +352,21 @@ MTH_DS_Families = {
|
|||||||
"Growl",
|
"Growl",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
-- ── Added TWoW 1.18.1 "Nightmares of Ursol" ──────────────────
|
||||||
|
["Moths"] = {
|
||||||
|
["icon"] = "Ability_Hunter_Pet_Moth", -- TODO: confirm MPQ icon name
|
||||||
|
["named"] = 0,
|
||||||
|
["coords"] = 0,
|
||||||
|
["food"] = {
|
||||||
|
"fruit",
|
||||||
|
"fungus",
|
||||||
|
},
|
||||||
|
["abilities"] = {
|
||||||
|
"Bite",
|
||||||
|
"Cower",
|
||||||
|
"Growl",
|
||||||
|
"Pollen Burst", -- family unique: 40 Focus, Instant, 30s CD
|
||||||
|
-- Heals party 308-338 (30yd), -20% atk speed targets (10yd, 8s)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,890 @@
|
|||||||
|
-- MetaHunt: Beast appearance skin variants per family
|
||||||
|
-- AUTO-GENERATED by .tools — do not edit by hand.
|
||||||
|
-- Source DBC(s): CreatureDisplayInfo.dbc, CreatureModelData.dbc
|
||||||
|
-- Generated: 2026-03-23 15:09 UTC
|
||||||
|
-- Total skins: 258 across 20 families
|
||||||
|
|
||||||
|
if not MTH_DS then MTH_DS = {} end
|
||||||
|
|
||||||
|
MTH_DS_BeastSkins = {
|
||||||
|
["Bats"] = {
|
||||||
|
{id=1954, tex="BatSkin01", unique=false, modelPath="Creature\\FelBat\\FelBat.mdx"},
|
||||||
|
{id=3956, tex="BatSkinBrown01", unique=false, modelPath="Creature\\FelBat\\FelBat.mdx"},
|
||||||
|
{id=4185, tex="BatSkinViolet01", unique=false, modelPath="Creature\\FelBat\\FelBat.mdx"},
|
||||||
|
{id=4735, tex="BatSkinWhite01", unique=false, modelPath="Creature\\FelBat\\FelBat.mdx"},
|
||||||
|
{id=15191, tex="MobatSkinBlue01", unique=true, modelPath="Creature\\mobat\\Mobat.mdx"},
|
||||||
|
},
|
||||||
|
["Bears"] = {
|
||||||
|
{id=706, tex="BearSkinBlack", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=806, tex="BearSkinBlue", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=820, tex="BearSkinDrkBrown", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=822, tex="BearSkinBrown", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=865, tex="BearSkinWhite", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=1082, tex="BearSkinBlackDiseased", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=1083, tex="BearSkinDrkBrownDiseased", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=9492, tex="BearSkinrex2", unique=false, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=18352, tex="PolarBearCubSkin", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=19113, tex="FatherBear", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=20635, tex="BearSkinBrownDiseased", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=20636, tex="BearSkinBlueDiseased", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=20637, tex="BearSkinWhiteDiseased", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=21549, tex="bearskinblue2", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
{id=21550, tex="bearskinblue3", unique=true, modelPath="Creature\\bear\\Bear.mdx"},
|
||||||
|
},
|
||||||
|
["Boars"] = {
|
||||||
|
{id=193, tex="BoarSkinIvory", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=377, tex="BoarSkinBrown", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=381, tex="BoarSkinBlue", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=2450, tex="BoarSkinIvoryArmored", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=3026, tex="BoarSkinCrimson", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=4713, tex="BoarSkinBrownArmored", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=4714, tex="BoarSkinBlueArmored", unique=true, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=6121, tex="BoarSkinUndead", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=8869, tex="BoarSkinYellow", unique=false, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=18729, tex="QuillBeastBlue", unique=true, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
{id=20504, tex="BoarSkinQuel", unique=true, modelPath="Creature\\Boar\\Boar.mdx"},
|
||||||
|
},
|
||||||
|
["Carrion Birds"] = {
|
||||||
|
{id=388, tex="CarrionBirdSkin", unique=false, modelPath="Creature\\CarrionBird\\CarrionBird.mdx"},
|
||||||
|
{id=410, tex="CarrionBirdSkinBrown", unique=false, modelPath="Creature\\CarrionBird\\CarrionBird.mdx"},
|
||||||
|
{id=490, tex="CarrionBirdSkinRed", unique=false, modelPath="Creature\\CarrionBird\\CarrionBird.mdx"},
|
||||||
|
{id=507, tex="CarrionBirdSkinBlue", unique=false, modelPath="Creature\\CarrionBird\\CarrionBird.mdx"},
|
||||||
|
{id=18390, tex="CarrionBirdSkinWhite", unique=true, modelPath="Creature\\CarrionBird\\CarrionBird.mdx"},
|
||||||
|
},
|
||||||
|
["Cats"] = {
|
||||||
|
{id=320, tex="TigerSkinRed", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=321, tex="TigerSkinBlackStriped", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=599, tex="TigerSkinBlack", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=616, tex="TigerSkinWhite", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=632, tex="TigerSkinYellow", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=748, tex="TigerSkinSnow", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=892, tex="DruidCatSkinBlack", unique=true, modelPath="Creature\\DruidCat\\DruidCat.mdx"},
|
||||||
|
{id=1056, tex="TigerSkinBrown", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=1057, tex="LionSkinGold", unique=false, modelPath="Creature\\Lion\\Lion.mdx"},
|
||||||
|
{id=1933, tex="LionessSkinGold", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=1934, tex="LionSkinWhite", unique=false, modelPath="Creature\\Lion\\Lion.mdx"},
|
||||||
|
{id=3029, tex="TigerSkinDark", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=4424, tex="LionSkinBlack", unique=true, modelPath="Creature\\Lion\\Lion.mdx"},
|
||||||
|
{id=5448, tex="MaineCoon", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=5554, tex="OrangeTabby", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=5555, tex="SilverTabby", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=5556, tex="Bombay", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=5585, tex="Birman", unique=false, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=5586, tex="CornishRex", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=9209, tex="Cringer", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=9230, tex="TigerSkinGreen", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=9949, tex="TigerSkinIce", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=9954, tex="RidingTigerSkinLavender", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=9956, tex="RidingTigerSkinWhitenosaddle", unique=false, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=9958, tex="TigerSkinNostripeWhite", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=9989, tex="White", unique=false, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=10054, tex="RidingTigerSkinAqua", unique=false, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=11448, tex="TigerSkinBlackSpotted", unique=false, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=11709, tex="Salome", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=18027, tex="LynxSkinRed", unique=true, modelPath="Creature\\DruidCat\\DruidCat.mdx"},
|
||||||
|
{id=18028, tex="LynxSkinYellow", unique=true, modelPath="Creature\\DruidCat\\DruidCat.mdx"},
|
||||||
|
{id=18389, tex="Boots", unique=true, modelPath="Creature\\Cat\\Cat.mdx"},
|
||||||
|
{id=18426, tex="RidingTigerSkinYellownosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18427, tex="RidingTigerSkinIcenosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18428, tex="RidingTigerSkinRednosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18429, tex="RidingTigerSkinSnownosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18430, tex="RidingTigerSkinGoldnosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18431, tex="RidingTigerSkinBrownnosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18432, tex="RidingTigerSkinBlacknosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18433, tex="RidingTigerSkinDarknosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=18434, tex="RidingTigerSkinNostripeWhitenosaddle", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20388, tex="TIGERSKINBLACKGEM", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20389, tex="TigerSkinDiamond", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20390, tex="TigerSkinJade", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20391, tex="TigerSkinRuby", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20392, tex="TigerSkinSaphire", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20393, tex="TigerSkinTurquoise", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
{id=20410, tex="LionessSkinEmerald", unique=true, modelPath="Creature\\Tiger\\Tiger.mdx"},
|
||||||
|
{id=20437, tex="RidingTigerSkinDarknosaddle.blp", unique=true, modelPath="Creature\\FrostSabre\\FrostSabre.mdx"},
|
||||||
|
},
|
||||||
|
["Crabs"] = {
|
||||||
|
{id=342, tex="CrabSkinBronze", unique=false, modelPath="Creature\\Crab\\Crab.mdx"},
|
||||||
|
{id=979, tex="CrabSkinSaphire", unique=false, modelPath="Creature\\Crab\\Crab.mdx"},
|
||||||
|
{id=981, tex="CrabSkinIvory", unique=false, modelPath="Creature\\Crab\\Crab.mdx"},
|
||||||
|
{id=1307, tex="CrabSkinVermillian", unique=false, modelPath="Creature\\Crab\\Crab.mdx"},
|
||||||
|
{id=18757, tex="CrabSkinDarkDiamond", unique=true, modelPath="Creature\\Crab\\Crab.mdx"},
|
||||||
|
{id=18758, tex="CrabSkinTrueSilver", unique=true, modelPath="Creature\\Crab\\Crab.mdx"},
|
||||||
|
},
|
||||||
|
["Crocolisks"] = {
|
||||||
|
{id=807, tex="CrocodileSkinSwamp", unique=false, modelPath="Creature\\Crocodile\\Crocodile.mdx"},
|
||||||
|
{id=833, tex="CrocodileSkinRiver", unique=false, modelPath="Creature\\Crocodile\\Crocodile.mdx"},
|
||||||
|
{id=925, tex="CrocodileSkinMarsh", unique=false, modelPath="Creature\\Crocodile\\Crocodile.mdx"},
|
||||||
|
{id=1609, tex="CrocodileSkinAlbino", unique=false, modelPath="Creature\\Crocodile\\Crocodile.mdx"},
|
||||||
|
},
|
||||||
|
["Foxes"] = {
|
||||||
|
{id=18004, tex="MistFoxSkin", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=18005, tex="MistFoxSkinArctic", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=18006, tex="MistFoxSkinBlack", unique=false, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=18007, tex="MistFoxSkinBrown", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=18008, tex="MistFoxSkinRed", unique=false, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=18244, tex="MistFoxSkinSpirit", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=18773, tex="MistFoxSkinPink", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=19105, tex="MistFoxSkinEvil", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=19106, tex="MistFoxSkinGolden", unique=true, modelPath="Creature\\Mistfox\\Mistfox.mdx"},
|
||||||
|
{id=21282, tex="fox2_black", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21283, tex="fox2_blue", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21284, tex="fox2_darkred", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21285, tex="fox2_green", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21286, tex="fox2_orange", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21287, tex="fox2_purple", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21288, tex="fox2_red", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21289, tex="fox2_teal", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
{id=21290, tex="fox2_white", unique=true, modelPath="Creature\\fox2\\fox2.mdx"},
|
||||||
|
},
|
||||||
|
["Gorillas"] = {
|
||||||
|
{id=792, tex="GorillaSkinSilver", unique=false, modelPath="Creature\\Gorilla\\Gorilla.mdx"},
|
||||||
|
{id=809, tex="GorillaSkinBlack", unique=false, modelPath="Creature\\Gorilla\\Gorilla.mdx"},
|
||||||
|
{id=838, tex="GorillaSkinGrey", unique=false, modelPath="Creature\\Gorilla\\Gorilla.mdx"},
|
||||||
|
{id=840, tex="GorillaSkinWhite", unique=false, modelPath="Creature\\Gorilla\\Gorilla.mdx"},
|
||||||
|
{id=3186, tex="GorillaSkinRed", unique=false, modelPath="Creature\\Gorilla\\Gorilla.mdx"},
|
||||||
|
{id=8841, tex="GorillaSkinAmy", unique=true, modelPath="Creature\\Gorilla\\Gorilla.mdx"},
|
||||||
|
},
|
||||||
|
["Hyenas"] = {
|
||||||
|
{id=1534, tex="HyenaSkinOarnge", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
{id=1536, tex="HyenaSkin", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
{id=2709, tex="HyenaSkinRed", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
{id=2710, tex="HyenaSkinYellow", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
{id=2713, tex="HyenaSkinBlue", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
{id=2714, tex="HyenaSkinWhite", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
{id=2726, tex="HyenaSkinBlack", unique=false, modelPath="Creature\\Hyena\\Hyena.mdx"},
|
||||||
|
},
|
||||||
|
["Moths"] = {
|
||||||
|
{id=21298, tex="mothardenwealdmount_blue", unique=true, modelPath="Creature\\mothardenwealdmount\\mothardenwealdmount.mdx"},
|
||||||
|
{id=21299, tex="mothardenwealdmount_dark", unique=true, modelPath="Creature\\mothardenwealdmount\\mothardenwealdmount.mdx"},
|
||||||
|
{id=21300, tex="mothardenwealdmount_mint", unique=true, modelPath="Creature\\mothardenwealdmount\\mothardenwealdmount.mdx"},
|
||||||
|
{id=21301, tex="mothardenwealdmount_red", unique=true, modelPath="Creature\\mothardenwealdmount\\mothardenwealdmount.mdx"},
|
||||||
|
{id=21431, tex="MothSkinBeige", unique=true, modelPath="Creature\\Moth\\Moth.mdx"},
|
||||||
|
{id=21432, tex="MothSkinBlue", unique=true, modelPath="Creature\\Moth\\Moth.mdx"},
|
||||||
|
{id=21433, tex="mothskingrey", unique=true, modelPath="Creature\\Moth\\Moth.mdx"},
|
||||||
|
{id=21434, tex="MothSkinRed", unique=true, modelPath="Creature\\Moth\\Moth.mdx"},
|
||||||
|
{id=21435, tex="MothSkinWhite", unique=true, modelPath="Creature\\Moth\\Moth.mdx"},
|
||||||
|
{id=21436, tex="mothskinyellow", unique=true, modelPath="Creature\\Moth\\Moth.mdx"},
|
||||||
|
},
|
||||||
|
["Owls"] = {
|
||||||
|
{id=4566, tex="OwlBrown", unique=false, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=4877, tex="OwlGrey", unique=false, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=6212, tex="OwlWhite", unique=false, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=6298, tex="OwlBlue", unique=true, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=6299, tex="OwlBlack", unique=true, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=18338, tex="Eagle", unique=false, modelPath="Creature\\Eagle\\Eagle.mdx"},
|
||||||
|
{id=18339, tex="BrownEagle", unique=true, modelPath="Creature\\Eagle\\Eagle.mdx"},
|
||||||
|
{id=18368, tex="OwlSpirit", unique=true, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=18746, tex="EagleRaven", unique=true, modelPath="Creature\\Eagle\\Eagle.mdx"},
|
||||||
|
{id=21109, tex="OwlRuby", unique=true, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
{id=21110, tex="OwlSapphire", unique=true, modelPath="Creature\\Owl\\Owl.mdx"},
|
||||||
|
},
|
||||||
|
["Raptors"] = {
|
||||||
|
{id=180, tex="RaptorSkinOrange", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=322, tex="RaptorSkinMottledDarkGreen", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=675, tex="RaptorSkinMottledBlueGreen", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=787, tex="RaptorSkinYellow", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=960, tex="RaptorSkinViolet", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=1337, tex="RaptorSkinGrey", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=1959, tex="RaptorSkinRed", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
{id=5291, tex="RidingRaptorSkinObsidian", unique=false, modelPath="Creature\\Raptor\\Raptor.mdx"},
|
||||||
|
},
|
||||||
|
["Scorpids"] = {
|
||||||
|
{id=2414, tex="ScorpionskinPink", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=2485, tex="ScorpionskinBeige", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=2487, tex="ScorpionskinYellow", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=2488, tex="ScorpionskinBlack", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=2489, tex="ScorpionskinRed", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=2729, tex="ScorpionskinGolden", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=2730, tex="ScorpionskinBlue", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=7469, tex="SilithidScarabSkinBlack", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=8971, tex="SilithidScarabSkinRed", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=9028, tex="SilithidScarabSkinWhite", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=9469, tex="SilithidScarabSkinYellow", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=10983, tex="ScorpionskinSilver", unique=false, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
{id=11093, tex="SilithidScarabSkinTeal", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=11104, tex="SilithidScarabSkinGold", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=11107, tex="SilithidScarabSkinPurple", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=11143, tex="SilithidScarabSkinTan", unique=false, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=18373, tex="SilithidScarabSkinGreen", unique=true, modelPath="Creature\\SILITHIDSCARAB\\SilithidScarab.mdx"},
|
||||||
|
{id=21268, tex="ScorpionskinDarkIron", unique=true, modelPath="Creature\\Scorpion\\Scorpion.mdx"},
|
||||||
|
},
|
||||||
|
["Serpents"] = {
|
||||||
|
{id=1206, tex="SnakeSkinBlack", unique=false, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=1986, tex="SnakeSkinDarkGreenYellow", unique=false, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=1987, tex="SnakeSkinYellowBlack", unique=false, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=2954, tex="SnakeSkinRedWhiteBlack", unique=true, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=2955, tex="SnakeSkinWhite", unique=false, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=2956, tex="SnakeSkinBlue", unique=false, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=2957, tex="SnakeSkinBrown", unique=true, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=2958, tex="SnakeSkinGreen", unique=false, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=4305, tex="SerpantSkinWhite", unique=false, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=4312, tex="SerpantSkinPurple", unique=false, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=4317, tex="SerpantSkinBlue", unique=false, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=4435, tex="SerpantSkinGreen", unique=false, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=6303, tex="SnakeSkinRed", unique=true, modelPath="Creature\\snake\\snake.mdx"},
|
||||||
|
{id=11034, tex="SerpantSkinOlive", unique=false, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=15182, tex="SerpantSkinBrown", unique=true, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=20633, tex="SerpantSkinViolet", unique=true, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=20634, tex="SerpantSkinRuby", unique=true, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
{id=21269, tex="SerpentSkinRuby", unique=true, modelPath="Creature\\Serpent\\Serpent.mdx"},
|
||||||
|
},
|
||||||
|
["Spiders"] = {
|
||||||
|
{id=30, tex="MineSpiderSkinSteel", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=283, tex="MineSpiderSkinGreen", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=336, tex="TarantulaSkinGreen", unique=false, modelPath="Creature\\Tarantula\\Tarantula.mdx"},
|
||||||
|
{id=366, tex="TarantulaSkinOrange", unique=false, modelPath="Creature\\Tarantula\\Tarantula.mdx"},
|
||||||
|
{id=513, tex="MineSpiderSkinOlive", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=520, tex="TarantulaSkinBrown", unique=false, modelPath="Creature\\Tarantula\\Tarantula.mdx"},
|
||||||
|
{id=711, tex="MineSpiderSkinWetLands", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=955, tex="MineSpiderSkinCave", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=963, tex="MineSpiderSkinBlood", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=1091, tex="TarantulaSkinGrey", unique=false, modelPath="Creature\\Tarantula\\Tarantula.mdx"},
|
||||||
|
{id=2536, tex="MineSpiderSkinJungle", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=4456, tex="MineSpiderSkinCrystal", unique=false, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
{id=4457, tex="TarantulaSkinMagma", unique=false, modelPath="Creature\\Tarantula\\Tarantula.mdx"},
|
||||||
|
{id=15937, tex="MineSpiderSkinViolet", unique=true, modelPath="Creature\\MineSpider\\MineSpider.mdx"},
|
||||||
|
},
|
||||||
|
["Tallstriders"] = {
|
||||||
|
{id=38, tex="TallStriderSkinTurquoise", unique=false, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=178, tex="TallStriderSkinBrown", unique=false, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=1220, tex="TallStriderSkinGray", unique=false, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=1221, tex="TallStriderSkinIvory", unique=false, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=1281, tex="TallStriderSkinPurple", unique=true, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=1961, tex="TallStriderSkinPink", unique=true, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=20509, tex="HawkstriderBlue", unique=true, modelPath="Creature\\Hawkstrider\\Hawkstrider.mdx"},
|
||||||
|
{id=20510, tex="HawkstriderGold", unique=true, modelPath="Creature\\Hawkstrider\\Hawkstrider.mdx"},
|
||||||
|
{id=20511, tex="HawkstriderGreen", unique=true, modelPath="Creature\\Hawkstrider\\Hawkstrider.mdx"},
|
||||||
|
{id=20512, tex="HawkstriderRed", unique=true, modelPath="Creature\\Hawkstrider\\Hawkstrider.mdx"},
|
||||||
|
{id=20513, tex="HawkstriderWhite", unique=true, modelPath="Creature\\Hawkstrider\\Hawkstrider.mdx"},
|
||||||
|
{id=21554, tex="TallStriderSkinBlue", unique=true, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
{id=21555, tex="TallStriderSkinViolet", unique=true, modelPath="Creature\\Tallstrider\\TallStrider.mdx"},
|
||||||
|
},
|
||||||
|
["Turtles"] = {
|
||||||
|
{id=1244, tex="SeaTurtleSkin", unique=false, modelPath="Creature\\SeaTurtle\\SeaTurtle.mdx"},
|
||||||
|
{id=2307, tex="SeaTurtleSkinWhite", unique=false, modelPath="Creature\\SeaTurtle\\SeaTurtle.mdx"},
|
||||||
|
{id=4829, tex="SeaTurtleSkinGrey", unique=false, modelPath="Creature\\SeaTurtle\\SeaTurtle.mdx"},
|
||||||
|
{id=5026, tex="SeaTurtleSkinRed", unique=false, modelPath="Creature\\SeaTurtle\\SeaTurtle.mdx"},
|
||||||
|
{id=5126, tex="SeaTurtleSkinBlue", unique=false, modelPath="Creature\\SeaTurtle\\SeaTurtle.mdx"},
|
||||||
|
{id=16259, tex="TurtleSkinGreen", unique=false, modelPath="Creature\\Turtle\\Turtle.mdx"},
|
||||||
|
{id=16360, tex="TurtleSkinBrown", unique=true, modelPath="Creature\\Turtle\\Turtle.mdx"},
|
||||||
|
{id=16361, tex="TurtleSkinBlack", unique=true, modelPath="Creature\\Turtle\\Turtle.mdx"},
|
||||||
|
},
|
||||||
|
["Wind Serpents"] = {
|
||||||
|
{id=1336, tex="WindSerpentSkin", unique=false, modelPath="Creature\\WindSerpent\\WindSerpent.mdx"},
|
||||||
|
{id=2699, tex="WindSerpentSkinRed", unique=false, modelPath="Creature\\WindSerpent\\WindSerpent.mdx"},
|
||||||
|
{id=2700, tex="WindSerpentSkinGreen", unique=false, modelPath="Creature\\WindSerpent\\WindSerpent.mdx"},
|
||||||
|
{id=2703, tex="WindSerpentSkinWhite", unique=false, modelPath="Creature\\WindSerpent\\WindSerpent.mdx"},
|
||||||
|
{id=3006, tex="WindSerpentSkinBlack", unique=false, modelPath="Creature\\WindSerpent\\WindSerpent.mdx"},
|
||||||
|
{id=18386, tex="WindSerpentSkinOarnge", unique=true, modelPath="Creature\\WindSerpent\\WindSerpent.mdx"},
|
||||||
|
{id=20514, tex="ManaWurmSkinBlack", unique=true, modelPath="Creature\\Manawurm\\manawurm.mdx"},
|
||||||
|
{id=20515, tex="MANAWURMSKINGREEN", unique=true, modelPath="Creature\\Manawurm\\manawurm.mdx"},
|
||||||
|
{id=20516, tex="ManaWurmSkinPurple", unique=true, modelPath="Creature\\Manawurm\\manawurm.mdx"},
|
||||||
|
{id=20517, tex="ManaWurmSkinQuel", unique=true, modelPath="Creature\\Manawurm\\manawurm.mdx"},
|
||||||
|
{id=20518, tex="ManaWurmSkinSilver1", unique=true, modelPath="Creature\\Manawurm\\manawurm.mdx"},
|
||||||
|
{id=20519, tex="ManaWurmSkinWhite", unique=true, modelPath="Creature\\Manawurm\\manawurm.mdx"},
|
||||||
|
},
|
||||||
|
["Wolves"] = {
|
||||||
|
{id=73, tex="Direwolfskinbrown", unique=true, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=161, tex="WolfSkinCoyote", unique=false, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=165, tex="WolfSkinTimber", unique=false, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=246, tex="DireWolfSkinDarkBlack", unique=false, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=644, tex="WolfSkinBlack", unique=false, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=720, tex="DireWolfSkinLightBlue", unique=false, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=776, tex="WolfSkinArctic", unique=false, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=868, tex="WolfSkinArcticAlpha", unique=true, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=1950, tex="WolfSkin_Ghost", unique=true, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=3916, tex="HoundSkinBlue", unique=false, modelPath="Creature\\DarkHound\\DarkHound.mdx"},
|
||||||
|
{id=4124, tex="WolfSkinDiseased", unique=false, modelPath="Creature\\Wolf\\Wolf.mdx"},
|
||||||
|
{id=6195, tex="HoundSkinGrey", unique=false, modelPath="Creature\\DarkHound\\DarkHound.mdx"},
|
||||||
|
{id=7890, tex="HoundSkinPurple", unique=false, modelPath="Creature\\DarkHound\\DarkHound.mdx"},
|
||||||
|
{id=8180, tex="HoundSkinRed", unique=false, modelPath="Creature\\DarkHound\\DarkHound.mdx"},
|
||||||
|
{id=9369, tex="DireWolfSkinReddishBrown", unique=false, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=9564, tex="DireWolfSkinLightGrey", unique=false, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=9567, tex="DireWolfSkinBlueBrown", unique=true, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=9568, tex="DireWolfSkinDarkBrown", unique=false, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=11414, tex="DireWolfSkinDarkGrey", unique=true, modelPath="Creature\\DireWolf\\DireWolf.mdx"},
|
||||||
|
{id=14312, tex="HoundSkinWhite", unique=false, modelPath="Creature\\DarkHound\\DarkHound.mdx"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Maps any beast displayId to the canonical skin id used in MTH_DS_BeastSkins
|
||||||
|
-- Total: 577 entries
|
||||||
|
MTH_DS_DisplayToSkin = {
|
||||||
|
[368] = 30,
|
||||||
|
[372] = 165,
|
||||||
|
[380] = 165,
|
||||||
|
[382] = 366,
|
||||||
|
[389] = 193,
|
||||||
|
[418] = 30,
|
||||||
|
[447] = 165,
|
||||||
|
[471] = 320,
|
||||||
|
[498] = 366,
|
||||||
|
[499] = 193,
|
||||||
|
[503] = 193,
|
||||||
|
[538] = 513,
|
||||||
|
[539] = 30,
|
||||||
|
[545] = 283,
|
||||||
|
[557] = 161,
|
||||||
|
[566] = 520,
|
||||||
|
[598] = 320,
|
||||||
|
[604] = 165,
|
||||||
|
[607] = 381,
|
||||||
|
[613] = 599,
|
||||||
|
[614] = 320,
|
||||||
|
[615] = 322,
|
||||||
|
[633] = 599,
|
||||||
|
[641] = 342,
|
||||||
|
[643] = 161,
|
||||||
|
[647] = 165,
|
||||||
|
[648] = 322,
|
||||||
|
[649] = 180,
|
||||||
|
[651] = 366,
|
||||||
|
[659] = 513,
|
||||||
|
[666] = 165,
|
||||||
|
[670] = 180,
|
||||||
|
[671] = 180,
|
||||||
|
[672] = 180,
|
||||||
|
[673] = 180,
|
||||||
|
[674] = 322,
|
||||||
|
[676] = 322,
|
||||||
|
[677] = 675,
|
||||||
|
[695] = 322,
|
||||||
|
[698] = 320,
|
||||||
|
[699] = 342,
|
||||||
|
[703] = 377,
|
||||||
|
[704] = 377,
|
||||||
|
[707] = 706,
|
||||||
|
[709] = 336,
|
||||||
|
[719] = 706,
|
||||||
|
[741] = 246,
|
||||||
|
[744] = 381,
|
||||||
|
[749] = 748,
|
||||||
|
[755] = 675,
|
||||||
|
[759] = 336,
|
||||||
|
[760] = 336,
|
||||||
|
[762] = 706,
|
||||||
|
[768] = 283,
|
||||||
|
[780] = 644,
|
||||||
|
[781] = 644,
|
||||||
|
[782] = 644,
|
||||||
|
[783] = 165,
|
||||||
|
[784] = 644,
|
||||||
|
[785] = 776,
|
||||||
|
[788] = 180,
|
||||||
|
[801] = 776,
|
||||||
|
[802] = 776,
|
||||||
|
[814] = 807,
|
||||||
|
[815] = 807,
|
||||||
|
[821] = 520,
|
||||||
|
[827] = 520,
|
||||||
|
[831] = 807,
|
||||||
|
[834] = 833,
|
||||||
|
[835] = 807,
|
||||||
|
[837] = 792,
|
||||||
|
[839] = 809,
|
||||||
|
[841] = 792,
|
||||||
|
[842] = 838,
|
||||||
|
[843] = 838,
|
||||||
|
[844] = 792,
|
||||||
|
[845] = 809,
|
||||||
|
[855] = 776,
|
||||||
|
[869] = 776,
|
||||||
|
[902] = 822,
|
||||||
|
[903] = 165,
|
||||||
|
[909] = 520,
|
||||||
|
[910] = 520,
|
||||||
|
[913] = 865,
|
||||||
|
[917] = 632,
|
||||||
|
[918] = 632,
|
||||||
|
[945] = 180,
|
||||||
|
[948] = 180,
|
||||||
|
[949] = 675,
|
||||||
|
[954] = 748,
|
||||||
|
[957] = 283,
|
||||||
|
[958] = 955,
|
||||||
|
[959] = 955,
|
||||||
|
[961] = 787,
|
||||||
|
[982] = 822,
|
||||||
|
[996] = 979,
|
||||||
|
[997] = 981,
|
||||||
|
[998] = 979,
|
||||||
|
[999] = 981,
|
||||||
|
[1000] = 979,
|
||||||
|
[1001] = 981,
|
||||||
|
[1006] = 822,
|
||||||
|
[1007] = 806,
|
||||||
|
[1008] = 632,
|
||||||
|
[1030] = 720,
|
||||||
|
[1034] = 807,
|
||||||
|
[1035] = 925,
|
||||||
|
[1036] = 925,
|
||||||
|
[1037] = 833,
|
||||||
|
[1038] = 925,
|
||||||
|
[1039] = 833,
|
||||||
|
[1040] = 38,
|
||||||
|
[1041] = 178,
|
||||||
|
[1042] = 178,
|
||||||
|
[1043] = 632,
|
||||||
|
[1055] = 632,
|
||||||
|
[1058] = 1056,
|
||||||
|
[1059] = 1056,
|
||||||
|
[1080] = 807,
|
||||||
|
[1087] = 955,
|
||||||
|
[1088] = 513,
|
||||||
|
[1089] = 513,
|
||||||
|
[1090] = 955,
|
||||||
|
[1094] = 809,
|
||||||
|
[1095] = 599,
|
||||||
|
[1100] = 161,
|
||||||
|
[1103] = 1091,
|
||||||
|
[1104] = 1091,
|
||||||
|
[1105] = 388,
|
||||||
|
[1106] = 388,
|
||||||
|
[1157] = 955,
|
||||||
|
[1160] = 955,
|
||||||
|
[1164] = 161,
|
||||||
|
[1167] = 193,
|
||||||
|
[1192] = 507,
|
||||||
|
[1207] = 776,
|
||||||
|
[1208] = 377,
|
||||||
|
[1210] = 490,
|
||||||
|
[1219] = 178,
|
||||||
|
[1222] = 161,
|
||||||
|
[1228] = 388,
|
||||||
|
[1229] = 388,
|
||||||
|
[1250] = 833,
|
||||||
|
[1251] = 833,
|
||||||
|
[1259] = 180,
|
||||||
|
[1283] = 178,
|
||||||
|
[1284] = 1221,
|
||||||
|
[1338] = 960,
|
||||||
|
[1339] = 1337,
|
||||||
|
[1340] = 1337,
|
||||||
|
[1535] = 1534,
|
||||||
|
[1742] = 1336,
|
||||||
|
[1744] = 960,
|
||||||
|
[1746] = 1337,
|
||||||
|
[1747] = 960,
|
||||||
|
[1873] = 513,
|
||||||
|
[1938] = 1307,
|
||||||
|
[1939] = 1307,
|
||||||
|
[1955] = 1954,
|
||||||
|
[1960] = 1959,
|
||||||
|
[1962] = 1959,
|
||||||
|
[1971] = 1057,
|
||||||
|
[1972] = 1057,
|
||||||
|
[1973] = 1057,
|
||||||
|
[1974] = 1336,
|
||||||
|
[1975] = 1336,
|
||||||
|
[1977] = 1057,
|
||||||
|
[1978] = 1933,
|
||||||
|
[1989] = 336,
|
||||||
|
[1990] = 822,
|
||||||
|
[2031] = 1056,
|
||||||
|
[2239] = 979,
|
||||||
|
[2278] = 1056,
|
||||||
|
[2279] = 616,
|
||||||
|
[2300] = 1056,
|
||||||
|
[2301] = 1536,
|
||||||
|
[2305] = 410,
|
||||||
|
[2308] = 2307,
|
||||||
|
[2352] = 246,
|
||||||
|
[2378] = 822,
|
||||||
|
[2424] = 366,
|
||||||
|
[2433] = 30,
|
||||||
|
[2437] = 599,
|
||||||
|
[2453] = 2450,
|
||||||
|
[2486] = 2485,
|
||||||
|
[2491] = 2488,
|
||||||
|
[2537] = 2536,
|
||||||
|
[2538] = 2536,
|
||||||
|
[2539] = 2536,
|
||||||
|
[2540] = 283,
|
||||||
|
[2541] = 283,
|
||||||
|
[2542] = 366,
|
||||||
|
[2543] = 366,
|
||||||
|
[2544] = 366,
|
||||||
|
[2545] = 366,
|
||||||
|
[2546] = 366,
|
||||||
|
[2548] = 925,
|
||||||
|
[2549] = 925,
|
||||||
|
[2550] = 807,
|
||||||
|
[2570] = 1959,
|
||||||
|
[2571] = 1959,
|
||||||
|
[2573] = 1959,
|
||||||
|
[2574] = 1959,
|
||||||
|
[2609] = 1534,
|
||||||
|
[2702] = 2699,
|
||||||
|
[2705] = 2703,
|
||||||
|
[2706] = 2700,
|
||||||
|
[2707] = 2700,
|
||||||
|
[2708] = 2700,
|
||||||
|
[2711] = 2710,
|
||||||
|
[2712] = 2710,
|
||||||
|
[2715] = 2714,
|
||||||
|
[2716] = 2714,
|
||||||
|
[2731] = 2730,
|
||||||
|
[2732] = 2487,
|
||||||
|
[2741] = 1220,
|
||||||
|
[2765] = 2729,
|
||||||
|
[2766] = 2729,
|
||||||
|
[2850] = 1609,
|
||||||
|
[2864] = 2488,
|
||||||
|
[2902] = 1244,
|
||||||
|
[2995] = 2958,
|
||||||
|
[2996] = 1609,
|
||||||
|
[3027] = 3026,
|
||||||
|
[3030] = 3029,
|
||||||
|
[3031] = 3029,
|
||||||
|
[3035] = 3026,
|
||||||
|
[3126] = 1206,
|
||||||
|
[3187] = 3186,
|
||||||
|
[3188] = 3186,
|
||||||
|
[3200] = 806,
|
||||||
|
[3201] = 806,
|
||||||
|
[3202] = 165,
|
||||||
|
[3203] = 165,
|
||||||
|
[3204] = 2699,
|
||||||
|
[3205] = 2699,
|
||||||
|
[3247] = 2489,
|
||||||
|
[3248] = 490,
|
||||||
|
[4065] = 2699,
|
||||||
|
[4090] = 1609,
|
||||||
|
[4091] = 2700,
|
||||||
|
[4167] = 2956,
|
||||||
|
[4268] = 1206,
|
||||||
|
[4343] = 1986,
|
||||||
|
[4440] = 1987,
|
||||||
|
[4442] = 960,
|
||||||
|
[4458] = 4457,
|
||||||
|
[4472] = 748,
|
||||||
|
[4480] = 4312,
|
||||||
|
[4613] = 161,
|
||||||
|
[4615] = 4566,
|
||||||
|
[4636] = 2710,
|
||||||
|
[4689] = 2709,
|
||||||
|
[4716] = 4713,
|
||||||
|
[4732] = 3956,
|
||||||
|
[4733] = 4185,
|
||||||
|
[4734] = 3956,
|
||||||
|
[4767] = 4317,
|
||||||
|
[4768] = 4435,
|
||||||
|
[5027] = 5026,
|
||||||
|
[5030] = 5026,
|
||||||
|
[5052] = 2307,
|
||||||
|
[5066] = 1933,
|
||||||
|
[5067] = 599,
|
||||||
|
[5068] = 3029,
|
||||||
|
[5069] = 632,
|
||||||
|
[5127] = 5126,
|
||||||
|
[5242] = 960,
|
||||||
|
[5244] = 792,
|
||||||
|
[5245] = 838,
|
||||||
|
[5290] = 675,
|
||||||
|
[5292] = 960,
|
||||||
|
[5294] = 792,
|
||||||
|
[5295] = 838,
|
||||||
|
[5296] = 838,
|
||||||
|
[5510] = 822,
|
||||||
|
[5557] = 342,
|
||||||
|
[5558] = 981,
|
||||||
|
[5559] = 979,
|
||||||
|
[5560] = 1307,
|
||||||
|
[5905] = 2488,
|
||||||
|
[5966] = 4305,
|
||||||
|
[5985] = 2489,
|
||||||
|
[6068] = 2488,
|
||||||
|
[6069] = 2488,
|
||||||
|
[6070] = 2488,
|
||||||
|
[6073] = 1091,
|
||||||
|
[6076] = 1220,
|
||||||
|
[6082] = 1056,
|
||||||
|
[6122] = 6121,
|
||||||
|
[6126] = 1244,
|
||||||
|
[6196] = 6195,
|
||||||
|
[6210] = 616,
|
||||||
|
[6213] = 1091,
|
||||||
|
[6214] = 1091,
|
||||||
|
[6248] = 616,
|
||||||
|
[6300] = 4877,
|
||||||
|
[6368] = 5126,
|
||||||
|
[6468] = 5291,
|
||||||
|
[6805] = 3029,
|
||||||
|
[6807] = 3026,
|
||||||
|
[6808] = 336,
|
||||||
|
[6942] = 1056,
|
||||||
|
[6943] = 599,
|
||||||
|
[7046] = 5126,
|
||||||
|
[7114] = 5126,
|
||||||
|
[7339] = 644,
|
||||||
|
[7347] = 2489,
|
||||||
|
[7348] = 490,
|
||||||
|
[7349] = 490,
|
||||||
|
[7409] = 1206,
|
||||||
|
[7470] = 7469,
|
||||||
|
[7510] = 4457,
|
||||||
|
[7511] = 7469,
|
||||||
|
[7569] = 2703,
|
||||||
|
[7619] = 7469,
|
||||||
|
[7691] = 2703,
|
||||||
|
[7829] = 3006,
|
||||||
|
[7836] = 4829,
|
||||||
|
[7837] = 4829,
|
||||||
|
[7839] = 4829,
|
||||||
|
[7840] = 4829,
|
||||||
|
[7891] = 7890,
|
||||||
|
[7892] = 7890,
|
||||||
|
[7893] = 7890,
|
||||||
|
[7894] = 4185,
|
||||||
|
[7896] = 1954,
|
||||||
|
[7897] = 4185,
|
||||||
|
[7906] = 2699,
|
||||||
|
[8014] = 520,
|
||||||
|
[8050] = 2714,
|
||||||
|
[8129] = 840,
|
||||||
|
[8173] = 2955,
|
||||||
|
[8174] = 1987,
|
||||||
|
[8181] = 8180,
|
||||||
|
[8271] = 4456,
|
||||||
|
[8472] = 675,
|
||||||
|
[8473] = 960,
|
||||||
|
[8808] = 4185,
|
||||||
|
[8837] = 865,
|
||||||
|
[8838] = 806,
|
||||||
|
[8839] = 792,
|
||||||
|
[8840] = 806,
|
||||||
|
[8842] = 865,
|
||||||
|
[8843] = 706,
|
||||||
|
[8844] = 3186,
|
||||||
|
[8870] = 381,
|
||||||
|
[8871] = 8869,
|
||||||
|
[8969] = 2487,
|
||||||
|
[8970] = 2487,
|
||||||
|
[9019] = 8180,
|
||||||
|
[9020] = 3916,
|
||||||
|
[9021] = 3916,
|
||||||
|
[9022] = 7890,
|
||||||
|
[9029] = 9028,
|
||||||
|
[9050] = 675,
|
||||||
|
[9074] = 1954,
|
||||||
|
[9276] = 1083,
|
||||||
|
[9277] = 1083,
|
||||||
|
[9278] = 4124,
|
||||||
|
[9280] = 4124,
|
||||||
|
[9287] = 644,
|
||||||
|
[9354] = 7469,
|
||||||
|
[9370] = 9369,
|
||||||
|
[9371] = 9369,
|
||||||
|
[9372] = 9369,
|
||||||
|
[9509] = 644,
|
||||||
|
[9511] = 644,
|
||||||
|
[9535] = 3956,
|
||||||
|
[9558] = 644,
|
||||||
|
[9562] = 246,
|
||||||
|
[9563] = 246,
|
||||||
|
[9565] = 981,
|
||||||
|
[9566] = 979,
|
||||||
|
[9569] = 9568,
|
||||||
|
[9570] = 342,
|
||||||
|
[9571] = 342,
|
||||||
|
[9572] = 9568,
|
||||||
|
[9573] = 979,
|
||||||
|
[9749] = 2488,
|
||||||
|
[9750] = 4735,
|
||||||
|
[9755] = 4456,
|
||||||
|
[9756] = 4456,
|
||||||
|
[9829] = 513,
|
||||||
|
[9910] = 30,
|
||||||
|
[9913] = 2699,
|
||||||
|
[9929] = 4456,
|
||||||
|
[9934] = 336,
|
||||||
|
[9950] = 9949,
|
||||||
|
[9951] = 9949,
|
||||||
|
[9953] = 616,
|
||||||
|
[9955] = 9949,
|
||||||
|
[9957] = 9949,
|
||||||
|
[9990] = 9989,
|
||||||
|
[9992] = 9230,
|
||||||
|
[9993] = 9230,
|
||||||
|
[9997] = 4456,
|
||||||
|
[10015] = 193,
|
||||||
|
[10031] = 8971,
|
||||||
|
[10033] = 1954,
|
||||||
|
[10055] = 1934,
|
||||||
|
[10113] = 10054,
|
||||||
|
[10114] = 1934,
|
||||||
|
[10133] = 840,
|
||||||
|
[10183] = 2699,
|
||||||
|
[10209] = 246,
|
||||||
|
[10270] = 2726,
|
||||||
|
[10271] = 2726,
|
||||||
|
[10273] = 507,
|
||||||
|
[10274] = 776,
|
||||||
|
[10278] = 720,
|
||||||
|
[10618] = 865,
|
||||||
|
[10824] = 388,
|
||||||
|
[10825] = 410,
|
||||||
|
[10826] = 507,
|
||||||
|
[10827] = 490,
|
||||||
|
[10828] = 6212,
|
||||||
|
[10829] = 4877,
|
||||||
|
[10830] = 4877,
|
||||||
|
[10831] = 4877,
|
||||||
|
[10832] = 4877,
|
||||||
|
[10833] = 6212,
|
||||||
|
[10902] = 2726,
|
||||||
|
[10903] = 2713,
|
||||||
|
[10904] = 2713,
|
||||||
|
[10947] = 2307,
|
||||||
|
[10984] = 2487,
|
||||||
|
[10985] = 2487,
|
||||||
|
[10986] = 2414,
|
||||||
|
[10987] = 2414,
|
||||||
|
[10988] = 10983,
|
||||||
|
[10991] = 2700,
|
||||||
|
[11029] = 320,
|
||||||
|
[11031] = 320,
|
||||||
|
[11032] = 3956,
|
||||||
|
[11089] = 9469,
|
||||||
|
[11094] = 11093,
|
||||||
|
[11098] = 2485,
|
||||||
|
[11105] = 11104,
|
||||||
|
[11108] = 11107,
|
||||||
|
[11144] = 11143,
|
||||||
|
[11315] = 1959,
|
||||||
|
[11316] = 787,
|
||||||
|
[11317] = 960,
|
||||||
|
[11318] = 675,
|
||||||
|
[11319] = 322,
|
||||||
|
[11348] = 366,
|
||||||
|
[11411] = 246,
|
||||||
|
[11412] = 720,
|
||||||
|
[11413] = 9564,
|
||||||
|
[11415] = 9564,
|
||||||
|
[11416] = 776,
|
||||||
|
[11417] = 9564,
|
||||||
|
[11418] = 9564,
|
||||||
|
[11419] = 9564,
|
||||||
|
[11420] = 9369,
|
||||||
|
[11421] = 246,
|
||||||
|
[11422] = 720,
|
||||||
|
[11444] = 9958,
|
||||||
|
[11445] = 9958,
|
||||||
|
[11446] = 616,
|
||||||
|
[11447] = 320,
|
||||||
|
[11449] = 321,
|
||||||
|
[11450] = 321,
|
||||||
|
[11451] = 1056,
|
||||||
|
[11452] = 599,
|
||||||
|
[11453] = 11448,
|
||||||
|
[11454] = 3029,
|
||||||
|
[11455] = 320,
|
||||||
|
[11829] = 4735,
|
||||||
|
[11908] = 820,
|
||||||
|
[11909] = 820,
|
||||||
|
[11910] = 599,
|
||||||
|
[12151] = 11093,
|
||||||
|
[12156] = 11107,
|
||||||
|
[12157] = 11104,
|
||||||
|
[12159] = 9469,
|
||||||
|
[12433] = 410,
|
||||||
|
[12966] = 2710,
|
||||||
|
[13096] = 7469,
|
||||||
|
[13097] = 10983,
|
||||||
|
[13111] = 963,
|
||||||
|
[13589] = 1609,
|
||||||
|
[14256] = 925,
|
||||||
|
[14313] = 490,
|
||||||
|
[14315] = 822,
|
||||||
|
[14316] = 822,
|
||||||
|
[14318] = 11448,
|
||||||
|
[14319] = 507,
|
||||||
|
[14364] = 9956,
|
||||||
|
[14557] = 11034,
|
||||||
|
[14558] = 4435,
|
||||||
|
[14559] = 4305,
|
||||||
|
[14562] = 3956,
|
||||||
|
[14572] = 599,
|
||||||
|
[14657] = 5126,
|
||||||
|
[14658] = 4829,
|
||||||
|
[14659] = 1244,
|
||||||
|
[14660] = 5026,
|
||||||
|
[14661] = 2307,
|
||||||
|
[14780] = 1954,
|
||||||
|
[14853] = 711,
|
||||||
|
[14935] = 599,
|
||||||
|
[14950] = 955,
|
||||||
|
[14952] = 955,
|
||||||
|
[15072] = 711,
|
||||||
|
[15132] = 4317,
|
||||||
|
[15133] = 4435,
|
||||||
|
[15135] = 4312,
|
||||||
|
[15136] = 711,
|
||||||
|
[15137] = 3006,
|
||||||
|
[15138] = 320,
|
||||||
|
[15145] = 833,
|
||||||
|
[15150] = 4317,
|
||||||
|
[15151] = 320,
|
||||||
|
[15180] = 9369,
|
||||||
|
[15181] = 14312,
|
||||||
|
[15204] = 9369,
|
||||||
|
[15227] = 4735,
|
||||||
|
[15275] = 2699,
|
||||||
|
[15302] = 3186,
|
||||||
|
[15327] = 2489,
|
||||||
|
[15336] = 2485,
|
||||||
|
[15339] = 11104,
|
||||||
|
[15383] = 10983,
|
||||||
|
[15384] = 2729,
|
||||||
|
[15385] = 10983,
|
||||||
|
[15422] = 2730,
|
||||||
|
[15423] = 2730,
|
||||||
|
[15433] = 2488,
|
||||||
|
[15464] = 9028,
|
||||||
|
[15467] = 11104,
|
||||||
|
[15468] = 11143,
|
||||||
|
[15469] = 2485,
|
||||||
|
[15470] = 2729,
|
||||||
|
[15471] = 2489,
|
||||||
|
[15533] = 2414,
|
||||||
|
[15534] = 6212,
|
||||||
|
[15682] = 11107,
|
||||||
|
[15878] = 776,
|
||||||
|
[15929] = 7469,
|
||||||
|
[15938] = 513,
|
||||||
|
[15939] = 2536,
|
||||||
|
[15964] = 14312,
|
||||||
|
[15969] = 3916,
|
||||||
|
[16145] = 5126,
|
||||||
|
[16359] = 16259,
|
||||||
|
[16622] = 5585,
|
||||||
|
[18115] = 9492,
|
||||||
|
[18177] = 18008,
|
||||||
|
[18353] = 18338,
|
||||||
|
[18493] = 18006,
|
||||||
|
[20369] = 18027,
|
||||||
|
[20370] = 1933,
|
||||||
|
[20371] = 11448,
|
||||||
|
[20372] = 321,
|
||||||
|
[20373] = 9230,
|
||||||
|
[20374] = 18432,
|
||||||
|
[20375] = 18431,
|
||||||
|
[20376] = 18433,
|
||||||
|
[20377] = 18430,
|
||||||
|
[20378] = 18427,
|
||||||
|
[20379] = 18434,
|
||||||
|
[20380] = 18428,
|
||||||
|
[20381] = 18429,
|
||||||
|
[20382] = 9956,
|
||||||
|
[20383] = 18426,
|
||||||
|
[20384] = 11448,
|
||||||
|
[20385] = 321,
|
||||||
|
[20386] = 9230,
|
||||||
|
[20387] = 1933,
|
||||||
|
[20394] = 20388,
|
||||||
|
[20395] = 20389,
|
||||||
|
[20396] = 20390,
|
||||||
|
[20397] = 20391,
|
||||||
|
[20398] = 20392,
|
||||||
|
[20399] = 20393,
|
||||||
|
}
|
||||||
+32590
-6387
File diff suppressed because it is too large
Load Diff
+11602
-11602
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,844 @@
|
|||||||
|
-- MetaHunt: Hunter spell data extracted from Spell.dbc (SpellFamilyName=9). Field layout: 173 fields. Indexed by spell ID: MTH_DS_HunterSpellsDBC[spellId]. Named lookup (rank 1): MTH_DS_HunterSpellsByName['SpellName'].
|
||||||
|
-- AUTO-GENERATED by .tools — do not edit by hand.
|
||||||
|
-- Source DBC(s): Spell.dbc, SpellCastTimes.dbc, SpellDuration.dbc, SpellIcon.dbc
|
||||||
|
-- Generated: 2026-03-20 14:10 UTC
|
||||||
|
if not MTH_DS then MTH_DS = {} end
|
||||||
|
|
||||||
|
MTH_DS_HunterSpellsDBC = {}
|
||||||
|
do
|
||||||
|
local t = MTH_DS_HunterSpellsDBC
|
||||||
|
t[19596] = {name="[Deprecated] Bestial Swiftness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19574] = {name="[Deprecated] Bestial Wrath",cast=0,cd=120000,categoryCD=120000,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19500] = {name="[Deprecated] Hawk Eye",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19457] = {name="[Deprecated] Improved Arcane Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19458] = {name="[Deprecated] Improved Arcane Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24386] = {name="[Deprecated] Improved Aspect of the Monkey",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24387] = {name="[Deprecated] Improved Aspect of the Monkey",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19424] = {name="[Deprecated] Improved Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19425] = {name="[Deprecated] Improved Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19494] = {name="[Deprecated] Improved Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19234] = {name="[Deprecated] Improved Wing Clip",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19235] = {name="[Deprecated] Improved Wing Clip",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19374] = {name="[Deprecated] Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19375] = {name="[Deprecated] Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19562] = {name="[Deprecated] Pathfinding",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19563] = {name="[Deprecated] Pathfinding",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[14275] = {name="[Deprecated] Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=6000,manaCost=90,icon="",familyFlags=32768}
|
||||||
|
t[14276] = {name="[Deprecated] Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=3600000,manaCost=125,icon="",familyFlags=32768}
|
||||||
|
t[14277] = {name="[Deprecated] Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=165,icon="",familyFlags=32768}
|
||||||
|
t[19611] = {name="[Deprecated] Thick Hide",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19613] = {name="[Deprecated] Thick Hide",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51520] = {name="[Deprecated] Trueshot Aura Percent Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51521] = {name="[Deprecated] Trueshot Aura Percent Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51522] = {name="[Deprecated] Trueshot Aura Percent Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[28752] = {name="Adrenaline Rush",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19434] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=60000,manaCost=75,icon="",familyFlags=131072}
|
||||||
|
t[20900] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=5000,manaCost=115,icon="",familyFlags=131072}
|
||||||
|
t[20901] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=1000,manaCost=160,icon="",familyFlags=131072}
|
||||||
|
t[20902] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=210,icon="",familyFlags=131072}
|
||||||
|
t[20903] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=260,icon="",familyFlags=131072}
|
||||||
|
t[20904] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=310,icon="",familyFlags=131072}
|
||||||
|
t[27632] = {name="Aimed Shot",cast=3000,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=310,icon="",familyFlags=131072}
|
||||||
|
t[23721] = {name="Arcane Infused",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3044] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=600000,manaCost=25,icon="",familyFlags=2048}
|
||||||
|
t[14281] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=30000,manaCost=35,icon="",familyFlags=2048}
|
||||||
|
t[14282] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=60000,manaCost=50,icon="",familyFlags=2048}
|
||||||
|
t[14283] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=5000,manaCost=80,icon="",familyFlags=2048}
|
||||||
|
t[14284] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=1000,manaCost=105,icon="",familyFlags=2048}
|
||||||
|
t[14285] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=135,icon="",familyFlags=2048}
|
||||||
|
t[14286] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=160,icon="",familyFlags=2048}
|
||||||
|
t[14287] = {name="Arcane Shot",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=190,icon="",familyFlags=2048}
|
||||||
|
t[23157] = {name="Arcane Shot Mana Reduction",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[13161] = {name="Aspect of the Beast",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1800000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[5118] = {name="Aspect of the Cheetah",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=40,icon="",familyFlags=2097152}
|
||||||
|
t[45651] = {name="Aspect of the Fox",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=140,icon="",familyFlags=0}
|
||||||
|
t[13165] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=20,icon="",familyFlags=1048576}
|
||||||
|
t[14318] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=20000,manaCost=35,icon="",familyFlags=1048576}
|
||||||
|
t[14319] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=5000,manaCost=50,icon="",familyFlags=1048576}
|
||||||
|
t[14320] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=11000,manaCost=70,icon="",familyFlags=1048576}
|
||||||
|
t[14321] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=90,icon="",familyFlags=1048576}
|
||||||
|
t[14322] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=110,icon="",familyFlags=1048576}
|
||||||
|
t[25296] = {name="Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=120,icon="",familyFlags=1048576}
|
||||||
|
t[13163] = {name="Aspect of the Monkey",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=20,icon="",familyFlags=524288}
|
||||||
|
t[13159] = {name="Aspect of the Pack",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=100,icon="",familyFlags=2097152}
|
||||||
|
t[45652] = {name="Aspect of the Snake",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[45664] = {name="Aspect of the Snake",cast=0,cd=1500,categoryCD=1500,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45649] = {name="Aspect of the Turtle",cast=0,cd=180000,categoryCD=180000,recoveryCD=0,duration=60000,manaCost=10,icon="",familyFlags=0}
|
||||||
|
t[20043] = {name="Aspect of the Wild",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=90,icon="",familyFlags=0}
|
||||||
|
t[20190] = {name="Aspect of the Wild",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=115,icon="",familyFlags=0}
|
||||||
|
t[45650] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=20,icon="",familyFlags=1048576}
|
||||||
|
t[51496] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=20000,manaCost=35,icon="",familyFlags=1048576}
|
||||||
|
t[51497] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=5000,manaCost=50,icon="",familyFlags=1048576}
|
||||||
|
t[51498] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=11000,manaCost=70,icon="",familyFlags=1048576}
|
||||||
|
t[51499] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=90,icon="",familyFlags=1048576}
|
||||||
|
t[51500] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=110,icon="",familyFlags=1048576}
|
||||||
|
t[51501] = {name="Aspect of the Wolf",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=120,icon="",familyFlags=1048576}
|
||||||
|
t[75] = {name="Auto Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[46023] = {name="Avoidance",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19767] = {name="Aynasha's Bow",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[46321] = {name="Baited Shot",cast=0,cd=8000,categoryCD=8000,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19461] = {name="Barrage",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19462] = {name="Barrage",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24691] = {name="Barrage",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[22996] = {name="Battle Standard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23005] = {name="Battle Standard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23034] = {name="Battle Standard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23035] = {name="Battle Standard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23538] = {name="Battle Standard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23539] = {name="Battle Standard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[47355] = {name="Beast Mastery",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29233] = {name="Beast of the Unseen Path",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19590] = {name="Bestial Discipline",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19592] = {name="Bestial Discipline",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19603] = {name="Bestial Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19605] = {name="Bestial Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19606] = {name="Bestial Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19607] = {name="Bestial Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19608] = {name="Bestial Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51554] = {name="Bestial Precision",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51555] = {name="Bestial Precision",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24395] = {name="Bestial Wrath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24396] = {name="Bestial Wrath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24397] = {name="Bestial Wrath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26592] = {name="Bestial Wrath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[17253] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=10000,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17255] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=15000,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17256] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=230000,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17257] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=160000,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17258] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=6000,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17259] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=1200000,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17260] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[17261] = {name="Bite",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=35,icon="",familyFlags=0}
|
||||||
|
t[36523] = {name="Bubble Barrier",cast=0,cd=30000,categoryCD=0,recoveryCD=30000,duration=60000,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[36524] = {name="Bubble Barrier",cast=0,cd=30000,categoryCD=0,recoveryCD=30000,duration=160000,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[36525] = {name="Bubble Barrier",cast=0,cd=30000,categoryCD=0,recoveryCD=30000,duration=1200000,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[36526] = {name="Bubble Barrier",cast=0,cd=30000,categoryCD=0,recoveryCD=30000,duration=0,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[51575] = {name="Carve",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52415] = {name="Carve",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=11000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52416] = {name="Carve",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24348] = {name="Cheetah Sprint",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3009] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[3010] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[16827] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[16828] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=15000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[16829] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=230000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[16830] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=160000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[16831] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=6000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[16832] = {name="Claw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[19239] = {name="Clever Traps",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19245] = {name="Clever Traps",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[20576] = {name="Command",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[21563] = {name="Command",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[5116] = {name="Concussive Shot",cast=0,cd=12000,categoryCD=12000,recoveryCD=0,duration=15000,manaCost=0,icon="",familyFlags=512}
|
||||||
|
t[23158] = {name="Concussive Shot Cooldown Reduction",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[49559] = {name="Coordinated Assault",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[28317] = {name="Copy of Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[19306] = {name="Counterattack",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=1800000,manaCost=45,icon="",familyFlags=0}
|
||||||
|
t[20909] = {name="Counterattack",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=3600000,manaCost=65,icon="",familyFlags=0}
|
||||||
|
t[20910] = {name="Counterattack",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=0,manaCost=85,icon="",familyFlags=0}
|
||||||
|
t[36548] = {name="Death Roll",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=60000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[36549] = {name="Death Roll",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=60000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[36550] = {name="Death Roll",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=1800000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[36551] = {name="Death Roll",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=1200000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[36552] = {name="Death Roll",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=0,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[36553] = {name="Death Roll",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=0,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[24992] = {name="Demonic Transformation",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23578] = {name="Detect Weakness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19263] = {name="Deterrence",cast=0,cd=300000,categoryCD=300000,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[781] = {name="Disengage",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=60000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[14272] = {name="Disengage",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=0,manaCost=100,icon="",familyFlags=0}
|
||||||
|
t[14273] = {name="Disengage",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=0,manaCost=150,icon="",familyFlags=0}
|
||||||
|
t[14274] = {name="Distracting Shot",cast=0,cd=8000,categoryCD=0,recoveryCD=8000,duration=60000,manaCost=30,icon="",familyFlags=65536}
|
||||||
|
t[15629] = {name="Distracting Shot",cast=0,cd=8000,categoryCD=0,recoveryCD=8000,duration=1800000,manaCost=50,icon="",familyFlags=65536}
|
||||||
|
t[15630] = {name="Distracting Shot",cast=0,cd=8000,categoryCD=0,recoveryCD=8000,duration=1200000,manaCost=70,icon="",familyFlags=65536}
|
||||||
|
t[15631] = {name="Distracting Shot",cast=0,cd=8000,categoryCD=0,recoveryCD=8000,duration=0,manaCost=90,icon="",familyFlags=65536}
|
||||||
|
t[15632] = {name="Distracting Shot",cast=0,cd=8000,categoryCD=0,recoveryCD=8000,duration=0,manaCost=110,icon="",familyFlags=65536}
|
||||||
|
t[20736] = {name="Distracting Shot",cast=0,cd=8000,categoryCD=0,recoveryCD=8000,duration=30000,manaCost=20,icon="",familyFlags=65536}
|
||||||
|
t[19416] = {name="Efficiency",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19417] = {name="Efficiency",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19418] = {name="Efficiency",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19419] = {name="Efficiency",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19420] = {name="Efficiency",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51552] = {name="Elusiveness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51553] = {name="Elusiveness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51517] = {name="Endless Quiver",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51518] = {name="Endless Quiver",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19583] = {name="Endurance Training",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19584] = {name="Endurance Training",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19585] = {name="Endurance Training",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19586] = {name="Endurance Training",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19587] = {name="Endurance Training",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19184] = {name="Entrapment",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19387] = {name="Entrapment",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19388] = {name="Entrapment",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19389] = {name="Entrapment",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19390] = {name="Entrapment",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[13813] = {name="Explosive Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=275,icon="",familyFlags=128}
|
||||||
|
t[14316] = {name="Explosive Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=395,icon="",familyFlags=128}
|
||||||
|
t[14317] = {name="Explosive Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=520,icon="",familyFlags=128}
|
||||||
|
t[13812] = {name="Explosive Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=4}
|
||||||
|
t[14314] = {name="Explosive Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=4}
|
||||||
|
t[14315] = {name="Explosive Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=4}
|
||||||
|
t[51519] = {name="Extra Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[1002] = {name="Eyes of the Beast",cast=2000,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=20,icon="",familyFlags=4194304}
|
||||||
|
t[17331] = {name="Fang of the Crystal Spider",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52402] = {name="Faster Bleeds 5 (Hunter)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[5384] = {name="Feign Death",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=1800000,manaCost=80,icon="Spell_Nature_Regenerate",familyFlags=256}
|
||||||
|
t[19598] = {name="Ferocity",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19599] = {name="Ferocity",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19600] = {name="Ferocity",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19601] = {name="Ferocity",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19602] = {name="Ferocity",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[46269] = {name="Fire Breath",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[46270] = {name="Fire Breath",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=0,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[19781] = {name="Flame Spear",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=75000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[1543] = {name="Flare",cast=0,cd=15000,categoryCD=15000,recoveryCD=0,duration=6000,manaCost=50,icon="Spell_Magic_PolymorphChicken",familyFlags=0}
|
||||||
|
t[1499] = {name="Freezing Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=60000,manaCost=50,icon="",familyFlags=128}
|
||||||
|
t[14310] = {name="Freezing Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=1200000,manaCost=75,icon="",familyFlags=128}
|
||||||
|
t[14311] = {name="Freezing Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=100,icon="",familyFlags=128}
|
||||||
|
t[27753] = {name="Freezing Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=100,icon="Spell_Nature_Regenerate",familyFlags=128}
|
||||||
|
t[21750] = {name="Freezing Trap (TEST)",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=60000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[3355] = {name="Freezing Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=8}
|
||||||
|
t[14308] = {name="Freezing Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=8}
|
||||||
|
t[14309] = {name="Freezing Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=8}
|
||||||
|
t[19621] = {name="Frenzy",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19622] = {name="Frenzy",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19623] = {name="Frenzy",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19624] = {name="Frenzy",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19625] = {name="Frenzy",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[13809] = {name="Frost Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=5000,manaCost=60,icon="",familyFlags=128}
|
||||||
|
t[13810] = {name="Frost Trap Aura",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=5000,manaCost=0,icon="",familyFlags=16}
|
||||||
|
t[14207] = {name="Frost Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=5000,manaCost=0,icon="",familyFlags=16}
|
||||||
|
t[24597] = {name="Furious Howl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=0,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[24603] = {name="Furious Howl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=1200000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[24604] = {name="Furious Howl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=60000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[24605] = {name="Furious Howl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=160000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[46296] = {name="Grace",cast=0,cd=60000,categoryCD=60000,recoveryCD=0,duration=60000,manaCost=10,icon="Spell_Nature_GuardianWard",familyFlags=0}
|
||||||
|
t[14824] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[14825] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[14826] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[14827] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[14828] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[14829] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29413] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29414] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29415] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29416] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29417] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[29418] = {name="Haste",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19498] = {name="Hawk Eye",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19499] = {name="Hawk Eye",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[21942] = {name="Hunter Giant Stalker",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[1130] = {name="Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=600000,manaCost=15,icon="",familyFlags=1024}
|
||||||
|
t[14323] = {name="Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=45000,manaCost=30,icon="",familyFlags=1024}
|
||||||
|
t[14324] = {name="Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=45,icon="",familyFlags=1024}
|
||||||
|
t[14325] = {name="Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=60,icon="",familyFlags=1024}
|
||||||
|
t[13795] = {name="Immolation Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=230000,manaCost=50,icon="",familyFlags=128}
|
||||||
|
t[14302] = {name="Immolation Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=240000,manaCost=90,icon="",familyFlags=128}
|
||||||
|
t[14303] = {name="Immolation Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=1000,manaCost=135,icon="",familyFlags=128}
|
||||||
|
t[14304] = {name="Immolation Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=190,icon="",familyFlags=128}
|
||||||
|
t[14305] = {name="Immolation Trap",cast=0,cd=15000,categoryCD=0,recoveryCD=15000,duration=0,manaCost=245,icon="",familyFlags=128}
|
||||||
|
t[13797] = {name="Immolation Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=230000,manaCost=0,icon="",familyFlags=4}
|
||||||
|
t[14298] = {name="Immolation Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=240000,manaCost=0,icon="Spell_Nature_MoonGlow",familyFlags=4}
|
||||||
|
t[14299] = {name="Immolation Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1000,manaCost=0,icon="Spell_Nature_MoonGlow",familyFlags=4}
|
||||||
|
t[14300] = {name="Immolation Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Nature_MoonGlow",familyFlags=4}
|
||||||
|
t[14301] = {name="Immolation Trap Effect",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Nature_MoonGlow",familyFlags=4}
|
||||||
|
t[15860] = {name="Impale",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="Spell_Holy_Resurrection",familyFlags=1}
|
||||||
|
t[16001] = {name="Impale",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="Spell_Holy_Resurrection",familyFlags=1}
|
||||||
|
t[24049] = {name="Impale",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="Spell_Holy_Resurrection",familyFlags=1}
|
||||||
|
t[26548] = {name="Impale",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="Spell_Holy_Resurrection",familyFlags=1}
|
||||||
|
t[23559] = {name="Improved Aspect of the Hawk",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19407] = {name="Improved Concussive Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19412] = {name="Improved Concussive Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19413] = {name="Improved Concussive Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19414] = {name="Improved Concussive Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19415] = {name="Improved Concussive Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24465] = {name="Improved Concussive Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19378] = {name="Improved Explosive Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19379] = {name="Improved Explosive Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19557] = {name="Improved Eyes of the Beast",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19558] = {name="Improved Eyes of the Beast",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45662] = {name="Improved Eyes of the Beast",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45663] = {name="Improved Eyes of the Beast",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19286] = {name="Improved Feign Death",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19287] = {name="Improved Feign Death",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24432] = {name="Improved Feign Death",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19288] = {name="Improved Freezing Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24298] = {name="Improved Freezing Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24299] = {name="Improved Freezing Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19421] = {name="Improved Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19422] = {name="Improved Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19423] = {name="Improved Hunter's Mark",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19246] = {name="Improved Immolation Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19247] = {name="Improved Immolation Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19248] = {name="Improved Immolation Trap",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19572] = {name="Improved Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19573] = {name="Improved Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23560] = {name="Improved Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24406] = {name="Improved Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19549] = {name="Improved Primal Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19550] = {name="Improved Primal Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19551] = {name="Improved Primal Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19575] = {name="Improved Revive Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24443] = {name="Improved Revive Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19491] = {name="Improved Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19493] = {name="Improved Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24467] = {name="Improved Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51515] = {name="Improved Steady Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51516] = {name="Improved Steady Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19464] = {name="Improved Stings",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19465] = {name="Improved Stings",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19466] = {name="Improved Stings",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19467] = {name="Improved Stings",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19468] = {name="Improved Stings",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52603] = {name="Improved Swift Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[23566] = {name="Improved Volley and Multishot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19228] = {name="Improved Wing Clip",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19232] = {name="Improved Wing Clip",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19233] = {name="Improved Wing Clip",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[22854] = {name="Increased Hunter Pet Damage",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[27205] = {name="Increased Pet Damage +3%",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52413] = {name="Increased Pet Damage +4%",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[41827] = {name="Kill Command",cast=0,cd=12000,categoryCD=12000,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Holy_PrayerOfHealing",familyFlags=0}
|
||||||
|
t[41828] = {name="Kill Command",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19162] = {name="Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19163] = {name="Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19165] = {name="Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19370] = {name="Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19371] = {name="Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19373] = {name="Killer Instinct",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[20907] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=80,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[20908] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=95,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[24118] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=65,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[24119] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=80,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[24120] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=95,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[45653] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=65,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[45654] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=80,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[45655] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=95,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[45656] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45657] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=80,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[45658] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=95,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[48049] = {name="Lacerate",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[48050] = {name="Lacerate",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[24844] = {name="Lightning Breath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=50,icon="Spell_Shadow_GatherShadows",familyFlags=0}
|
||||||
|
t[25008] = {name="Lightning Breath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=30000,manaCost=50,icon="Spell_Shadow_GatherShadows",familyFlags=0}
|
||||||
|
t[25009] = {name="Lightning Breath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=160000,manaCost=50,icon="Spell_Shadow_GatherShadows",familyFlags=0}
|
||||||
|
t[25010] = {name="Lightning Breath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1000,manaCost=50,icon="Spell_Shadow_GatherShadows",familyFlags=0}
|
||||||
|
t[25011] = {name="Lightning Breath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=50,icon="Spell_Shadow_GatherShadows",familyFlags=0}
|
||||||
|
t[25012] = {name="Lightning Breath",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=50,icon="Spell_Shadow_GatherShadows",familyFlags=0}
|
||||||
|
t[19168] = {name="Lightning Reflexes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19180] = {name="Lightning Reflexes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19181] = {name="Lightning Reflexes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24296] = {name="Lightning Reflexes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24297] = {name="Lightning Reflexes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[46297] = {name="Lizard Bolt",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=30000,manaCost=35,icon="Ability_Gouge",familyFlags=0}
|
||||||
|
t[46298] = {name="Lizard Bolt",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=160000,manaCost=35,icon="Ability_Gouge",familyFlags=0}
|
||||||
|
t[46299] = {name="Lizard Bolt",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1000,manaCost=35,icon="Ability_Gouge",familyFlags=0}
|
||||||
|
t[46300] = {name="Lizard Bolt",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=35,icon="Ability_Gouge",familyFlags=0}
|
||||||
|
t[46301] = {name="Lizard Bolt",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=35,icon="Ability_Gouge",familyFlags=0}
|
||||||
|
t[136] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=30000,manaCost=50,icon="",familyFlags=8388608}
|
||||||
|
t[3111] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=90,icon="",familyFlags=8388608}
|
||||||
|
t[3661] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=5000,manaCost=155,icon="",familyFlags=8388608}
|
||||||
|
t[3662] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1000,manaCost=225,icon="",familyFlags=8388608}
|
||||||
|
t[13542] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=300,icon="",familyFlags=8388608}
|
||||||
|
t[13543] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=385,icon="",familyFlags=8388608}
|
||||||
|
t[13544] = {name="Mend Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=480,icon="",familyFlags=8388608}
|
||||||
|
t[1495] = {name="Mongoose Bite",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=230000,manaCost=30,icon="Trade_BrewPoison",familyFlags=2}
|
||||||
|
t[14269] = {name="Mongoose Bite",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=1800000,manaCost=40,icon="Trade_BrewPoison",familyFlags=2}
|
||||||
|
t[14270] = {name="Mongoose Bite",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=0,manaCost=50,icon="Trade_BrewPoison",familyFlags=2}
|
||||||
|
t[14271] = {name="Mongoose Bite",cast=0,cd=5000,categoryCD=0,recoveryCD=5000,duration=0,manaCost=65,icon="Trade_BrewPoison",familyFlags=2}
|
||||||
|
t[19485] = {name="Mortal Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19487] = {name="Mortal Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19488] = {name="Mortal Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19489] = {name="Mortal Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19490] = {name="Mortal Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[2643] = {name="Multi-Shot",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=20000,manaCost=100,icon="",familyFlags=4096}
|
||||||
|
t[14288] = {name="Multi-Shot",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=1800000,manaCost=140,icon="",familyFlags=4096}
|
||||||
|
t[14289] = {name="Multi-Shot",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=3600000,manaCost=175,icon="",familyFlags=4096}
|
||||||
|
t[14290] = {name="Multi-Shot",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=0,manaCost=210,icon="",familyFlags=4096}
|
||||||
|
t[25294] = {name="Multi-Shot",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=0,manaCost=230,icon="",familyFlags=4096}
|
||||||
|
t[28751] = {name="Multi-Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[28539] = {name="Multi-Shot Damage Increase",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52602] = {name="Multishot and Carve Cooldown",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[28761] = {name="Not There",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[36532] = {name="Packleader",cast=0,cd=90000,categoryCD=90000,recoveryCD=0,duration=60000,manaCost=50,icon="INV_Potion_40",familyFlags=0}
|
||||||
|
t[36562] = {name="Packleader",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="INV_Potion_40",familyFlags=0}
|
||||||
|
t[19559] = {name="Pathfinding",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19560] = {name="Pathfinding",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52685] = {name="Pet Focus Regen Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51512] = {name="Piercing Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51513] = {name="Piercing Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51514] = {name="Piercing Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[46292] = {name="Pin",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=230000,manaCost=10,icon="",familyFlags=0}
|
||||||
|
t[46293] = {name="Pin",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=6000,manaCost=10,icon="",familyFlags=0}
|
||||||
|
t[46294] = {name="Pin",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=10,icon="",familyFlags=0}
|
||||||
|
t[46295] = {name="Pin",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=10,icon="",familyFlags=0}
|
||||||
|
t[51576] = {name="Planning Ahead",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51577] = {name="Planning Ahead",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51578] = {name="Planning Ahead Dummy",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[46271] = {name="Poison Spit",cast=0,cd=8000,categoryCD=8000,recoveryCD=8000,duration=300000,manaCost=35,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[46272] = {name="Poison Spit",cast=0,cd=8000,categoryCD=8000,recoveryCD=8000,duration=0,manaCost=35,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[46273] = {name="Poison Spit",cast=0,cd=8000,categoryCD=8000,recoveryCD=8000,duration=0,manaCost=35,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[24450] = {name="Prowl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=1800000,manaCost=40,icon="Spell_Fire_Fireball02",familyFlags=0}
|
||||||
|
t[24452] = {name="Prowl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=1200000,manaCost=40,icon="Spell_Fire_Fireball02",familyFlags=0}
|
||||||
|
t[24453] = {name="Prowl",cast=0,cd=10000,categoryCD=0,recoveryCD=10000,duration=0,manaCost=40,icon="Spell_Fire_Fireball02",familyFlags=0}
|
||||||
|
t[51547] = {name="Quick Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51548] = {name="Quick Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51549] = {name="Quick Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51550] = {name="Quick Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51551] = {name="Quick Shots",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51542] = {name="Quick Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Shadow_ImpPhaseShift",familyFlags=0}
|
||||||
|
t[51543] = {name="Quick Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Shadow_ImpPhaseShift",familyFlags=0}
|
||||||
|
t[51544] = {name="Quick Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Shadow_ImpPhaseShift",familyFlags=0}
|
||||||
|
t[51545] = {name="Quick Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Shadow_ImpPhaseShift",familyFlags=0}
|
||||||
|
t[51546] = {name="Quick Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="Spell_Shadow_ImpPhaseShift",familyFlags=0}
|
||||||
|
t[19511] = {name="Ranged Weapon Specialization",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3045] = {name="Rapid Fire",cast=0,cd=300000,categoryCD=0,recoveryCD=300000,duration=240000,manaCost=100,icon="",familyFlags=32}
|
||||||
|
t[28755] = {name="Rapid Fire",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[2973] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=10000,manaCost=15,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14260] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=15000,manaCost=25,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14261] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=230000,manaCost=35,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14262] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=160000,manaCost=45,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14263] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=6000,manaCost=55,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14264] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=1200000,manaCost=70,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14265] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=85,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[14266] = {name="Raptor Strike",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=100,icon="Spell_Nature_NatureTouchGrow",familyFlags=2}
|
||||||
|
t[23989] = {name="Readiness",cast=0,cd=300000,categoryCD=300000,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51570] = {name="Resourcefulness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51571] = {name="Resourcefulness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51572] = {name="Resourcefulness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51573] = {name="Resourcefulness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51574] = {name="Resourcefulness",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[982] = {name="Revive Pet",cast=10000,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=16777216}
|
||||||
|
t[23499] = {name="Revive Pet",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=16777216}
|
||||||
|
t[36535] = {name="Roar of Fortitude",cast=0,cd=120000,categoryCD=120000,recoveryCD=0,duration=1800000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[36536] = {name="Savage Rend",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=35,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[36537] = {name="Savage Rend",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=30000,manaCost=35,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[36538] = {name="Savage Rend",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=160000,manaCost=35,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[36539] = {name="Savage Rend",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=1000,manaCost=35,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[36540] = {name="Savage Rend",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=0,manaCost=35,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[36541] = {name="Savage Rend",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=0,manaCost=35,icon="INV_Gauntlets_06",familyFlags=0}
|
||||||
|
t[46282] = {name="Savage Rend",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[46283] = {name="Savage Rend",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[46284] = {name="Savage Rend",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[46285] = {name="Savage Rend",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[46286] = {name="Savage Rend",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=25,icon="",familyFlags=0}
|
||||||
|
t[19159] = {name="Savage Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19160] = {name="Savage Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19503] = {name="Scatter Shot",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=1800000,manaCost=0,icon="INV_Flask_05",familyFlags=262144}
|
||||||
|
t[23601] = {name="Scatter Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1800000,manaCost=0,icon="INV_Flask_05",familyFlags=262144}
|
||||||
|
t[24583] = {name="Scorpid Poison",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=160000,manaCost=25,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[24586] = {name="Scorpid Poison",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=1200000,manaCost=25,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[24587] = {name="Scorpid Poison",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=0,manaCost=25,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[24640] = {name="Scorpid Poison",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=15000,manaCost=25,icon="Spell_Nature_LightningShield",familyFlags=0}
|
||||||
|
t[45659] = {name="Scorpid Stike",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=165,icon="",familyFlags=32768}
|
||||||
|
t[3043] = {name="Scorpid Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=45000,manaCost=70,icon="",familyFlags=32768}
|
||||||
|
t[51509] = {name="Scorpid Sting Damage Reduction",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=45000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24423] = {name="Screech",cast=0,cd=5000,categoryCD=5000,recoveryCD=0,duration=15000,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[24577] = {name="Screech",cast=0,cd=5000,categoryCD=5000,recoveryCD=0,duration=160000,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[24578] = {name="Screech",cast=0,cd=5000,categoryCD=5000,recoveryCD=0,duration=0,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[24579] = {name="Screech",cast=0,cd=5000,categoryCD=5000,recoveryCD=0,duration=0,manaCost=20,icon="",familyFlags=0}
|
||||||
|
t[1978] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=15,icon="",familyFlags=16384}
|
||||||
|
t[13549] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=30,icon="",familyFlags=16384}
|
||||||
|
t[13550] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=20000,manaCost=50,icon="",familyFlags=16384}
|
||||||
|
t[13551] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=240000,manaCost=80,icon="",familyFlags=16384}
|
||||||
|
t[13552] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=115,icon="",familyFlags=16384}
|
||||||
|
t[13553] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=3600000,manaCost=150,icon="",familyFlags=16384}
|
||||||
|
t[13554] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=190,icon="",familyFlags=16384}
|
||||||
|
t[13555] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=230,icon="",familyFlags=16384}
|
||||||
|
t[25295] = {name="Serpent Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=250,icon="",familyFlags=16384}
|
||||||
|
t[45661] = {name="Serpent Strike",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=250,icon="",familyFlags=16384}
|
||||||
|
t[29218] = {name="Server Spell",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26064] = {name="Shell Shield",cast=0,cd=60000,categoryCD=60000,recoveryCD=0,duration=60000,manaCost=10,icon="",familyFlags=0}
|
||||||
|
t[6660] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[15547] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[15620] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[16100] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[16496] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[17353] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[18561] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[20463] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[22121] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[22411] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[22907] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[23073] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[23337] = {name="Shoot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[2480] = {name="Shoot Bow",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[7919] = {name="Shoot Crossbow",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[7918] = {name="Shoot Gun",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=10000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[25200] = {name="Shoot Silithus Rifleman Long Range",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[26282] = {name="Shoot Tauren Rifleman",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[28318] = {name="Slime Shot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[19501] = {name="Spell - Reuse 19501",cast=0,cd=30000,categoryCD=30000,recoveryCD=0,duration=1800000,manaCost=0,icon="",familyFlags=262144}
|
||||||
|
t[27919] = {name="Spit",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=1}
|
||||||
|
t[28758] = {name="Stalker's Ally",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3035] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3036] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=120000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3037] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=45000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3038] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=1800000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3668] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=11000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45970] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=11000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45972] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=11000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[45974] = {name="Steady Shot",cast=1000,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[52684] = {name="Steady Shot and Raptor Strike Crit Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51579] = {name="Stinging Nettle",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51580] = {name="Stinging Nettle",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[36531] = {name="Strider Presence",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=50,icon="",familyFlags=0}
|
||||||
|
t[49557] = {name="Strike Together",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[49558] = {name="Strike Together",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26173] = {name="Striker's Arcane Shot Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26174] = {name="Striker's Rapid Fire Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24416] = {name="Superior Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24269] = {name="Superior Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24270] = {name="Superior Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24271] = {name="Superior Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24272] = {name="Superior Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24273] = {name="Superior Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19290] = {name="Surefooted",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19294] = {name="Surefooted",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24283] = {name="Surefooted",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24286] = {name="Surefooted",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[24287] = {name="Surefooted",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19255] = {name="Survivalist",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19256] = {name="Survivalist",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19257] = {name="Survivalist",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19258] = {name="Survivalist",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19259] = {name="Survivalist",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19552] = {name="Swift Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19553] = {name="Swift Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19554] = {name="Swift Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19555] = {name="Swift Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19556] = {name="Swift Aspects",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19454] = {name="Swiftshot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19455] = {name="Swiftshot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19456] = {name="Swiftshot",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[46287] = {name="Swipe",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=20,icon="Spell_Frost_ChillingBolt",familyFlags=0}
|
||||||
|
t[46288] = {name="Swipe",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=20,icon="Spell_Frost_ChillingBolt",familyFlags=0}
|
||||||
|
t[46289] = {name="Swipe",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=20,icon="Spell_Frost_ChillingBolt",familyFlags=0}
|
||||||
|
t[46290] = {name="Swipe",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=20,icon="Spell_Frost_ChillingBolt",familyFlags=0}
|
||||||
|
t[46291] = {name="Swipe",cast=0,cd=10000,categoryCD=10000,recoveryCD=0,duration=10000,manaCost=20,icon="Spell_Frost_ChillingBolt",familyFlags=0}
|
||||||
|
t[19678] = {name="Tame Adult Plainstrider",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19683] = {name="Tame Armored Scorpid",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44017] = {name="Tame Armored Scorpid",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[46705] = {name="Tame Ashfeather Swooper",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[46701] = {name="Tame Blackvenom Scorpid",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[50904] = {name="Tame Decrepit Darkhound",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44007] = {name="Tame Decrepit Darkhound.",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19681] = {name="Tame Dire Mottled Boar",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44013] = {name="Tame Dire Mottled Boar.",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[46091] = {name="Tame Elder Crimson Lynx",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[50905] = {name="Tame Greater Dusk Bat",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44009] = {name="Tame Greater Duskbat",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19597] = {name="Tame Ice Claw Bear",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44023] = {name="Tame Ice Claw Bear",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[46093] = {name="Tame Ivory Hawkstrider",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19677] = {name="Tame Large Crag Boar",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44019] = {name="Tame Large Crag Boar.",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[46095] = {name="Tame Lavender Mana Wyrm",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[46703] = {name="Tame Muckreef Crawler",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19685] = {name="Tame Nightsaber Stalker",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19679] = {name="Tame Prairie Stalker",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44003] = {name="Tame Prowler",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19676] = {name="Tame Snow Leopard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44021] = {name="Tame Snow Leopard",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44001] = {name="Tame Stonetusk Boar",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19686] = {name="Tame Strigid Screecher",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19682] = {name="Tame Surf Crawler",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44015] = {name="Tame Surf Crawler",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19680] = {name="Tame Swoop",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44011] = {name="Tame Tirisfal Plagued Bear",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[50906] = {name="Tame Tirisfal Plagued Bear",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[19684] = {name="Tame Webwood Lurker",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[44005] = {name="Tame Young Forest Bear",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2048}
|
||||||
|
t[8875] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=33554432}
|
||||||
|
t[19580] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=67108864}
|
||||||
|
t[19581] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=134217728}
|
||||||
|
t[19582] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=268435456}
|
||||||
|
t[19589] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=536870912}
|
||||||
|
t[19591] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=1073741824}
|
||||||
|
t[20782] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[20784] = {name="Tamed Pet Passive (DND)",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=2147483648}
|
||||||
|
t[19609] = {name="Thick Hide",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19610] = {name="Thick Hide",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19612] = {name="Thick Hide",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[10277] = {name="Throw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[15607] = {name="Throw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[15795] = {name="Throw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[16000] = {name="Throw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19785] = {name="Throw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=75000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[22887] = {name="Throw",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=60000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26090] = {name="Thunderstomp",cast=0,cd=40000,categoryCD=40000,recoveryCD=0,duration=1800000,manaCost=60,icon="",familyFlags=0}
|
||||||
|
t[26187] = {name="Thunderstomp",cast=0,cd=40000,categoryCD=40000,recoveryCD=0,duration=1200000,manaCost=60,icon="",familyFlags=0}
|
||||||
|
t[26188] = {name="Thunderstomp",cast=0,cd=40000,categoryCD=40000,recoveryCD=0,duration=0,manaCost=60,icon="",familyFlags=0}
|
||||||
|
t[51156] = {name="Thunderstomp",cast=0,cd=40000,categoryCD=40000,recoveryCD=0,duration=0,manaCost=60,icon="",familyFlags=0}
|
||||||
|
t[19801] = {name="Tranquilizing Shot",cast=0,cd=20000,categoryCD=20000,recoveryCD=0,duration=0,manaCost=270,icon="Ability_Warrior_Disarm",familyFlags=65536}
|
||||||
|
t[19376] = {name="Trap Mastery",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19377] = {name="Trap Mastery",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51581] = {name="Trap Mastery",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19506] = {name="Trueshot Aura",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[20905] = {name="Trueshot Aura",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[20906] = {name="Trueshot Aura",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19616] = {name="Unleashed Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19617] = {name="Unleashed Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19618] = {name="Unleashed Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19619] = {name="Unleashed Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[19620] = {name="Unleashed Fury",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26176] = {name="Unseen Path Pet Bonus",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51586] = {name="Untamed Trapper",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51584] = {name="Vicious Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[51585] = {name="Vicious Strikes",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[3034] = {name="Viper Sting",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=1000,manaCost=135,icon="",familyFlags=65536}
|
||||||
|
t[14279] = {name="Viper Sting",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=175,icon="",familyFlags=65536}
|
||||||
|
t[14280] = {name="Viper Sting",cast=0,cd=6000,categoryCD=0,recoveryCD=6000,duration=0,manaCost=215,icon="",familyFlags=65536}
|
||||||
|
t[45660] = {name="Viper Strike",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=215,icon="",familyFlags=65536}
|
||||||
|
t[1510] = {name="Volley",cast=0,cd=60000,categoryCD=0,recoveryCD=60000,duration=1200000,manaCost=350,icon="",familyFlags=8192}
|
||||||
|
t[14294] = {name="Volley",cast=0,cd=60000,categoryCD=0,recoveryCD=60000,duration=0,manaCost=420,icon="",familyFlags=8192}
|
||||||
|
t[14295] = {name="Volley",cast=0,cd=60000,categoryCD=0,recoveryCD=60000,duration=0,manaCost=490,icon="",familyFlags=8192}
|
||||||
|
t[22908] = {name="Volley",cast=0,cd=60000,categoryCD=0,recoveryCD=60000,duration=0,manaCost=0,icon="",familyFlags=8192}
|
||||||
|
t[36533] = {name="Web",cast=0,cd=60000,categoryCD=0,recoveryCD=60000,duration=0,manaCost=50,icon="Spell_Holy_Heal02",familyFlags=0}
|
||||||
|
t[26226] = {name="Widow Bite",cast=0,cd=4000,categoryCD=0,recoveryCD=4000,duration=60000,manaCost=40,icon="Ability_Hunter_AimedShot",familyFlags=0}
|
||||||
|
t[2974] = {name="Wing Clip",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=30000,manaCost=40,icon="INV_Food_Egg_02",familyFlags=64}
|
||||||
|
t[14267] = {name="Wing Clip",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=11000,manaCost=60,icon="INV_Food_Egg_02",familyFlags=64}
|
||||||
|
t[14268] = {name="Wing Clip",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=0,manaCost=80,icon="INV_Food_Egg_02",familyFlags=64}
|
||||||
|
t[27633] = {name="Wing Clip",cast=0,cd=3000,categoryCD=0,recoveryCD=3000,duration=0,manaCost=80,icon="INV_Food_Egg_02",familyFlags=64}
|
||||||
|
t[19386] = {name="Wyvern Sting",cast=0,cd=120000,categoryCD=0,recoveryCD=120000,duration=1200000,manaCost=115,icon="",familyFlags=65536}
|
||||||
|
t[24131] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=1200000,manaCost=0,icon="",familyFlags=65536}
|
||||||
|
t[24132] = {name="Wyvern Sting",cast=0,cd=120000,categoryCD=0,recoveryCD=120000,duration=0,manaCost=155,icon="",familyFlags=65536}
|
||||||
|
t[24133] = {name="Wyvern Sting",cast=0,cd=120000,categoryCD=0,recoveryCD=120000,duration=0,manaCost=205,icon="",familyFlags=65536}
|
||||||
|
t[24134] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=65536}
|
||||||
|
t[24135] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=65536}
|
||||||
|
t[24335] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=205,icon="",familyFlags=0}
|
||||||
|
t[24336] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=65536}
|
||||||
|
t[26180] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=0}
|
||||||
|
t[26233] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=65536}
|
||||||
|
t[26748] = {name="Wyvern Sting",cast=0,cd=0,categoryCD=0,recoveryCD=0,duration=0,manaCost=0,icon="",familyFlags=65536}
|
||||||
|
end
|
||||||
|
|
||||||
|
MTH_DS_HunterSpellsByName = {}
|
||||||
|
do
|
||||||
|
local t = MTH_DS_HunterSpellsByName
|
||||||
|
t["[Deprecated] Bestial Swiftness"] = MTH_DS_HunterSpellsDBC[19596]
|
||||||
|
t["[Deprecated] Bestial Wrath"] = MTH_DS_HunterSpellsDBC[19574]
|
||||||
|
t["[Deprecated] Hawk Eye"] = MTH_DS_HunterSpellsDBC[19500]
|
||||||
|
t["[Deprecated] Improved Arcane Shot"] = MTH_DS_HunterSpellsDBC[19457]
|
||||||
|
t["[Deprecated] Improved Aspect of the Monkey"] = MTH_DS_HunterSpellsDBC[24386]
|
||||||
|
t["[Deprecated] Improved Hunter's Mark"] = MTH_DS_HunterSpellsDBC[19424]
|
||||||
|
t["[Deprecated] Improved Scorpid Sting"] = MTH_DS_HunterSpellsDBC[19494]
|
||||||
|
t["[Deprecated] Improved Wing Clip"] = MTH_DS_HunterSpellsDBC[19234]
|
||||||
|
t["[Deprecated] Killer Instinct"] = MTH_DS_HunterSpellsDBC[19374]
|
||||||
|
t["[Deprecated] Pathfinding"] = MTH_DS_HunterSpellsDBC[19562]
|
||||||
|
t["[Deprecated] Scorpid Sting"] = MTH_DS_HunterSpellsDBC[14275]
|
||||||
|
t["[Deprecated] Thick Hide"] = MTH_DS_HunterSpellsDBC[19611]
|
||||||
|
t["[Deprecated] Trueshot Aura Percent Bonus"] = MTH_DS_HunterSpellsDBC[51520]
|
||||||
|
t["Adrenaline Rush"] = MTH_DS_HunterSpellsDBC[28752]
|
||||||
|
t["Aimed Shot"] = MTH_DS_HunterSpellsDBC[19434]
|
||||||
|
t["Arcane Infused"] = MTH_DS_HunterSpellsDBC[23721]
|
||||||
|
t["Arcane Shot"] = MTH_DS_HunterSpellsDBC[3044]
|
||||||
|
t["Arcane Shot Mana Reduction"] = MTH_DS_HunterSpellsDBC[23157]
|
||||||
|
t["Aspect of the Beast"] = MTH_DS_HunterSpellsDBC[13161]
|
||||||
|
t["Aspect of the Cheetah"] = MTH_DS_HunterSpellsDBC[5118]
|
||||||
|
t["Aspect of the Fox"] = MTH_DS_HunterSpellsDBC[45651]
|
||||||
|
t["Aspect of the Hawk"] = MTH_DS_HunterSpellsDBC[13165]
|
||||||
|
t["Aspect of the Monkey"] = MTH_DS_HunterSpellsDBC[13163]
|
||||||
|
t["Aspect of the Pack"] = MTH_DS_HunterSpellsDBC[13159]
|
||||||
|
t["Aspect of the Snake"] = MTH_DS_HunterSpellsDBC[45652]
|
||||||
|
t["Aspect of the Turtle"] = MTH_DS_HunterSpellsDBC[45649]
|
||||||
|
t["Aspect of the Wild"] = MTH_DS_HunterSpellsDBC[20043]
|
||||||
|
t["Aspect of the Wolf"] = MTH_DS_HunterSpellsDBC[45650]
|
||||||
|
t["Auto Shot"] = MTH_DS_HunterSpellsDBC[75]
|
||||||
|
t["Avoidance"] = MTH_DS_HunterSpellsDBC[46023]
|
||||||
|
t["Aynasha's Bow"] = MTH_DS_HunterSpellsDBC[19767]
|
||||||
|
t["Baited Shot"] = MTH_DS_HunterSpellsDBC[46321]
|
||||||
|
t["Barrage"] = MTH_DS_HunterSpellsDBC[19461]
|
||||||
|
t["Battle Standard"] = MTH_DS_HunterSpellsDBC[22996]
|
||||||
|
t["Beast Mastery"] = MTH_DS_HunterSpellsDBC[47355]
|
||||||
|
t["Beast of the Unseen Path"] = MTH_DS_HunterSpellsDBC[29233]
|
||||||
|
t["Bestial Discipline"] = MTH_DS_HunterSpellsDBC[19590]
|
||||||
|
t["Bestial Fury"] = MTH_DS_HunterSpellsDBC[19603]
|
||||||
|
t["Bestial Precision"] = MTH_DS_HunterSpellsDBC[51554]
|
||||||
|
t["Bestial Wrath"] = MTH_DS_HunterSpellsDBC[24395]
|
||||||
|
t["Bite"] = MTH_DS_HunterSpellsDBC[17253]
|
||||||
|
t["Bubble Barrier"] = MTH_DS_HunterSpellsDBC[36523]
|
||||||
|
t["Carve"] = MTH_DS_HunterSpellsDBC[51575]
|
||||||
|
t["Cheetah Sprint"] = MTH_DS_HunterSpellsDBC[24348]
|
||||||
|
t["Claw"] = MTH_DS_HunterSpellsDBC[3009]
|
||||||
|
t["Clever Traps"] = MTH_DS_HunterSpellsDBC[19239]
|
||||||
|
t["Command"] = MTH_DS_HunterSpellsDBC[20576]
|
||||||
|
t["Concussive Shot"] = MTH_DS_HunterSpellsDBC[5116]
|
||||||
|
t["Concussive Shot Cooldown Reduction"] = MTH_DS_HunterSpellsDBC[23158]
|
||||||
|
t["Coordinated Assault"] = MTH_DS_HunterSpellsDBC[49559]
|
||||||
|
t["Copy of Shoot"] = MTH_DS_HunterSpellsDBC[28317]
|
||||||
|
t["Counterattack"] = MTH_DS_HunterSpellsDBC[19306]
|
||||||
|
t["Death Roll"] = MTH_DS_HunterSpellsDBC[36548]
|
||||||
|
t["Demonic Transformation"] = MTH_DS_HunterSpellsDBC[24992]
|
||||||
|
t["Detect Weakness"] = MTH_DS_HunterSpellsDBC[23578]
|
||||||
|
t["Deterrence"] = MTH_DS_HunterSpellsDBC[19263]
|
||||||
|
t["Disengage"] = MTH_DS_HunterSpellsDBC[781]
|
||||||
|
t["Distracting Shot"] = MTH_DS_HunterSpellsDBC[14274]
|
||||||
|
t["Efficiency"] = MTH_DS_HunterSpellsDBC[19416]
|
||||||
|
t["Elusiveness"] = MTH_DS_HunterSpellsDBC[51552]
|
||||||
|
t["Endless Quiver"] = MTH_DS_HunterSpellsDBC[51517]
|
||||||
|
t["Endurance Training"] = MTH_DS_HunterSpellsDBC[19583]
|
||||||
|
t["Entrapment"] = MTH_DS_HunterSpellsDBC[19184]
|
||||||
|
t["Explosive Trap"] = MTH_DS_HunterSpellsDBC[13813]
|
||||||
|
t["Explosive Trap Effect"] = MTH_DS_HunterSpellsDBC[13812]
|
||||||
|
t["Extra Shot"] = MTH_DS_HunterSpellsDBC[51519]
|
||||||
|
t["Eyes of the Beast"] = MTH_DS_HunterSpellsDBC[1002]
|
||||||
|
t["Fang of the Crystal Spider"] = MTH_DS_HunterSpellsDBC[17331]
|
||||||
|
t["Faster Bleeds 5 (Hunter)"] = MTH_DS_HunterSpellsDBC[52402]
|
||||||
|
t["Feign Death"] = MTH_DS_HunterSpellsDBC[5384]
|
||||||
|
t["Ferocity"] = MTH_DS_HunterSpellsDBC[19598]
|
||||||
|
t["Fire Breath"] = MTH_DS_HunterSpellsDBC[46269]
|
||||||
|
t["Flame Spear"] = MTH_DS_HunterSpellsDBC[19781]
|
||||||
|
t["Flare"] = MTH_DS_HunterSpellsDBC[1543]
|
||||||
|
t["Freezing Trap"] = MTH_DS_HunterSpellsDBC[1499]
|
||||||
|
t["Freezing Trap (TEST)"] = MTH_DS_HunterSpellsDBC[21750]
|
||||||
|
t["Freezing Trap Effect"] = MTH_DS_HunterSpellsDBC[3355]
|
||||||
|
t["Frenzy"] = MTH_DS_HunterSpellsDBC[19621]
|
||||||
|
t["Frost Trap"] = MTH_DS_HunterSpellsDBC[13809]
|
||||||
|
t["Frost Trap Aura"] = MTH_DS_HunterSpellsDBC[13810]
|
||||||
|
t["Frost Trap Effect"] = MTH_DS_HunterSpellsDBC[14207]
|
||||||
|
t["Furious Howl"] = MTH_DS_HunterSpellsDBC[24597]
|
||||||
|
t["Grace"] = MTH_DS_HunterSpellsDBC[46296]
|
||||||
|
t["Haste"] = MTH_DS_HunterSpellsDBC[14824]
|
||||||
|
t["Hawk Eye"] = MTH_DS_HunterSpellsDBC[19498]
|
||||||
|
t["Hunter Giant Stalker"] = MTH_DS_HunterSpellsDBC[21942]
|
||||||
|
t["Hunter's Mark"] = MTH_DS_HunterSpellsDBC[1130]
|
||||||
|
t["Immolation Trap"] = MTH_DS_HunterSpellsDBC[13795]
|
||||||
|
t["Immolation Trap Effect"] = MTH_DS_HunterSpellsDBC[13797]
|
||||||
|
t["Impale"] = MTH_DS_HunterSpellsDBC[15860]
|
||||||
|
t["Improved Aspect of the Hawk"] = MTH_DS_HunterSpellsDBC[23559]
|
||||||
|
t["Improved Concussive Shot"] = MTH_DS_HunterSpellsDBC[19407]
|
||||||
|
t["Improved Explosive Trap"] = MTH_DS_HunterSpellsDBC[19378]
|
||||||
|
t["Improved Eyes of the Beast"] = MTH_DS_HunterSpellsDBC[19557]
|
||||||
|
t["Improved Feign Death"] = MTH_DS_HunterSpellsDBC[19286]
|
||||||
|
t["Improved Freezing Trap"] = MTH_DS_HunterSpellsDBC[19288]
|
||||||
|
t["Improved Hunter's Mark"] = MTH_DS_HunterSpellsDBC[19421]
|
||||||
|
t["Improved Immolation Trap"] = MTH_DS_HunterSpellsDBC[19246]
|
||||||
|
t["Improved Mend Pet"] = MTH_DS_HunterSpellsDBC[19572]
|
||||||
|
t["Improved Primal Aspects"] = MTH_DS_HunterSpellsDBC[19549]
|
||||||
|
t["Improved Revive Pet"] = MTH_DS_HunterSpellsDBC[19575]
|
||||||
|
t["Improved Scorpid Sting"] = MTH_DS_HunterSpellsDBC[19491]
|
||||||
|
t["Improved Serpent Sting"] = MTH_DS_HunterSpellsDBC[24467]
|
||||||
|
t["Improved Steady Shot"] = MTH_DS_HunterSpellsDBC[51515]
|
||||||
|
t["Improved Stings"] = MTH_DS_HunterSpellsDBC[19464]
|
||||||
|
t["Improved Swift Aspects"] = MTH_DS_HunterSpellsDBC[52603]
|
||||||
|
t["Improved Volley and Multishot"] = MTH_DS_HunterSpellsDBC[23566]
|
||||||
|
t["Improved Wing Clip"] = MTH_DS_HunterSpellsDBC[19228]
|
||||||
|
t["Increased Hunter Pet Damage"] = MTH_DS_HunterSpellsDBC[22854]
|
||||||
|
t["Increased Pet Damage +3%"] = MTH_DS_HunterSpellsDBC[27205]
|
||||||
|
t["Increased Pet Damage +4%"] = MTH_DS_HunterSpellsDBC[52413]
|
||||||
|
t["Kill Command"] = MTH_DS_HunterSpellsDBC[41827]
|
||||||
|
t["Killer Instinct"] = MTH_DS_HunterSpellsDBC[19162]
|
||||||
|
t["Lacerate"] = MTH_DS_HunterSpellsDBC[20907]
|
||||||
|
t["Lightning Breath"] = MTH_DS_HunterSpellsDBC[24844]
|
||||||
|
t["Lightning Reflexes"] = MTH_DS_HunterSpellsDBC[19168]
|
||||||
|
t["Lizard Bolt"] = MTH_DS_HunterSpellsDBC[46297]
|
||||||
|
t["Mend Pet"] = MTH_DS_HunterSpellsDBC[136]
|
||||||
|
t["Mongoose Bite"] = MTH_DS_HunterSpellsDBC[1495]
|
||||||
|
t["Mortal Shots"] = MTH_DS_HunterSpellsDBC[19485]
|
||||||
|
t["Multi-Shot"] = MTH_DS_HunterSpellsDBC[2643]
|
||||||
|
t["Multi-Shot Damage Increase"] = MTH_DS_HunterSpellsDBC[28539]
|
||||||
|
t["Multishot and Carve Cooldown"] = MTH_DS_HunterSpellsDBC[52602]
|
||||||
|
t["Not There"] = MTH_DS_HunterSpellsDBC[28761]
|
||||||
|
t["Packleader"] = MTH_DS_HunterSpellsDBC[36532]
|
||||||
|
t["Pathfinding"] = MTH_DS_HunterSpellsDBC[19559]
|
||||||
|
t["Pet Focus Regen Bonus"] = MTH_DS_HunterSpellsDBC[52685]
|
||||||
|
t["Piercing Shots"] = MTH_DS_HunterSpellsDBC[51512]
|
||||||
|
t["Pin"] = MTH_DS_HunterSpellsDBC[46292]
|
||||||
|
t["Planning Ahead"] = MTH_DS_HunterSpellsDBC[51576]
|
||||||
|
t["Planning Ahead Dummy"] = MTH_DS_HunterSpellsDBC[51578]
|
||||||
|
t["Poison Spit"] = MTH_DS_HunterSpellsDBC[46271]
|
||||||
|
t["Prowl"] = MTH_DS_HunterSpellsDBC[24450]
|
||||||
|
t["Quick Shots"] = MTH_DS_HunterSpellsDBC[51547]
|
||||||
|
t["Quick Strikes"] = MTH_DS_HunterSpellsDBC[51542]
|
||||||
|
t["Ranged Weapon Specialization"] = MTH_DS_HunterSpellsDBC[19511]
|
||||||
|
t["Rapid Fire"] = MTH_DS_HunterSpellsDBC[3045]
|
||||||
|
t["Raptor Strike"] = MTH_DS_HunterSpellsDBC[2973]
|
||||||
|
t["Readiness"] = MTH_DS_HunterSpellsDBC[23989]
|
||||||
|
t["Resourcefulness"] = MTH_DS_HunterSpellsDBC[51570]
|
||||||
|
t["Revive Pet"] = MTH_DS_HunterSpellsDBC[982]
|
||||||
|
t["Roar of Fortitude"] = MTH_DS_HunterSpellsDBC[36535]
|
||||||
|
t["Savage Rend"] = MTH_DS_HunterSpellsDBC[36536]
|
||||||
|
t["Savage Strikes"] = MTH_DS_HunterSpellsDBC[19159]
|
||||||
|
t["Scatter Shot"] = MTH_DS_HunterSpellsDBC[19503]
|
||||||
|
t["Scorpid Poison"] = MTH_DS_HunterSpellsDBC[24583]
|
||||||
|
t["Scorpid Stike"] = MTH_DS_HunterSpellsDBC[45659]
|
||||||
|
t["Scorpid Sting"] = MTH_DS_HunterSpellsDBC[3043]
|
||||||
|
t["Scorpid Sting Damage Reduction"] = MTH_DS_HunterSpellsDBC[51509]
|
||||||
|
t["Screech"] = MTH_DS_HunterSpellsDBC[24423]
|
||||||
|
t["Serpent Sting"] = MTH_DS_HunterSpellsDBC[1978]
|
||||||
|
t["Serpent Strike"] = MTH_DS_HunterSpellsDBC[45661]
|
||||||
|
t["Server Spell"] = MTH_DS_HunterSpellsDBC[29218]
|
||||||
|
t["Shell Shield"] = MTH_DS_HunterSpellsDBC[26064]
|
||||||
|
t["Shoot"] = MTH_DS_HunterSpellsDBC[6660]
|
||||||
|
t["Shoot Bow"] = MTH_DS_HunterSpellsDBC[2480]
|
||||||
|
t["Shoot Crossbow"] = MTH_DS_HunterSpellsDBC[7919]
|
||||||
|
t["Shoot Gun"] = MTH_DS_HunterSpellsDBC[7918]
|
||||||
|
t["Shoot Silithus Rifleman Long Range"] = MTH_DS_HunterSpellsDBC[25200]
|
||||||
|
t["Shoot Tauren Rifleman"] = MTH_DS_HunterSpellsDBC[26282]
|
||||||
|
t["Slime Shot"] = MTH_DS_HunterSpellsDBC[28318]
|
||||||
|
t["Spell - Reuse 19501"] = MTH_DS_HunterSpellsDBC[19501]
|
||||||
|
t["Spit"] = MTH_DS_HunterSpellsDBC[27919]
|
||||||
|
t["Stalker's Ally"] = MTH_DS_HunterSpellsDBC[28758]
|
||||||
|
t["Steady Shot"] = MTH_DS_HunterSpellsDBC[3035]
|
||||||
|
t["Steady Shot and Raptor Strike Crit Bonus"] = MTH_DS_HunterSpellsDBC[52684]
|
||||||
|
t["Stinging Nettle"] = MTH_DS_HunterSpellsDBC[51579]
|
||||||
|
t["Strider Presence"] = MTH_DS_HunterSpellsDBC[36531]
|
||||||
|
t["Strike Together"] = MTH_DS_HunterSpellsDBC[49557]
|
||||||
|
t["Striker's Arcane Shot Bonus"] = MTH_DS_HunterSpellsDBC[26173]
|
||||||
|
t["Striker's Rapid Fire Bonus"] = MTH_DS_HunterSpellsDBC[26174]
|
||||||
|
t["Superior Aspects"] = MTH_DS_HunterSpellsDBC[24416]
|
||||||
|
t["Superior Strikes"] = MTH_DS_HunterSpellsDBC[24269]
|
||||||
|
t["Surefooted"] = MTH_DS_HunterSpellsDBC[19290]
|
||||||
|
t["Survivalist"] = MTH_DS_HunterSpellsDBC[19255]
|
||||||
|
t["Swift Aspects"] = MTH_DS_HunterSpellsDBC[19552]
|
||||||
|
t["Swiftshot"] = MTH_DS_HunterSpellsDBC[19454]
|
||||||
|
t["Swipe"] = MTH_DS_HunterSpellsDBC[46287]
|
||||||
|
t["Tame Adult Plainstrider"] = MTH_DS_HunterSpellsDBC[19678]
|
||||||
|
t["Tame Armored Scorpid"] = MTH_DS_HunterSpellsDBC[19683]
|
||||||
|
t["Tame Ashfeather Swooper"] = MTH_DS_HunterSpellsDBC[46705]
|
||||||
|
t["Tame Blackvenom Scorpid"] = MTH_DS_HunterSpellsDBC[46701]
|
||||||
|
t["Tame Decrepit Darkhound"] = MTH_DS_HunterSpellsDBC[50904]
|
||||||
|
t["Tame Decrepit Darkhound."] = MTH_DS_HunterSpellsDBC[44007]
|
||||||
|
t["Tame Dire Mottled Boar"] = MTH_DS_HunterSpellsDBC[19681]
|
||||||
|
t["Tame Dire Mottled Boar."] = MTH_DS_HunterSpellsDBC[44013]
|
||||||
|
t["Tame Elder Crimson Lynx"] = MTH_DS_HunterSpellsDBC[46091]
|
||||||
|
t["Tame Greater Dusk Bat"] = MTH_DS_HunterSpellsDBC[50905]
|
||||||
|
t["Tame Greater Duskbat"] = MTH_DS_HunterSpellsDBC[44009]
|
||||||
|
t["Tame Ice Claw Bear"] = MTH_DS_HunterSpellsDBC[19597]
|
||||||
|
t["Tame Ivory Hawkstrider"] = MTH_DS_HunterSpellsDBC[46093]
|
||||||
|
t["Tame Large Crag Boar"] = MTH_DS_HunterSpellsDBC[19677]
|
||||||
|
t["Tame Large Crag Boar."] = MTH_DS_HunterSpellsDBC[44019]
|
||||||
|
t["Tame Lavender Mana Wyrm"] = MTH_DS_HunterSpellsDBC[46095]
|
||||||
|
t["Tame Muckreef Crawler"] = MTH_DS_HunterSpellsDBC[46703]
|
||||||
|
t["Tame Nightsaber Stalker"] = MTH_DS_HunterSpellsDBC[19685]
|
||||||
|
t["Tame Prairie Stalker"] = MTH_DS_HunterSpellsDBC[19679]
|
||||||
|
t["Tame Prowler"] = MTH_DS_HunterSpellsDBC[44003]
|
||||||
|
t["Tame Snow Leopard"] = MTH_DS_HunterSpellsDBC[19676]
|
||||||
|
t["Tame Stonetusk Boar"] = MTH_DS_HunterSpellsDBC[44001]
|
||||||
|
t["Tame Strigid Screecher"] = MTH_DS_HunterSpellsDBC[19686]
|
||||||
|
t["Tame Surf Crawler"] = MTH_DS_HunterSpellsDBC[19682]
|
||||||
|
t["Tame Swoop"] = MTH_DS_HunterSpellsDBC[19680]
|
||||||
|
t["Tame Tirisfal Plagued Bear"] = MTH_DS_HunterSpellsDBC[44011]
|
||||||
|
t["Tame Webwood Lurker"] = MTH_DS_HunterSpellsDBC[19684]
|
||||||
|
t["Tame Young Forest Bear"] = MTH_DS_HunterSpellsDBC[44005]
|
||||||
|
t["Tamed Pet Passive (DND)"] = MTH_DS_HunterSpellsDBC[8875]
|
||||||
|
t["Thick Hide"] = MTH_DS_HunterSpellsDBC[19609]
|
||||||
|
t["Throw"] = MTH_DS_HunterSpellsDBC[10277]
|
||||||
|
t["Thunderstomp"] = MTH_DS_HunterSpellsDBC[26090]
|
||||||
|
t["Tranquilizing Shot"] = MTH_DS_HunterSpellsDBC[19801]
|
||||||
|
t["Trap Mastery"] = MTH_DS_HunterSpellsDBC[19376]
|
||||||
|
t["Trueshot Aura"] = MTH_DS_HunterSpellsDBC[19506]
|
||||||
|
t["Unleashed Fury"] = MTH_DS_HunterSpellsDBC[19616]
|
||||||
|
t["Unseen Path Pet Bonus"] = MTH_DS_HunterSpellsDBC[26176]
|
||||||
|
t["Untamed Trapper"] = MTH_DS_HunterSpellsDBC[51586]
|
||||||
|
t["Vicious Strikes"] = MTH_DS_HunterSpellsDBC[51584]
|
||||||
|
t["Viper Sting"] = MTH_DS_HunterSpellsDBC[3034]
|
||||||
|
t["Viper Strike"] = MTH_DS_HunterSpellsDBC[45660]
|
||||||
|
t["Volley"] = MTH_DS_HunterSpellsDBC[1510]
|
||||||
|
t["Web"] = MTH_DS_HunterSpellsDBC[36533]
|
||||||
|
t["Widow Bite"] = MTH_DS_HunterSpellsDBC[26226]
|
||||||
|
t["Wing Clip"] = MTH_DS_HunterSpellsDBC[2974]
|
||||||
|
t["Wyvern Sting"] = MTH_DS_HunterSpellsDBC[19386]
|
||||||
|
end
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
|
||||||
|
-- ds-hunter-spells.lua
|
||||||
|
-- Hunter spell data for TWoW 1.18.1 "Nightmares of Ursol"
|
||||||
|
-- Used by: ExpAmmo cycle tracker, HunterBook (future spell reference tab)
|
||||||
|
--
|
||||||
|
-- TODO markers:
|
||||||
|
-- SPELL_ID : exact spell ID not yet extracted from Spell.dbc (needs MPQ)
|
||||||
|
-- ICON : icon texture not yet confirmed from game files
|
||||||
|
-- VERIFY : value observed in patch notes but subject to change on PTR/live
|
||||||
|
-- PENDING : mechanic not yet verified against live server
|
||||||
|
|
||||||
|
if not MTH_DS then MTH_DS = {} end
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- BASELINE HUNTER SPELLS (available to all specs from 1.18.1)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
MTH_DS_HunterSpells = {
|
||||||
|
|
||||||
|
["baseline"] = {
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Steady Shot",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["note"] = "Moved from Marksmanship talent tree to baseline at level 20.",
|
||||||
|
["castTime"] = "1.5s", -- TODO VERIFY
|
||||||
|
["cooldown"] = "n/a",
|
||||||
|
["school"] = "Physical",
|
||||||
|
["icon"] = "Ability_Hunter_SteadyShot", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Trueshot Aura",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["note"] = "Moved from Marksmanship capstone to baseline. All hunters now get this.",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "n/a",
|
||||||
|
["school"] = "Physical",
|
||||||
|
["icon"] = "Ability_Trueshot", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Aspect of the Viper",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["note"] = "New baseline aspect learned at level 56. Regenerates mana while dealing reduced damage.",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "n/a",
|
||||||
|
["school"] = "Nature",
|
||||||
|
["icon"] = "Spell_Nature_Poison", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Volley",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["note"] = "Changed from channelled to a 3-second cast AoE. Now a proper cast-bar spell.",
|
||||||
|
["castTime"] = "3s", -- TODO VERIFY
|
||||||
|
["cooldown"] = "n/a",
|
||||||
|
["school"] = "Physical",
|
||||||
|
["icon"] = "Ability_Whirlwind", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- MARKSMANSHIP TALENTS (1.18.1 changes)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
["marksmanship"] = {
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Aimed Shot",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["note"] = "Now has a visible 2s cast bar. Triggers ExpAmmo cycle start (resets to FIRE state).",
|
||||||
|
["castTime"] = "2s",
|
||||||
|
["cooldown"] = "26s", -- TODO VERIFY vs Spell.dbc
|
||||||
|
["school"] = "Physical",
|
||||||
|
["icon"] = "Inv_Spear_07", -- TODO ICON confirm
|
||||||
|
["expAmmoTrigger"] = true, -- resets ExpAmmo cycle to state 1 (FIRE)
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Lock and Load",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["talentRow"] = 7, -- MM capstone row
|
||||||
|
["note"] = "10s proc buff. Triggered by Aimed Shot crit or trap activation (TODO VERIFY exact condition).",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "n/a",
|
||||||
|
["duration"] = "10s", -- TODO VERIFY
|
||||||
|
["school"] = "Physical",
|
||||||
|
["type"] = "buff_proc",
|
||||||
|
["icon"] = "Ability_Hunter_LockAndLoad", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Rapid Fire",
|
||||||
|
["note"] = "15% haste, 15s duration, 5min CD. Unchanged in 1.18.1 baseline values.",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "5min",
|
||||||
|
["duration"] = "15s",
|
||||||
|
["school"] = "Physical",
|
||||||
|
["type"] = "buff",
|
||||||
|
["icon"] = "Ability_Hunter_RapidKilling",
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- BEAST MASTERY TALENTS (1.18.1 changes)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
["beastmastery"] = {
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Bestial Wrath",
|
||||||
|
["note"] = "Returned to BM tree. 18s buff, 90s CD (1.5min). Pet immune to fear/CC during.",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "90s",
|
||||||
|
["duration"] = "18s", -- TODO VERIFY
|
||||||
|
["school"] = "Physical",
|
||||||
|
["type"] = "buff",
|
||||||
|
["icon"] = "Ability_Druid_Ferociousbite", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Kill Command",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["talentRow"] = 7, -- BM capstone row
|
||||||
|
["note"] = "8s CD, triggered on crit. Commands pet to inflict bonus damage on next hit.",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "8s",
|
||||||
|
["school"] = "Physical",
|
||||||
|
["icon"] = "Ability_Hunter_KillCommand", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Scent of Blood",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["talentRow"] = 5,
|
||||||
|
["note"] = "8s pet rage proc buff. Triggers when Bestial Wrath is active (TODO VERIFY exact condition).",
|
||||||
|
["castTime"] = "Instant (proc)",
|
||||||
|
["cooldown"] = "n/a",
|
||||||
|
["duration"] = "8s", -- TODO VERIFY
|
||||||
|
["school"] = "Physical",
|
||||||
|
["type"] = "buff_proc",
|
||||||
|
["icon"] = "Ability_Warrior_BloodFrenzy", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Baited Shot",
|
||||||
|
["removedIn"] = "1.18.1",
|
||||||
|
["note"] = "REMOVED. Replaced by Kill Command as the BM capstone. Any saved data for this spell can be cleared.",
|
||||||
|
["deprecated"] = true,
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- SURVIVAL TALENTS (1.18.1 changes)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
["survival"] = {
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Alone Against the World",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["talentRow"] = 2,
|
||||||
|
["note"] = "New 2-point talent. Bonus to pet/self when no group members nearby (TODO VERIFY exact bonus values).",
|
||||||
|
["type"] = "passive",
|
||||||
|
["icon"] = "Ability_Hunter_AloneAgainstTheWorld", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["name"] = "Lacerate",
|
||||||
|
["addedIn"] = "1.18.1",
|
||||||
|
["note"] = "40% Attack Power bleed, +15% from all bleed sides. (TODO VERIFY: rank values from Spell.dbc).",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["school"] = "Physical",
|
||||||
|
["type"] = "dot",
|
||||||
|
["icon"] = "Ability_Hunter_Lacerate", -- TODO ICON confirm
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- EXPERIMENTAL AMMUNITION (new 1.18.1 mechanic)
|
||||||
|
-- States cycle: FIRE -> ARCANE -> NATURE -> (loop)
|
||||||
|
-- Aimed Shot resets cycle to FIRE each time it is fired.
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
["expAmmoStates"] = {
|
||||||
|
|
||||||
|
{
|
||||||
|
["state"] = 1,
|
||||||
|
["label"] = "Fire Ammo",
|
||||||
|
["school"] = "Fire",
|
||||||
|
["duration"] = "60s", -- TODO VERIFY from server
|
||||||
|
["consumeSpell"] = "Multi-Shot", -- TODO VERIFY spell that consumes this state
|
||||||
|
["icon"] = "Spell_Fire_FlameBolt", -- TODO ICON confirm
|
||||||
|
["buffName"] = nil, -- TODO: exact buff name from Spell.dbc
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["state"] = 2,
|
||||||
|
["label"] = "Arcane Ammo",
|
||||||
|
["school"] = "Arcane",
|
||||||
|
["duration"] = "60s", -- TODO VERIFY
|
||||||
|
["consumeSpell"] = "Arcane Shot", -- TODO VERIFY
|
||||||
|
["icon"] = "Spell_Arcane_ArcaneMissiles", -- TODO ICON confirm
|
||||||
|
["buffName"] = nil, -- TODO: exact buff name from Spell.dbc
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
["state"] = 3,
|
||||||
|
["label"] = "Nature Ammo",
|
||||||
|
["school"] = "Nature",
|
||||||
|
["duration"] = "60s", -- TODO VERIFY
|
||||||
|
["consumeSpell"] = "Serpent Sting", -- TODO VERIFY
|
||||||
|
["icon"] = "Spell_Nature_NatureBolt", -- TODO ICON confirm
|
||||||
|
["buffName"] = nil, -- TODO: exact buff name from Spell.dbc
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
@@ -137,6 +137,11 @@ local MTH_DS_AtlasSources = {
|
|||||||
[9426] = {["boss"] = true, },
|
[9426] = {["boss"] = true, },
|
||||||
[9456] = {["boss"] = true, },
|
[9456] = {["boss"] = true, },
|
||||||
[9487] = {["boss"] = true, },
|
[9487] = {["boss"] = true, },
|
||||||
|
[42198] = {["crafted"] = true, },
|
||||||
|
[42199] = {["crafted"] = true, },
|
||||||
|
[42200] = {["crafted"] = true, },
|
||||||
|
[42201] = {["crafted"] = true, },
|
||||||
|
[42202] = {["crafted"] = true, },
|
||||||
}
|
}
|
||||||
|
|
||||||
for itemId, sourceMap in pairs(MTH_DS_AtlasSources) do
|
for itemId, sourceMap in pairs(MTH_DS_AtlasSources) do
|
||||||
|
|||||||
@@ -6308,6 +6308,13 @@ MTH_DS_ItemOrigins = {
|
|||||||
["level"] = 25,
|
["level"] = 25,
|
||||||
["classification"] = 0,
|
["classification"] = 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
["id"] = 62906,
|
||||||
|
["name"] = "Elendon Truebough",
|
||||||
|
["tag"] = "Weapons",
|
||||||
|
["level"] = 44,
|
||||||
|
["classification"] = 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -11066,6 +11073,12 @@ MTH_DS_ItemOrigins = {
|
|||||||
["level"] = 40,
|
["level"] = 40,
|
||||||
["classification"] = 0,
|
["classification"] = 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
["id"] = 62843,
|
||||||
|
["name"] = "Ornala",
|
||||||
|
["level"] = 53,
|
||||||
|
["classification"] = 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -11747,6 +11760,19 @@ MTH_DS_ItemOrigins = {
|
|||||||
["level"] = 25,
|
["level"] = 25,
|
||||||
["classification"] = 0,
|
["classification"] = 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
["id"] = 62906,
|
||||||
|
["name"] = "Elendon Truebough",
|
||||||
|
["tag"] = "Weapons",
|
||||||
|
["level"] = 44,
|
||||||
|
["classification"] = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
["id"] = 62843,
|
||||||
|
["name"] = "Ornala",
|
||||||
|
["level"] = 53,
|
||||||
|
["classification"] = 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1121,6 +1121,51 @@ MTH_DS_AmmoItems = {
|
|||||||
[13219] = 0,
|
[13219] = 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[42198] = {
|
||||||
|
["name"] = "Bright Wood Arrows",
|
||||||
|
["level"] = 35,
|
||||||
|
["reqlevel"] = 30,
|
||||||
|
["icon"] = "INV_Ammo_Arrow_02",
|
||||||
|
["subtype"] = "arrow",
|
||||||
|
["dps"] = 10.5,
|
||||||
|
["crafted"] = true,
|
||||||
|
},
|
||||||
|
[42199] = {
|
||||||
|
["name"] = "Shade Wood Arrows",
|
||||||
|
["level"] = 45,
|
||||||
|
["reqlevel"] = 40,
|
||||||
|
["icon"] = "INV_Ammo_Arrow_02",
|
||||||
|
["subtype"] = "arrow",
|
||||||
|
["dps"] = 14.5,
|
||||||
|
["crafted"] = true,
|
||||||
|
},
|
||||||
|
[42200] = {
|
||||||
|
["name"] = "Smooth Ironfeather Arrows",
|
||||||
|
["level"] = 55,
|
||||||
|
["reqlevel"] = 50,
|
||||||
|
["icon"] = "INV_Ammo_Arrow_02",
|
||||||
|
["subtype"] = "arrow",
|
||||||
|
["dps"] = 17.5,
|
||||||
|
["crafted"] = true,
|
||||||
|
},
|
||||||
|
[42201] = {
|
||||||
|
["name"] = "Starfeather Arrows",
|
||||||
|
["level"] = 60,
|
||||||
|
["reqlevel"] = 55,
|
||||||
|
["icon"] = "INV_Ammo_Arrow_02",
|
||||||
|
["subtype"] = "arrow",
|
||||||
|
["dps"] = 19,
|
||||||
|
["crafted"] = true,
|
||||||
|
},
|
||||||
|
[42202] = {
|
||||||
|
["name"] = "Enchanted Thorium Shells",
|
||||||
|
["level"] = 60,
|
||||||
|
["reqlevel"] = 55,
|
||||||
|
["icon"] = "INV_Ammo_Bullet_03",
|
||||||
|
["subtype"] = "bullet",
|
||||||
|
["dps"] = 19,
|
||||||
|
["crafted"] = true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
MTH_DS_Items = MTH_DS_AmmoItems
|
MTH_DS_Items = MTH_DS_AmmoItems
|
||||||
+125
-117
@@ -2,120 +2,128 @@ if not MTH_DS then MTH_DS = {} end
|
|||||||
|
|
||||||
MTH_DS_MinimapSizes = {
|
MTH_DS_MinimapSizes = {
|
||||||
[0] = { 0, 0 },
|
[0] = { 0, 0 },
|
||||||
[1] = { 4925, 3283.34 },
|
[9] = { 5137.50, 3425.00 }, -- Mulgore
|
||||||
[3] = { 2487.5, 1658.34 },
|
[11] = { 2487.50, 1658.34 }, -- Barrens
|
||||||
[4] = { 3350, 2233.3 },
|
[15] = { 2170.84, 1447.90 }, -- Alterac
|
||||||
[8] = { 2293.75, 1529.17 },
|
[19] = { 5287.50, 3525.00 }, -- BlastedLands
|
||||||
[10] = { 2700, 1800.03 },
|
[20] = { 4518.75, 3012.50 }, -- Tirisfal
|
||||||
[11] = { 4135.42, 2756.25 },
|
[21] = { 4200.00, 2800.00 }, -- Silverpine
|
||||||
[12] = { 3470.84, 2314.62 },
|
[22] = { 2231.25, 1487.50 }, -- WesternPlaguelands
|
||||||
[14] = { 5287.5, 3525 },
|
[23] = { 3870.83, 2581.25 }, -- EasternPlaguelands
|
||||||
[15] = { 5250, 3500 },
|
[24] = { 3200.00, 2133.33 }, -- Hilsbrad
|
||||||
[16] = { 5070.84, 3381.25 },
|
[26] = { 3850.00, 2566.67 }, -- Hinterlands
|
||||||
[17] = { 10133.34, 6756.25 },
|
[27] = { 4925.00, 3283.34 }, -- DunMorogh
|
||||||
[25] = { 711.56, 468.68 },
|
[29] = { 2929.16, 1952.08 }, -- BurningSteppes
|
||||||
[28] = { 4300, 2866.67 },
|
[30] = { 3470.84, 2314.62 }, -- Elwynn
|
||||||
[33] = { 6381.25, 4254.1 },
|
[32] = { 5091.66, 3393.70 }, -- DeadwindPass
|
||||||
[36] = { 2800, 1866.67 },
|
[34] = { 2700.00, 1800.03 }, -- Duskwood
|
||||||
[38] = { 2758.33, 1839.58 },
|
[35] = { 2293.75, 1529.17 }, -- LochModan
|
||||||
[40] = { 3500, 2333.3 },
|
[37] = { 6381.25, 4254.10 }, -- Stranglethorn
|
||||||
[41] = { 2500, 1666.63 },
|
[39] = { 4135.42, 2756.25 }, -- Westfall
|
||||||
[44] = { 2170.84, 1447.9 },
|
[40] = { 10133.34, 6756.25 }, -- Wetlands
|
||||||
[45] = { 3600, 2400 },
|
[41] = { 5250.00, 3500.00 }, -- Teldrassil
|
||||||
[46] = { 2929.16, 1952.08 },
|
[42] = { 6550.00, 4366.66 }, -- Darkshore
|
||||||
[47] = { 3850, 2566.67 },
|
[43] = { 5766.67, 3843.75 }, -- Ashenvale
|
||||||
[51] = { 2231.25, 1487.5 },
|
[61] = { 4400.00, 2933.33 }, -- ThousandNeedles
|
||||||
[85] = { 4518.75, 3012.5 },
|
[81] = { 6018.00, 4010.00 }, -- StonetalonMountains
|
||||||
[130] = { 4200, 2800 },
|
[101] = { 4495.83, 2997.91 }, -- Desolace
|
||||||
[139] = { 3870.83, 2581.25 },
|
[121] = { 6950.00, 4633.33 }, -- Feralas
|
||||||
[141] = { 5091.66, 3393.7 },
|
[141] = { 2800.00, 1866.67 }, -- Dustwallow
|
||||||
[148] = { 6550, 4366.66 },
|
[161] = { 6900.00, 4600.00 }, -- Tanaris
|
||||||
[209] = { 381, 254 },
|
[181] = { 3600.00, 2400.00 }, -- Azshara
|
||||||
[215] = { 5137.5, 3425 },
|
[182] = { 5750.00, 3833.33 }, -- Felwood
|
||||||
[267] = { 3200, 2133.33 },
|
[201] = { 3700.00, 2466.66 }, -- UngoroCrater
|
||||||
[331] = { 5766.67, 3843.75 },
|
[241] = { 2308.33, 1539.59 }, -- Moonglade
|
||||||
[357] = { 6950, 4633.33 },
|
[261] = { 3483.33, 2322.92 }, -- Silithus
|
||||||
[361] = { 5750, 3833.33 },
|
[281] = { 7100.00, 4733.33 }, -- Winterspring
|
||||||
[400] = { 4400, 2933.33 },
|
[301] = { 1737.50, 1158.34 }, -- Stormwind
|
||||||
[405] = { 4495.83, 2997.91 },
|
[321] = { 1402.61, 935.42 }, -- Orgrimmar
|
||||||
[406] = { 6018, 4010 },
|
[341] = { 790.63, 527.61 }, -- Ironforge
|
||||||
[408] = { 3092.1, 2047 },
|
[362] = { 1043.75, 695.83 }, -- ThunderBluff
|
||||||
[409] = { 2901.45, 1915.9 },
|
[381] = { 1058.33, 705.71 }, -- Darnassus
|
||||||
[440] = { 6900, 4600 },
|
[382] = { 959.37, 640.11 }, -- Undercity
|
||||||
[490] = { 3700, 2466.66 },
|
[401] = { 4237.50, 2825.00 }, -- AlteracValley
|
||||||
[491] = { 736.45, 490.96 },
|
[443] = { 1145.84, 764.58 }, -- WarsongGulch
|
||||||
[493] = { 2308.33, 1539.59 },
|
[461] = { 1756.25, 1170.83 }, -- ArathiBasin
|
||||||
[616] = { 3206, 2142 },
|
[500] = { 828.00, 541.00 }, -- pfQ876
|
||||||
[618] = { 7100, 4733.33 },
|
[501] = { 3206.00, 2142.00 }, -- pfQ616
|
||||||
[717] = { 378.15, 252.1 },
|
[502] = { 3159.00, 2108.00 }, -- pfQ4012
|
||||||
[718] = { 572.78, 381.85 },
|
[503] = { 988.63, 1393.17 }, -- pfQ5023
|
||||||
[719] = { 1221.87, 806.42 },
|
[504] = { 2901.45, 1915.90 }, -- pfQ409
|
||||||
[721] = { 769.67, 513.11 },
|
[505] = { 3092.10, 2047.00 }, -- pfQ408
|
||||||
[722] = { 881, 589 },
|
[507] = { 3227.00, 2187.00 }, -- pfQ5121
|
||||||
[796] = { 203.66, 135.04 },
|
[509] = { 1468.00, 976.00 }, -- pfQ2040
|
||||||
[876] = { 828, 541 },
|
[510] = { 3666.00, 2442.00 }, -- pfQ5179
|
||||||
[1176] = { 1383.33, 922.91 },
|
[511] = { 1608.00, 1075.00 }, -- pfQ5024
|
||||||
[1337] = { 893.67, 595.78 },
|
[512] = { 2472.00, 1665.00 }, -- pfQ5536
|
||||||
[1377] = { 3483.33, 2322.92 },
|
[513] = { 3082.00, 2061.00 }, -- pfQ5225
|
||||||
[1477] = { 695.03, 463.35 },
|
[514] = { 449.89, 300.00 }, -- pfQ1581
|
||||||
[1497] = { 959.37, 640.11 },
|
[516] = { 572.78, 381.85 }, -- pfQ718
|
||||||
[1519] = { 1737.5, 1158.34 },
|
[517] = { 2112.09, 1410.89 }, -- pfQ2100
|
||||||
[1537] = { 790.63, 527.61 },
|
[518] = { 769.67, 513.11 }, -- pfQ721
|
||||||
[1581] = { 449.89, 300 },
|
[519] = { 711.56, 468.68 }, -- pfQ25
|
||||||
[1583] = { 886.84, 591.23 },
|
[520] = { 203.66, 135.04 }, -- pfQ796
|
||||||
[1584] = { 1985, 1268 },
|
[521] = { 893.67, 595.78 }, -- pfQ1337
|
||||||
[1637] = { 1402.61, 935.42 },
|
[522] = { 4139.02, 2946.00 }, -- pfQ3478
|
||||||
[1638] = { 1043.75, 695.83 },
|
[523] = { 1348.24, 888.09 }, -- pfQ1941
|
||||||
[1657] = { 1058.33, 705.71 },
|
[601] = { 1432.00, 977.00 }, -- pfQ5130
|
||||||
[1941] = { 1348.24, 888.09 },
|
[603] = { 738.86, 492.57 }, -- pfQ2437
|
||||||
[1977] = { 2120.83, 1414.6 },
|
[605] = { 1383.33, 922.91 }, -- pfQ1176
|
||||||
[2017] = { 1185.35, 789.86 },
|
[607] = { 695.03, 463.35 }, -- pfQ1477
|
||||||
[2040] = { 1468, 976 },
|
[609] = { 1221.87, 806.42 }, -- pfQ719
|
||||||
[2057] = { 320.05, 213.37 },
|
[611] = { 378.15, 252.10 }, -- pfQ717
|
||||||
[2100] = { 2112.09, 1410.89 },
|
[617] = { 1495.00, 983.00 }, -- pfQ2717
|
||||||
[2159] = { 483.11, 322.08 },
|
[619] = { 2120.83, 1414.60 }, -- pfQ1977
|
||||||
[2257] = { 312, 208 },
|
[623] = { 1985.00, 1268.00 }, -- pfQ1584
|
||||||
[2366] = { 1085.86, 726.61 },
|
[625] = { 2512.50, 1675.00 }, -- pfQ3429
|
||||||
[2437] = { 738.86, 492.57 },
|
[627] = { 483.11, 322.08 }, -- pfQ2159
|
||||||
[2557] = { 1324, 869 },
|
[629] = { 886.84, 591.23 }, -- pfQ1583
|
||||||
[2597] = { 4237.5, 2825 },
|
[635] = { 499.43, 332.95 }, -- pfQ2677
|
||||||
[2677] = { 499.43, 332.95 },
|
[637] = { 656.59, 434.97 }, -- pfQ5138
|
||||||
[2717] = { 1495, 983 },
|
[639] = { 881.00, 589.00 }, -- pfQ722
|
||||||
[3277] = { 1145.84, 764.58 },
|
[641] = { 736.45, 490.96 }, -- pfQ491
|
||||||
[3358] = { 1756.25, 1170.83 },
|
[643] = { 619.98, 413.32 }, -- pfQ5136
|
||||||
[3428] = { 977.56, 651.7 },
|
[644] = { 320.19, 213.46 }, -- pfQ5135
|
||||||
[3429] = { 2512.5, 1675 },
|
[645] = { 612.69, 408.46 }, -- pfQ5153
|
||||||
[3456] = { 1991.69, 1318.42 },
|
[646] = { 703.30, 468.87 }, -- pfQ5163
|
||||||
[3457] = { 823, 549 },
|
[648] = { 320.05, 213.37 }, -- pfQ2057
|
||||||
[3478] = { 4139.02, 2946 },
|
[650] = { 381.00, 254.00 }, -- pfQ209
|
||||||
[4012] = { 3159, 2108 },
|
[652] = { 1185.35, 789.86 }, -- pfQ2017
|
||||||
[5023] = { 988.63, 1393.17 },
|
[654] = { 977.56, 651.70 }, -- pfQ3428
|
||||||
[5024] = { 1608, 1075 },
|
[655] = { 2777.54, 1851.69 }, -- pfQ5147
|
||||||
[5053] = { 1007.7, 671.8 },
|
[657] = { 619.00, 410.00 }, -- pfQ5723
|
||||||
[5077] = { 2643.21, 1751.16 },
|
[659] = { 312.00, 208.00 }, -- pfQ2257
|
||||||
[5086] = { 546.75, 391.9 },
|
[662] = { 1271.99, 845.48 }, -- pfQ5204
|
||||||
[5087] = { 354.5, 234.74 },
|
[663] = { 1085.86, 726.61 }, -- pfQ2366
|
||||||
[5097] = { 1273.1, 853.72 },
|
[665] = { 1250.18, 837.44 }, -- pfQ5208
|
||||||
[5103] = { 752.12, 510.33 },
|
[667] = { 1991.69, 1318.42 }, -- pfQ3456
|
||||||
[5121] = { 3227, 2187 },
|
[668] = { 652.10, 439.67 }, -- pfQ5148
|
||||||
[5130] = { 1432, 977 },
|
[670] = { 2643.21, 1751.16 }, -- pfQ5077
|
||||||
[5135] = { 320.19, 213.46 },
|
[672] = { 752.12, 510.33 }, -- pfQ5103
|
||||||
[5136] = { 619.98, 413.32 },
|
[674] = { 546.75, 391.90 }, -- pfQ5086
|
||||||
[5138] = { 656.59, 434.97 },
|
[676] = { 354.50, 234.74 }, -- pfQ5087
|
||||||
[5144] = { 309, 208 },
|
[678] = { 1273.10, 853.72 }, -- pfQ5097
|
||||||
[5147] = { 2777.54, 1851.69 },
|
[680] = { 1007.70, 671.80 }, -- pfQ5053
|
||||||
[5148] = { 652.1, 439.67 },
|
[682] = { 823.00, 549.00 }, -- pfQ3457
|
||||||
[5153] = { 612.69, 408.46 },
|
[683] = { 2800.00, 1868.00 }, -- pfQ5557
|
||||||
[5163] = { 703.3, 468.87 },
|
[684] = { 5387.00, 3584.00 }, -- pfQ5602
|
||||||
[5179] = { 3666, 2442 },
|
[685] = { 3098.00, 2068.00 }, -- pfQ5561
|
||||||
[5204] = { 1271.99, 845.48 },
|
[686] = { 3241.00, 2157.00 }, -- pfQ5581
|
||||||
[5208] = { 1250.18, 837.44 },
|
[689] = { 1324.00, 869.00 }, -- pfQ2557
|
||||||
[5225] = { 3082, 2061 },
|
[691] = { 1634.00, 1073.00 }, -- pfQ5601
|
||||||
[5536] = { 2472, 1665 },
|
[693] = { 1980.00, 1350.00 }, -- pfQ5628
|
||||||
[5557] = { 2800, 1868 },
|
[698] = { 1234.00, 829.00 }, -- pfQ5641
|
||||||
[5561] = { 3098, 2068 },
|
[699] = { 7856.00, 5241.00 }, -- pfQ5642
|
||||||
[5581] = { 3241, 2157 },
|
[700] = { 861.00, 607.00 }, -- pfQ1769
|
||||||
[5601] = { 1634, 1073 },
|
[701] = { 1347.00, 971.00 }, -- pfQ5640
|
||||||
[5602] = { 5387, 3584 },
|
[702] = { 1047.00, 694.00 }, -- pfQ5722
|
||||||
[5628] = { 1980, 1350 },
|
[704] = { 1011.00, 653.00 }, -- pfQ5734
|
||||||
}
|
[705] = { 440.00, 279.00 }, -- pfQ5731
|
||||||
|
[613] = { 1125.00, 740.00 },
|
||||||
|
[615] = { 893.67, 595.78 },
|
||||||
|
[621] = { 1919.00, 1250.00 },
|
||||||
|
[631] = { 1170.00, 785.00 },
|
||||||
|
[633] = { 2112.09, 1410.89 },
|
||||||
|
[696] = { 1425.00, 962.00 },
|
||||||
|
[5144] = { 309.00, 208.00 },
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
-- MetaHunt: Pet spell DBC acquire-method overlay (learnMethod, minRank, nextSpellId)
|
||||||
|
-- AUTO-GENERATED by .tools — do not edit by hand.
|
||||||
|
-- Source DBC(s): SkillLineAbility.dbc, SkillLine.dbc
|
||||||
|
-- Generated: 2026-03-20 13:57 UTC
|
||||||
|
|
||||||
|
-- This file patches MTH_DS_PetSpells.allSpells entries with DBC-authoritative
|
||||||
|
-- learnMethod, minRank, and nextSpellId values.
|
||||||
|
-- Load order: after ds-pet-spells.lua and ds-pet-spells-trainer.lua
|
||||||
|
|
||||||
|
if not MTH_DS_PetSpells or not MTH_DS_PetSpells.allSpells then return end
|
||||||
|
|
||||||
|
local _acquire = {
|
||||||
|
[1747] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[1748] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[1749] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[1750] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[1751] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[1853] = { learnMethod="unknown(1)", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[2975] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[2976] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[2977] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[2980] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[2981] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[2982] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[3666] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[3667] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4195] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4196] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4197] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4198] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4199] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4200] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4201] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[4202] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[5048] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[5049] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[5149] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[7370] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[14922] = { learnMethod="unknown(1)", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[14923] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[14924] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[14925] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[14926] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[14927] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[16698] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17254] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17262] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17263] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17264] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17265] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17266] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17267] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[17268] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23100] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23111] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23112] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23146] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23149] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23150] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23163] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23166] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[23167] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24424] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24440] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24441] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24451] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24454] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24455] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24463] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24464] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24475] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24476] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24477] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24478] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24490] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24494] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24495] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24508] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24509] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24510] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24511] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24512] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24513] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24514] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24515] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24516] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24547] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24556] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24557] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24558] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24559] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24560] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24561] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24562] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24580] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24581] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24582] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24584] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24588] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24589] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24599] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24607] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24608] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24609] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24631] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24632] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24641] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[24845] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[25013] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[25014] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[25015] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[25016] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[25017] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[25077] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26065] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26094] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26184] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26185] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26186] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26189] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26190] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[26202] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[28343] = { learnMethod="trainer", minRank=1, nextSpellId=0, skillLineId=261 },
|
||||||
|
[46023] = { learnMethod="trainer", minRank=0, nextSpellId=0, skillLineId=261 },
|
||||||
|
[46303] = { learnMethod="trainer", minRank=0, nextSpellId=0, skillLineId=261 },
|
||||||
|
[46307] = { learnMethod="trainer", minRank=0, nextSpellId=0, skillLineId=261 },
|
||||||
|
[51154] = { learnMethod="trainer", minRank=0, nextSpellId=0, skillLineId=261 },
|
||||||
|
[51155] = { learnMethod="trainer", minRank=0, nextSpellId=0, skillLineId=261 },
|
||||||
|
[51157] = { learnMethod="trainer", minRank=0, nextSpellId=0, skillLineId=261 },
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, spell in ipairs(MTH_DS_PetSpells.allSpells) do
|
||||||
|
local meta = _acquire[spell.id]
|
||||||
|
if meta then
|
||||||
|
spell.learnMethod = meta.learnMethod
|
||||||
|
spell.minRank = meta.minRank
|
||||||
|
spell.nextSpellId = meta.nextSpellId
|
||||||
|
spell.skillLineId = meta.skillLineId
|
||||||
|
end
|
||||||
|
end
|
||||||
+45
-7
@@ -25,6 +25,7 @@ MTH_DS_PetSpells = {
|
|||||||
"Strider Presence",
|
"Strider Presence",
|
||||||
"Thunderstomp",
|
"Thunderstomp",
|
||||||
"Web",
|
"Web",
|
||||||
|
"Pollen Burst",
|
||||||
},
|
},
|
||||||
["allSpells"] = {
|
["allSpells"] = {
|
||||||
{
|
{
|
||||||
@@ -1804,15 +1805,30 @@ MTH_DS_PetSpells = {
|
|||||||
"(6) Apply Aura #26: Root",
|
"(6) Apply Aura #26: Root",
|
||||||
},
|
},
|
||||||
["icon"] = "Ability_Ensnare",
|
["icon"] = "Ability_Ensnare",
|
||||||
["id"] = 4167,
|
["id"] = 36533,
|
||||||
["name"] = "Web",
|
["name"] = "Web",
|
||||||
["range"] = "20 yards (Short Range)",
|
["range"] = "20 yards (Short Range)",
|
||||||
["rank"] = "",
|
["rank"] = "",
|
||||||
["rankNumber"] = 0,
|
["rankNumber"] = 0,
|
||||||
["school"] = "Physical",
|
["school"] = "Physical",
|
||||||
["sourceUrl"] = "https://database.turtlecraft.gg/?spell=4167",
|
["sourceUrl"] = "https://database.turtlecraft.gg/?spell=36533",
|
||||||
["trainLevel"] = 22,
|
["trainLevel"] = 22,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
["ability"] = "Pollen Burst",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "30 seconds",
|
||||||
|
["cost"] = "40 Focus",
|
||||||
|
["description"] = "Heal party members within 30 yards for 308 to 338 and reduce the attack speed of targets within 10 yards by 20% for 8 sec.",
|
||||||
|
["icon"] = "pollen_burst_2",
|
||||||
|
["id"] = 42051,
|
||||||
|
["name"] = "Pollen Burst",
|
||||||
|
["rank"] = "",
|
||||||
|
["rankNumber"] = 0,
|
||||||
|
["school"] = "Nature",
|
||||||
|
["sourceUrl"] = "https://database.turtlecraft.gg/?spell=42051",
|
||||||
|
["trainLevel"] = 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
["byAbility"] = {
|
["byAbility"] = {
|
||||||
["Bite"] = {
|
["Bite"] = {
|
||||||
@@ -3744,17 +3760,39 @@ MTH_DS_PetSpells = {
|
|||||||
"(6) Apply Aura #26: Root",
|
"(6) Apply Aura #26: Root",
|
||||||
},
|
},
|
||||||
["icon"] = "Ability_Ensnare",
|
["icon"] = "Ability_Ensnare",
|
||||||
["id"] = 4167,
|
["id"] = 36533,
|
||||||
["name"] = "Web",
|
["name"] = "Web",
|
||||||
["range"] = "20 yards (Short Range)",
|
["range"] = "20 yards (Short Range)",
|
||||||
["rank"] = "",
|
["rank"] = "",
|
||||||
["rankNumber"] = 0,
|
["rankNumber"] = 0,
|
||||||
["school"] = "Physical",
|
["school"] = "Physical",
|
||||||
["sourceUrl"] = "https://database.turtlecraft.gg/?spell=4167",
|
["sourceUrl"] = "https://database.turtlecraft.gg/?spell=36533",
|
||||||
["trainLevel"] = 22,
|
["trainLevel"] = 22,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
["Pollen Burst"] = {
|
||||||
|
["ability"] = "Pollen Burst",
|
||||||
|
["searchUrl"] = "https://database.turtlecraft.gg/?search=Pollen+Burst",
|
||||||
|
["spellCount"] = 1,
|
||||||
|
["spells"] = {
|
||||||
|
{
|
||||||
|
["ability"] = "Pollen Burst",
|
||||||
|
["castTime"] = "Instant",
|
||||||
|
["cooldown"] = "30 seconds",
|
||||||
|
["cost"] = "40 Focus",
|
||||||
|
["description"] = "Heal party members within 30 yards for 308 to 338 and reduce the attack speed of targets within 10 yards by 20% for 8 sec.",
|
||||||
|
["icon"] = "pollen_burst_2",
|
||||||
|
["id"] = 42051,
|
||||||
|
["name"] = "Pollen Burst",
|
||||||
|
["rank"] = "",
|
||||||
|
["rankNumber"] = 0,
|
||||||
|
["school"] = "Nature",
|
||||||
|
["sourceUrl"] = "https://database.turtlecraft.gg/?spell=42051",
|
||||||
|
["trainLevel"] = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
["cleanedBy"] = "post-process quality rules v2 hard-gate",
|
["cleanedBy"] = "post-process quality rules v2 hard-gate",
|
||||||
["droppedDuplicates"] = {
|
["droppedDuplicates"] = {
|
||||||
@@ -4293,14 +4331,14 @@ MTH_DS_PetSpells = {
|
|||||||
{
|
{
|
||||||
["ability"] = "Web",
|
["ability"] = "Web",
|
||||||
["droppedId"] = 12023,
|
["droppedId"] = 12023,
|
||||||
["keptId"] = 4167,
|
["keptId"] = 36533,
|
||||||
["mode"] = "lower-score",
|
["mode"] = "lower-score",
|
||||||
["rankNumber"] = 0,
|
["rankNumber"] = 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
["ability"] = "Web",
|
["ability"] = "Web",
|
||||||
["droppedId"] = 36533,
|
["droppedId"] = 4167,
|
||||||
["keptId"] = 4167,
|
["keptId"] = 36533,
|
||||||
["mode"] = "lower-score",
|
["mode"] = "lower-score",
|
||||||
["rankNumber"] = 0,
|
["rankNumber"] = 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
-- MetaHunt: Stable slot prices
|
||||||
|
-- AUTO-GENERATED by .tools — do not edit by hand.
|
||||||
|
-- Source DBC(s): StableSlotPrices.dbc
|
||||||
|
-- Generated: 2026-03-20 13:57 UTC
|
||||||
|
|
||||||
|
if not MTH_DS then MTH_DS = {} end
|
||||||
|
|
||||||
|
MTH_DS_StableSlotPrices = {
|
||||||
|
[1] = {
|
||||||
|
["cost_copper"] = 500,
|
||||||
|
["cost_gold"] = 0,
|
||||||
|
["cost_silver"] = 5,
|
||||||
|
["cost_copper_remainder"] = 0,
|
||||||
|
["display"] = "0g 5s 0c",
|
||||||
|
["acquireMethod"] = "gold",
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
["cost_copper"] = 50000,
|
||||||
|
["cost_gold"] = 5,
|
||||||
|
["cost_silver"] = 0,
|
||||||
|
["cost_copper_remainder"] = 0,
|
||||||
|
["display"] = "5g 0s 0c",
|
||||||
|
["acquireMethod"] = "gold",
|
||||||
|
},
|
||||||
|
[3] = {
|
||||||
|
["cost_copper"] = 2500000,
|
||||||
|
["cost_gold"] = 250,
|
||||||
|
["cost_silver"] = 0,
|
||||||
|
["cost_copper_remainder"] = 0,
|
||||||
|
["display"] = "250g 0s 0c",
|
||||||
|
["acquireMethod"] = "gold",
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
["cost_copper"] = 0,
|
||||||
|
["cost_gold"] = 0,
|
||||||
|
["cost_silver"] = 0,
|
||||||
|
["cost_copper_remainder"] = 0,
|
||||||
|
["display"] = "Shop",
|
||||||
|
["acquireMethod"] = "shop",
|
||||||
|
},
|
||||||
|
}
|
||||||
+23493
-23493
File diff suppressed because it is too large
Load Diff
+223
-167
File diff suppressed because it is too large
Load Diff
+219
-219
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,97 @@
|
|||||||
|
-- MetaHunt: Zone DBC enrichment (worldBounds, dbcAreaId, dbcMapId, dbcName)
|
||||||
|
-- AUTO-GENERATED by .tools — do not edit by hand.
|
||||||
|
-- Source DBC(s): WorldMapArea.dbc, AreaTable.dbc
|
||||||
|
-- Generated: 2026-03-20 13:57 UTC
|
||||||
|
|
||||||
|
if not MTH_DS_Zones then return end
|
||||||
|
|
||||||
|
-- WMA ID=301 map=0 'Stormwind'
|
||||||
|
if MTH_DS_Zones[1519] then
|
||||||
|
MTH_DS_Zones[1519]["dbcAreaId"] = 1519
|
||||||
|
MTH_DS_Zones[1519]["dbcMapId"] = 0
|
||||||
|
MTH_DS_Zones[1519]["dbcName"] = "Stormwind"
|
||||||
|
MTH_DS_Zones[1519]["worldBounds"] = {
|
||||||
|
["left"] = 1722.92,
|
||||||
|
["right"] = -14.58,
|
||||||
|
["top"] = -7995.8301,
|
||||||
|
["bottom"] = -9154.1699,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- WMA ID=321 map=1 'Ogrimmar'
|
||||||
|
if MTH_DS_Zones[1637] then
|
||||||
|
MTH_DS_Zones[1637]["dbcAreaId"] = 1637
|
||||||
|
MTH_DS_Zones[1637]["dbcMapId"] = 1
|
||||||
|
MTH_DS_Zones[1637]["dbcName"] = "Ogrimmar"
|
||||||
|
MTH_DS_Zones[1637]["worldBounds"] = {
|
||||||
|
["left"] = -3680.6001,
|
||||||
|
["right"] = -5083.21,
|
||||||
|
["top"] = 2273.8799,
|
||||||
|
["bottom"] = 1338.46,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- WMA ID=362 map=1 'ThunderBluff'
|
||||||
|
if MTH_DS_Zones[1638] then
|
||||||
|
MTH_DS_Zones[1638]["dbcAreaId"] = 1638
|
||||||
|
MTH_DS_Zones[1638]["dbcMapId"] = 1
|
||||||
|
MTH_DS_Zones[1638]["dbcName"] = "ThunderBluff"
|
||||||
|
MTH_DS_Zones[1638]["worldBounds"] = {
|
||||||
|
["left"] = 516.67,
|
||||||
|
["right"] = -527.08,
|
||||||
|
["top"] = -850.0,
|
||||||
|
["bottom"] = -1545.83,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- WMA ID=381 map=1 'Darnassis'
|
||||||
|
if MTH_DS_Zones[1657] then
|
||||||
|
MTH_DS_Zones[1657]["dbcAreaId"] = 1657
|
||||||
|
MTH_DS_Zones[1657]["dbcMapId"] = 1
|
||||||
|
MTH_DS_Zones[1657]["dbcName"] = "Darnassis"
|
||||||
|
MTH_DS_Zones[1657]["worldBounds"] = {
|
||||||
|
["left"] = 2938.3601,
|
||||||
|
["right"] = 1880.03,
|
||||||
|
["top"] = 10238.3203,
|
||||||
|
["bottom"] = 9532.5898,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- WMA ID=382 map=0 'Undercity'
|
||||||
|
if MTH_DS_Zones[1497] then
|
||||||
|
MTH_DS_Zones[1497]["dbcAreaId"] = 1497
|
||||||
|
MTH_DS_Zones[1497]["dbcMapId"] = 0
|
||||||
|
MTH_DS_Zones[1497]["dbcName"] = "Undercity"
|
||||||
|
MTH_DS_Zones[1497]["worldBounds"] = {
|
||||||
|
["left"] = 873.19,
|
||||||
|
["right"] = -86.18,
|
||||||
|
["top"] = 1877.95,
|
||||||
|
["bottom"] = 1237.84,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- WMA ID=508 map=1 'AmaniAlor'
|
||||||
|
if MTH_DS_Zones[2041] then
|
||||||
|
MTH_DS_Zones[2041]["dbcAreaId"] = 2041
|
||||||
|
MTH_DS_Zones[2041]["dbcMapId"] = 1
|
||||||
|
MTH_DS_Zones[2041]["dbcName"] = "AmaniAlor"
|
||||||
|
MTH_DS_Zones[2041]["worldBounds"] = {
|
||||||
|
["left"] = 3112.0,
|
||||||
|
["right"] = 1599.0,
|
||||||
|
["top"] = 3437.0,
|
||||||
|
["bottom"] = 2434.0,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- WMA ID=509 map=0 'AlahThalas'
|
||||||
|
if MTH_DS_Zones[2040] then
|
||||||
|
MTH_DS_Zones[2040]["dbcAreaId"] = 2040
|
||||||
|
MTH_DS_Zones[2040]["dbcMapId"] = 0
|
||||||
|
MTH_DS_Zones[2040]["dbcName"] = "AlahThalas"
|
||||||
|
MTH_DS_Zones[2040]["worldBounds"] = {
|
||||||
|
["left"] = -2169.0,
|
||||||
|
["right"] = -3637.0,
|
||||||
|
["top"] = 4907.0,
|
||||||
|
["bottom"] = 3931.0,
|
||||||
|
}
|
||||||
|
end
|
||||||
@@ -72,4 +72,6 @@ MTH_DS_ZoneNamesFallback = {
|
|||||||
[5581] = "Northwind",
|
[5581] = "Northwind",
|
||||||
[5601] = "Dragonmaw Retreat",
|
[5601] = "Dragonmaw Retreat",
|
||||||
[5602] = "Grim Reaches",
|
[5602] = "Grim Reaches",
|
||||||
|
[5641] = "Windhorn Canyon",
|
||||||
|
[5642] = "Moonwhisper Coast",
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,402 @@
|
|||||||
|
-- MetaHunt: WMA (WorldMapArea.dbc) zone reference data
|
||||||
|
-- AUTO-GENERATED by .tools/migrate_wma.py — do not edit by hand.
|
||||||
|
-- Source: Haxxor WMA CSV (patch-9.mpq)
|
||||||
|
--
|
||||||
|
-- Provides MTH_MAP_PFQ_TO_WMA: pfQ AreaTable ID → WMA ID lookup
|
||||||
|
-- Used by map-markers.lua to translate GetCurrentMapAreaID() results
|
||||||
|
-- and by GetCurrentMapID() to return WMA zone IDs for coord matching.
|
||||||
|
--
|
||||||
|
-- Provides MTH_DS_WMAZones: WMA ID → worldBounds + pfqAreaId
|
||||||
|
-- Used for map overlay features without modifying the pfQ-keyed MTH_DS_Zones.
|
||||||
|
|
||||||
|
if not MTH_DS then MTH_DS = {} end
|
||||||
|
|
||||||
|
-- pfQ AreaTable ID → WMA ID runtime bridge
|
||||||
|
MTH_MAP_PFQ_TO_WMA = {
|
||||||
|
[1] = 27, -- DunMorogh
|
||||||
|
[3] = 17, -- Badlands
|
||||||
|
[4] = 19, -- BlastedLands
|
||||||
|
[8] = 38, -- SwampOfSorrows
|
||||||
|
[10] = 34, -- Duskwood
|
||||||
|
[11] = 40, -- Wetlands
|
||||||
|
[12] = 30, -- Elwynn
|
||||||
|
[14] = 4, -- Durotar
|
||||||
|
[15] = 141, -- Dustwallow
|
||||||
|
[16] = 181, -- Aszhara
|
||||||
|
[17] = 11, -- Barrens
|
||||||
|
[25] = 519, -- BlackrockMountain
|
||||||
|
[28] = 22, -- WesternPlaguelands
|
||||||
|
[33] = 37, -- Stranglethorn
|
||||||
|
[36] = 15, -- Alterac
|
||||||
|
[38] = 35, -- LochModan
|
||||||
|
[40] = 39, -- Westfall
|
||||||
|
[41] = 32, -- DeadwindPass
|
||||||
|
[44] = 36, -- Redridge
|
||||||
|
[45] = 16, -- Arathi
|
||||||
|
[46] = 29, -- BurningSteppes
|
||||||
|
[47] = 26, -- Hinterlands
|
||||||
|
[51] = 28, -- SearingGorge
|
||||||
|
[85] = 20, -- Tirisfal
|
||||||
|
[130] = 21, -- Silverpine
|
||||||
|
[139] = 23, -- EasternPlaguelands
|
||||||
|
[141] = 41, -- Teldrassil
|
||||||
|
[148] = 42, -- Darkshore
|
||||||
|
[209] = 650, -- ShadowfangKeep
|
||||||
|
[215] = 9, -- Mulgore
|
||||||
|
[267] = 24, -- Hilsbrad
|
||||||
|
[331] = 43, -- Ashenvale
|
||||||
|
[357] = 121, -- Feralas
|
||||||
|
[361] = 182, -- Felwood
|
||||||
|
[400] = 61, -- ThousandNeedles
|
||||||
|
[405] = 101, -- Desolace
|
||||||
|
[406] = 81, -- StonetalonMountains
|
||||||
|
[408] = 505, -- Gillijim
|
||||||
|
[409] = 504, -- Lapidis
|
||||||
|
[440] = 161, -- Tanaris
|
||||||
|
[490] = 201, -- UngoroCrater
|
||||||
|
[491] = 641, -- RazorfenKraul
|
||||||
|
[493] = 241, -- Moonglade
|
||||||
|
[616] = 501, -- Hyjal
|
||||||
|
[618] = 281, -- Winterspring
|
||||||
|
[717] = 611, -- TheStockade
|
||||||
|
[718] = 516, -- WailingCavernsEntrance
|
||||||
|
[719] = 609, -- BlackFathomDeeps
|
||||||
|
[721] = 518, -- GnomereganEntrance
|
||||||
|
[722] = 639, -- RazorfenDowns
|
||||||
|
[796] = 520, -- ScarletMonasteryEntrance
|
||||||
|
[876] = 500, -- GMIsland
|
||||||
|
[1176] = 605, -- ZulFarrak
|
||||||
|
[1337] = 521, -- UldamanEntrance
|
||||||
|
[1377] = 261, -- Silithus
|
||||||
|
[1477] = 607, -- TheTempleOfAtalHakkar
|
||||||
|
[1497] = 382, -- Undercity
|
||||||
|
[1519] = 301, -- Stormwind
|
||||||
|
[1537] = 341, -- Ironforge
|
||||||
|
[1581] = 514, -- DeadminesEntrance
|
||||||
|
[1583] = 629, -- BlackrockSpire
|
||||||
|
[1584] = 623, -- BlackrockDepths
|
||||||
|
[1637] = 321, -- Orgrimmar
|
||||||
|
[1638] = 362, -- ThunderBluff
|
||||||
|
[1657] = 381, -- Darnassus
|
||||||
|
[1769] = 700, -- TimbermawTunnels
|
||||||
|
[1941] = 523, -- CavernsOfTime
|
||||||
|
[1977] = 619, -- ZulGurub
|
||||||
|
[2017] = 652, -- Stratholme
|
||||||
|
[2040] = 509, -- AlahThalas
|
||||||
|
[2057] = 648, -- Scholomance
|
||||||
|
[2100] = 517, -- MaraudonEntrance
|
||||||
|
[2159] = 627, -- OnyxiasLair
|
||||||
|
[2257] = 659, -- DeeprunTram
|
||||||
|
[2366] = 663, -- BlackMorass2f
|
||||||
|
[2437] = 603, -- Ragefire
|
||||||
|
[2557] = 689, -- DireMaulEntrance
|
||||||
|
[2597] = 401, -- AlteracValley
|
||||||
|
[2677] = 635, -- BlackwingLair
|
||||||
|
[2717] = 617, -- MoltenCore
|
||||||
|
[3277] = 443, -- WarsongGulch
|
||||||
|
[3358] = 461, -- ArathiBasin
|
||||||
|
[3428] = 654, -- AhnQiraj
|
||||||
|
[3429] = 625, -- RuinsofAhnQiraj
|
||||||
|
[3456] = 667, -- Naxxramas
|
||||||
|
[3457] = 682, -- UpperKarazhan
|
||||||
|
[3478] = 522, -- AhnQirajEntrance
|
||||||
|
[4012] = 502, -- ScarletEnclave
|
||||||
|
[5023] = 503, -- Sunnyglade
|
||||||
|
[5024] = 511, -- Icepoint
|
||||||
|
[5053] = 680, -- Moomoo
|
||||||
|
[5077] = 670, -- CrescentGrove
|
||||||
|
[5086] = 674, -- KarazhanCrypt
|
||||||
|
[5087] = 676, -- StormwindVault
|
||||||
|
[5097] = 678, -- EmeraldSanctum
|
||||||
|
[5103] = 672, -- HateforgeQuarry
|
||||||
|
[5121] = 507, -- TelAbim
|
||||||
|
[5130] = 601, -- WinterVeilVale
|
||||||
|
[5135] = 644, -- ScarletMonastery2f
|
||||||
|
[5136] = 643, -- ScarletMonastery
|
||||||
|
[5138] = 637, -- TheDeadmines
|
||||||
|
[5147] = 655, -- AhnQiraj2f
|
||||||
|
[5148] = 668, -- Naxxramas2f
|
||||||
|
[5153] = 645, -- ScarletMonastery3f
|
||||||
|
[5163] = 646, -- ScarletMonastery4f
|
||||||
|
[5179] = 510, -- Gilneas
|
||||||
|
[5204] = 662, -- BlackMorass
|
||||||
|
[5208] = 665, -- GilneasCity
|
||||||
|
[5225] = 513, -- ThalassianHighlands
|
||||||
|
[5536] = 512, -- BlackstoneIsland
|
||||||
|
[5557] = 683, -- UpperKarazhan2f
|
||||||
|
[5561] = 685, -- Balor
|
||||||
|
[5581] = 686, -- Northwind
|
||||||
|
[5601] = 691, -- DragonmawRetreat
|
||||||
|
[5602] = 684, -- GrimReaches
|
||||||
|
[5628] = 693, -- StormwroughtRuins
|
||||||
|
[5640] = 701, -- TimbermawEntrance
|
||||||
|
[5641] = 698, -- WindhornCanyon
|
||||||
|
[5642] = 699, -- Moonwhisper
|
||||||
|
[5722] = 702, -- ThornGorge
|
||||||
|
[5723] = 657, -- Karazhan
|
||||||
|
[5731] = 705, -- WindhornCanyonEntrance
|
||||||
|
[5734] = 704, -- FrostmaneHollow
|
||||||
|
}
|
||||||
|
|
||||||
|
-- WMA ID → pfQ AreaTable ID (for fallback lookups)
|
||||||
|
MTH_MAP_WMA_TO_PFQ = {
|
||||||
|
[4] = 14, -- Durotar
|
||||||
|
[9] = 215, -- Mulgore
|
||||||
|
[11] = 17, -- Barrens
|
||||||
|
[15] = 36, -- Alterac
|
||||||
|
[16] = 45, -- Arathi
|
||||||
|
[17] = 3, -- Badlands
|
||||||
|
[19] = 4, -- BlastedLands
|
||||||
|
[20] = 85, -- Tirisfal
|
||||||
|
[21] = 130, -- Silverpine
|
||||||
|
[22] = 28, -- WesternPlaguelands
|
||||||
|
[23] = 139, -- EasternPlaguelands
|
||||||
|
[24] = 267, -- Hilsbrad
|
||||||
|
[26] = 47, -- Hinterlands
|
||||||
|
[27] = 1, -- DunMorogh
|
||||||
|
[28] = 51, -- SearingGorge
|
||||||
|
[29] = 46, -- BurningSteppes
|
||||||
|
[30] = 12, -- Elwynn
|
||||||
|
[32] = 41, -- DeadwindPass
|
||||||
|
[34] = 10, -- Duskwood
|
||||||
|
[35] = 38, -- LochModan
|
||||||
|
[36] = 44, -- Redridge
|
||||||
|
[37] = 33, -- Stranglethorn
|
||||||
|
[38] = 8, -- SwampOfSorrows
|
||||||
|
[39] = 40, -- Westfall
|
||||||
|
[40] = 11, -- Wetlands
|
||||||
|
[41] = 141, -- Teldrassil
|
||||||
|
[42] = 148, -- Darkshore
|
||||||
|
[43] = 331, -- Ashenvale
|
||||||
|
[61] = 400, -- ThousandNeedles
|
||||||
|
[81] = 406, -- StonetalonMountains
|
||||||
|
[101] = 405, -- Desolace
|
||||||
|
[121] = 357, -- Feralas
|
||||||
|
[141] = 15, -- Dustwallow
|
||||||
|
[161] = 440, -- Tanaris
|
||||||
|
[181] = 16, -- Aszhara
|
||||||
|
[182] = 361, -- Felwood
|
||||||
|
[201] = 490, -- UngoroCrater
|
||||||
|
[241] = 493, -- Moonglade
|
||||||
|
[261] = 1377, -- Silithus
|
||||||
|
[281] = 618, -- Winterspring
|
||||||
|
[301] = 1519, -- Stormwind
|
||||||
|
[321] = 1637, -- Orgrimmar
|
||||||
|
[341] = 1537, -- Ironforge
|
||||||
|
[362] = 1638, -- ThunderBluff
|
||||||
|
[381] = 1657, -- Darnassus
|
||||||
|
[382] = 1497, -- Undercity
|
||||||
|
[401] = 2597, -- AlteracValley
|
||||||
|
[443] = 3277, -- WarsongGulch
|
||||||
|
[461] = 3358, -- ArathiBasin
|
||||||
|
[500] = 876, -- GMIsland
|
||||||
|
[501] = 616, -- Hyjal
|
||||||
|
[502] = 4012, -- ScarletEnclave
|
||||||
|
[503] = 5023, -- Sunnyglade
|
||||||
|
[504] = 409, -- Lapidis
|
||||||
|
[505] = 408, -- Gillijim
|
||||||
|
[507] = 5121, -- TelAbim
|
||||||
|
[509] = 2040, -- AlahThalas
|
||||||
|
[510] = 5179, -- Gilneas
|
||||||
|
[511] = 5024, -- Icepoint
|
||||||
|
[512] = 5536, -- BlackstoneIsland
|
||||||
|
[513] = 5225, -- ThalassianHighlands
|
||||||
|
[514] = 1581, -- DeadminesEntrance
|
||||||
|
[516] = 718, -- WailingCavernsEntrance
|
||||||
|
[517] = 2100, -- MaraudonEntrance
|
||||||
|
[518] = 721, -- GnomereganEntrance
|
||||||
|
[519] = 25, -- BlackrockMountain
|
||||||
|
[520] = 796, -- ScarletMonasteryEntrance
|
||||||
|
[521] = 1337, -- UldamanEntrance
|
||||||
|
[522] = 3478, -- AhnQirajEntrance
|
||||||
|
[523] = 1941, -- CavernsOfTime
|
||||||
|
[601] = 5130, -- WinterVeilVale
|
||||||
|
[603] = 2437, -- Ragefire
|
||||||
|
[605] = 1176, -- ZulFarrak
|
||||||
|
[607] = 1477, -- TheTempleOfAtalHakkar
|
||||||
|
[609] = 719, -- BlackFathomDeeps
|
||||||
|
[611] = 717, -- TheStockade
|
||||||
|
[617] = 2717, -- MoltenCore
|
||||||
|
[619] = 1977, -- ZulGurub
|
||||||
|
[623] = 1584, -- BlackrockDepths
|
||||||
|
[625] = 3429, -- RuinsofAhnQiraj
|
||||||
|
[627] = 2159, -- OnyxiasLair
|
||||||
|
[629] = 1583, -- BlackrockSpire
|
||||||
|
[635] = 2677, -- BlackwingLair
|
||||||
|
[637] = 5138, -- TheDeadmines
|
||||||
|
[639] = 722, -- RazorfenDowns
|
||||||
|
[641] = 491, -- RazorfenKraul
|
||||||
|
[643] = 5136, -- ScarletMonastery
|
||||||
|
[644] = 5135, -- ScarletMonastery2f
|
||||||
|
[645] = 5153, -- ScarletMonastery3f
|
||||||
|
[646] = 5163, -- ScarletMonastery4f
|
||||||
|
[648] = 2057, -- Scholomance
|
||||||
|
[650] = 209, -- ShadowfangKeep
|
||||||
|
[652] = 2017, -- Stratholme
|
||||||
|
[654] = 3428, -- AhnQiraj
|
||||||
|
[655] = 5147, -- AhnQiraj2f
|
||||||
|
[657] = 5723, -- Karazhan
|
||||||
|
[659] = 2257, -- DeeprunTram
|
||||||
|
[662] = 5204, -- BlackMorass
|
||||||
|
[663] = 2366, -- BlackMorass2f
|
||||||
|
[665] = 5208, -- GilneasCity
|
||||||
|
[667] = 3456, -- Naxxramas
|
||||||
|
[668] = 5148, -- Naxxramas2f
|
||||||
|
[670] = 5077, -- CrescentGrove
|
||||||
|
[672] = 5103, -- HateforgeQuarry
|
||||||
|
[674] = 5086, -- KarazhanCrypt
|
||||||
|
[676] = 5087, -- StormwindVault
|
||||||
|
[678] = 5097, -- EmeraldSanctum
|
||||||
|
[680] = 5053, -- Moomoo
|
||||||
|
[682] = 3457, -- UpperKarazhan
|
||||||
|
[683] = 5557, -- UpperKarazhan2f
|
||||||
|
[684] = 5602, -- GrimReaches
|
||||||
|
[685] = 5561, -- Balor
|
||||||
|
[686] = 5581, -- Northwind
|
||||||
|
[689] = 2557, -- DireMaulEntrance
|
||||||
|
[691] = 5601, -- DragonmawRetreat
|
||||||
|
[693] = 5628, -- StormwroughtRuins
|
||||||
|
[698] = 5641, -- WindhornCanyon
|
||||||
|
[699] = 5642, -- Moonwhisper
|
||||||
|
[700] = 1769, -- TimbermawTunnels
|
||||||
|
[701] = 5640, -- TimbermawEntrance
|
||||||
|
[702] = 5722, -- ThornGorge
|
||||||
|
[704] = 5734, -- FrostmaneHollow
|
||||||
|
[705] = 5731, -- WindhornCanyonEntrance
|
||||||
|
}
|
||||||
|
|
||||||
|
-- WMA ID → worldBounds + pfqAreaId (for map overlay and minimap calibration)
|
||||||
|
MTH_DS_WMAZones = {
|
||||||
|
[4] = { pfqAreaId=14, mapId=1, left=-1962.50, right=-7250.00, top=1808.33, bottom=-1716.67, width=5287.50, height=3525.00 }, -- Durotar
|
||||||
|
[9] = { pfqAreaId=215, mapId=1, left=2047.92, right=-3089.58, top=-272.92, bottom=-3697.92, width=5137.50, height=3425.00 }, -- Mulgore
|
||||||
|
[11] = { pfqAreaId=17, mapId=1, left=2622.92, right=-7510.42, top=1612.50, bottom=-5143.75, width=10133.34, height=6756.25 }, -- Barrens
|
||||||
|
[13] = { pfqAreaId=0, mapId=1, left=17066.60, right=-19733.21, top=12799.90, bottom=-11733.30, width=36799.81, height=24533.20 }, -- Kalimdor
|
||||||
|
[14] = { pfqAreaId=0, mapId=0, left=16000.00, right=-19199.90, top=7466.60, bottom=-16000.00, width=35199.90, height=23466.60 }, -- Azeroth
|
||||||
|
[15] = { pfqAreaId=36, mapId=0, left=783.33, right=-2016.67, top=1500.00, bottom=-366.67, width=2800.00, height=1866.67 }, -- Alterac
|
||||||
|
[16] = { pfqAreaId=45, mapId=0, left=-866.67, right=-4466.67, top=-133.33, bottom=-2533.33, width=3600.00, height=2400.00 }, -- Arathi
|
||||||
|
[17] = { pfqAreaId=3, mapId=0, left=-2079.17, right=-4566.67, top=-5889.58, bottom=-7547.92, width=2487.50, height=1658.34 }, -- Badlands
|
||||||
|
[19] = { pfqAreaId=4, mapId=0, left=-1241.67, right=-4591.67, top=-10566.67, bottom=-12800.00, width=3350.00, height=2233.33 }, -- BlastedLands
|
||||||
|
[20] = { pfqAreaId=85, mapId=0, left=3033.33, right=-1485.42, top=3837.50, bottom=825.00, width=4518.75, height=3012.50 }, -- Tirisfal
|
||||||
|
[21] = { pfqAreaId=130, mapId=0, left=3450.00, right=-750.00, top=1666.67, bottom=-1133.33, width=4200.00, height=2800.00 }, -- Silverpine
|
||||||
|
[22] = { pfqAreaId=28, mapId=0, left=416.67, right=-3883.33, top=3366.67, bottom=500.00, width=4300.00, height=2866.67 }, -- WesternPlaguelands
|
||||||
|
[23] = { pfqAreaId=139, mapId=0, left=-2185.42, right=-6056.25, top=3800.00, bottom=1218.75, width=3870.83, height=2581.25 }, -- EasternPlaguelands
|
||||||
|
[24] = { pfqAreaId=267, mapId=0, left=1066.67, right=-2133.33, top=400.00, bottom=-1733.33, width=3200.00, height=2133.33 }, -- Hilsbrad
|
||||||
|
[26] = { pfqAreaId=47, mapId=0, left=-1575.00, right=-5425.00, top=1466.67, bottom=-1100.00, width=3850.00, height=2566.67 }, -- Hinterlands
|
||||||
|
[27] = { pfqAreaId=1, mapId=0, left=1802.08, right=-3122.92, top=-3877.08, bottom=-7160.42, width=4925.00, height=3283.34 }, -- DunMorogh
|
||||||
|
[28] = { pfqAreaId=51, mapId=0, left=-322.92, right=-2554.17, top=-6100.00, bottom=-7587.50, width=2231.25, height=1487.50 }, -- SearingGorge
|
||||||
|
[29] = { pfqAreaId=46, mapId=0, left=-266.67, right=-3195.83, top=-7031.25, bottom=-8983.33, width=2929.16, height=1952.08 }, -- BurningSteppes
|
||||||
|
[30] = { pfqAreaId=12, mapId=0, left=1535.42, right=-1935.42, top=-7939.58, bottom=-10254.17, width=3470.84, height=2314.59 }, -- Elwynn
|
||||||
|
[32] = { pfqAreaId=41, mapId=0, left=-833.33, right=-3333.33, top=-9866.67, bottom=-11533.33, width=2500.00, height=1666.66 }, -- DeadwindPass
|
||||||
|
[34] = { pfqAreaId=10, mapId=0, left=833.33, right=-1866.67, top=-9716.67, bottom=-11516.67, width=2700.00, height=1800.00 }, -- Duskwood
|
||||||
|
[35] = { pfqAreaId=38, mapId=0, left=-1993.75, right=-4752.08, top=-4487.50, bottom=-6327.08, width=2758.33, height=1839.58 }, -- LochModan
|
||||||
|
[36] = { pfqAreaId=44, mapId=0, left=-1570.83, right=-3741.67, top=-8575.00, bottom=-10022.92, width=2170.84, height=1447.92 }, -- Redridge
|
||||||
|
[37] = { pfqAreaId=33, mapId=0, left=2220.83, right=-4160.42, top=-11168.75, bottom=-15422.92, width=6381.25, height=4254.17 }, -- Stranglethorn
|
||||||
|
[38] = { pfqAreaId=8, mapId=0, left=-2222.92, right=-4516.67, top=-9620.83, bottom=-11150.00, width=2293.75, height=1529.17 }, -- SwampOfSorrows
|
||||||
|
[39] = { pfqAreaId=40, mapId=0, left=3016.67, right=-483.33, top=-9400.00, bottom=-11733.33, width=3500.00, height=2333.33 }, -- Westfall
|
||||||
|
[40] = { pfqAreaId=11, mapId=0, left=-389.58, right=-4525.00, top=-2147.92, bottom=-4904.17, width=4135.42, height=2756.25 }, -- Wetlands
|
||||||
|
[41] = { pfqAreaId=141, mapId=1, left=3814.58, right=-1277.08, top=11831.25, bottom=8437.50, width=5091.66, height=3393.75 }, -- Teldrassil
|
||||||
|
[42] = { pfqAreaId=148, mapId=1, left=2941.67, right=-3608.33, top=8333.33, bottom=3966.67, width=6550.00, height=4366.66 }, -- Darkshore
|
||||||
|
[43] = { pfqAreaId=331, mapId=1, left=1700.00, right=-4066.67, top=4672.92, bottom=829.17, width=5766.67, height=3843.75 }, -- Ashenvale
|
||||||
|
[61] = { pfqAreaId=400, mapId=1, left=-433.33, right=-4833.33, top=-3966.67, bottom=-6900.00, width=4400.00, height=2933.33 }, -- ThousandNeedles
|
||||||
|
[81] = { pfqAreaId=406, mapId=1, left=3245.83, right=-1637.50, top=2916.67, bottom=-339.58, width=4883.33, height=3256.25 }, -- StonetalonMountains
|
||||||
|
[101] = { pfqAreaId=405, mapId=1, left=4233.33, right=-262.50, top=452.08, bottom=-2545.83, width=4495.83, height=2997.91 }, -- Desolace
|
||||||
|
[121] = { pfqAreaId=357, mapId=1, left=5441.67, right=-1508.33, top=-2366.67, bottom=-7000.00, width=6950.00, height=4633.33 }, -- Feralas
|
||||||
|
[141] = { pfqAreaId=15, mapId=1, left=-975.00, right=-6225.00, top=-2033.33, bottom=-5533.33, width=5250.00, height=3500.00 }, -- Dustwallow
|
||||||
|
[161] = { pfqAreaId=440, mapId=1, left=-218.75, right=-7118.75, top=-5875.00, bottom=-10475.00, width=6900.00, height=4600.00 }, -- Tanaris
|
||||||
|
[181] = { pfqAreaId=16, mapId=1, left=-3277.08, right=-8347.92, top=5341.67, bottom=1960.42, width=5070.84, height=3381.25 }, -- Aszhara
|
||||||
|
[182] = { pfqAreaId=361, mapId=1, left=1641.67, right=-4108.33, top=7133.33, bottom=3300.00, width=5750.00, height=3833.33 }, -- Felwood
|
||||||
|
[201] = { pfqAreaId=490, mapId=1, left=533.33, right=-3166.67, top=-5966.67, bottom=-8433.33, width=3700.00, height=2466.66 }, -- UngoroCrater
|
||||||
|
[241] = { pfqAreaId=493, mapId=1, left=-1381.25, right=-3689.58, top=8491.67, bottom=6952.08, width=2308.33, height=1539.59 }, -- Moonglade
|
||||||
|
[261] = { pfqAreaId=1377, mapId=1, left=2537.50, right=-945.83, top=-5958.33, bottom=-8281.25, width=3483.33, height=2322.92 }, -- Silithus
|
||||||
|
[281] = { pfqAreaId=618, mapId=1, left=-316.67, right=-7416.67, top=8533.33, bottom=3800.00, width=7100.00, height=4733.33 }, -- Winterspring
|
||||||
|
[301] = { pfqAreaId=1519, mapId=0, left=1722.92, right=-14.58, top=-7995.83, bottom=-9154.17, width=1737.50, height=1158.34 }, -- Stormwind
|
||||||
|
[321] = { pfqAreaId=1637, mapId=1, left=-3680.60, right=-5083.21, top=2273.88, bottom=1338.46, width=1402.61, height=935.42 }, -- Orgrimmar
|
||||||
|
[341] = { pfqAreaId=1537, mapId=0, left=-713.59, right=-1504.22, top=-4569.24, bottom=-5096.85, width=790.63, height=527.61 }, -- Ironforge
|
||||||
|
[362] = { pfqAreaId=1638, mapId=1, left=516.67, right=-527.08, top=-850.00, bottom=-1545.83, width=1043.75, height=695.83 }, -- ThunderBluff
|
||||||
|
[381] = { pfqAreaId=1657, mapId=1, left=2938.36, right=1880.03, top=10238.32, bottom=9532.59, width=1058.33, height=705.73 }, -- Darnassus
|
||||||
|
[382] = { pfqAreaId=1497, mapId=0, left=873.19, right=-86.18, top=1877.95, bottom=1237.84, width=959.37, height=640.11 }, -- Undercity
|
||||||
|
[401] = { pfqAreaId=2597, mapId=30, left=1781.25, right=-2456.25, top=1085.42, bottom=-1739.58, width=4237.50, height=2825.00 }, -- AlteracValley
|
||||||
|
[443] = { pfqAreaId=3277, mapId=489, left=2041.67, right=895.83, top=1627.08, bottom=862.50, width=1145.84, height=764.58 }, -- WarsongGulch
|
||||||
|
[461] = { pfqAreaId=3358, mapId=529, left=1858.33, right=102.08, top=1508.33, bottom=337.50, width=1756.25, height=1170.83 }, -- ArathiBasin
|
||||||
|
[500] = { pfqAreaId=876, mapId=1, left=16748.00, right=15920.00, top=16525.00, bottom=15984.00, width=828.00, height=541.00 }, -- GMIsland
|
||||||
|
[501] = { pfqAreaId=616, mapId=1, left=-1080.00, right=-4286.00, top=6125.00, bottom=3983.00, width=3206.00, height=2142.00 }, -- Hyjal
|
||||||
|
[502] = { pfqAreaId=4012, mapId=0, left=-4050.00, right=-7209.00, top=3087.00, bottom=979.00, width=3159.00, height=2108.00 }, -- ScarletEnclave
|
||||||
|
[503] = { pfqAreaId=5023, mapId=27, left=1013.00, right=-435.00, top=1823.00, bottom=858.00, width=1448.00, height=965.00 }, -- Sunnyglade
|
||||||
|
[504] = { pfqAreaId=409, mapId=0, left=4933.33, right=2031.88, top=-11043.48, bottom=-12959.42, width=2901.45, height=1915.94 }, -- Lapidis
|
||||||
|
[505] = { pfqAreaId=408, mapId=0, left=4436.22, right=1344.12, top=-12528.71, bottom=-14575.72, width=3092.10, height=2047.01 }, -- Gillijim
|
||||||
|
[507] = { pfqAreaId=5121, mapId=1, left=-5179.00, right=-8406.00, top=-7184.00, bottom=-9371.00, width=3227.00, height=2187.00 }, -- TelAbim
|
||||||
|
[509] = { pfqAreaId=2040, mapId=0, left=-2169.00, right=-3637.00, top=4907.00, bottom=3931.00, width=1468.00, height=976.00 }, -- AlahThalas
|
||||||
|
[510] = { pfqAreaId=5179, mapId=0, left=3253.00, right=-413.00, top=-359.00, bottom=-2801.00, width=3666.00, height=2442.00 }, -- Gilneas
|
||||||
|
[511] = { pfqAreaId=5024, mapId=1, left=-5595.00, right=-7203.00, top=14405.00, bottom=13330.00, width=1608.00, height=1075.00 }, -- Icepoint
|
||||||
|
[512] = { pfqAreaId=5536, mapId=1, left=-6274.00, right=-8746.00, top=799.00, bottom=-866.00, width=2472.00, height=1665.00 }, -- BlackstoneIsland
|
||||||
|
[513] = { pfqAreaId=5225, mapId=0, left=-1005.00, right=-4087.00, top=4952.00, bottom=2891.00, width=3082.00, height=2061.00 }, -- ThalassianHighlands
|
||||||
|
[514] = { pfqAreaId=1581, mapId=0, left=1793.18, right=1343.29, top=-11054.94, bottom=-11354.86, width=449.89, height=299.92 }, -- DeadminesEntrance
|
||||||
|
[516] = { pfqAreaId=718, mapId=1, left=-1900.87, right=-2473.65, top=-488.64, bottom=-870.49, width=572.78, height=381.85 }, -- WailingCavernsEntrance
|
||||||
|
[517] = { pfqAreaId=2100, mapId=1, left=3208.00, right=2384.00, top=-1096.00, bottom=-1646.00, width=824.00, height=550.00 }, -- MaraudonEntrance
|
||||||
|
[518] = { pfqAreaId=721, mapId=0, left=1027.64, right=456.45, top=-4806.32, bottom=-5185.46, width=571.19, height=379.14 }, -- GnomereganEntrance
|
||||||
|
[519] = { pfqAreaId=25, mapId=0, left=-760.94, right=-1472.50, top=-7327.82, bottom=-7796.50, width=711.56, height=468.68 }, -- BlackrockMountain
|
||||||
|
[520] = { pfqAreaId=796, mapId=0, left=-659.96, right=-863.62, top=2947.37, bottom=2812.33, width=203.66, height=135.04 }, -- ScarletMonasteryEntrance
|
||||||
|
[521] = { pfqAreaId=1337, mapId=0, left=-2747.15, right=-3310.46, top=-5953.41, bottom=-6329.51, width=563.31, height=376.10 }, -- UldamanEntrance
|
||||||
|
[522] = { pfqAreaId=3478, mapId=1, left=3932.67, right=-206.35, top=-8005.20, bottom=-10951.25, width=4139.02, height=2946.05 }, -- AhnQirajEntrance
|
||||||
|
[523] = { pfqAreaId=1941, mapId=1, left=-3695.85, right=-5044.09, top=-8023.09, bottom=-8911.18, width=1348.24, height=888.09 }, -- CavernsOfTime
|
||||||
|
[601] = { pfqAreaId=5130, mapId=813, left=1916.00, right=484.00, top=-2332.00, bottom=-3309.00, width=1432.00, height=977.00 }, -- WinterVeilVale
|
||||||
|
[603] = { pfqAreaId=2437, mapId=389, left=452.87, right=-285.99, top=39.62, bottom=-452.95, width=738.86, height=492.57 }, -- Ragefire
|
||||||
|
[605] = { pfqAreaId=1176, mapId=209, left=1625.00, right=241.67, top=2052.08, bottom=1129.17, width=1383.33, height=922.91 }, -- ZulFarrak
|
||||||
|
[607] = { pfqAreaId=1477, mapId=109, left=442.76, right=-252.27, top=-255.17, bottom=-718.52, width=695.03, height=463.35 }, -- TheTempleOfAtalHakkar
|
||||||
|
[609] = { pfqAreaId=719, mapId=48, left=485.41, right=-736.46, top=-107.91, bottom=-914.33, width=1221.87, height=806.42 }, -- BlackFathomDeeps
|
||||||
|
[611] = { pfqAreaId=717, mapId=34, left=189.82, right=-188.33, top=220.63, bottom=-31.47, width=378.15, height=252.10 }, -- TheStockade
|
||||||
|
[613] = { pfqAreaId=721, mapId=90, left=863.00, right=-262.00, top=-245.00, bottom=-985.00, width=1125.00, height=740.00 }, -- Gnomeregan
|
||||||
|
[615] = { pfqAreaId=1337, mapId=70, left=645.12, right=-248.55, top=204.31, bottom=-391.47, width=893.67, height=595.78 }, -- Uldaman
|
||||||
|
[617] = { pfqAreaId=2717, mapId=409, left=-11.00, right=-1506.00, top=1439.00, bottom=456.00, width=1495.00, height=983.00 }, -- MoltenCore
|
||||||
|
[619] = { pfqAreaId=1977, mapId=309, left=-612.50, right=-2733.33, top=-11225.00, bottom=-12639.58, width=2120.83, height=1414.58 }, -- ZulGurub
|
||||||
|
[621] = { pfqAreaId=2557, mapId=429, left=1007.00, right=-912.00, top=955.00, bottom=-295.00, width=1919.00, height=1250.00 }, -- DireMaul
|
||||||
|
[623] = { pfqAreaId=1584, mapId=230, left=875.00, right=-1110.00, top=1513.00, bottom=245.00, width=1985.00, height=1268.00 }, -- BlackrockDepths
|
||||||
|
[625] = { pfqAreaId=3429, mapId=509, left=3035.42, right=522.92, top=-8233.33, bottom=-9908.33, width=2512.50, height=1675.00 }, -- RuinsofAhnQiraj
|
||||||
|
[627] = { pfqAreaId=2159, mapId=249, left=155.00, right=-366.00, top=86.00, bottom=-262.00, width=521.00, height=348.00 }, -- OnyxiasLair
|
||||||
|
[629] = { pfqAreaId=1583, mapId=229, left=10.59, right=-876.25, top=304.40, bottom=-286.83, width=886.84, height=591.23 }, -- BlackrockSpire
|
||||||
|
[631] = { pfqAreaId=718, mapId=43, left=790.00, right=-380.00, top=215.00, bottom=-570.00, width=1170.00, height=785.00 }, -- WailingCaverns
|
||||||
|
[633] = { pfqAreaId=2100, mapId=349, left=485.41, right=-1626.68, top=1199.76, bottom=-211.13, width=2112.09, height=1410.89 }, -- Maraudon
|
||||||
|
[635] = { pfqAreaId=2677, mapId=469, left=-645.00, right=-1422.00, top=-7255.00, bottom=-7760.00, width=777.00, height=505.00 }, -- BlackwingLair
|
||||||
|
[637] = { pfqAreaId=5138, mapId=36, left=-322.94, right=-979.53, top=36.93, bottom=-398.04, width=656.59, height=434.97 }, -- TheDeadmines
|
||||||
|
[639] = { pfqAreaId=722, mapId=129, left=1271.00, right=390.00, top=2683.00, bottom=2094.00, width=881.00, height=589.00 }, -- RazorfenDowns
|
||||||
|
[641] = { pfqAreaId=491, mapId=47, left=2058.92, right=1322.47, top=2349.64, bottom=1858.68, width=736.45, height=490.96 }, -- RazorfenKraul
|
||||||
|
[643] = { pfqAreaId=5136, mapId=189, left=1567.97, right=947.99, top=2030.18, bottom=1616.86, width=619.98, height=413.32 }, -- ScarletMonastery
|
||||||
|
[644] = { pfqAreaId=5135, mapId=189, left=-162.27, right=-482.46, top=307.37, bottom=93.91, width=320.19, height=213.46 }, -- ScarletMonastery2f
|
||||||
|
[645] = { pfqAreaId=5153, mapId=189, left=50.27, right=-562.42, top=2009.10, bottom=1600.64, width=612.69, height=408.46 }, -- ScarletMonastery3f
|
||||||
|
[646] = { pfqAreaId=5163, mapId=189, left=1743.99, right=1040.69, top=1281.29, bottom=812.42, width=703.30, height=468.87 }, -- ScarletMonastery4f
|
||||||
|
[648] = { pfqAreaId=2057, mapId=289, left=251.41, right=-68.64, top=317.70, bottom=104.33, width=320.05, height=213.37 }, -- Scholomance
|
||||||
|
[650] = { pfqAreaId=209, mapId=33, left=2436.00, right=2055.00, top=-61.00, bottom=-315.00, width=381.00, height=254.00 }, -- ShadowfangKeep
|
||||||
|
[652] = { pfqAreaId=2017, mapId=329, left=-2639.83, right=-3825.18, top=4163.90, bottom=3374.04, width=1185.35, height=789.86 }, -- Stratholme
|
||||||
|
[654] = { pfqAreaId=3428, mapId=531, left=2515.63, right=1538.07, top=-8051.80, bottom=-8703.50, width=977.56, height=651.70 }, -- AhnQiraj
|
||||||
|
[655] = { pfqAreaId=5147, mapId=531, left=2915.62, right=138.08, top=-7659.29, bottom=-9510.98, width=2777.54, height=1851.69 }, -- AhnQiraj2f
|
||||||
|
[657] = { pfqAreaId=5723, mapId=532, left=-1546.00, right=-2165.00, top=-10789.00, bottom=-11199.00, width=619.00, height=410.00 }, -- Karazhan
|
||||||
|
[659] = { pfqAreaId=2257, mapId=369, left=2623.50, right=2311.50, top=95.50, bottom=-112.50, width=312.00, height=208.00 }, -- DeeprunTram
|
||||||
|
[662] = { pfqAreaId=5204, mapId=269, left=7338.47, right=6066.48, top=-1247.55, bottom=-2093.03, width=1271.99, height=845.48 }, -- BlackMorass
|
||||||
|
[663] = { pfqAreaId=2366, mapId=269, left=7651.85, right=6565.99, top=-1500.47, bottom=-2227.08, width=1085.86, height=726.61 }, -- BlackMorass2f
|
||||||
|
[665] = { pfqAreaId=5208, mapId=815, left=3290.32, right=2040.14, top=-760.72, bottom=-1598.16, width=1250.18, height=837.44 }, -- GilneasCity
|
||||||
|
[667] = { pfqAreaId=3456, mapId=533, left=-2375.27, right=-4366.96, top=3656.70, bottom=2338.28, width=1991.69, height=1318.42 }, -- Naxxramas
|
||||||
|
[668] = { pfqAreaId=5148, mapId=533, left=-4869.36, right=-5521.46, top=3816.56, bottom=3376.89, width=652.10, height=439.67 }, -- Naxxramas2f
|
||||||
|
[670] = { pfqAreaId=5077, mapId=802, left=1207.72, right=-1435.49, top=882.98, bottom=-868.18, width=2643.21, height=1751.16 }, -- CrescentGrove
|
||||||
|
[672] = { pfqAreaId=5103, mapId=808, left=-3024.33, right=-3776.45, top=-7888.28, bottom=-8398.61, width=752.12, height=510.33 }, -- HateforgeQuarry
|
||||||
|
[674] = { pfqAreaId=5086, mapId=800, left=-1302.51, right=-1849.26, top=-10916.17, bottom=-11308.14, width=546.75, height=391.97 }, -- KarazhanCrypt
|
||||||
|
[676] = { pfqAreaId=5087, mapId=35, left=314.34, right=-40.16, top=89.30, bottom=-145.44, width=354.50, height=234.74 }, -- StormwindVault
|
||||||
|
[678] = { pfqAreaId=5097, mapId=807, left=3939.10, right=2666.00, top=3519.72, bottom=2666.00, width=1273.10, height=853.72 }, -- EmeraldSanctum
|
||||||
|
[680] = { pfqAreaId=5053, mapId=801, left=17296.30, right=16288.62, top=17158.52, bottom=16486.73, width=1007.68, height=671.79 }, -- Moomoo
|
||||||
|
[682] = { pfqAreaId=3457, mapId=814, left=-1378.00, right=-2201.00, top=-10887.00, bottom=-11436.00, width=823.00, height=549.00 }, -- UpperKarazhan
|
||||||
|
[683] = { pfqAreaId=5557, mapId=814, left=-1483.00, right=-4283.00, top=-5800.00, bottom=-7668.00, width=2800.00, height=1868.00 }, -- UpperKarazhan2f
|
||||||
|
[684] = { pfqAreaId=5602, mapId=0, left=-2072.00, right=-7459.00, top=-2904.00, bottom=-6488.00, width=5387.00, height=3584.00 }, -- GrimReaches
|
||||||
|
[685] = { pfqAreaId=5561, mapId=0, left=4728.00, right=1630.00, top=-7577.00, bottom=-9645.00, width=3098.00, height=2068.00 }, -- Balor
|
||||||
|
[686] = { pfqAreaId=5581, mapId=0, left=2258.00, right=-983.00, top=-6327.00, bottom=-8484.00, width=3241.00, height=2157.00 }, -- Northwind
|
||||||
|
[689] = { pfqAreaId=2557, mapId=1, left=2014.00, right=690.00, top=-3401.00, bottom=-4270.00, width=1324.00, height=869.00 }, -- DireMaulEntrance
|
||||||
|
[691] = { pfqAreaId=5601, mapId=816, left=-3428.00, right=-5062.00, top=-5599.00, bottom=-6672.00, width=1634.00, height=1073.00 }, -- DragonmawRetreat
|
||||||
|
[693] = { pfqAreaId=5628, mapId=818, left=-3365.00, right=-5345.00, top=-5424.00, bottom=-6774.00, width=1980.00, height=1350.00 }, -- StormwroughtRuins
|
||||||
|
[694] = { pfqAreaId=0, mapId=0, left=0.00, right=0.00, top=0.00, bottom=0.00, width=0.00, height=0.00 }, -- World
|
||||||
|
[696] = { pfqAreaId=5640, mapId=819, left=-2991.00, right=-4416.00, top=-7195.00, bottom=-8157.00, width=1425.00, height=962.00 }, -- Timbermaw
|
||||||
|
[698] = { pfqAreaId=5641, mapId=820, left=-3184.00, right=-4418.00, top=-7163.00, bottom=-7992.00, width=1234.00, height=829.00 }, -- WindhornCanyon
|
||||||
|
[699] = { pfqAreaId=5642, mapId=1, left=-1354.00, right=-9210.00, top=10204.00, bottom=4963.00, width=7856.00, height=5241.00 }, -- Moonwhisper
|
||||||
|
[700] = { pfqAreaId=1769, mapId=1, left=-1862.00, right=-2723.00, top=7395.00, bottom=6788.00, width=861.00, height=607.00 }, -- TimbermawTunnels
|
||||||
|
[701] = { pfqAreaId=5640, mapId=1, left=-4646.00, right=-5993.00, top=5175.00, bottom=4204.00, width=1347.00, height=971.00 }, -- TimbermawEntrance
|
||||||
|
[702] = { pfqAreaId=5722, mapId=821, left=2105.00, right=1058.00, top=2522.00, bottom=1828.00, width=1047.00, height=694.00 }, -- ThornGorge
|
||||||
|
[704] = { pfqAreaId=5734, mapId=822, left=-3157.00, right=-4168.00, top=-7453.00, bottom=-8106.00, width=1011.00, height=653.00 }, -- FrostmaneHollow
|
||||||
|
[705] = { pfqAreaId=5731, mapId=1, left=-3231.00, right=-3671.00, top=-5053.00, bottom=-5332.00, width=440.00, height=279.00 }, -- WindhornCanyonEntrance
|
||||||
|
}
|
||||||
-1052
File diff suppressed because it is too large
Load Diff
@@ -56,6 +56,11 @@ local function MTH_DS_ApplyCapturedProjectileQualities()
|
|||||||
[18042] = 2,
|
[18042] = 2,
|
||||||
[19316] = 2,
|
[19316] = 2,
|
||||||
[19317] = 2,
|
[19317] = 2,
|
||||||
|
[42198] = 2,
|
||||||
|
[42199] = 2,
|
||||||
|
[42200] = 2,
|
||||||
|
[42201] = 3,
|
||||||
|
[42202] = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
for itemId, quality in pairs(capturedQualityByItemId) do
|
for itemId, quality in pairs(capturedQualityByItemId) do
|
||||||
|
|||||||
+7
-1
@@ -1,7 +1,6 @@
|
|||||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||||
..\FrameXML\UI.xsd">
|
..\FrameXML\UI.xsd">
|
||||||
<Include file="..\api\constants.lua"/>
|
<Include file="..\api\constants.lua"/>
|
||||||
<Include file="..\api\debug-frame.lua"/>
|
|
||||||
<Include file="..\api\minimap-button.lua"/>
|
<Include file="..\api\minimap-button.lua"/>
|
||||||
<Include file="..\api\AutoStrip.xml"/>
|
<Include file="..\api\AutoStrip.xml"/>
|
||||||
<Include file="..\api\AutoStrip.lua"/>
|
<Include file="..\api\AutoStrip.lua"/>
|
||||||
@@ -17,6 +16,9 @@
|
|||||||
<Include file="..\api\options-autobuy.lua"/>
|
<Include file="..\api\options-autobuy.lua"/>
|
||||||
<Include file="..\api\options-autoquest.lua"/>
|
<Include file="..\api\options-autoquest.lua"/>
|
||||||
<Include file="..\api\options-icu.lua"/>
|
<Include file="..\api\options-icu.lua"/>
|
||||||
|
<Include file="..\api\options-expammo.lua"/>
|
||||||
|
<Include file="..\api\profile.lua"/>
|
||||||
|
<Include file="..\api\options-profiles.lua"/>
|
||||||
<Include file="..\api\options-shell.lua"/>
|
<Include file="..\api\options-shell.lua"/>
|
||||||
<Include file="..\api\options-zbuttons.lua"/>
|
<Include file="..\api\options-zbuttons.lua"/>
|
||||||
<Include file="..\api\options-feedomatic.lua"/>
|
<Include file="..\api\options-feedomatic.lua"/>
|
||||||
@@ -29,7 +31,9 @@
|
|||||||
<Include file="..\api\hunterbook-tab-npcfinder.lua"/>
|
<Include file="..\api\hunterbook-tab-npcfinder.lua"/>
|
||||||
<Include file="..\api\hunterbook-tab-stable.lua"/>
|
<Include file="..\api\hunterbook-tab-stable.lua"/>
|
||||||
<Include file="..\api\hunterbook-tab-pethistory.lua"/>
|
<Include file="..\api\hunterbook-tab-pethistory.lua"/>
|
||||||
|
<Include file="..\api\hunterbook-model-viewer.lua"/>
|
||||||
<Include file="..\api\map-markers.lua"/>
|
<Include file="..\api\map-markers.lua"/>
|
||||||
|
<Include file="..\api\debug-frame.lua"/>
|
||||||
<Include file="..\api\core-framework.lua"/>
|
<Include file="..\api\core-framework.lua"/>
|
||||||
<Include file="..\api\core-scan-stablemaster.lua"/>
|
<Include file="..\api\core-scan-stablemaster.lua"/>
|
||||||
<Include file="..\api\pets-service-lifecycle.lua"/>
|
<Include file="..\api\pets-service-lifecycle.lua"/>
|
||||||
@@ -38,6 +42,8 @@
|
|||||||
<Include file="..\api\pets-service-stablescan.lua"/>
|
<Include file="..\api\pets-service-stablescan.lua"/>
|
||||||
<Include file="..\api\core-scan-beasttraining.lua"/>
|
<Include file="..\api\core-scan-beasttraining.lua"/>
|
||||||
<Include file="..\api\core-scan-spellbookpet.lua"/>
|
<Include file="..\api\core-scan-spellbookpet.lua"/>
|
||||||
|
<Include file="..\api\beastlore-scan.lua"/>
|
||||||
|
<Include file="..\api\core-scan-huntertalents.lua"/>
|
||||||
<Include file="..\api\core.lua"/>
|
<Include file="..\api\core.lua"/>
|
||||||
<Include file="..\api\version-check.lua"/>
|
<Include file="..\api\version-check.lua"/>
|
||||||
<Include file="..\api\localization.lua"/>
|
<Include file="..\api\localization.lua"/>
|
||||||
|
|||||||
@@ -26,4 +26,7 @@ MetaHunt Module Loader
|
|||||||
|
|
||||||
<!-- ICU Module - ENABLED (runtime default: disabled) -->
|
<!-- ICU Module - ENABLED (runtime default: disabled) -->
|
||||||
<Include file="..\modules\icu\loader.xml"/>
|
<Include file="..\modules\icu\loader.xml"/>
|
||||||
|
|
||||||
|
<!-- Experimental Ammunition Module - ENABLED -->
|
||||||
|
<Include file="..\modules\expammo\loader.xml"/>
|
||||||
</Ui>
|
</Ui>
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ MTH_LocaleData = MTH_LocaleData or {}
|
|||||||
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
||||||
|
|
||||||
MTH_LocaleData.spells.deDE = {
|
MTH_LocaleData.spells.deDE = {
|
||||||
|
["Aimed Shot"] = "Gezielter Schuss",
|
||||||
|
["Kill Command"] = "Todesbefehl",
|
||||||
|
["Lock and Load"] = "Lock and Load",
|
||||||
|
["Scent of Blood"] = "Blutgeruch",
|
||||||
|
["Aspect of the Viper"] = "Aspekt der Viper",
|
||||||
["Banish"] = "Verbannen",
|
["Banish"] = "Verbannen",
|
||||||
["Bestial Wrath"] = "Zorn des Wildtiers",
|
["Bestial Wrath"] = "Zorn des Wildtiers",
|
||||||
["Concussive Shot"] = "Erschütternder Schuss",
|
["Concussive Shot"] = "Erschütternder Schuss",
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ MTH_LocaleData = MTH_LocaleData or {}
|
|||||||
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
||||||
|
|
||||||
MTH_LocaleData.spells.enUS = {
|
MTH_LocaleData.spells.enUS = {
|
||||||
|
["Aimed Shot"] = "Aimed Shot",
|
||||||
|
["Kill Command"] = "Kill Command",
|
||||||
|
["Lock and Load"] = "Lock and Load",
|
||||||
|
["Scent of Blood"] = "Scent of Blood",
|
||||||
|
["Aspect of the Viper"] = "Aspect of the Viper",
|
||||||
["Banish"] = "Banish",
|
["Banish"] = "Banish",
|
||||||
["Bestial Wrath"] = "Bestial Wrath",
|
["Bestial Wrath"] = "Bestial Wrath",
|
||||||
["Concussive Shot"] = "Concussive Shot",
|
["Concussive Shot"] = "Concussive Shot",
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ MTH_LocaleData = MTH_LocaleData or {}
|
|||||||
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
||||||
|
|
||||||
MTH_LocaleData.spells.esES = {
|
MTH_LocaleData.spells.esES = {
|
||||||
|
["Aimed Shot"] = "Aimed Shot",
|
||||||
|
["Aspect of the Viper"] = "Aspect of the Viper",
|
||||||
|
["Kill Command"] = "Kill Command",
|
||||||
|
["Lock and Load"] = "Lock and Load",
|
||||||
|
["Scent of Blood"] = "Scent of Blood",
|
||||||
["Banish"] = "Banish",
|
["Banish"] = "Banish",
|
||||||
["Bestial Wrath"] = "Bestial Wrath",
|
["Bestial Wrath"] = "Bestial Wrath",
|
||||||
["Concussive Shot"] = "Concussive Shot",
|
["Concussive Shot"] = "Concussive Shot",
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ MTH_LocaleData = MTH_LocaleData or {}
|
|||||||
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
||||||
|
|
||||||
MTH_LocaleData.spells.ptBR = {
|
MTH_LocaleData.spells.ptBR = {
|
||||||
|
["Aimed Shot"] = "Aimed Shot",
|
||||||
|
["Aspect of the Viper"] = "Aspect of the Viper",
|
||||||
|
["Kill Command"] = "Kill Command",
|
||||||
|
["Lock and Load"] = "Lock and Load",
|
||||||
|
["Scent of Blood"] = "Scent of Blood",
|
||||||
["Banish"] = "Banish",
|
["Banish"] = "Banish",
|
||||||
["Bestial Wrath"] = "Bestial Wrath",
|
["Bestial Wrath"] = "Bestial Wrath",
|
||||||
["Concussive Shot"] = "Concussive Shot",
|
["Concussive Shot"] = "Concussive Shot",
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ MTH_LocaleData = MTH_LocaleData or {}
|
|||||||
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
||||||
|
|
||||||
MTH_LocaleData.spells.ruRU = {
|
MTH_LocaleData.spells.ruRU = {
|
||||||
|
["Aimed Shot"] = "Прицельный выстрел",
|
||||||
|
["Aspect of the Viper"] = "Аспект гадюки",
|
||||||
|
["Kill Command"] = "Приказ убивать",
|
||||||
|
["Lock and Load"] = "Lock and Load",
|
||||||
|
["Scent of Blood"] = "Запах крови",
|
||||||
["Banish"] = "Изгнание",
|
["Banish"] = "Изгнание",
|
||||||
["Bestial Wrath"] = "Звериный гнев",
|
["Bestial Wrath"] = "Звериный гнев",
|
||||||
["Concussive Shot"] = "Контузящий выстрел",
|
["Concussive Shot"] = "Контузящий выстрел",
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ MTH_LocaleData = MTH_LocaleData or {}
|
|||||||
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
MTH_LocaleData.spells = MTH_LocaleData.spells or {}
|
||||||
|
|
||||||
MTH_LocaleData.spells.zhCN = {
|
MTH_LocaleData.spells.zhCN = {
|
||||||
|
["Aimed Shot"] = "瞄准射击",
|
||||||
|
["Aspect of the Viper"] = "毒蛇图腾",
|
||||||
|
["Kill Command"] = "猎杀命令",
|
||||||
|
["Lock and Load"] = "Lock and Load",
|
||||||
|
["Scent of Blood"] = "血腥气息",
|
||||||
["Banish"] = "放逐术",
|
["Banish"] = "放逐术",
|
||||||
["Bestial Wrath"] = "狂野怒火",
|
["Bestial Wrath"] = "狂野怒火",
|
||||||
["Concussive Shot"] = "震荡射击",
|
["Concussive Shot"] = "震荡射击",
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ MTH_LocaleData.ui.enUS = {
|
|||||||
BINDING_HEADER_ZTrapHeader = "[MetaHunt] ZTrap Buttons",
|
BINDING_HEADER_ZTrapHeader = "[MetaHunt] ZTrap Buttons",
|
||||||
BINDING_HEADER_ZPetHeader = "[MetaHunt] ZPet Buttons",
|
BINDING_HEADER_ZPetHeader = "[MetaHunt] ZPet Buttons",
|
||||||
BINDING_HEADER_ZAmmoHeader = "[MetaHunt] ZAmmo Buttons",
|
BINDING_HEADER_ZAmmoHeader = "[MetaHunt] ZAmmo Buttons",
|
||||||
|
BINDING_HEADER_ExpAmmoHeader = "[MetaHunt] MM Widget",
|
||||||
|
BINDING_NAME_EXPAMMOACTION = "MM Widget Action",
|
||||||
|
|
||||||
FEEDOMATIC_NAME = "Feed-O-Matic",
|
FEEDOMATIC_NAME = "Feed-O-Matic",
|
||||||
FEEDOMATIC_DESC = "Helps a Hunter keep his pets well fed",
|
FEEDOMATIC_DESC = "Helps a Hunter keep his pets well fed",
|
||||||
|
|||||||
@@ -9,9 +9,6 @@ local Engine = MTH_AutoBuyEngine
|
|||||||
local AB_AMMO_BY_NAME = nil
|
local AB_AMMO_BY_NAME = nil
|
||||||
local AB_FOOD_DIET_BY_ITEM_ID = nil
|
local AB_FOOD_DIET_BY_ITEM_ID = nil
|
||||||
|
|
||||||
local function AB_Trace(message)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local function AB_ParseItemIdFromLink(link)
|
local function AB_ParseItemIdFromLink(link)
|
||||||
if type(link) ~= "string" then
|
if type(link) ~= "string" then
|
||||||
@@ -1180,7 +1177,6 @@ end
|
|||||||
|
|
||||||
function Engine:ExecutePlan(plan)
|
function Engine:ExecutePlan(plan)
|
||||||
if type(plan) ~= "table" or type(plan.actions) ~= "table" then
|
if type(plan) ~= "table" or type(plan.actions) ~= "table" then
|
||||||
AB_Trace("ExecutePlan skipped: invalid plan table")
|
|
||||||
return 0, 0
|
return 0, 0
|
||||||
end
|
end
|
||||||
local executedActions = 0
|
local executedActions = 0
|
||||||
@@ -1189,10 +1185,6 @@ function Engine:ExecutePlan(plan)
|
|||||||
if type(action) == "table" and action.index then
|
if type(action) == "table" and action.index then
|
||||||
local stacksToBuy = math.floor(tonumber(action.quantityStacks) or 0)
|
local stacksToBuy = math.floor(tonumber(action.quantityStacks) or 0)
|
||||||
if stacksToBuy > 0 then
|
if stacksToBuy > 0 then
|
||||||
AB_Trace("ExecutePlan action index=" .. tostring(action.index)
|
|
||||||
.. " itemId=" .. tostring(action.itemId)
|
|
||||||
.. " stacks=" .. tostring(stacksToBuy)
|
|
||||||
.. " reason=" .. tostring(plan.reason or ""))
|
|
||||||
for i = 1, stacksToBuy do
|
for i = 1, stacksToBuy do
|
||||||
BuyMerchantItem(action.index)
|
BuyMerchantItem(action.index)
|
||||||
end
|
end
|
||||||
@@ -1201,7 +1193,6 @@ function Engine:ExecutePlan(plan)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
AB_Trace("ExecutePlan done actions=" .. tostring(executedActions) .. " stacks=" .. tostring(requestedStacks) .. " reason=" .. tostring(plan.reason or ""))
|
|
||||||
return executedActions, requestedStacks
|
return executedActions, requestedStacks
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1264,42 +1255,30 @@ local function AB_AnnouncePurchases(actions)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Engine:OnMerchantEvent(eventName)
|
function Engine:OnMerchantEvent(eventName)
|
||||||
AB_Trace("OnMerchantEvent start event=" .. tostring(eventName)
|
|
||||||
.. " sessionExecuted=" .. tostring(self._merchantSessionExecuted and true or false)
|
|
||||||
.. " engineEnabled=" .. tostring(self:IsEnabled() and true or false))
|
|
||||||
|
|
||||||
if eventName == "MERCHANT_SHOW" then
|
if eventName == "MERCHANT_SHOW" then
|
||||||
self._merchantSessionExecuted = false
|
self._merchantSessionExecuted = false
|
||||||
AB_Trace("MERCHANT_SHOW resets session execution flag")
|
|
||||||
elseif eventName == "MERCHANT_UPDATE" and self._merchantSessionExecuted then
|
elseif eventName == "MERCHANT_UPDATE" and self._merchantSessionExecuted then
|
||||||
AB_Trace("MERCHANT_UPDATE ignored: already executed this merchant session")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsEnabled() then
|
if not self:IsEnabled() then
|
||||||
AB_Trace("event ignored: autobuy module disabled")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local snapshot = self:ScanMerchant()
|
local snapshot = self:ScanMerchant()
|
||||||
AB_Trace("snapshot rows=" .. tostring(snapshot and snapshot.count or 0))
|
|
||||||
local foodPlan = self:BuildFoodPlan(snapshot)
|
local foodPlan = self:BuildFoodPlan(snapshot)
|
||||||
local ammoPlan = self:BuildAmmoPlan(snapshot)
|
local ammoPlan = self:BuildAmmoPlan(snapshot)
|
||||||
|
|
||||||
AB_Trace("foodPlan reason=" .. tostring(foodPlan.reason) .. " actions=" .. tostring(table.getn(foodPlan.actions or {})))
|
|
||||||
for i = 1, table.getn(foodPlan.debugLines or {}) do
|
for i = 1, table.getn(foodPlan.debugLines or {}) do
|
||||||
AB_Trace("food#" .. tostring(i) .. " " .. tostring(foodPlan.debugLines[i]))
|
|
||||||
end
|
end
|
||||||
AB_Trace("ammoPlan reason=" .. tostring(ammoPlan.reason) .. " actions=" .. tostring(table.getn(ammoPlan.actions or {})))
|
|
||||||
for i = 1, table.getn(ammoPlan.debugLines or {}) do
|
for i = 1, table.getn(ammoPlan.debugLines or {}) do
|
||||||
AB_Trace("ammo#" .. tostring(i) .. " " .. tostring(ammoPlan.debugLines[i]))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local totalRequestedStacks = 0
|
local totalRequestedStacks = 0
|
||||||
if table.getn(foodPlan.actions or {}) > 0 then
|
if table.getn(foodPlan.actions or {}) > 0 then
|
||||||
local _, requestedStacks = self:ExecutePlan(foodPlan)
|
local _, requestedStacks = self:ExecutePlan(foodPlan)
|
||||||
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
||||||
AB_Trace("food plan executed requestedStacks=" .. tostring(requestedStacks))
|
|
||||||
if requestedStacks > 0 then
|
if requestedStacks > 0 then
|
||||||
AB_AnnouncePurchases(foodPlan.actions)
|
AB_AnnouncePurchases(foodPlan.actions)
|
||||||
end
|
end
|
||||||
@@ -1308,19 +1287,15 @@ function Engine:OnMerchantEvent(eventName)
|
|||||||
if table.getn(ammoPlan.actions or {}) > 0 then
|
if table.getn(ammoPlan.actions or {}) > 0 then
|
||||||
local _, requestedStacks = self:ExecutePlan(ammoPlan)
|
local _, requestedStacks = self:ExecutePlan(ammoPlan)
|
||||||
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
||||||
AB_Trace("ammo plan executed requestedStacks=" .. tostring(requestedStacks))
|
|
||||||
if requestedStacks > 0 then
|
if requestedStacks > 0 then
|
||||||
local moved = AB_MoveAmmoStacksToSpecialBags(300)
|
local moved = AB_MoveAmmoStacksToSpecialBags(300)
|
||||||
AB_Trace("ammo restack moved=" .. tostring(moved))
|
|
||||||
AB_AnnouncePurchases(ammoPlan.actions)
|
AB_AnnouncePurchases(ammoPlan.actions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if totalRequestedStacks > 0 then
|
if totalRequestedStacks > 0 then
|
||||||
self._merchantSessionExecuted = true
|
self._merchantSessionExecuted = true
|
||||||
AB_Trace("session marked executed requestedStacks=" .. tostring(totalRequestedStacks))
|
|
||||||
else
|
else
|
||||||
AB_Trace("no purchases requested in this event")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
local MTH_AutoBuy = {
|
local MTH_AutoBuy = {
|
||||||
name = "autobuy",
|
name = "autobuy",
|
||||||
enabled = false,
|
enabled = false,
|
||||||
version = "1.1.0",
|
|
||||||
events = {
|
events = {
|
||||||
"VARIABLES_LOADED",
|
"VARIABLES_LOADED",
|
||||||
"MERCHANT_SHOW",
|
"MERCHANT_SHOW",
|
||||||
@@ -24,16 +23,13 @@ end
|
|||||||
|
|
||||||
local AB_Engine
|
local AB_Engine
|
||||||
|
|
||||||
local function AB_Trace(message)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local function AB_EnsureBridgeFrame(moduleRef)
|
local function AB_EnsureBridgeFrame(moduleRef)
|
||||||
if MTH_AutoBuy._bridgeFrame then
|
if MTH_AutoBuy._bridgeFrame then
|
||||||
return MTH_AutoBuy._bridgeFrame
|
return MTH_AutoBuy._bridgeFrame
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame", "MTH_AutoBuyBridgeFrame")
|
local frame = CreateFrame("Frame", "MTH_AutoBuyBridge")
|
||||||
if not frame then
|
if not frame then
|
||||||
AB_Log("failed to create bridge frame", "error")
|
AB_Log("failed to create bridge frame", "error")
|
||||||
return nil
|
return nil
|
||||||
@@ -42,19 +38,16 @@ local function AB_EnsureBridgeFrame(moduleRef)
|
|||||||
frame:RegisterEvent("MERCHANT_SHOW")
|
frame:RegisterEvent("MERCHANT_SHOW")
|
||||||
frame:RegisterEvent("MERCHANT_UPDATE")
|
frame:RegisterEvent("MERCHANT_UPDATE")
|
||||||
frame:RegisterEvent("MERCHANT_CLOSED")
|
frame:RegisterEvent("MERCHANT_CLOSED")
|
||||||
frame:SetScript("OnEvent", function(_, eventName)
|
frame:SetScript("OnEvent", function()
|
||||||
eventName = eventName or event
|
local eventName = event
|
||||||
local engine = AB_Engine()
|
local engine = AB_Engine()
|
||||||
if not engine then
|
if not engine then
|
||||||
AB_Trace("bridge event=" .. tostring(eventName) .. " engine missing")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if eventName == "MERCHANT_SHOW" or eventName == "MERCHANT_UPDATE" then
|
if eventName == "MERCHANT_SHOW" or eventName == "MERCHANT_UPDATE" then
|
||||||
AB_Trace("bridge " .. tostring(eventName) .. " -> engine")
|
|
||||||
engine:OnMerchantEvent(eventName)
|
engine:OnMerchantEvent(eventName)
|
||||||
elseif eventName == "MERCHANT_CLOSED" then
|
elseif eventName == "MERCHANT_CLOSED" then
|
||||||
AB_Trace("bridge MERCHANT_CLOSED -> engine")
|
|
||||||
if engine.OnMerchantClosed then
|
if engine.OnMerchantClosed then
|
||||||
engine:OnMerchantClosed()
|
engine:OnMerchantClosed()
|
||||||
end
|
end
|
||||||
@@ -77,10 +70,8 @@ local function AB_SetBridgeActive(active)
|
|||||||
frame:RegisterEvent("MERCHANT_UPDATE")
|
frame:RegisterEvent("MERCHANT_UPDATE")
|
||||||
frame:RegisterEvent("MERCHANT_CLOSED")
|
frame:RegisterEvent("MERCHANT_CLOSED")
|
||||||
MTH_AutoBuy._bridgeActive = true
|
MTH_AutoBuy._bridgeActive = true
|
||||||
AB_Trace("bridge active=true")
|
|
||||||
else
|
else
|
||||||
MTH_AutoBuy._bridgeActive = false
|
MTH_AutoBuy._bridgeActive = false
|
||||||
AB_Trace("bridge active=false (frame missing)")
|
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -91,7 +82,6 @@ local function AB_SetBridgeActive(active)
|
|||||||
frame:UnregisterEvent("MERCHANT_CLOSED")
|
frame:UnregisterEvent("MERCHANT_CLOSED")
|
||||||
end
|
end
|
||||||
MTH_AutoBuy._bridgeActive = false
|
MTH_AutoBuy._bridgeActive = false
|
||||||
AB_Trace("bridge active=false")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
AB_Engine = function()
|
AB_Engine = function()
|
||||||
@@ -102,15 +92,12 @@ function MTH_AutoBuy:init()
|
|||||||
local engine = AB_Engine()
|
local engine = AB_Engine()
|
||||||
if not engine then
|
if not engine then
|
||||||
AB_Log("init failed: engine missing", "error")
|
AB_Log("init failed: engine missing", "error")
|
||||||
AB_Trace("init failed: engine missing")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
engine:Init()
|
engine:Init()
|
||||||
self.initialized = true
|
self.initialized = true
|
||||||
AB_SetBridgeActive(self.enabled and true or false)
|
AB_SetBridgeActive(self.enabled and true or false)
|
||||||
AB_Trace("init done")
|
|
||||||
if self.enabled then
|
if self.enabled then
|
||||||
AB_Log("module initialized", "debug")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -120,53 +107,38 @@ function MTH_AutoBuy:setEnabled(enabled)
|
|||||||
end
|
end
|
||||||
local engine = AB_Engine()
|
local engine = AB_Engine()
|
||||||
if not engine then
|
if not engine then
|
||||||
AB_Trace("setEnabled ignored: engine missing")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local store = engine:EnsureDefaults()
|
local store = engine:EnsureDefaults()
|
||||||
store.enabled = enabled and true or false
|
store.enabled = enabled and true or false
|
||||||
AB_SetBridgeActive(store.enabled and true or false)
|
AB_SetBridgeActive(store.enabled and true or false)
|
||||||
AB_Trace("setEnabled store.enabled=" .. tostring(store.enabled))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_AutoBuy:onEvent(event)
|
function MTH_AutoBuy:onEvent(event)
|
||||||
local engine = AB_Engine()
|
local engine = AB_Engine()
|
||||||
if not engine then
|
if not engine then
|
||||||
AB_Log("onEvent ignored: engine missing, event=" .. tostring(event), "debug")
|
|
||||||
AB_Trace("engine missing, event=" .. tostring(event))
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if self._bridgeActive and (event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" or event == "MERCHANT_CLOSED") then
|
if self._bridgeActive and (event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" or event == "MERCHANT_CLOSED") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
AB_Log("onEvent event=" .. tostring(event) .. " module.enabled=" .. tostring(self.enabled), "debug")
|
|
||||||
|
|
||||||
if event == "VARIABLES_LOADED" then
|
if event == "VARIABLES_LOADED" then
|
||||||
engine:Init()
|
engine:Init()
|
||||||
AB_SetBridgeActive(self.enabled and true or false)
|
AB_SetBridgeActive(self.enabled and true or false)
|
||||||
AB_Log("onEvent VARIABLES_LOADED -> engine init", "debug")
|
engine:EnsureDefaults()
|
||||||
local store = engine:EnsureDefaults()
|
|
||||||
AB_Trace("VARIABLES_LOADED module.enabled=" .. tostring(self.enabled)
|
|
||||||
.. " store.enabled=" .. tostring(store and store.enabled)
|
|
||||||
.. " projectiles.enabled=" .. tostring(store and store.projectiles and store.projectiles.enabled))
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self.enabled then
|
if not self.enabled then
|
||||||
AB_Log("onEvent ignored: module disabled", "debug")
|
|
||||||
if event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" then
|
if event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" then
|
||||||
AB_Trace(tostring(event) .. " ignored: module disabled")
|
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" then
|
if event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" then
|
||||||
AB_Log("onEvent merchant event forwarded: " .. tostring(event), "debug")
|
|
||||||
AB_Trace("forwarding " .. tostring(event) .. " to engine")
|
|
||||||
engine:OnMerchantEvent(event)
|
engine:OnMerchantEvent(event)
|
||||||
elseif event == "MERCHANT_CLOSED" then
|
elseif event == "MERCHANT_CLOSED" then
|
||||||
AB_Trace("forwarding MERCHANT_CLOSED to engine")
|
|
||||||
if engine.OnMerchantClosed then
|
if engine.OnMerchantClosed then
|
||||||
engine:OnMerchantClosed()
|
engine:OnMerchantClosed()
|
||||||
end
|
end
|
||||||
@@ -174,7 +146,6 @@ function MTH_AutoBuy:onEvent(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MTH_AutoBuy:cleanup()
|
function MTH_AutoBuy:cleanup()
|
||||||
AB_Log("module cleanup", "debug")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH:RegisterModule("autobuy", MTH_AutoBuy)
|
MTH:RegisterModule("autobuy", MTH_AutoBuy)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
local MTH_AutoQuest = {
|
local MTH_AutoQuest = {
|
||||||
name = "autoquest",
|
name = "autoquest",
|
||||||
enabled = false,
|
enabled = false,
|
||||||
version = "1.1.0",
|
|
||||||
events = {
|
events = {
|
||||||
"GOSSIP_SHOW",
|
"GOSSIP_SHOW",
|
||||||
"QUEST_GREETING",
|
"QUEST_GREETING",
|
||||||
@@ -34,7 +33,6 @@ local QA_ITEM_BLASTED_BOAR_LUNG_NAME = "Blasted Boar Lung"
|
|||||||
local QA_ITEM_VULTURE_GIZZARD_NAME = "Vulture Gizzard"
|
local QA_ITEM_VULTURE_GIZZARD_NAME = "Vulture Gizzard"
|
||||||
local QA_ITEM_GROUND_SCORPOK_ASSAY_NAME = "Ground Scorpok Assay"
|
local QA_ITEM_GROUND_SCORPOK_ASSAY_NAME = "Ground Scorpok Assay"
|
||||||
|
|
||||||
local QA_DirectEventFrame = nil
|
|
||||||
local QA_TooltipHooked = false
|
local QA_TooltipHooked = false
|
||||||
local QA_TooltipPollFrame = nil
|
local QA_TooltipPollFrame = nil
|
||||||
local QA_TooltipRefreshFrame = nil
|
local QA_TooltipRefreshFrame = nil
|
||||||
@@ -292,7 +290,8 @@ local function QA_CountItemInBags(expectedId, expectedName)
|
|||||||
for slot = 1, slots do
|
for slot = 1, slots do
|
||||||
local link = getContainerItemLink(bag, slot)
|
local link = getContainerItemLink(bag, slot)
|
||||||
if type(link) == "string" and link ~= "" then
|
if type(link) == "string" and link ~= "" then
|
||||||
local itemId = tonumber(string.match(link, "item:(%d+)"))
|
local _, _, itemIdStr = string.find(link, "item:(%d+)")
|
||||||
|
local itemId = tonumber(itemIdStr)
|
||||||
local itemName = nil
|
local itemName = nil
|
||||||
if type(getItemInfo) == "function" then
|
if type(getItemInfo) == "function" then
|
||||||
itemName = getItemInfo(link)
|
itemName = getItemInfo(link)
|
||||||
@@ -456,8 +455,8 @@ local function QA_EnsureTooltipHook()
|
|||||||
|
|
||||||
if hasHookScript and onTooltipSetUnitExists then
|
if hasHookScript and onTooltipSetUnitExists then
|
||||||
pcall(function()
|
pcall(function()
|
||||||
GameTooltip:HookScript("OnTooltipSetUnit", function(self)
|
GameTooltip:HookScript("OnTooltipSetUnit", function()
|
||||||
QA_AppendDrazialTooltip(self, "hook:setunit")
|
QA_AppendDrazialTooltip(this, "hook:setunit")
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
elseif hasSetScript and hasGetScript and onTooltipSetUnitExists then
|
elseif hasSetScript and hasGetScript and onTooltipSetUnitExists then
|
||||||
@@ -466,11 +465,11 @@ local function QA_EnsureTooltipHook()
|
|||||||
end)
|
end)
|
||||||
if okGetPrev then
|
if okGetPrev then
|
||||||
pcall(function()
|
pcall(function()
|
||||||
GameTooltip:SetScript("OnTooltipSetUnit", function(self)
|
GameTooltip:SetScript("OnTooltipSetUnit", function()
|
||||||
if type(previous) == "function" then
|
if type(previous) == "function" then
|
||||||
previous(self)
|
previous()
|
||||||
end
|
end
|
||||||
QA_AppendDrazialTooltip(self, "script:setunit")
|
QA_AppendDrazialTooltip(this, "script:setunit")
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -478,8 +477,8 @@ local function QA_EnsureTooltipHook()
|
|||||||
|
|
||||||
if hasHookScript and onShowExists then
|
if hasHookScript and onShowExists then
|
||||||
pcall(function()
|
pcall(function()
|
||||||
GameTooltip:HookScript("OnShow", function(self)
|
GameTooltip:HookScript("OnShow", function()
|
||||||
QA_AppendDrazialTooltip(self, "hook:show")
|
QA_AppendDrazialTooltip(this, "hook:show")
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
elseif hasSetScript and hasGetScript and onShowExists then
|
elseif hasSetScript and hasGetScript and onShowExists then
|
||||||
@@ -488,11 +487,11 @@ local function QA_EnsureTooltipHook()
|
|||||||
end)
|
end)
|
||||||
if okGetPrevShow then
|
if okGetPrevShow then
|
||||||
pcall(function()
|
pcall(function()
|
||||||
GameTooltip:SetScript("OnShow", function(self)
|
GameTooltip:SetScript("OnShow", function()
|
||||||
if type(previousShow) == "function" then
|
if type(previousShow) == "function" then
|
||||||
previousShow(self)
|
previousShow()
|
||||||
end
|
end
|
||||||
QA_AppendDrazialTooltip(self, "script:show")
|
QA_AppendDrazialTooltip(this, "script:show")
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -505,17 +504,17 @@ local function QA_EnsureTooltipPoller()
|
|||||||
if QA_TooltipPollFrame then
|
if QA_TooltipPollFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local frame = CreateFrame("Frame", "MTH_AutoQuestTooltipPollFrame")
|
local frame = CreateFrame("Frame", "MTH_AQTooltipPoll")
|
||||||
if not frame then
|
if not frame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
frame._mthElapsed = 0
|
frame._mthElapsed = 0
|
||||||
frame:SetScript("OnUpdate", function(self, elapsed)
|
frame:SetScript("OnUpdate", function()
|
||||||
self._mthElapsed = (self._mthElapsed or 0) + (elapsed or arg1 or 0)
|
this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0)
|
||||||
if self._mthElapsed < 0.20 then
|
if this._mthElapsed < 0.20 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self._mthElapsed = 0
|
this._mthElapsed = 0
|
||||||
if not (MTH_AutoQuest and MTH_AutoQuest.enabled) then
|
if not (MTH_AutoQuest and MTH_AutoQuest.enabled) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -591,16 +590,16 @@ end
|
|||||||
local function QA_RequestTooltipRefresh(delaySeconds)
|
local function QA_RequestTooltipRefresh(delaySeconds)
|
||||||
delaySeconds = tonumber(delaySeconds) or 0.10
|
delaySeconds = tonumber(delaySeconds) or 0.10
|
||||||
if not QA_TooltipRefreshFrame then
|
if not QA_TooltipRefreshFrame then
|
||||||
QA_TooltipRefreshFrame = CreateFrame("Frame", "MTH_AutoQuestTooltipRefreshFrame")
|
QA_TooltipRefreshFrame = CreateFrame("Frame", "MTH_AQTooltipRefresh")
|
||||||
if not QA_TooltipRefreshFrame then
|
if not QA_TooltipRefreshFrame then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
QA_TooltipRefreshFrame:SetScript("OnUpdate", function(self, elapsed)
|
QA_TooltipRefreshFrame:SetScript("OnUpdate", function()
|
||||||
local frameRef = self or this or QA_TooltipRefreshFrame
|
local frameRef = this or QA_TooltipRefreshFrame
|
||||||
if not frameRef then
|
if not frameRef then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
frameRef._elapsed = (frameRef._elapsed or 0) + (elapsed or arg1 or 0)
|
frameRef._elapsed = (frameRef._elapsed or 0) + (arg1 or 0)
|
||||||
if frameRef._elapsed < (frameRef._delay or 0.10) then
|
if frameRef._elapsed < (frameRef._delay or 0.10) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -915,48 +914,14 @@ local function QA_RunProfileAutomation(eventName, profile)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function QA_SetDirectEventFrameActive(active)
|
-- NOTE: QA_DirectEventFrame removed (Phase 2 fix #22b)
|
||||||
if not QA_DirectEventFrame then
|
-- The central event router already dispatches GOSSIP_SHOW, QUEST_GREETING,
|
||||||
return
|
-- QUEST_DETAIL, QUEST_PROGRESS, QUEST_COMPLETE to MTH_AutoQuest:onEvent().
|
||||||
end
|
-- Having a second frame register the same events caused double-dispatch.
|
||||||
if active then
|
|
||||||
QA_DirectEventFrame:RegisterEvent("GOSSIP_SHOW")
|
|
||||||
QA_DirectEventFrame:RegisterEvent("QUEST_GREETING")
|
|
||||||
QA_DirectEventFrame:RegisterEvent("QUEST_DETAIL")
|
|
||||||
QA_DirectEventFrame:RegisterEvent("QUEST_PROGRESS")
|
|
||||||
QA_DirectEventFrame:RegisterEvent("QUEST_COMPLETE")
|
|
||||||
else
|
|
||||||
QA_DirectEventFrame:UnregisterAllEvents()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function QA_EnsureDirectEventFrame(moduleRef)
|
|
||||||
if QA_DirectEventFrame then
|
|
||||||
return QA_DirectEventFrame
|
|
||||||
end
|
|
||||||
local frame = CreateFrame("Frame", "MTH_AutoQuestEventFrame")
|
|
||||||
if not frame then
|
|
||||||
QA_Debug("direct frame create failed")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
frame:SetScript("OnEvent", function(_, eventName)
|
|
||||||
eventName = eventName or event
|
|
||||||
if not (moduleRef and moduleRef.enabled) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
QA_Debug("directEvent=" .. tostring(eventName))
|
|
||||||
QA_RunProfileAutomation(eventName, QA_PROFILE_SCORPOK)
|
|
||||||
QA_RunProfileAutomation(eventName, QA_PROFILE_SISSIES)
|
|
||||||
end)
|
|
||||||
QA_DirectEventFrame = frame
|
|
||||||
return frame
|
|
||||||
end
|
|
||||||
|
|
||||||
function MTH_AutoQuest:init()
|
function MTH_AutoQuest:init()
|
||||||
local store = QA_GetOptionsStore()
|
local store = QA_GetOptionsStore()
|
||||||
self.initialized = true
|
self.initialized = true
|
||||||
QA_EnsureDirectEventFrame(self)
|
|
||||||
QA_SetDirectEventFrameActive(self.enabled and true or false)
|
|
||||||
QA_Debug("init: module active=" .. tostring(self.enabled and true or false)
|
QA_Debug("init: module active=" .. tostring(self.enabled and true or false)
|
||||||
.. ", option scorpokDrazial=" .. tostring(store and store.scorpokDrazial and true or false)
|
.. ", option scorpokDrazial=" .. tostring(store and store.scorpokDrazial and true or false)
|
||||||
.. ", option arrowsForSissies=" .. tostring(store and store.arrowsForSissies and true or false)
|
.. ", option arrowsForSissies=" .. tostring(store and store.arrowsForSissies and true or false)
|
||||||
@@ -965,7 +930,6 @@ end
|
|||||||
|
|
||||||
function MTH_AutoQuest:setEnabled(enabled)
|
function MTH_AutoQuest:setEnabled(enabled)
|
||||||
self.enabled = enabled and true or false
|
self.enabled = enabled and true or false
|
||||||
QA_SetDirectEventFrameActive(self.enabled and true or false)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_AutoQuest:onEvent(eventName)
|
function MTH_AutoQuest:onEvent(eventName)
|
||||||
@@ -981,7 +945,7 @@ function MTH_AutoQuest:onEvent(eventName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MTH_AutoQuest:cleanup()
|
function MTH_AutoQuest:cleanup()
|
||||||
QA_SetDirectEventFrameActive(false)
|
-- no-op: direct event frame removed in Phase 2
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH:RegisterModule("autoquest", MTH_AutoQuest)
|
MTH:RegisterModule("autoquest", MTH_AutoQuest)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ function MTH_ChronometerHunterInstallData(engine)
|
|||||||
engine:AddTimer(engine.SPELL, BS["Flare"], 30, 0, 0, 0, { cr = "YELLOW", rc = true })
|
engine:AddTimer(engine.SPELL, BS["Flare"], 30, 0, 0, 0, { cr = "YELLOW", rc = true })
|
||||||
engine:AddTimer(engine.SPELL, BS["Hunter's Mark"], 120, 1, 0, 0, { cr = "RED", rc = true })
|
engine:AddTimer(engine.SPELL, BS["Hunter's Mark"], 120, 1, 0, 0, { cr = "RED", rc = true })
|
||||||
engine:AddTimer(engine.SPELL, BS["Immolation Trap"], 60, 0, 0, 0, { gr = 1, cr = "ORANGE", ea = { [BS["Immolation Trap Effect"]] = 60 } })
|
engine:AddTimer(engine.SPELL, BS["Immolation Trap"], 60, 0, 0, 0, { gr = 1, cr = "ORANGE", ea = { [BS["Immolation Trap Effect"]] = 60 } })
|
||||||
|
engine:AddTimer(engine.SPELL, BS["Kill Command"], 12, 0, 0, 0, { cr = "RED", rc = true })
|
||||||
engine:AddTimer(engine.SPELL, BS["Rapid Fire"], 15, 0, 1, 1, { cr = "RED" })
|
engine:AddTimer(engine.SPELL, BS["Rapid Fire"], 15, 0, 1, 1, { cr = "RED" })
|
||||||
engine:AddTimer(engine.SPELL, BS["Scare Beast"], 10, 1, 0, 0, { cr = "BLUE", rc = true, d = { rs = 5 } })
|
engine:AddTimer(engine.SPELL, BS["Scare Beast"], 10, 1, 0, 0, { cr = "BLUE", rc = true, d = { rs = 5 } })
|
||||||
engine:AddTimer(engine.SPELL, BS["Scatter Shot"], 4, 1, 0, 0, { cr = "MAROON" })
|
engine:AddTimer(engine.SPELL, BS["Scatter Shot"], 4, 1, 0, 0, { cr = "MAROON" })
|
||||||
@@ -38,16 +39,26 @@ function MTH_ChronometerHunterInstallData(engine)
|
|||||||
engine:AddTimer(engine.SPELL, BS["Wyvern Sting"], 12, 1, 0, 0, { gr = 2, cr = "MAROON", rc = true })
|
engine:AddTimer(engine.SPELL, BS["Wyvern Sting"], 12, 1, 0, 0, { gr = 2, cr = "MAROON", rc = true })
|
||||||
engine:AddTimer(engine.SPELL, BS["Feed Pet"], 20, 0, 0, 0, { cr = "MAROON" })
|
engine:AddTimer(engine.SPELL, BS["Feed Pet"], 20, 0, 0, 0, { cr = "MAROON" })
|
||||||
|
|
||||||
engine:AddTimer(engine.EVENT, BS["Explosive Trap Effect"], 20, 1, 0, 1, { gr = 1, cr = "ORANGE", a = 1, xn = BS["Explosive Trap"] })
|
-- Trap effects: no "a=1" here — primed by the SPELL timer's "ea" chain (cast hook sets timer.v
|
||||||
engine:AddTimer(engine.EVENT, BS["Freezing Trap Effect"], 10, 1, 0, 1, { gr = 1, cr = "CYAN", a = 1, d = { rs = 5, tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Freezing Trap"] })
|
-- and timer.t). Using "a=1" would trigger on any hunter's affliction message since
|
||||||
engine:AddTimer(engine.EVENT, BS["Frost Trap Aura"], 30, 0, 0, 0, { gr = 1, cr = "CYAN", a = 1, d = { tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Frost Trap"] })
|
-- CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS never embeds a caster name.
|
||||||
engine:AddTimer(engine.EVENT, BS["Immolation Trap Effect"], 15, 1, 0, 1, { gr = 1, cr = "ORANGE", a = 1, xn = BS["Immolation Trap"] })
|
engine:AddTimer(engine.EVENT, BS["Explosive Trap Effect"], 20, 1, 0, 1, { gr = 1, cr = "ORANGE", xn = BS["Explosive Trap"] })
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Freezing Trap Effect"], 10, 1, 0, 1, { gr = 1, cr = "CYAN", d = { rs = 5, tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Freezing Trap"] })
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Frost Trap Aura"], 30, 0, 0, 0, { gr = 1, cr = "CYAN", d = { tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Frost Trap"] })
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Immolation Trap Effect"], 15, 1, 0, 1, { gr = 1, cr = "ORANGE", xn = BS["Immolation Trap"] })
|
||||||
engine:AddTimer(engine.EVENT, BS["Improved Concussive Shot"], 3, 1, 0, 0, { a = 1, cr = "BLUE", xn = BS["Concussive Shot"] })
|
engine:AddTimer(engine.EVENT, BS["Improved Concussive Shot"], 3, 1, 0, 0, { a = 1, cr = "BLUE", xn = BS["Concussive Shot"] })
|
||||||
engine:AddTimer(engine.EVENT, BS["Improved Wing Clip"], 5, 1, 0, 0, { a = 1, cr = "MAROON", xn = BS["Wing Clip"] })
|
engine:AddTimer(engine.EVENT, BS["Improved Wing Clip"], 5, 1, 0, 0, { a = 1, cr = "MAROON", xn = BS["Wing Clip"] })
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Lock and Load"], 10, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\ability_hunter_lockandload" }) -- 10s (tooltip confirmed; expires when consumed)
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Scent of Blood"], 8, 0, 1, 1, { a = 1, cr = "RED" })
|
||||||
engine:AddTimer(engine.EVENT, BS["Piercing Shot"], 8, 1, 0, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_Hunter_DisarmingShot" })
|
engine:AddTimer(engine.EVENT, BS["Piercing Shot"], 8, 1, 0, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_Hunter_DisarmingShot" })
|
||||||
engine:AddTimer(engine.EVENT, BS["Entrapment"], 5, 1, 0, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Spell_Nature_StrangleVines" })
|
engine:AddTimer(engine.EVENT, BS["Entrapment"], 5, 1, 0, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Spell_Nature_StrangleVines" })
|
||||||
engine:AddTimer(engine.EVENT, BS["Quick Shots"], 12, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Ability_Warrior_InnerRage" })
|
engine:AddTimer(engine.EVENT, BS["Quick Shots"], 12, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Ability_Warrior_InnerRage" })
|
||||||
engine:AddTimer(engine.EVENT, BS["Wing Clip"], 10, 1, 0, 1, { a = 1, cr = "YELLOW" })
|
engine:AddTimer(engine.EVENT, BS["Wing Clip"], 10, 1, 0, 1, { a = 1, cr = "YELLOW" })
|
||||||
|
-- Experimental Ammunition: target-side debuffs (from consumed ammo state)
|
||||||
|
-- Poisonous Ammunition consumed: reduces target armor 15s (Nature)
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Poisonous Ammunition"], 15, 1, 0, 1, { a = 1, cr = "GREEN", tx = "Interface\\Icons\\Ability_PoisonArrow" })
|
||||||
|
-- Enchanted Ammunition consumed: magic resist debuff 6s (Arcane)
|
||||||
|
engine:AddTimer(engine.EVENT, BS["Enchanted Ammunition"], 6, 1, 0, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_TheBlackArrow" })
|
||||||
engine:AddTimer(engine.EVENT, BS["Scorpid Poison"], 10, 1, 0, 0, { gr = 3, cr = "PURPLE", a = 1, dn = 1 })
|
engine:AddTimer(engine.EVENT, BS["Scorpid Poison"], 10, 1, 0, 0, { gr = 3, cr = "PURPLE", a = 1, dn = 1 })
|
||||||
engine:AddTimer(engine.EVENT, BS["Devilsaur Fury"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Devilsaur Eye"], tx = "Interface\\Icons\\Ability_Hunter_Pet_Raptor" })
|
engine:AddTimer(engine.EVENT, BS["Devilsaur Fury"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Devilsaur Eye"], tx = "Interface\\Icons\\Ability_Hunter_Pet_Raptor" })
|
||||||
engine:AddTimer(engine.EVENT, BS["Restless Strength"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Zandalarian Hero Medallion"], tx = "Interface\\Icons\\INV_Jewelry_Necklace_13" })
|
engine:AddTimer(engine.EVENT, BS["Restless Strength"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Zandalarian Hero Medallion"], tx = "Interface\\Icons\\INV_Jewelry_Necklace_13" })
|
||||||
|
|||||||
+182
-71
@@ -58,19 +58,20 @@ Chronometer.dataSetup = {}
|
|||||||
|
|
||||||
local latins = { I = 1, II = 2, III = 3, IV = 4, V = 5, VI = 6, VII = 7, VIII = 8, IX = 9, X = 10, XI = 11, XII = 12, XIII = 13, XIV = 14 }
|
local latins = { I = 1, II = 2, III = 3, IV = 4, V = 5, VI = 6, VII = 7, VIII = 8, IX = 9, X = 10, XI = 11, XII = 12, XIII = 13, XIV = 14 }
|
||||||
local BAR_GROUP = "MTHChronometer"
|
local BAR_GROUP = "MTHChronometer"
|
||||||
local PARSER_OWNER = "MTHChronometerHunter"
|
|
||||||
local MTH_CHRON_TRACE_ENABLED = false
|
|
||||||
|
|
||||||
local function MTH_CHRON_Trace(msg)
|
-- When growing up the group attachment point must flip so bars stack above the
|
||||||
if not MTH_CHRON_TRACE_ENABLED then
|
-- anchor rather than below it. CandyBar uses the stored group point as-is when
|
||||||
return
|
-- positioning each bar, so SetCandyBarGroupGrowth alone is not enough.
|
||||||
end
|
local function applyGrowup(self, growup)
|
||||||
if MTH and MTH.Print then
|
if growup then
|
||||||
MTH:Print("[CHRONTRACE] " .. tostring(msg), "debug")
|
self:SetCandyBarGroupPoint(BAR_GROUP, "BOTTOM", self.anchor, "TOP", 0, 0)
|
||||||
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
else
|
||||||
DEFAULT_CHAT_FRAME:AddMessage("[CHRONTRACE] " .. tostring(msg))
|
self:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0)
|
||||||
end
|
end
|
||||||
|
self:SetCandyBarGroupGrowth(BAR_GROUP, growup)
|
||||||
end
|
end
|
||||||
|
local PARSER_OWNER = "MTHChronometerHunter"
|
||||||
|
|
||||||
|
|
||||||
local function MTH_CHRON_FormatBarPosition(profile)
|
local function MTH_CHRON_FormatBarPosition(profile)
|
||||||
local bp = profile and profile.barposition
|
local bp = profile and profile.barposition
|
||||||
@@ -195,13 +196,11 @@ end
|
|||||||
|
|
||||||
local function ensureProfile()
|
local function ensureProfile()
|
||||||
if not MTH or not MTH.GetModuleCharSavedVariables then
|
if not MTH or not MTH.GetModuleCharSavedVariables then
|
||||||
MTH_CHRON_Trace("ensureProfile fallback defaults (no MTH store)")
|
|
||||||
return shallowCopy(DEFAULTS)
|
return shallowCopy(DEFAULTS)
|
||||||
end
|
end
|
||||||
|
|
||||||
local store = MTH:GetModuleCharSavedVariables("chronometer")
|
local store = MTH:GetModuleCharSavedVariables("chronometer")
|
||||||
if type(store) ~= "table" then
|
if type(store) ~= "table" then
|
||||||
MTH_CHRON_Trace("ensureProfile fallback defaults (invalid store)")
|
|
||||||
return shallowCopy(DEFAULTS)
|
return shallowCopy(DEFAULTS)
|
||||||
end
|
end
|
||||||
if type(store.profile) ~= "table"
|
if type(store.profile) ~= "table"
|
||||||
@@ -211,10 +210,8 @@ local function ensureProfile()
|
|||||||
local legacyChar = MTH_CharSavedVariables.chronometer
|
local legacyChar = MTH_CharSavedVariables.chronometer
|
||||||
if type(legacyChar.profile) == "table" then
|
if type(legacyChar.profile) == "table" then
|
||||||
store.profile = deepCopyValue(legacyChar.profile)
|
store.profile = deepCopyValue(legacyChar.profile)
|
||||||
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_CharSavedVariables.chronometer.profile")
|
|
||||||
elseif type(legacyChar.barposition) == "table" then
|
elseif type(legacyChar.barposition) == "table" then
|
||||||
store.profile = { barposition = deepCopyValue(legacyChar.barposition) }
|
store.profile = { barposition = deepCopyValue(legacyChar.barposition) }
|
||||||
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_CharSavedVariables.chronometer.barposition")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if type(store.profile) ~= "table"
|
if type(store.profile) ~= "table"
|
||||||
@@ -224,17 +221,14 @@ local function ensureProfile()
|
|||||||
local legacyAccount = MTH_SavedVariables.chronometer
|
local legacyAccount = MTH_SavedVariables.chronometer
|
||||||
if type(legacyAccount.profile) == "table" then
|
if type(legacyAccount.profile) == "table" then
|
||||||
store.profile = deepCopyValue(legacyAccount.profile)
|
store.profile = deepCopyValue(legacyAccount.profile)
|
||||||
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_SavedVariables.chronometer.profile")
|
|
||||||
elseif type(legacyAccount.barposition) == "table" then
|
elseif type(legacyAccount.barposition) == "table" then
|
||||||
store.profile = { barposition = deepCopyValue(legacyAccount.barposition) }
|
store.profile = { barposition = deepCopyValue(legacyAccount.barposition) }
|
||||||
MTH_CHRON_Trace("ensureProfile migrated legacy MTH_SavedVariables.chronometer.barposition")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if type(store.profile) ~= "table" and MTH.GetModuleSavedVariables then
|
if type(store.profile) ~= "table" and MTH.GetModuleSavedVariables then
|
||||||
local accountStore = MTH:GetModuleSavedVariables("chronometer")
|
local accountStore = MTH:GetModuleSavedVariables("chronometer")
|
||||||
if type(accountStore) == "table" and type(accountStore.profile) == "table" then
|
if type(accountStore) == "table" and type(accountStore.profile) == "table" then
|
||||||
store.profile = deepCopyValue(accountStore.profile)
|
store.profile = deepCopyValue(accountStore.profile)
|
||||||
MTH_CHRON_Trace("ensureProfile copied account profile into char store")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if type(store.profile) ~= "table" then
|
if type(store.profile) ~= "table" then
|
||||||
@@ -242,17 +236,14 @@ local function ensureProfile()
|
|||||||
end
|
end
|
||||||
if type(store.profile.barposition) ~= "table" and type(store.barposition) == "table" then
|
if type(store.profile.barposition) ~= "table" and type(store.barposition) == "table" then
|
||||||
store.profile.barposition = deepCopyValue(store.barposition)
|
store.profile.barposition = deepCopyValue(store.barposition)
|
||||||
MTH_CHRON_Trace("ensureProfile migrated legacy char barposition -> profile.barposition")
|
|
||||||
end
|
end
|
||||||
if type(store.profile.barposition) ~= "table" and MTH.GetModuleSavedVariables then
|
if type(store.profile.barposition) ~= "table" and MTH.GetModuleSavedVariables then
|
||||||
local accountStore = MTH:GetModuleSavedVariables("chronometer")
|
local accountStore = MTH:GetModuleSavedVariables("chronometer")
|
||||||
if type(accountStore) == "table" then
|
if type(accountStore) == "table" then
|
||||||
if type(accountStore.barposition) == "table" then
|
if type(accountStore.barposition) == "table" then
|
||||||
store.profile.barposition = deepCopyValue(accountStore.barposition)
|
store.profile.barposition = deepCopyValue(accountStore.barposition)
|
||||||
MTH_CHRON_Trace("ensureProfile migrated legacy account barposition -> profile.barposition")
|
|
||||||
elseif type(accountStore.profile) == "table" and type(accountStore.profile.barposition) == "table" then
|
elseif type(accountStore.profile) == "table" and type(accountStore.profile.barposition) == "table" then
|
||||||
store.profile.barposition = deepCopyValue(accountStore.profile.barposition)
|
store.profile.barposition = deepCopyValue(accountStore.profile.barposition)
|
||||||
MTH_CHRON_Trace("ensureProfile copied account profile.barposition -> char profile.barposition")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -282,7 +273,6 @@ local function ensureProfile()
|
|||||||
profile.disabledSpells.HUNTER = {}
|
profile.disabledSpells.HUNTER = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_CHRON_Trace("ensureProfile result barposition=" .. MTH_CHRON_FormatBarPosition(profile))
|
|
||||||
|
|
||||||
return profile
|
return profile
|
||||||
end
|
end
|
||||||
@@ -309,8 +299,6 @@ local function MTH_CHRON_PersistAnchorPosition(self, reason)
|
|||||||
self.profile.barposition.relativePoint = relPoint
|
self.profile.barposition.relativePoint = relPoint
|
||||||
self.profile.barposition.x = x
|
self.profile.barposition.x = x
|
||||||
self.profile.barposition.y = y
|
self.profile.barposition.y = y
|
||||||
MTH_CHRON_Trace("persist-anchor reason=" .. tostring(reason or "")
|
|
||||||
.. " profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -330,8 +318,6 @@ local function MTH_CHRON_RestoreAnchorFromProfile(self, reason)
|
|||||||
local ppoint = tostring(bp.point or "")
|
local ppoint = tostring(bp.point or "")
|
||||||
local prelpoint = tostring(bp.relativePoint or "")
|
local prelpoint = tostring(bp.relativePoint or "")
|
||||||
if not (px and py and ppoint ~= "") then
|
if not (px and py and ppoint ~= "") then
|
||||||
MTH_CHRON_Trace("restore-anchor skipped reason=" .. tostring(reason or "")
|
|
||||||
.. " profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if prelpoint == "" then
|
if prelpoint == "" then
|
||||||
@@ -339,8 +325,6 @@ local function MTH_CHRON_RestoreAnchorFromProfile(self, reason)
|
|||||||
end
|
end
|
||||||
self.anchor:ClearAllPoints()
|
self.anchor:ClearAllPoints()
|
||||||
self.anchor:SetPoint(ppoint, UIParent, prelpoint, px, py)
|
self.anchor:SetPoint(ppoint, UIParent, prelpoint, px, py)
|
||||||
MTH_CHRON_Trace("restore-anchor applied reason=" .. tostring(reason or "")
|
|
||||||
.. " frame=" .. MTH_CHRON_DescribePoint(self.anchor))
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -485,16 +469,22 @@ local function getActionSpell(slot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not Chronometer._scanTooltip then
|
if not Chronometer._scanTooltip then
|
||||||
Chronometer._scanTooltip = CreateFrame("GameTooltip", "MTH_ChronometerScanTooltip", UIParent, "GameTooltipTemplate")
|
local tip = CreateFrame("GameTooltip", "MTH_ChrBarProbe", UIParent)
|
||||||
Chronometer._scanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
tip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||||
|
for i = 1, 4 do
|
||||||
|
local L = tip:CreateFontString("MTH_ChrBarProbeTextLeft"..i, "ARTWORK", "GameTooltipText")
|
||||||
|
local R = tip:CreateFontString("MTH_ChrBarProbeTextRight"..i, "ARTWORK", "GameTooltipText")
|
||||||
|
tip:AddFontStrings(L, R)
|
||||||
|
end
|
||||||
|
Chronometer._scanTooltip = tip
|
||||||
end
|
end
|
||||||
|
|
||||||
local tooltip = Chronometer._scanTooltip
|
local tooltip = Chronometer._scanTooltip
|
||||||
tooltip:ClearLines()
|
tooltip:ClearLines()
|
||||||
tooltip:SetAction(slot)
|
tooltip:SetAction(slot)
|
||||||
|
|
||||||
local left1 = getglobal("MTH_ChronometerScanTooltipTextLeft1")
|
local left1 = getglobal("MTH_ChrBarProbeTextLeft1")
|
||||||
local left2 = getglobal("MTH_ChronometerScanTooltipTextLeft2")
|
local left2 = getglobal("MTH_ChrBarProbeTextLeft2")
|
||||||
local spellName = left1 and left1:GetText() or nil
|
local spellName = left1 and left1:GetText() or nil
|
||||||
if not spellName or spellName == "" then
|
if not spellName or spellName == "" then
|
||||||
return nil, 0
|
return nil, 0
|
||||||
@@ -521,7 +511,6 @@ function Chronometer:MTH_Initialize()
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.profile = ensureProfile()
|
self.profile = ensureProfile()
|
||||||
MTH_CHRON_Trace("MTH_Initialize profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
|
||||||
self.parser = ParserLib:GetInstance("1.1")
|
self.parser = ParserLib:GetInstance("1.1")
|
||||||
|
|
||||||
self.COLOR_MAP = {
|
self.COLOR_MAP = {
|
||||||
@@ -532,7 +521,6 @@ function Chronometer:MTH_Initialize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.anchor = self:CreateAnchor("MetaHunt Chronometer", 0, 1, 0)
|
self.anchor = self:CreateAnchor("MetaHunt Chronometer", 0, 1, 0)
|
||||||
MTH_CHRON_Trace("MTH_Initialize anchor-created point=" .. MTH_CHRON_DescribePoint(self.anchor))
|
|
||||||
self:RegisterCandyBarGroup(BAR_GROUP)
|
self:RegisterCandyBarGroup(BAR_GROUP)
|
||||||
self:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0)
|
self:SetCandyBarGroupPoint(BAR_GROUP, "TOP", self.anchor, "BOTTOM", 0, 0)
|
||||||
|
|
||||||
@@ -541,19 +529,16 @@ end
|
|||||||
|
|
||||||
function Chronometer:MTH_Enable()
|
function Chronometer:MTH_Enable()
|
||||||
self._mth_explicitEnable = true
|
self._mth_explicitEnable = true
|
||||||
MTH_CHRON_Trace("MTH_Enable called")
|
|
||||||
self:MTH_Initialize()
|
self:MTH_Initialize()
|
||||||
self:OnEnable()
|
self:OnEnable()
|
||||||
self._mth_explicitEnable = nil
|
self._mth_explicitEnable = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Chronometer:MTH_Disable()
|
function Chronometer:MTH_Disable()
|
||||||
MTH_CHRON_Trace("MTH_Disable called")
|
|
||||||
self:OnDisable()
|
self:OnDisable()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Chronometer:OnEnable()
|
function Chronometer:OnEnable()
|
||||||
MTH_CHRON_Trace("OnEnable begin enabled=" .. tostring(self._mth_enabled and true or false))
|
|
||||||
if self._mth_enabled then
|
if self._mth_enabled then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -583,11 +568,9 @@ function Chronometer:OnEnable()
|
|||||||
self._mth_enabled = true
|
self._mth_enabled = true
|
||||||
|
|
||||||
self.profile = ensureProfile()
|
self.profile = ensureProfile()
|
||||||
MTH_CHRON_Trace("OnEnable profile-after-ensure=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
applyGrowup(self, self.profile.growup and true or false)
|
||||||
self:SetCandyBarGroupGrowth(BAR_GROUP, self.profile.growup and true or false)
|
|
||||||
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
|
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
|
||||||
if self.anchor then
|
if self.anchor then
|
||||||
MTH_CHRON_Trace("OnEnable anchor-current-point=" .. MTH_CHRON_DescribePoint(self.anchor))
|
|
||||||
end
|
end
|
||||||
MTH_CHRON_RestoreAnchorFromProfile(self, "OnEnable")
|
MTH_CHRON_RestoreAnchorFromProfile(self, "OnEnable")
|
||||||
|
|
||||||
@@ -609,14 +592,18 @@ function Chronometer:OnEnable()
|
|||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_AURA_GONE_SELF", function(event, info) self:SPELL_FADE(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_AURA_GONE_SELF", function(event, info) self:SPELL_FADE(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_AURA_GONE_OTHER", function(event, info) self:SPELL_FADE(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_AURA_GONE_OTHER", function(event, info) self:SPELL_FADE(event, info) end)
|
||||||
|
|
||||||
|
-- Registered events:
|
||||||
|
-- SELF_BUFFS / SELF_DAMAGE → our own procs & self-damage (source == ParserLib_SELF confirmed)
|
||||||
|
-- CREATURE_DAMAGE → DOT ticks on creatures ("from your X" embeds source; filtered in SPELL_PERIODIC)
|
||||||
|
-- CREATURE_BUFFS → debuff APPLICATION on creatures ("X is afflicted by Y"; no source embedded).
|
||||||
|
-- Needed for non-ticking debuffs: Poisonous/Enchanted Ammunition, Piercing Shot.
|
||||||
|
-- Foreign-bar risk is mitigated in SPELL_PERIODIC by requiring victim == target
|
||||||
|
-- when source is nil and no confirmed cast record exists.
|
||||||
|
-- FRIENDLYPLAYER_*, HOSTILEPLAYER_* are other players' events → intentionally NOT registered.
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE", function(event, info) self:SPELL_PERIODIC(event, info) end)
|
|
||||||
|
|
||||||
local enableRoM = false
|
local enableRoM = false
|
||||||
for _, timer in pairs(self.timers[self.SPELL] or {}) do
|
for _, timer in pairs(self.timers[self.SPELL] or {}) do
|
||||||
@@ -675,15 +662,34 @@ function Chronometer:OnEnable()
|
|||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_SELF_DAMAGE", function(event, info) self:SELF_DAMAGE(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_SELF_DAMAGE", function(event, info) self:SELF_DAMAGE(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF", function(event, info) self:SELF_DAMAGE(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF", function(event, info) self:SELF_DAMAGE(event, info) end)
|
||||||
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_FAILED_LOCALPLAYER", function(event, info) self:SPELL_FAILED(event, info) end)
|
self.parser:RegisterEvent(PARSER_OWNER, "CHAT_MSG_SPELL_FAILED_LOCALPLAYER", function(event, info) self:SPELL_FAILED(event, info) end)
|
||||||
|
|
||||||
|
-- NamPower: register authoritative self-aura events for instant bar
|
||||||
|
-- kill and duration resync. The ParserLib chat paths remain active as
|
||||||
|
-- they handle creature/target debuffs that NamPower cannot see.
|
||||||
|
if MTH and MTH.nampower then
|
||||||
|
self._nampowerSpellIdCache = {}
|
||||||
|
self:RegisterEvent("BUFF_ADDED_SELF")
|
||||||
|
self:RegisterEvent("BUFF_REMOVED_SELF")
|
||||||
|
self:RegisterEvent("DEBUFF_ADDED_SELF")
|
||||||
|
self:RegisterEvent("DEBUFF_REMOVED_SELF")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Chronometer:VARIABLES_LOADED()
|
function Chronometer:VARIABLES_LOADED()
|
||||||
self.profile = ensureProfile()
|
self.profile = ensureProfile()
|
||||||
|
if self._mth_enabled then
|
||||||
|
applyGrowup(self, self.profile.growup and true or false)
|
||||||
|
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
|
||||||
|
end
|
||||||
MTH_CHRON_RestoreAnchorFromProfile(self, "VARIABLES_LOADED")
|
MTH_CHRON_RestoreAnchorFromProfile(self, "VARIABLES_LOADED")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Chronometer:PLAYER_ENTERING_WORLD()
|
function Chronometer:PLAYER_ENTERING_WORLD()
|
||||||
self.profile = ensureProfile()
|
self.profile = ensureProfile()
|
||||||
|
if self._mth_enabled then
|
||||||
|
applyGrowup(self, self.profile.growup and true or false)
|
||||||
|
self:SetCandyBarGroupVerticalSpacing(BAR_GROUP, self.profile.spacing or 0)
|
||||||
|
end
|
||||||
MTH_CHRON_RestoreAnchorFromProfile(self, "PLAYER_ENTERING_WORLD")
|
MTH_CHRON_RestoreAnchorFromProfile(self, "PLAYER_ENTERING_WORLD")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -695,9 +701,7 @@ function Chronometer:OnDisable()
|
|||||||
if not self._mth_enabled then
|
if not self._mth_enabled then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
MTH_CHRON_Trace("OnDisable begin profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
|
||||||
if self.anchor then
|
if self.anchor then
|
||||||
MTH_CHRON_Trace("OnDisable anchor-point=" .. MTH_CHRON_DescribePoint(self.anchor))
|
|
||||||
end
|
end
|
||||||
MTH_CHRON_PersistAnchorPosition(self, "OnDisable")
|
MTH_CHRON_PersistAnchorPosition(self, "OnDisable")
|
||||||
self._mth_enabled = false
|
self._mth_enabled = false
|
||||||
@@ -1191,7 +1195,7 @@ function Chronometer:ToggleAnchor()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Chronometer:CreateAnchor(text, r, g, b)
|
function Chronometer:CreateAnchor(text, r, g, b)
|
||||||
local frame = CreateFrame("Button", "MTHChronometerAnchor", UIParent)
|
local frame = CreateFrame("Button", "MTH_ChronometerAnchor", UIParent)
|
||||||
frame:SetWidth(220)
|
frame:SetWidth(220)
|
||||||
frame:SetHeight(25)
|
frame:SetHeight(25)
|
||||||
frame.owner = self
|
frame.owner = self
|
||||||
@@ -1203,7 +1207,6 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
|||||||
local py = tonumber(self.profile and self.profile.barposition and self.profile.barposition.y)
|
local py = tonumber(self.profile and self.profile.barposition and self.profile.barposition.y)
|
||||||
local ppoint = tostring(self.profile and self.profile.barposition and self.profile.barposition.point or "")
|
local ppoint = tostring(self.profile and self.profile.barposition and self.profile.barposition.point or "")
|
||||||
local prelpoint = tostring(self.profile and self.profile.barposition and self.profile.barposition.relativePoint or "")
|
local prelpoint = tostring(self.profile and self.profile.barposition and self.profile.barposition.relativePoint or "")
|
||||||
MTH_CHRON_Trace("CreateAnchor saved-in profile=" .. MTH_CHRON_FormatBarPosition(self.profile))
|
|
||||||
if px ~= nil and py ~= nil then
|
if px ~= nil and py ~= nil then
|
||||||
if ppoint == "" then
|
if ppoint == "" then
|
||||||
ppoint = "TOPLEFT"
|
ppoint = "TOPLEFT"
|
||||||
@@ -1213,31 +1216,26 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
|||||||
end
|
end
|
||||||
frame:ClearAllPoints()
|
frame:ClearAllPoints()
|
||||||
frame:SetPoint(ppoint, UIParent, prelpoint, px, py)
|
frame:SetPoint(ppoint, UIParent, prelpoint, px, py)
|
||||||
MTH_CHRON_Trace("CreateAnchor restored point=" .. MTH_CHRON_DescribePoint(frame))
|
|
||||||
else
|
else
|
||||||
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 50)
|
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 50)
|
||||||
MTH_CHRON_Trace("CreateAnchor default point=" .. MTH_CHRON_DescribePoint(frame))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
frame:SetScript("OnDragStart", function(self)
|
frame:SetScript("OnDragStart", function()
|
||||||
self = self or this
|
if not this or not this.StartMoving then
|
||||||
if not self or not self.StartMoving then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
MTH_CHRON_Trace("anchor drag-start point=" .. MTH_CHRON_DescribePoint(self))
|
this:StartMoving()
|
||||||
self:StartMoving()
|
|
||||||
end)
|
end)
|
||||||
frame:SetScript("OnDragStop", function(self)
|
frame:SetScript("OnDragStop", function()
|
||||||
self = self or this
|
if not this then
|
||||||
if not self then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.StopMovingOrSizing then
|
if this.StopMovingOrSizing then
|
||||||
self:StopMovingOrSizing()
|
this:StopMovingOrSizing()
|
||||||
end
|
end
|
||||||
|
|
||||||
local point, _, _, x, y = self:GetPoint()
|
local point, _, _, x, y = this:GetPoint()
|
||||||
x = tonumber(x)
|
x = tonumber(x)
|
||||||
y = tonumber(y)
|
y = tonumber(y)
|
||||||
if not x or not y then
|
if not x or not y then
|
||||||
@@ -1246,16 +1244,14 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
|||||||
|
|
||||||
x = math.floor(x + 0.5)
|
x = math.floor(x + 0.5)
|
||||||
y = math.floor(y + 0.5)
|
y = math.floor(y + 0.5)
|
||||||
self:ClearAllPoints()
|
this:ClearAllPoints()
|
||||||
self:SetPoint(point or "TOPLEFT", UIParent, point or "TOPLEFT", x, y)
|
this:SetPoint(point or "TOPLEFT", UIParent, point or "TOPLEFT", x, y)
|
||||||
|
|
||||||
if self.owner and self.owner.profile and type(self.owner.profile.barposition) == "table" then
|
if this.owner and this.owner.profile and type(this.owner.profile.barposition) == "table" then
|
||||||
self.owner.profile.barposition.point = point or "TOPLEFT"
|
this.owner.profile.barposition.point = point or "TOPLEFT"
|
||||||
self.owner.profile.barposition.relativePoint = point or "TOPLEFT"
|
this.owner.profile.barposition.relativePoint = point or "TOPLEFT"
|
||||||
self.owner.profile.barposition.x = x
|
this.owner.profile.barposition.x = x
|
||||||
self.owner.profile.barposition.y = y
|
this.owner.profile.barposition.y = y
|
||||||
MTH_CHRON_Trace("anchor drag-stop saved profile=" .. MTH_CHRON_FormatBarPosition(self.owner.profile)
|
|
||||||
.. " frame=" .. MTH_CHRON_DescribePoint(self))
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -1284,6 +1280,85 @@ function Chronometer:CreateAnchor(text, r, g, b)
|
|||||||
return frame
|
return frame
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ────────────────────────────────────────────────────────────
|
||||||
|
-- NamPower self-aura handlers
|
||||||
|
-- ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
-- Helper: resolve spellId → spell name, with cache
|
||||||
|
local function NP_ResolveName(cache, spellId)
|
||||||
|
if not spellId or spellId == 0 then return nil end
|
||||||
|
local name = cache[spellId]
|
||||||
|
if name then return name end
|
||||||
|
name = GetSpellRecField(spellId, "name")
|
||||||
|
if name and name ~= "" then
|
||||||
|
cache[spellId] = name
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- BUFF / DEBUFF removed from the player → kill matching self-bar instantly
|
||||||
|
function Chronometer:BUFF_REMOVED_SELF()
|
||||||
|
if not self.profile.fadeonfade then return end
|
||||||
|
local spellId = arg3
|
||||||
|
local name = NP_ResolveName(self._nampowerSpellIdCache, spellId)
|
||||||
|
if not name then return end
|
||||||
|
self:KillBar(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
Chronometer.DEBUFF_REMOVED_SELF = Chronometer.BUFF_REMOVED_SELF
|
||||||
|
|
||||||
|
-- BUFF / DEBUFF added to the player → resync running bar duration
|
||||||
|
function Chronometer:BUFF_ADDED_SELF()
|
||||||
|
local spellId = arg3
|
||||||
|
local name = NP_ResolveName(self._nampowerSpellIdCache, spellId)
|
||||||
|
if not name then return end
|
||||||
|
|
||||||
|
-- Find the matching self-bar
|
||||||
|
local bar = nil
|
||||||
|
for i = 1, 20 do
|
||||||
|
if self.bars[i].id and self.bars[i].name == name then
|
||||||
|
local tgt = self.bars[i].target
|
||||||
|
if tgt == "none" or tgt == UnitName("player") then
|
||||||
|
bar = self.bars[i]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not bar then return end
|
||||||
|
|
||||||
|
-- Get authoritative remaining duration from NamPower aura array
|
||||||
|
local remaining = nil
|
||||||
|
local auras = GetUnitField("player", "aura")
|
||||||
|
if auras then
|
||||||
|
for slot = 1, 48 do
|
||||||
|
if auras[slot] == spellId then
|
||||||
|
local _, ms = GetPlayerAuraDuration(slot - 1)
|
||||||
|
if ms and ms > 0 then
|
||||||
|
remaining = ms / 1000
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not remaining then
|
||||||
|
-- Fallback: use base DBC duration
|
||||||
|
local dms = GetSpellDuration(spellId)
|
||||||
|
if dms and dms > 0 then
|
||||||
|
remaining = dms / 1000
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not remaining then return end
|
||||||
|
|
||||||
|
-- Resync: update total first (allows SetTimeLeft to extend), then set remaining
|
||||||
|
self:SetCandyBarTime(bar.id, remaining)
|
||||||
|
self:SetCandyBarTimeLeft(bar.id, remaining)
|
||||||
|
end
|
||||||
|
|
||||||
|
Chronometer.DEBUFF_ADDED_SELF = Chronometer.BUFF_ADDED_SELF
|
||||||
|
|
||||||
|
-- ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function Chronometer:COMBAT_DEATH(event, info)
|
function Chronometer:COMBAT_DEATH(event, info)
|
||||||
if not self.profile.fadeonkill then return end
|
if not self.profile.fadeonkill then return end
|
||||||
if info.type == "experience" then
|
if info.type == "experience" then
|
||||||
@@ -1301,9 +1376,11 @@ function Chronometer:SPELL_FADE(event, info)
|
|||||||
if not self.profile.fadeonfade then return end
|
if not self.profile.fadeonfade then return end
|
||||||
if info.skill == BS["Banish"] then return end
|
if info.skill == BS["Banish"] then return end
|
||||||
if info.type == "fade" then
|
if info.type == "fade" then
|
||||||
|
-- Only act when the fade is on the player or on their target, not on other players
|
||||||
if info.victim == ParserLib_SELF then
|
if info.victim == ParserLib_SELF then
|
||||||
return self:KillBar(info.skill)
|
return self:KillBar(info.skill)
|
||||||
end
|
end
|
||||||
|
if info.source and info.source ~= ParserLib_SELF then return end
|
||||||
return self:KillBar(info.skill, info.victim)
|
return self:KillBar(info.skill, info.victim)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1311,8 +1388,20 @@ end
|
|||||||
function Chronometer:SPELL_PERIODIC(event, info)
|
function Chronometer:SPELL_PERIODIC(event, info)
|
||||||
local aura, rank, unit, isgain
|
local aura, rank, unit, isgain
|
||||||
|
|
||||||
|
-- Primary filter: explicit non-self source → always ignore (other player's confirmed event)
|
||||||
|
if info.source and info.source ~= ParserLib_SELF then return end
|
||||||
|
|
||||||
|
-- Secondary filter: creature/friendly periodic events do NOT embed a caster name,
|
||||||
|
-- so info.source is nil even for other players' effects. Track whether this event
|
||||||
|
-- was provably ours (SELF_BUFFS / SELF_DAMAGE events give source == ParserLib_SELF).
|
||||||
|
local sourceIsConfirmedSelf = (info.source == ParserLib_SELF)
|
||||||
|
|
||||||
if info.type == "buff" then
|
if info.type == "buff" then
|
||||||
isgain = 1
|
isgain = 1
|
||||||
|
-- Buff gained by someone other than self with no source confirmation → another player's proc
|
||||||
|
if not sourceIsConfirmedSelf and info.victim ~= nil and info.victim ~= ParserLib_SELF then
|
||||||
|
return
|
||||||
|
end
|
||||||
elseif info.type == "debuff" then
|
elseif info.type == "debuff" then
|
||||||
isgain = nil
|
isgain = nil
|
||||||
elseif not info.isDOT then
|
elseif not info.isDOT then
|
||||||
@@ -1340,7 +1429,27 @@ function Chronometer:SPELL_PERIODIC(event, info)
|
|||||||
if timer.k.t then
|
if timer.k.t then
|
||||||
if not unit then unit = UnitName("player") end
|
if not unit then unit = UnitName("player") end
|
||||||
if timer.k.s then
|
if timer.k.s then
|
||||||
if timer.t and timer.t ~= unit then return end
|
-- Selforselect: four-tier confirmation.
|
||||||
|
-- 1. Confirmed cast record (timer.t set by CastSpell hook): require target match.
|
||||||
|
-- 2. Confirmed self source (SELF_BUFFS / SELF_DAMAGE events, source == SELF): accept.
|
||||||
|
-- 3. Cast-window confirmed (timer.v fresh, timer.t nil): untargeted spells like traps
|
||||||
|
-- where the caster is known but the trigger victim cannot be predicted in advance.
|
||||||
|
-- Accept unconditionally — the mob that walked into the trap may not be our target.
|
||||||
|
-- 4. Source unconfirmed AND no cast record (CREATURE_BUFFS affliction messages never
|
||||||
|
-- embed a caster name): fall back to target-check. This lets non-ticking debuffs
|
||||||
|
-- (Poisonous Ammo, Enchanted Ammo, Piercing Shot…) show when applied to our current
|
||||||
|
-- target, while blocking the same debuff on a mob we are NOT targeting (i.e. another
|
||||||
|
-- player's debuff on a different dummy).
|
||||||
|
if timer.t then
|
||||||
|
if timer.t ~= unit then return end
|
||||||
|
elseif sourceIsConfirmedSelf then
|
||||||
|
-- source confirmed → accept unconditionally
|
||||||
|
elseif timer.v and timer.v > GetTime() then
|
||||||
|
-- cast-window confirmed, timer.t nil → untargeted cast (e.g. trap placed on ground)
|
||||||
|
-- victim unknown at cast time; accept whatever mob triggered it
|
||||||
|
elseif not UnitExists("target") or unit ~= UnitName("target") then
|
||||||
|
return
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if not UnitExists("target") or unit ~= UnitName("target") then return end
|
if not UnitExists("target") or unit ~= UnitName("target") then return end
|
||||||
end
|
end
|
||||||
@@ -1400,7 +1509,9 @@ function Chronometer:UNIT_AURA(unit)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local hasFeedAura = false
|
local hasFeedAura = false
|
||||||
if type(UnitBuff) == "function" then
|
if type(MTH_FEED_HasPetFeedBuff) == "function" then
|
||||||
|
hasFeedAura = MTH_FEED_HasPetFeedBuff()
|
||||||
|
elseif type(UnitBuff) == "function" then
|
||||||
for i = 1, 32 do
|
for i = 1, 32 do
|
||||||
local texture = UnitBuff("pet", i)
|
local texture = UnitBuff("pet", i)
|
||||||
if not texture then
|
if not texture then
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ Documentation: http://web.archive.org/web/20070314234510/http://wowace.com/wiki/
|
|||||||
Description: A timer bars library.
|
Description: A timer bars library.
|
||||||
Dependencies: AceLibrary, AceOO-2.0, PaintChips-2.0
|
Dependencies: AceLibrary, AceOO-2.0, PaintChips-2.0
|
||||||
]]
|
]]
|
||||||
local match = string.match
|
|
||||||
local getn,setn,tinsert = table.getn, table.setn,table.insert
|
local getn,setn,tinsert = table.getn, table.setn,table.insert
|
||||||
local vmajor, vminor = "CandyBar-2.0", "$Revision: 16011 $"
|
local vmajor, vminor = "CandyBar-2.0", "$Revision: 16011 $"
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,14 @@
|
|||||||
local MTH_ChronometerModule = {
|
local MTH_ChronometerModule = {
|
||||||
name = "chronometer",
|
name = "chronometer",
|
||||||
enabled = true,
|
enabled = true,
|
||||||
version = "1.1.0",
|
|
||||||
events = {},
|
events = {},
|
||||||
initialized = false,
|
initialized = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
local MTH_CHRON_MODULE_TRACE_ENABLED = false
|
|
||||||
|
|
||||||
local function MTH_CHRON_ModuleTrace(msg)
|
|
||||||
if not MTH_CHRON_MODULE_TRACE_ENABLED then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if MTH and MTH.Print then
|
|
||||||
MTH:Print("[CHRONTRACE] " .. tostring(msg), "debug")
|
|
||||||
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
|
||||||
DEFAULT_CHAT_FRAME:AddMessage("[CHRONTRACE] " .. tostring(msg))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
|
local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
|
||||||
MTH_CHRON_ModuleTrace("module apply runtime enabled=" .. tostring(enabled and true or false))
|
|
||||||
if not MTH_ChronometerHunter then
|
if not MTH_ChronometerHunter then
|
||||||
MTH_CHRON_ModuleTrace("module apply runtime skipped (engine unavailable)")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if enabled then
|
if enabled then
|
||||||
@@ -37,18 +23,14 @@ local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MTH_ChronometerModule:init()
|
function MTH_ChronometerModule:init()
|
||||||
MTH_CHRON_ModuleTrace("module init begin enabled=" .. tostring(self.enabled and true or false))
|
|
||||||
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Initialize then
|
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Initialize then
|
||||||
MTH_ChronometerHunter:MTH_Initialize()
|
MTH_ChronometerHunter:MTH_Initialize()
|
||||||
end
|
end
|
||||||
MTH_CHRON_ApplyRuntimeEnabledState(self.enabled and true or false)
|
MTH_CHRON_ApplyRuntimeEnabledState(self.enabled and true or false)
|
||||||
self.initialized = true
|
self.initialized = true
|
||||||
MTH_CHRON_ModuleTrace("module init end initialized=true")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_ChronometerModule:setEnabled(enabled)
|
function MTH_ChronometerModule:setEnabled(enabled)
|
||||||
MTH_CHRON_ModuleTrace("module setEnabled enabled=" .. tostring(enabled and true or false)
|
|
||||||
.. " initialized=" .. tostring(self.initialized and true or false))
|
|
||||||
if not self.initialized then
|
if not self.initialized then
|
||||||
self:init()
|
self:init()
|
||||||
end
|
end
|
||||||
@@ -56,7 +38,6 @@ function MTH_ChronometerModule:setEnabled(enabled)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MTH_ChronometerModule:cleanup()
|
function MTH_ChronometerModule:cleanup()
|
||||||
MTH_CHRON_ModuleTrace("module cleanup")
|
|
||||||
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Disable then
|
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Disable then
|
||||||
MTH_ChronometerHunter:MTH_Disable()
|
MTH_ChronometerHunter:MTH_Disable()
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
|||||||
|
<!--
|
||||||
|
MetaHunt: Experimental Ammunition Module Loader
|
||||||
|
-->
|
||||||
|
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||||
|
<Include file="engine.lua"/>
|
||||||
|
</Ui>
|
||||||
+150
-273
@@ -56,12 +56,7 @@ FOM_LastChoiceReason = nil;
|
|||||||
FOM_RealmPlayer = nil;
|
FOM_RealmPlayer = nil;
|
||||||
FOM_LastPetName = nil;
|
FOM_LastPetName = nil;
|
||||||
FOM_LastFeedAttempt = nil;
|
FOM_LastFeedAttempt = nil;
|
||||||
FOM_TRACE_ENABLED = false;
|
local FOM_CORE_ATTEMPT_TRACKING_ENABLED = true;
|
||||||
local FOM_CORE_ATTEMPT_TRACKING_ENABLED = false;
|
|
||||||
local FOM_PERF_TRACE_ENABLED = false;
|
|
||||||
local FOM_PERF_TRACE_HISTORY_LIMIT = 80;
|
|
||||||
local FOM_PERF_TRACE_SPIKE_MS = 12;
|
|
||||||
local FOM_PERF_TRACE_HISTORY = {};
|
|
||||||
local FOM_LAST_SETUP_AT = 0;
|
local FOM_LAST_SETUP_AT = 0;
|
||||||
local FOM_LAST_SETUP_PET = nil;
|
local FOM_LAST_SETUP_PET = nil;
|
||||||
local FOM_LAST_QUEST_SCAN_AT = 0;
|
local FOM_LAST_QUEST_SCAN_AT = 0;
|
||||||
@@ -125,79 +120,15 @@ FOM_FamilyToLegacyMap = {
|
|||||||
["Wolves"] = WOLF,
|
["Wolves"] = WOLF,
|
||||||
};
|
};
|
||||||
|
|
||||||
local function FOM_Trace(message)
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
|
|
||||||
local function FOM_PerfNowMs()
|
|
||||||
if (type(debugprofilestop) == "function") then
|
|
||||||
local raw = tonumber(debugprofilestop()) or 0;
|
|
||||||
return raw / 1000;
|
|
||||||
end
|
|
||||||
if (type(GetTime) == "function") then
|
|
||||||
return (tonumber(GetTime()) or 0) * 1000;
|
|
||||||
end
|
|
||||||
return 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
local function FOM_PerfOut(message, forceShow)
|
|
||||||
local text = tostring(message or "");
|
|
||||||
if (text == "") then
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
if (type(MTH_DebugFrame) == "table" and type(MTH_DebugFrame.AddInfo) == "function") then
|
|
||||||
if (forceShow and type(MTH_DebugFrame.Show) == "function") then
|
|
||||||
MTH_DebugFrame:Show();
|
|
||||||
end
|
|
||||||
MTH_DebugFrame:AddInfo(text);
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
if (MTH and type(MTH.Print) == "function") then
|
|
||||||
MTH:Print(text, "debug");
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
if (type(GFWUtils) == "table" and type(GFWUtils.Print) == "function") then
|
|
||||||
GFWUtils.Print(text);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function FOM_PerfRecord(label, elapsedMs, detail, forcePrint)
|
|
||||||
if (not FOM_PERF_TRACE_ENABLED) then
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
local numericElapsed = tonumber(elapsedMs) or 0;
|
|
||||||
if (numericElapsed > 10000) then
|
|
||||||
numericElapsed = numericElapsed / 1000;
|
|
||||||
end
|
|
||||||
local row = {
|
|
||||||
ts = time and time() or 0,
|
|
||||||
label = tostring(label or "unknown"),
|
|
||||||
ms = numericElapsed,
|
|
||||||
detail = tostring(detail or ""),
|
|
||||||
};
|
|
||||||
table.insert(FOM_PERF_TRACE_HISTORY, row);
|
|
||||||
if (table.getn(FOM_PERF_TRACE_HISTORY) > FOM_PERF_TRACE_HISTORY_LIMIT) then
|
|
||||||
table.remove(FOM_PERF_TRACE_HISTORY, 1);
|
|
||||||
end
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
|
|
||||||
local function FOM_PerfDump()
|
|
||||||
if (table.getn(FOM_PERF_TRACE_HISTORY) <= 0) then
|
-- [DISABLED] NO-BUFF quarantine: set to true to re-enable.
|
||||||
FOM_PerfOut("[FOM PERF] no samples.", true);
|
-- When false, failed feeds are still logged but items are never
|
||||||
return;
|
-- blacklisted and the quarantine store is never consulted.
|
||||||
end
|
local FOM_QUARANTINE_ENABLED = false;
|
||||||
FOM_PerfOut("[FOM PERF] recent samples: " .. tostring(table.getn(FOM_PERF_TRACE_HISTORY)), true);
|
|
||||||
for i = 1, table.getn(FOM_PERF_TRACE_HISTORY) do
|
|
||||||
local row = FOM_PERF_TRACE_HISTORY[i];
|
|
||||||
if (type(row) == "table") then
|
|
||||||
FOM_PerfOut("[FOM PERF] #" .. tostring(i)
|
|
||||||
.. " " .. tostring(row.label)
|
|
||||||
.. " " .. string.format("%.2f", tonumber(row.ms) or 0) .. "ms"
|
|
||||||
.. (tostring(row.detail or "") ~= "" and (" | " .. tostring(row.detail)) or ""), false);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function FOM_GetServerProfile()
|
local function FOM_GetServerProfile()
|
||||||
return FOM_ServerProfiles[FOM_SERVER_PROFILE] or {};
|
return FOM_ServerProfiles[FOM_SERVER_PROFILE] or {};
|
||||||
@@ -260,6 +191,7 @@ local function FOM_GetFamilyKeyFromInfo(petInfo)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function FOM_RegisterNoBuffQuarantine(itemID, petInfo)
|
local function FOM_RegisterNoBuffQuarantine(itemID, petInfo)
|
||||||
|
if (not FOM_QUARANTINE_ENABLED) then return; end
|
||||||
local numericItem = tonumber(itemID);
|
local numericItem = tonumber(itemID);
|
||||||
if (numericItem == nil) then
|
if (numericItem == nil) then
|
||||||
return;
|
return;
|
||||||
@@ -288,12 +220,10 @@ local function FOM_RegisterNoBuffQuarantine(itemID, petInfo)
|
|||||||
end
|
end
|
||||||
row.lastObservedAt = time and time() or 0;
|
row.lastObservedAt = time and time() or 0;
|
||||||
row.reason = "no-buff";
|
row.reason = "no-buff";
|
||||||
FOM_Trace("quarantine add family='" .. tostring(familyKey)
|
|
||||||
.. "' itemId=" .. tostring(numericItem)
|
|
||||||
.. " minRejectPetLevel=" .. tostring(row.minRejectPetLevel));
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function FOM_IsQuarantined(itemID, petLevel, familyKey)
|
local function FOM_IsQuarantined(itemID, petLevel, familyKey)
|
||||||
|
if (not FOM_QUARANTINE_ENABLED) then return false; end
|
||||||
local numericItem = tonumber(itemID);
|
local numericItem = tonumber(itemID);
|
||||||
local numericPet = tonumber(petLevel);
|
local numericPet = tonumber(petLevel);
|
||||||
if (numericItem == nil or numericPet == nil or numericPet <= 0) then
|
if (numericItem == nil or numericPet == nil or numericPet <= 0) then
|
||||||
@@ -346,29 +276,6 @@ local function FOM_IsItemPetLevelCompatible(itemID, petLevel)
|
|||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
function FOM_CommandTrace(mode)
|
|
||||||
local arg = string.lower(tostring(mode or ""));
|
|
||||||
if (arg == "perf on") then
|
|
||||||
FOM_PERF_TRACE_ENABLED = true;
|
|
||||||
FOM_PerfOut("[FOM PERF] enabled.", true);
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
if (arg == "perf off") then
|
|
||||||
FOM_PERF_TRACE_ENABLED = false;
|
|
||||||
FOM_PerfOut("[FOM PERF] disabled.", true);
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
if (arg == "perf clear") then
|
|
||||||
FOM_PERF_TRACE_HISTORY = {};
|
|
||||||
FOM_PerfOut("[FOM PERF] cleared.", true);
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
if (arg == "perf dump") then
|
|
||||||
FOM_PerfDump();
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
FOM_PerfOut("Usage: /fomtrace perf on|off|dump|clear", true);
|
|
||||||
end
|
|
||||||
|
|
||||||
local function FOM_CoreFeedReady()
|
local function FOM_CoreFeedReady()
|
||||||
if (not FOM_CORE_ATTEMPT_TRACKING_ENABLED) then
|
if (not FOM_CORE_ATTEMPT_TRACKING_ENABLED) then
|
||||||
@@ -454,7 +361,7 @@ function FOM_BuildFamilyAliasMap()
|
|||||||
|
|
||||||
FOM_AddFamilyAlias("Carrion Bird", "Carrion Birds");
|
FOM_AddFamilyAlias("Carrion Bird", "Carrion Birds");
|
||||||
FOM_AddFamilyAlias("Wind Serpent", "Wind Serpents");
|
FOM_AddFamilyAlias("Wind Serpent", "Wind Serpents");
|
||||||
FOM_AddFamilyAlias("Serpent", "Serpents (Cobra)");
|
FOM_AddFamilyAlias("Serpent", "Serpents");
|
||||||
end
|
end
|
||||||
|
|
||||||
function FOM_GetCanonicalPetFamily(rawFamily)
|
function FOM_GetCanonicalPetFamily(rawFamily)
|
||||||
@@ -639,7 +546,6 @@ local function FOM_PruneUnknownFoodNoise(force)
|
|||||||
if (type(time) == "function") then
|
if (type(time) == "function") then
|
||||||
store.updatedAt = time();
|
store.updatedAt = time();
|
||||||
end
|
end
|
||||||
FOM_Trace("pruned unknown vendor-only non-food rows=" .. tostring(removed));
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return removed;
|
return removed;
|
||||||
@@ -685,7 +591,6 @@ local function FOM_PruneExceptionNoise()
|
|||||||
|
|
||||||
if (removed > 0 and store ~= nil and type(time) == "function") then
|
if (removed > 0 and store ~= nil and type(time) == "function") then
|
||||||
store.updatedAt = time();
|
store.updatedAt = time();
|
||||||
FOM_Trace("pruned inert exception rows=" .. tostring(removed));
|
|
||||||
end
|
end
|
||||||
return removed;
|
return removed;
|
||||||
end
|
end
|
||||||
@@ -780,7 +685,7 @@ local function FOM_DebugLogMerchantFoods(sourceEvent)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FOM_FeedButton_OnClick()
|
function MTH_FOM_FeedButton_OnClick()
|
||||||
if (arg1 == "RightButton") then
|
if (arg1 == "RightButton") then
|
||||||
if (MTH_OpenOptions) then
|
if (MTH_OpenOptions) then
|
||||||
MTH_OpenOptions("FeedOMatic");
|
MTH_OpenOptions("FeedOMatic");
|
||||||
@@ -790,7 +695,7 @@ function FOM_FeedButton_OnClick()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FOM_FeedButton_OnEnter()
|
function MTH_FOM_FeedButton_OnEnter()
|
||||||
if ( PetFrameHappiness.tooltip ) then
|
if ( PetFrameHappiness.tooltip ) then
|
||||||
GameTooltip:SetOwner(PetFrameHappiness, "ANCHOR_RIGHT");
|
GameTooltip:SetOwner(PetFrameHappiness, "ANCHOR_RIGHT");
|
||||||
GameTooltip:SetText(PetFrameHappiness.tooltip);
|
GameTooltip:SetText(PetFrameHappiness.tooltip);
|
||||||
@@ -807,7 +712,7 @@ function FOM_FeedButton_OnEnter()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function FOM_FeedButton_OnLeave()
|
function MTH_FOM_FeedButton_OnLeave()
|
||||||
GameTooltip:Hide();
|
GameTooltip:Hide();
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -824,10 +729,6 @@ function FOM_OnLoad()
|
|||||||
SLASH_FEEDOMATIC3 = "/feed";
|
SLASH_FEEDOMATIC3 = "/feed";
|
||||||
SLASH_FEEDOMATIC4 = "/petfeed"; -- Rauen's PetFeed compatibility
|
SLASH_FEEDOMATIC4 = "/petfeed"; -- Rauen's PetFeed compatibility
|
||||||
SLASH_FEEDOMATIC5 = "/pf";
|
SLASH_FEEDOMATIC5 = "/pf";
|
||||||
SLASH_FOMTRACE1 = "/fomtrace";
|
|
||||||
SlashCmdList["FOMTRACE"] = function(msg)
|
|
||||||
FOM_CommandTrace(msg);
|
|
||||||
end
|
|
||||||
SlashCmdList["FEEDOMATIC"] = function(msg)
|
SlashCmdList["FEEDOMATIC"] = function(msg)
|
||||||
if MTH_IsModuleEnabled and not MTH_IsModuleEnabled("feedomatic", false) then
|
if MTH_IsModuleEnabled and not MTH_IsModuleEnabled("feedomatic", false) then
|
||||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||||
@@ -985,13 +886,13 @@ function FOM_OnEvent(event, arg1)
|
|||||||
this:RegisterEvent("PLAYER_REGEN_ENABLED");
|
this:RegisterEvent("PLAYER_REGEN_ENABLED");
|
||||||
end
|
end
|
||||||
|
|
||||||
if (FOM_FeedButton == nil) then
|
if (MTH_FOM_FeedButton == nil) then
|
||||||
FOM_FeedButton = CreateFrame("Button", "FOM_FeedButton", PetFrameHappiness);
|
MTH_FOM_FeedButton = CreateFrame("Button", "MTH_FOM_FeedButton", PetFrameHappiness);
|
||||||
FOM_FeedButton:SetAllPoints(PetFrameHappiness);
|
MTH_FOM_FeedButton:SetAllPoints(PetFrameHappiness);
|
||||||
FOM_FeedButton:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
MTH_FOM_FeedButton:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
||||||
FOM_FeedButton:SetScript("OnClick", FOM_FeedButton_OnClick);
|
MTH_FOM_FeedButton:SetScript("OnClick", MTH_FOM_FeedButton_OnClick);
|
||||||
FOM_FeedButton:SetScript("OnEnter", FOM_FeedButton_OnEnter);
|
MTH_FOM_FeedButton:SetScript("OnEnter", MTH_FOM_FeedButton_OnEnter);
|
||||||
FOM_FeedButton:SetScript("OnLeave", FOM_FeedButton_OnLeave);
|
MTH_FOM_FeedButton:SetScript("OnLeave", MTH_FOM_FeedButton_OnLeave);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (FOM_Config.Level == "happy") then
|
if (FOM_Config.Level == "happy") then
|
||||||
@@ -1032,7 +933,7 @@ function FOM_OnEvent(event, arg1)
|
|||||||
end
|
end
|
||||||
if (foodID) then
|
if (foodID) then
|
||||||
FOM_LastFood = GFWUtils.ItemLink(foodID);
|
FOM_LastFood = GFWUtils.ItemLink(foodID);
|
||||||
GFWUtils.DebugLog("Manually fed "..FOM_LastFood);
|
FOM_DebugLog("Manually fed "..FOM_LastFood);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return;
|
return;
|
||||||
@@ -1072,8 +973,6 @@ function FOM_OnEvent(event, arg1)
|
|||||||
elseif ( event == "UI_ERROR_MESSAGE" ) then
|
elseif ( event == "UI_ERROR_MESSAGE" ) then
|
||||||
local lowerError = string.lower(tostring(arg1 or ""));
|
local lowerError = string.lower(tostring(arg1 or ""));
|
||||||
if (FOM_LastFood) then
|
if (FOM_LastFood) then
|
||||||
FOM_Trace("ui error while feeding message='" .. tostring(arg1 or "")
|
|
||||||
.. "' lower='" .. tostring(lowerError) .. "'")
|
|
||||||
end
|
end
|
||||||
local isLowLevelError = (arg1 and SPELL_FAILED_FOOD_LOWLEVEL and string.find(arg1, SPELL_FAILED_FOOD_LOWLEVEL))
|
local isLowLevelError = (arg1 and SPELL_FAILED_FOOD_LOWLEVEL and string.find(arg1, SPELL_FAILED_FOOD_LOWLEVEL))
|
||||||
or string.find(lowerError, "low level")
|
or string.find(lowerError, "low level")
|
||||||
@@ -1083,13 +982,8 @@ function FOM_OnEvent(event, arg1)
|
|||||||
or string.find(lowerError, "wrong pet food")
|
or string.find(lowerError, "wrong pet food")
|
||||||
or string.find(lowerError, "doesn't like")
|
or string.find(lowerError, "doesn't like")
|
||||||
or string.find(lowerError, "does not like")
|
or string.find(lowerError, "does not like")
|
||||||
FOM_Trace("ui error classify lowLevel=" .. tostring(isLowLevelError and true or false)
|
|
||||||
.. " wrongFood=" .. tostring(isWrongFoodError and true or false)
|
|
||||||
.. " hasAttempt=" .. tostring(type(FOM_LastFeedAttempt) == "table" and true or false)
|
|
||||||
.. " lastFood='" .. tostring(FOM_LastFood or "") .. "'")
|
|
||||||
|
|
||||||
if (isLowLevelError) then
|
if (isLowLevelError) then
|
||||||
FOM_Trace("reject reason=low-level")
|
|
||||||
if (type(FOM_LastFeedAttempt) == "table") then
|
if (type(FOM_LastFeedAttempt) == "table") then
|
||||||
FOM_CoreRecordReject(FOM_LastFeedAttempt.coreAttemptId, "low-level", arg1);
|
FOM_CoreRecordReject(FOM_LastFeedAttempt.coreAttemptId, "low-level", arg1);
|
||||||
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "low-level");
|
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "low-level");
|
||||||
@@ -1107,7 +1001,6 @@ function FOM_OnEvent(event, arg1)
|
|||||||
end
|
end
|
||||||
|
|
||||||
elseif (isWrongFoodError) then
|
elseif (isWrongFoodError) then
|
||||||
FOM_Trace("reject reason=wrong-food")
|
|
||||||
if (type(FOM_LastFeedAttempt) == "table") then
|
if (type(FOM_LastFeedAttempt) == "table") then
|
||||||
FOM_CoreRecordReject(FOM_LastFeedAttempt.coreAttemptId, "wrong-food", arg1);
|
FOM_CoreRecordReject(FOM_LastFeedAttempt.coreAttemptId, "wrong-food", arg1);
|
||||||
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "wrong-food");
|
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "wrong-food");
|
||||||
@@ -1116,9 +1009,6 @@ function FOM_OnEvent(event, arg1)
|
|||||||
if (FOM_LastFood) then
|
if (FOM_LastFood) then
|
||||||
local alertPetName = MTH_FOM_GetTrackedPetName() or "Your pet";
|
local alertPetName = MTH_FOM_GetTrackedPetName() or "Your pet";
|
||||||
local itemID = FOM_IDFromLink(FOM_LastFood);
|
local itemID = FOM_IDFromLink(FOM_LastFood);
|
||||||
FOM_Trace("learn reject wrongfood pet='" .. tostring(FOM_LastPetName or alertPetName)
|
|
||||||
.. "' itemId=" .. tostring(itemID)
|
|
||||||
.. " link='" .. tostring(FOM_LastFood) .. "'")
|
|
||||||
|
|
||||||
if ( FOM_Config.Alert == "chat") then
|
if ( FOM_Config.Alert == "chat") then
|
||||||
GFWUtils.Print(string.format(FOM_FEEDING_EAT_ANOTHER, alertPetName));
|
GFWUtils.Print(string.format(FOM_FEEDING_EAT_ANOTHER, alertPetName));
|
||||||
@@ -1236,16 +1126,27 @@ function FOM_DifficultyToNum(level)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local FOM_CachedPlayerClass = nil
|
||||||
|
local FOM_OnUpdateElapsed = 0
|
||||||
|
|
||||||
function FOM_OnUpdate(elapsed)
|
function FOM_OnUpdate(elapsed)
|
||||||
|
FOM_OnUpdateElapsed = FOM_OnUpdateElapsed + (elapsed or 0)
|
||||||
_, realClass = UnitClass("player");
|
if FOM_OnUpdateElapsed < 0.05 then
|
||||||
if (realClass ~= "HUNTER") then return; end
|
return
|
||||||
|
end
|
||||||
|
local dt = FOM_OnUpdateElapsed
|
||||||
|
FOM_OnUpdateElapsed = 0
|
||||||
|
|
||||||
|
if not FOM_CachedPlayerClass then
|
||||||
|
_, FOM_CachedPlayerClass = UnitClass("player")
|
||||||
|
end
|
||||||
|
if (FOM_CachedPlayerClass ~= "HUNTER") then return; end
|
||||||
|
|
||||||
-- If it's been more than a second since our last tradeskill update,
|
-- If it's been more than a second since our last tradeskill update,
|
||||||
-- we can allow the event to process again.
|
-- we can allow the event to process again.
|
||||||
FOM_TradeSkillLock.EventTimer = FOM_TradeSkillLock.EventTimer + elapsed;
|
FOM_TradeSkillLock.EventTimer = FOM_TradeSkillLock.EventTimer + dt;
|
||||||
if (FOM_TradeSkillLock.Locked) then
|
if (FOM_TradeSkillLock.Locked) then
|
||||||
FOM_TradeSkillLock.EventCooldown = FOM_TradeSkillLock.EventCooldown + elapsed;
|
FOM_TradeSkillLock.EventCooldown = FOM_TradeSkillLock.EventCooldown + dt;
|
||||||
if (FOM_TradeSkillLock.EventCooldown > FOM_TradeSkillLock.EventCooldownTime) then
|
if (FOM_TradeSkillLock.EventCooldown > FOM_TradeSkillLock.EventCooldownTime) then
|
||||||
|
|
||||||
FOM_TradeSkillLock.EventCooldown = 0;
|
FOM_TradeSkillLock.EventCooldown = 0;
|
||||||
@@ -1267,10 +1168,6 @@ function FOM_OnUpdate(elapsed)
|
|||||||
local elapsedSinceFeed = now - startedAt;
|
local elapsedSinceFeed = now - startedAt;
|
||||||
if (elapsedSinceFeed >= 0.10 and not FOM_LastFeedAttempt.loggedFirstCheck) then
|
if (elapsedSinceFeed >= 0.10 and not FOM_LastFeedAttempt.loggedFirstCheck) then
|
||||||
FOM_LastFeedAttempt.loggedFirstCheck = true;
|
FOM_LastFeedAttempt.loggedFirstCheck = true;
|
||||||
FOM_Trace("feed outcome check itemId=" .. tostring(FOM_LastFeedAttempt.itemId)
|
|
||||||
.. " pet='" .. tostring(FOM_LastFeedAttempt.petName or "")
|
|
||||||
.. "' hasFeedBuff=" .. tostring(FOM_HasFeedEffect() and true or false)
|
|
||||||
.. " elapsed=" .. string.format("%.2f", elapsedSinceFeed));
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (FOM_HasFeedEffect()) then
|
if (FOM_HasFeedEffect()) then
|
||||||
@@ -1286,10 +1183,8 @@ function FOM_OnUpdate(elapsed)
|
|||||||
SendChatMessage(string.format(FOM_FEEDING_FEED, confirmedPetName, confirmedFoodLink).. FOM_RandomEmote(), "EMOTE");
|
SendChatMessage(string.format(FOM_FEEDING_FEED, confirmedPetName, confirmedFoodLink).. FOM_RandomEmote(), "EMOTE");
|
||||||
end
|
end
|
||||||
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "accepted", "accepted");
|
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "accepted", "accepted");
|
||||||
FOM_Trace("feed outcome accepted-with-buff itemId=" .. tostring(FOM_LastFeedAttempt.itemId)
|
|
||||||
.. " pet='" .. tostring(FOM_LastFeedAttempt.petName or "")
|
|
||||||
.. "' elapsed=" .. string.format("%.2f", elapsedSinceFeed));
|
|
||||||
FOM_LastFeedAttempt = nil;
|
FOM_LastFeedAttempt = nil;
|
||||||
|
FOM_LastFood = nil;
|
||||||
elseif (elapsedSinceFeed >= 2.50) then
|
elseif (elapsedSinceFeed >= 2.50) then
|
||||||
local failedAttempt = FOM_LastFeedAttempt;
|
local failedAttempt = FOM_LastFeedAttempt;
|
||||||
if (FOM_LastFeedAttempt.coreAttemptId and type(MTH_FEED_RecordBuffOutcome) == "function") then
|
if (FOM_LastFeedAttempt.coreAttemptId and type(MTH_FEED_RecordBuffOutcome) == "function") then
|
||||||
@@ -1299,16 +1194,12 @@ function FOM_OnUpdate(elapsed)
|
|||||||
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "no-buff");
|
FOM_CoreFinalizeAttempt(FOM_LastFeedAttempt.coreAttemptId, "rejected", "no-buff");
|
||||||
local currentPetInfo = MTH_FOM_GetCorePetInfo();
|
local currentPetInfo = MTH_FOM_GetCorePetInfo();
|
||||||
FOM_RegisterNoBuffQuarantine(FOM_LastFeedAttempt.itemId, currentPetInfo);
|
FOM_RegisterNoBuffQuarantine(FOM_LastFeedAttempt.itemId, currentPetInfo);
|
||||||
if (type(MTH_FEED_BlockItemForPetLevel) == "function") then
|
if (FOM_QUARANTINE_ENABLED and type(MTH_FEED_BlockItemForPetLevel) == "function") then
|
||||||
pcall(MTH_FEED_BlockItemForPetLevel,
|
pcall(MTH_FEED_BlockItemForPetLevel,
|
||||||
FOM_LastFeedAttempt.itemId,
|
FOM_LastFeedAttempt.itemId,
|
||||||
tonumber(currentPetInfo and currentPetInfo.level) or nil,
|
tonumber(currentPetInfo and currentPetInfo.level) or nil,
|
||||||
"no-buff");
|
"no-buff");
|
||||||
end
|
end
|
||||||
FOM_Trace("feed outcome no-eating-buff itemId=" .. tostring(FOM_LastFeedAttempt.itemId)
|
|
||||||
.. " pet='" .. tostring(FOM_LastFeedAttempt.petName or "")
|
|
||||||
.. "' elapsed=" .. string.format("%.2f", elapsedSinceFeed)
|
|
||||||
.. " (likely not accepted by pet)");
|
|
||||||
FOM_LastFood = nil;
|
FOM_LastFood = nil;
|
||||||
FOM_LastFeedAttempt = nil;
|
FOM_LastFeedAttempt = nil;
|
||||||
|
|
||||||
@@ -1335,8 +1226,6 @@ function FOM_OnUpdate(elapsed)
|
|||||||
excludedCount = excludedCount + 1;
|
excludedCount = excludedCount + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
FOM_Trace("feed retry scheduled after no-buff retry=" .. tostring(retryCount + 1)
|
|
||||||
.. " excludedCount=" .. tostring(excludedCount));
|
|
||||||
FOM_Feed(nil, {
|
FOM_Feed(nil, {
|
||||||
retryCount = retryCount + 1,
|
retryCount = retryCount + 1,
|
||||||
excludedItemIds = excludedItemIds,
|
excludedItemIds = excludedItemIds,
|
||||||
@@ -1363,35 +1252,72 @@ end
|
|||||||
function FOM_CanFeed()
|
function FOM_CanFeed()
|
||||||
local petInfo = MTH_FOM_GetCorePetInfo();
|
local petInfo = MTH_FOM_GetCorePetInfo();
|
||||||
if ( not (petInfo and petInfo.liveExists) ) then
|
if ( not (petInfo and petInfo.liveExists) ) then
|
||||||
GFWUtils.DebugLog("Can't feed; pet doesn't exist.");
|
FOM_DebugLog("Can't feed; pet doesn't exist.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if ( tonumber(petInfo.health) and tonumber(petInfo.health) <= 0 ) then
|
if ( tonumber(petInfo.health) and tonumber(petInfo.health) <= 0 ) then
|
||||||
GFWUtils.DebugLog("Can't feed; pet is dead.");
|
FOM_DebugLog("Can't feed; pet is dead.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if ( UnitHealth("player") <= 0 ) then
|
if ( UnitHealth("player") <= 0 ) then
|
||||||
GFWUtils.DebugLog("Can't feed; I'm dead.");
|
FOM_DebugLog("Can't feed; I'm dead.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if ( CastingBarFrameStatusBar:IsVisible() ) then
|
if ( CastingBarFrameStatusBar:IsVisible() ) then
|
||||||
GFWUtils.DebugLog("Can't feed; casting a spell / tradeksill.");
|
FOM_DebugLog("Can't feed; casting a spell / tradeksill.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if ( UnitOnTaxi("player") ) then
|
if ( UnitOnTaxi("player") ) then
|
||||||
GFWUtils.DebugLog("Can't feed; flying.");
|
FOM_DebugLog("Can't feed; flying.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if ( FOM_State.InCombat ) or ( PlayerFrame.inCombat ) then
|
if ( FOM_State.InCombat ) or ( PlayerFrame.inCombat ) then
|
||||||
GFWUtils.DebugLog("Can't feed; in combat.");
|
FOM_DebugLog("Can't feed; in combat.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if ( LootFrame:IsVisible() ) then
|
if ( LootFrame:IsVisible() ) then
|
||||||
GFWUtils.DebugLog("Shouldn't feed; loot window is open.");
|
FOM_DebugLog("Shouldn't feed; loot window is open.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- NamPower path: scan aura array by spellId → name, no tooltip needed
|
||||||
|
if MTH and MTH.nampower and type(GetUnitField) == "function" and type(GetSpellRecField) == "function" then
|
||||||
|
local auras = GetUnitField("player", "aura")
|
||||||
|
if type(auras) == "table" then
|
||||||
|
local dontFeedNames = {
|
||||||
|
["Shadowmeld"] = true,
|
||||||
|
["Feign Death"] = true,
|
||||||
|
["Food"] = true,
|
||||||
|
["Drink"] = true,
|
||||||
|
["Refreshment"] = true,
|
||||||
|
}
|
||||||
|
for i = 1, 32 do
|
||||||
|
local sid = tonumber(auras[i])
|
||||||
|
if sid and sid > 0 then
|
||||||
|
local name = GetSpellRecField(sid, "name")
|
||||||
|
if name then
|
||||||
|
if dontFeedNames[name] then
|
||||||
|
FOM_DebugLog("Can't feed; buff detected: " .. name)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if UnitLevel("player") >= 40 then
|
||||||
|
local lname = string.lower(name)
|
||||||
|
for _, mountSub in FOM_MOUNT_NAME_SUBSTRINGS do
|
||||||
|
if string.find(lname, mountSub) then
|
||||||
|
FOM_DebugLog("Can't feed; mounted (" .. name .. ").")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Legacy path: texture + tooltip scanning
|
||||||
local buff, buffIndex;
|
local buff, buffIndex;
|
||||||
local dontFeedBuffTextures = {
|
local dontFeedBuffTextures = {
|
||||||
"Interface\\Icons\\Ability_Ambush", -- NE Shadowmeld (maybe not unique buff icon?)
|
"Interface\\Icons\\Ability_Ambush", -- NE Shadowmeld (maybe not unique buff icon?)
|
||||||
@@ -1408,20 +1334,20 @@ function FOM_CanFeed()
|
|||||||
if ( buff ~= nil) then
|
if ( buff ~= nil) then
|
||||||
for _, buffTexture in dontFeedBuffTextures do
|
for _, buffTexture in dontFeedBuffTextures do
|
||||||
if ( buff == buffTexture ) then
|
if ( buff == buffTexture ) then
|
||||||
GFWUtils.DebugLog("Can't feed; currently, eating, drinking, or feigning death.");
|
FOM_DebugLog("Can't feed; currently, eating, drinking, or feigning death.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ( UnitLevel("player") >= 40 ) then
|
if ( UnitLevel("player") >= 40 ) then
|
||||||
for _, buffTexture in mountTextureSubStrings do
|
for _, buffTexture in mountTextureSubStrings do
|
||||||
if ( string.find(buff, buffTexture) ) then
|
if ( string.find(buff, buffTexture) ) then
|
||||||
FOMTooltip:SetUnitBuff("player", buffIndex+1);
|
MTH_FOM_Tooltip:SetUnitBuff("player", buffIndex+1);
|
||||||
local msg = FOMTooltipTextLeft1:GetText();
|
local msg = MTH_FOM_TooltipTextLeft1:GetText();
|
||||||
if (msg ~= nil) then
|
if (msg ~= nil) then
|
||||||
msg = string.lower(msg);
|
msg = string.lower(msg);
|
||||||
for _, mountName in FOM_MOUNT_NAME_SUBSTRINGS do
|
for _, mountName in FOM_MOUNT_NAME_SUBSTRINGS do
|
||||||
if (string.find(msg, mountName)) then
|
if (string.find(msg, mountName)) then
|
||||||
GFWUtils.DebugLog("Can't feed; mounted.");
|
FOM_DebugLog("Can't feed; mounted.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1941,6 +1867,7 @@ function FOM_ChatCommandHandler(msg)
|
|||||||
if ( cmd == "add" ) then
|
if ( cmd == "add" ) then
|
||||||
for _, food in inputFoods do
|
for _, food in inputFoods do
|
||||||
local foodID = FOM_IDFromLink(food);
|
local foodID = FOM_IDFromLink(food);
|
||||||
|
FOM_ClearItemBans(foodID);
|
||||||
if ( FOM_AddFood(diet, tonumber(foodID)) ) then
|
if ( FOM_AddFood(diet, tonumber(foodID)) ) then
|
||||||
GFWUtils.Print("Added "..food.." to "..GFWUtils.Hilite(capDiet).." list.");
|
GFWUtils.Print("Added "..food.." to "..GFWUtils.Hilite(capDiet).." list.");
|
||||||
else
|
else
|
||||||
@@ -1973,13 +1900,13 @@ end
|
|||||||
function FOM_AddFood(diet, food)
|
function FOM_AddFood(diet, food)
|
||||||
|
|
||||||
if (FOM_Foods[diet] == nil) then
|
if (FOM_Foods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_Foods[diet] == nil");
|
FOM_DebugLog("FOM_Foods[diet] == nil");
|
||||||
end
|
end
|
||||||
if (FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil) then
|
if (FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil");
|
FOM_DebugLog("FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil");
|
||||||
end
|
end
|
||||||
if (FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil) then
|
if (FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil");
|
FOM_DebugLog("FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil");
|
||||||
end
|
end
|
||||||
if ( GFWTable.IndexOf(FOM_Foods[diet], food) == 0 ) then
|
if ( GFWTable.IndexOf(FOM_Foods[diet], food) == 0 ) then
|
||||||
if (FOM_AddedFoods == nil) then
|
if (FOM_AddedFoods == nil) then
|
||||||
@@ -2000,6 +1927,12 @@ function FOM_AddFood(diet, food)
|
|||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
-- Item is in the base list; clear it from RemovedFoods if present so it isn't banned
|
||||||
|
if (FOM_RemovedFoods and FOM_RemovedFoods[diet] and GFWTable.IndexOf(FOM_RemovedFoods[diet], food) ~= 0) then
|
||||||
|
table.remove( FOM_RemovedFoods[diet], GFWTable.IndexOf(FOM_RemovedFoods[diet], food) );
|
||||||
|
table.sort( FOM_RemovedFoods[diet] );
|
||||||
|
return true;
|
||||||
|
end
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2007,15 +1940,15 @@ end
|
|||||||
|
|
||||||
-- Remove a food from a list
|
-- Remove a food from a list
|
||||||
function FOM_RemoveFood(diet, food)
|
function FOM_RemoveFood(diet, food)
|
||||||
|
|
||||||
if (FOM_Foods[diet] == nil) then
|
if (FOM_Foods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_Foods[diet] == nil");
|
FOM_DebugLog("FOM_Foods[diet] == nil");
|
||||||
end
|
end
|
||||||
if (FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil) then
|
if (FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil");
|
FOM_DebugLog("FOM_AddedFoods == nil or FOM_AddedFoods[diet] == nil");
|
||||||
end
|
end
|
||||||
if (FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil) then
|
if (FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil");
|
FOM_DebugLog("FOM_RemovedFoods == nil or FOM_RemovedFoods[diet] == nil");
|
||||||
end
|
end
|
||||||
if ( GFWTable.IndexOf(FOM_Foods[diet], food) ~= 0 ) then
|
if ( GFWTable.IndexOf(FOM_Foods[diet], food) ~= 0 ) then
|
||||||
if (FOM_RemovedFoods == nil) then
|
if (FOM_RemovedFoods == nil) then
|
||||||
@@ -2046,6 +1979,42 @@ function FOM_RemoveFood(diet, food)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Clear quarantine, core exception blocks, and RemovedFoods ban for a specific item (called when user explicitly re-adds via /fom add)
|
||||||
|
function FOM_ClearItemBans(itemID)
|
||||||
|
local numericItem = tonumber(itemID);
|
||||||
|
if (numericItem == nil) then return; end
|
||||||
|
-- Clear from RemovedFoods across all diet lists
|
||||||
|
if (type(FOM_RemovedFoods) == "table") then
|
||||||
|
for diet, list in FOM_RemovedFoods do
|
||||||
|
if (type(list) == "table") then
|
||||||
|
local idx = GFWTable.IndexOf(list, numericItem);
|
||||||
|
if (idx ~= 0) then
|
||||||
|
table.remove(list, idx);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Clear FOM quarantine (all families)
|
||||||
|
local store = FOM_EnsureQuarantineStore();
|
||||||
|
if (type(store) == "table" and type(store.byFamily) == "table") then
|
||||||
|
for _, byItem in store.byFamily do
|
||||||
|
if (type(byItem) == "table") then
|
||||||
|
byItem[numericItem] = nil;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Clear core exception/block
|
||||||
|
if (type(MTH_FEED_GetStore) == "function") then
|
||||||
|
local coreStore = MTH_FEED_GetStore();
|
||||||
|
if (coreStore and coreStore.exceptions and type(coreStore.exceptions.byItemId) == "table") then
|
||||||
|
coreStore.exceptions.byItemId[numericItem] = nil;
|
||||||
|
coreStore.exceptions.byItemId[tostring(numericItem)] = nil;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Invalidate precompute cache so next feed re-scans
|
||||||
|
FOM_FEED_SCAN_CACHE = nil;
|
||||||
|
end
|
||||||
|
|
||||||
function FOM_IsBGActive()
|
function FOM_IsBGActive()
|
||||||
local bgNum = 1;
|
local bgNum = 1;
|
||||||
local status;
|
local status;
|
||||||
@@ -2151,6 +2120,9 @@ end
|
|||||||
|
|
||||||
-- Check Feed Effect
|
-- Check Feed Effect
|
||||||
function FOM_HasFeedEffect()
|
function FOM_HasFeedEffect()
|
||||||
|
if type(MTH_FEED_HasPetFeedBuff) == "function" then
|
||||||
|
return MTH_FEED_HasPetFeedBuff()
|
||||||
|
end
|
||||||
|
|
||||||
local i = 1;
|
local i = 1;
|
||||||
local buff;
|
local buff;
|
||||||
@@ -2275,7 +2247,6 @@ local function FOM_TryPickSinglePrecomputedFood(foodList, excludedItemIds, allow
|
|||||||
end
|
end
|
||||||
|
|
||||||
function FOM_Feed(aFood, options)
|
function FOM_Feed(aFood, options)
|
||||||
local feedStartMs = FOM_PerfNowMs();
|
|
||||||
options = options or {};
|
options = options or {};
|
||||||
local retryCount = tonumber(options.retryCount) or 0;
|
local retryCount = tonumber(options.retryCount) or 0;
|
||||||
local excludedItemIds = FOM_CloneSet(options.excludedItemIds);
|
local excludedItemIds = FOM_CloneSet(options.excludedItemIds);
|
||||||
@@ -2284,7 +2255,6 @@ function FOM_Feed(aFood, options)
|
|||||||
|
|
||||||
if MTH_IsModuleEnabled and not MTH_IsModuleEnabled("feedomatic", false) then
|
if MTH_IsModuleEnabled and not MTH_IsModuleEnabled("feedomatic", false) then
|
||||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||||
MTH:Print("[FOM WRAP] FOM_Feed blocked: module disabled", "debug")
|
|
||||||
end
|
end
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
@@ -2310,19 +2280,9 @@ function FOM_Feed(aFood, options)
|
|||||||
|
|
||||||
-- Assign Variable
|
-- Assign Variable
|
||||||
local pet = (MTH_FOM_IsValidPetName(petInfo.name) and petInfo.name) or "Your pet";
|
local pet = (MTH_FOM_IsValidPetName(petInfo.name) and petInfo.name) or "Your pet";
|
||||||
FOM_Trace("feed request pet='" .. tostring(pet)
|
|
||||||
.. "' level=" .. tostring(petInfo.level)
|
|
||||||
.. " happiness=" .. tostring(petInfo.happiness)
|
|
||||||
.. " manualFood='" .. tostring(aFood or "") .. "'"
|
|
||||||
.. " retry=" .. tostring(retryCount)
|
|
||||||
.. " excluded=" .. tostring(FOM_CountSetEntries(excludedItemIds)))
|
|
||||||
|
|
||||||
local checkSetupStartMs = FOM_PerfNowMs();
|
|
||||||
FOM_CheckSetup();
|
FOM_CheckSetup();
|
||||||
FOM_PerfRecord("FOM_CheckSetup", FOM_PerfNowMs() - checkSetupStartMs, "retry=" .. tostring(retryCount), false);
|
|
||||||
if (FOM_LastPetName == nil or FOM_LastPetName == "") then
|
if (FOM_LastPetName == nil or FOM_LastPetName == "") then
|
||||||
GFWUtils.DebugLog("Can't get pet info.");
|
|
||||||
FOM_PerfRecord("FOM_Feed total", FOM_PerfNowMs() - feedStartMs, "result=no-pet-name", true);
|
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2346,24 +2306,18 @@ function FOM_Feed(aFood, options)
|
|||||||
if ( foodBag == nil) then
|
if ( foodBag == nil) then
|
||||||
-- No Food Could be Found
|
-- No Food Could be Found
|
||||||
GFWUtils.Print(string.format(FOM_ERROR_FOOD_NOT_FOUND, pet, aFood));
|
GFWUtils.Print(string.format(FOM_ERROR_FOOD_NOT_FOUND, pet, aFood));
|
||||||
FOM_PerfRecord("FOM_Feed total", FOM_PerfNowMs() - feedStartMs, "result=manual-not-found", true);
|
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
FOM_LastChoiceReason = "manual selection";
|
FOM_LastChoiceReason = "manual selection";
|
||||||
else
|
else
|
||||||
local cachedChoiceStartMs = FOM_PerfNowMs();
|
|
||||||
local cachedBag, cachedSlot, cachedItemId = FOM_GetCachedAutoChoice(excludedItemIds);
|
local cachedBag, cachedSlot, cachedItemId = FOM_GetCachedAutoChoice(excludedItemIds);
|
||||||
if (cachedBag ~= nil and cachedSlot ~= nil) then
|
if (cachedBag ~= nil and cachedSlot ~= nil) then
|
||||||
foodBag, foodItem = cachedBag, cachedSlot;
|
foodBag, foodItem = cachedBag, cachedSlot;
|
||||||
FOM_LastChoiceReason = "cached previous food";
|
FOM_LastChoiceReason = "cached previous food";
|
||||||
FOM_PerfRecord("FOM_AutoChoice cache", FOM_PerfNowMs() - cachedChoiceStartMs,
|
|
||||||
"hit itemId=" .. tostring(cachedItemId), false);
|
|
||||||
else
|
else
|
||||||
FOM_PerfRecord("FOM_AutoChoice cache", FOM_PerfNowMs() - cachedChoiceStartMs, "miss", false);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (foodBag == nil) then
|
if (foodBag == nil) then
|
||||||
local precomputeStartMs = FOM_PerfNowMs();
|
|
||||||
local cacheNow = (type(GetTime) == "function") and (GetTime() or 0) or 0;
|
local cacheNow = (type(GetTime) == "function") and (GetTime() or 0) or 0;
|
||||||
if (retryCount <= 0
|
if (retryCount <= 0
|
||||||
and type(FOM_FEED_SCAN_CACHE) == "table"
|
and type(FOM_FEED_SCAN_CACHE) == "table"
|
||||||
@@ -2371,8 +2325,6 @@ function FOM_Feed(aFood, options)
|
|||||||
and type(FOM_FEED_SCAN_CACHE.foods) == "table") then
|
and type(FOM_FEED_SCAN_CACHE.foods) == "table") then
|
||||||
precomputedFoodList = FOM_CloneFoodList(FOM_FEED_SCAN_CACHE.foods);
|
precomputedFoodList = FOM_CloneFoodList(FOM_FEED_SCAN_CACHE.foods);
|
||||||
openSlots = tonumber(FOM_FEED_SCAN_CACHE.openSlots) or 0;
|
openSlots = tonumber(FOM_FEED_SCAN_CACHE.openSlots) or 0;
|
||||||
FOM_PerfRecord("FOM_Feed precompute", FOM_PerfNowMs() - precomputeStartMs,
|
|
||||||
"cache-hit foods=" .. tostring(table.getn(precomputedFoodList)) .. " openSlots=" .. tostring(openSlots), false);
|
|
||||||
else
|
else
|
||||||
precomputedFoodList = FOM_FlatFoodList();
|
precomputedFoodList = FOM_FlatFoodList();
|
||||||
openSlots = FOM_NumOpenBagSlots();
|
openSlots = FOM_NumOpenBagSlots();
|
||||||
@@ -2382,32 +2334,23 @@ function FOM_Feed(aFood, options)
|
|||||||
foods = FOM_CloneFoodList(precomputedFoodList),
|
foods = FOM_CloneFoodList(precomputedFoodList),
|
||||||
openSlots = openSlots,
|
openSlots = openSlots,
|
||||||
};
|
};
|
||||||
FOM_PerfRecord("FOM_Feed precompute", FOM_PerfNowMs() - precomputeStartMs,
|
|
||||||
"cache-miss foods=" .. tostring(table.getn(precomputedFoodList)) .. " openSlots=" .. tostring(openSlots), false);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local fastPickStartMs = FOM_PerfNowMs();
|
|
||||||
foodBag, foodItem = FOM_TryPickSinglePrecomputedFood(precomputedFoodList, excludedItemIds, (FOM_Config.AvoidUsefulFood and false or true));
|
foodBag, foodItem = FOM_TryPickSinglePrecomputedFood(precomputedFoodList, excludedItemIds, (FOM_Config.AvoidUsefulFood and false or true));
|
||||||
if (foodBag ~= nil) then
|
if (foodBag ~= nil) then
|
||||||
FOM_LastChoiceReason = "single candidate fast-path";
|
FOM_LastChoiceReason = "single candidate fast-path";
|
||||||
FOM_PerfRecord("FOM_SingleCandidate", FOM_PerfNowMs() - fastPickStartMs, "hit", false);
|
|
||||||
else
|
else
|
||||||
FOM_PerfRecord("FOM_SingleCandidate", FOM_PerfNowMs() - fastPickStartMs, "miss", false);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (foodBag == nil) then
|
if (foodBag == nil) then
|
||||||
local findStartMs = FOM_PerfNowMs();
|
|
||||||
foodBag, foodItem = FOM_NewFindFood(nil, excludedItemIds, precomputedFoodList, openSlots);
|
foodBag, foodItem = FOM_NewFindFood(nil, excludedItemIds, precomputedFoodList, openSlots);
|
||||||
FOM_PerfRecord("FOM_NewFindFood primary", FOM_PerfNowMs() - findStartMs, "found=" .. tostring(foodBag ~= nil), false);
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fallbackBag, fallbackItem = nil, nil;
|
local fallbackBag, fallbackItem = nil, nil;
|
||||||
if (not manualFood and foodBag == nil and FOM_Config.Fallback) then
|
if (not manualFood and foodBag == nil and FOM_Config.Fallback) then
|
||||||
local fallbackStartMs = FOM_PerfNowMs();
|
|
||||||
fallbackBag, fallbackItem = FOM_NewFindFood(1, excludedItemIds, precomputedFoodList, openSlots);
|
fallbackBag, fallbackItem = FOM_NewFindFood(1, excludedItemIds, precomputedFoodList, openSlots);
|
||||||
FOM_PerfRecord("FOM_NewFindFood fallback", FOM_PerfNowMs() - fallbackStartMs, "found=" .. tostring(fallbackBag ~= nil), false);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( foodBag == nil) then
|
if ( foodBag == nil) then
|
||||||
@@ -2422,12 +2365,10 @@ function FOM_Feed(aFood, options)
|
|||||||
-- No Food Could be Found
|
-- No Food Could be Found
|
||||||
GFWUtils.Print(string.format(FOM_ERROR_NO_FOOD, pet));
|
GFWUtils.Print(string.format(FOM_ERROR_NO_FOOD, pet));
|
||||||
FOM_LastChoiceReason = nil;
|
FOM_LastChoiceReason = nil;
|
||||||
FOM_PerfRecord("FOM_Feed total", FOM_PerfNowMs() - feedStartMs, "result=no-food", true);
|
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local prepareStartMs = FOM_PerfNowMs();
|
|
||||||
FOM_LastFood = GetContainerItemLink(foodBag, foodItem);
|
FOM_LastFood = GetContainerItemLink(foodBag, foodItem);
|
||||||
local selectedId = FOM_IDFromLink(FOM_LastFood)
|
local selectedId = FOM_IDFromLink(FOM_LastFood)
|
||||||
FOM_SetCachedAutoChoice(foodBag, foodItem, selectedId)
|
FOM_SetCachedAutoChoice(foodBag, foodItem, selectedId)
|
||||||
@@ -2446,26 +2387,15 @@ function FOM_Feed(aFood, options)
|
|||||||
petLevel = tonumber(petInfo and petInfo.level) or nil,
|
petLevel = tonumber(petInfo and petInfo.level) or nil,
|
||||||
foodLevel = selectedFoodLevel,
|
foodLevel = selectedFoodLevel,
|
||||||
})
|
})
|
||||||
FOM_PerfRecord("FOM_Feed prepare", FOM_PerfNowMs() - prepareStartMs, "itemId=" .. tostring(selectedId), false);
|
|
||||||
FOM_Trace("selected food link='" .. tostring(FOM_LastFood)
|
|
||||||
.. "' itemId=" .. tostring(selectedId)
|
|
||||||
.. " bag=" .. tostring(foodBag)
|
|
||||||
.. " slot=" .. tostring(foodItem)
|
|
||||||
.. " reason='" .. tostring(FOM_LastChoiceReason or "") .. "'")
|
|
||||||
|
|
||||||
GFWUtils.DebugLog("Picked "..FOM_LastFood.." (bag "..foodBag..", slot "..foodItem..") for feeding.");
|
FOM_DebugLog("Picked "..FOM_LastFood.." (bag "..foodBag..", slot "..foodItem..") for feeding.");
|
||||||
if (FOM_Config.Debug) then
|
if (FOM_Config.Debug) then
|
||||||
-- don't actually feed anything, just show what we would choose
|
-- don't actually feed anything, just show what we would choose
|
||||||
FOM_PerfRecord("FOM_Feed total", FOM_PerfNowMs() - feedStartMs, "result=debug", true);
|
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Actually feed the item to the pet
|
-- Actually feed the item to the pet
|
||||||
local dropStartMs = FOM_PerfNowMs();
|
|
||||||
PickupContainerItem(foodBag, foodItem);
|
PickupContainerItem(foodBag, foodItem);
|
||||||
FOM_Trace("feed execute pickup bag=" .. tostring(foodBag)
|
|
||||||
.. " slot=" .. tostring(foodItem)
|
|
||||||
.. " cursorHasItem=" .. tostring(CursorHasItem() and true or false))
|
|
||||||
if ( CursorHasItem() ) then
|
if ( CursorHasItem() ) then
|
||||||
MTH_FEED_SuppressChatUntil = (GetTime() or 0) + 2.0;
|
MTH_FEED_SuppressChatUntil = (GetTime() or 0) + 2.0;
|
||||||
MTH_FEED_SuppressChatFoodName = FOM_NameFromLink(FOM_LastFood);
|
MTH_FEED_SuppressChatFoodName = FOM_NameFromLink(FOM_LastFood);
|
||||||
@@ -2473,26 +2403,19 @@ function FOM_Feed(aFood, options)
|
|||||||
local ok = pcall(DropItemOnUnit, "pet");
|
local ok = pcall(DropItemOnUnit, "pet");
|
||||||
MTH_FEED_SuppressCoreDropHook = nil;
|
MTH_FEED_SuppressCoreDropHook = nil;
|
||||||
if (not ok) then
|
if (not ok) then
|
||||||
FOM_Trace("feed execute drop on pet failed during protected call");
|
|
||||||
end
|
end
|
||||||
FOM_Trace("feed execute drop on pet cursorHasItemAfterDrop=" .. tostring(CursorHasItem() and true or false))
|
|
||||||
end
|
end
|
||||||
FOM_PerfRecord("FOM_Feed drop", FOM_PerfNowMs() - dropStartMs, "cursor=" .. tostring(CursorHasItem() and true or false), false);
|
|
||||||
if (coreAttemptId and type(MTH_FEED_RecordClientDropResult) == "function") then
|
if (coreAttemptId and type(MTH_FEED_RecordClientDropResult) == "function") then
|
||||||
pcall(MTH_FEED_RecordClientDropResult, coreAttemptId, {
|
pcall(MTH_FEED_RecordClientDropResult, coreAttemptId, {
|
||||||
consumedFromCursor = (CursorHasItem() and false or true),
|
consumedFromCursor = (CursorHasItem() and false or true),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
if ( CursorHasItem() ) then
|
if ( CursorHasItem() ) then
|
||||||
FOM_Trace("feed execute immediate-fail item stayed on cursor; likely rejected before combat log/error parse")
|
|
||||||
PickupContainerItem(foodBag, foodItem);
|
PickupContainerItem(foodBag, foodItem);
|
||||||
FOM_CoreRecordReject(coreAttemptId, "client-drop-fail", nil);
|
FOM_CoreRecordReject(coreAttemptId, "client-drop-fail", nil);
|
||||||
FOM_CoreFinalizeAttempt(coreAttemptId, "rejected", "client-drop-fail");
|
FOM_CoreFinalizeAttempt(coreAttemptId, "rejected", "client-drop-fail");
|
||||||
FOM_Trace("feed execute returned item to bag")
|
|
||||||
FOM_PerfRecord("FOM_Feed total", FOM_PerfNowMs() - feedStartMs, "result=cursor-fail", true);
|
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
FOM_Trace("feed execute accepted by client (item consumed from cursor)")
|
|
||||||
if (selectedId ~= nil) then
|
if (selectedId ~= nil) then
|
||||||
excludedItemIds[selectedId] = true;
|
excludedItemIds[selectedId] = true;
|
||||||
end
|
end
|
||||||
@@ -2510,10 +2433,6 @@ function FOM_Feed(aFood, options)
|
|||||||
loggedFirstCheck = false,
|
loggedFirstCheck = false,
|
||||||
}
|
}
|
||||||
FOM_State.ShouldFeed = nil;
|
FOM_State.ShouldFeed = nil;
|
||||||
FOM_Trace("feed alert deferred until confirmation itemId=" .. tostring(selectedId)
|
|
||||||
.. " pet='" .. tostring(pet or "")
|
|
||||||
.. "' mode='" .. tostring(FOM_Config.Alert or "") .. "'")
|
|
||||||
FOM_PerfRecord("FOM_Feed total", FOM_PerfNowMs() - feedStartMs, "result=ok itemId=" .. tostring(selectedId), true);
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2567,9 +2486,9 @@ function FOM_IsTemporaryFood(itemLink)
|
|||||||
end
|
end
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
FOMTooltip:ClearLines();
|
MTH_FOM_Tooltip:ClearLines();
|
||||||
FOMTooltip:SetHyperlink(link);
|
MTH_FOM_Tooltip:SetHyperlink(link);
|
||||||
if (FOMTooltipTextLeft2:GetText() == ITEM_CONJURED) then
|
if (MTH_FOM_TooltipTextLeft2:GetText() == ITEM_CONJURED) then
|
||||||
if (numericItemId ~= nil) then
|
if (numericItemId ~= nil) then
|
||||||
FOM_TEMP_FOOD_CACHE[numericItemId] = true;
|
FOM_TEMP_FOOD_CACHE[numericItemId] = true;
|
||||||
end
|
end
|
||||||
@@ -2598,7 +2517,6 @@ local function FOM_EnsureQuestScanFresh(maxAgeSeconds)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function FOM_FlatFoodList()
|
function FOM_FlatFoodList()
|
||||||
local flatStartMs = FOM_PerfNowMs();
|
|
||||||
local foodList = {};
|
local foodList = {};
|
||||||
local overflowFoodList = {};
|
local overflowFoodList = {};
|
||||||
local scanned = 0;
|
local scanned = 0;
|
||||||
@@ -2688,27 +2606,10 @@ function FOM_FlatFoodList()
|
|||||||
if (table.getn(foodList) == 0 and table.getn(overflowFoodList) > 0) then
|
if (table.getn(foodList) == 0 and table.getn(overflowFoodList) > 0) then
|
||||||
foodList = overflowFoodList;
|
foodList = overflowFoodList;
|
||||||
end
|
end
|
||||||
FOM_Trace("flat food scan scanned=" .. tostring(scanned)
|
|
||||||
.. " inDiet=" .. tostring(inDiet)
|
|
||||||
.. " compatible=" .. tostring(compatibleCount)
|
|
||||||
.. " overflowCompatible=" .. tostring(overflowCompatibleCount)
|
|
||||||
.. " exceptionRejects=" .. tostring(rejectedByException)
|
|
||||||
.. " levelOverrideRejects=" .. tostring(rejectedByLevelOverride)
|
|
||||||
.. " quarantineRejects=" .. tostring(rejectedByQuarantine)
|
|
||||||
.. " unknownLevel=" .. tostring(unknownLevelCandidates)
|
|
||||||
.. " candidates=" .. tostring(table.getn(foodList)))
|
|
||||||
if (FOM_PERF_TRACE_ENABLED) then
|
|
||||||
FOM_PerfRecord("FOM_FlatFoodList", FOM_PerfNowMs() - flatStartMs,
|
|
||||||
"scanned=" .. tostring(scanned)
|
|
||||||
.. " inDiet=" .. tostring(inDiet)
|
|
||||||
.. " candidates=" .. tostring(table.getn(foodList)),
|
|
||||||
false);
|
|
||||||
end
|
|
||||||
return foodList;
|
return foodList;
|
||||||
end
|
end
|
||||||
|
|
||||||
function FOM_NewFindFood(fallback, excludedItemIds, precomputedFoodList, openSlotsOverride)
|
function FOM_NewFindFood(fallback, excludedItemIds, precomputedFoodList, openSlotsOverride)
|
||||||
local findStartMs = FOM_PerfNowMs();
|
|
||||||
local FlatFoodList = nil;
|
local FlatFoodList = nil;
|
||||||
if (type(precomputedFoodList) == "table") then
|
if (type(precomputedFoodList) == "table") then
|
||||||
FlatFoodList = FOM_CloneFoodList(precomputedFoodList);
|
FlatFoodList = FOM_CloneFoodList(precomputedFoodList);
|
||||||
@@ -2719,12 +2620,6 @@ function FOM_NewFindFood(fallback, excludedItemIds, precomputedFoodList, openSlo
|
|||||||
local reasonParts = {};
|
local reasonParts = {};
|
||||||
if (initialCount <= 0) then
|
if (initialCount <= 0) then
|
||||||
FOM_LastChoiceReason = nil;
|
FOM_LastChoiceReason = nil;
|
||||||
if (FOM_PERF_TRACE_ENABLED) then
|
|
||||||
FOM_PerfRecord("FOM_NewFindFood", FOM_PerfNowMs() - findStartMs,
|
|
||||||
"fallback=" .. tostring(fallback and true or false)
|
|
||||||
.. " initial=0 final=0",
|
|
||||||
false);
|
|
||||||
end
|
|
||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
local petInfo = MTH_FOM_GetCorePetInfo();
|
local petInfo = MTH_FOM_GetCorePetInfo();
|
||||||
@@ -2811,18 +2706,6 @@ function FOM_NewFindFood(fallback, excludedItemIds, precomputedFoodList, openSlo
|
|||||||
table.insert(reasonParts, "fallback allows useful food");
|
table.insert(reasonParts, "fallback allows useful food");
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
FOM_Trace("find food fallback=" .. tostring(fallback and true or false)
|
|
||||||
.. " initial=" .. tostring(initialCount)
|
|
||||||
.. " postConjured=" .. tostring(postConjuredCount)
|
|
||||||
.. " postFilters=" .. tostring(table.getn(FlatFoodList))
|
|
||||||
.. " reasons='" .. tostring(table.concat(reasonParts, ", ")) .. "'")
|
|
||||||
if (FOM_PERF_TRACE_ENABLED) then
|
|
||||||
FOM_PerfRecord("FOM_NewFindFood", FOM_PerfNowMs() - findStartMs,
|
|
||||||
"fallback=" .. tostring(fallback and true or false)
|
|
||||||
.. " initial=" .. tostring(initialCount)
|
|
||||||
.. " final=" .. tostring(table.getn(FlatFoodList)),
|
|
||||||
false);
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, foodInfo in FlatFoodList do
|
for _, foodInfo in FlatFoodList do
|
||||||
if (foodInfo.overflow) then
|
if (foodInfo.overflow) then
|
||||||
@@ -2836,15 +2719,9 @@ function FOM_NewFindFood(fallback, excludedItemIds, precomputedFoodList, openSlo
|
|||||||
else
|
else
|
||||||
FOM_LastChoiceReason = nil;
|
FOM_LastChoiceReason = nil;
|
||||||
end
|
end
|
||||||
FOM_Trace("find food result bag=" .. tostring(foodInfo.bag)
|
|
||||||
.. " slot=" .. tostring(foodInfo.slot)
|
|
||||||
.. " quality=" .. tostring(foodInfo.quality)
|
|
||||||
.. " useful=" .. tostring(foodInfo.useful and true or false)
|
|
||||||
.. " temp=" .. tostring(foodInfo.temp and true or false))
|
|
||||||
return foodInfo.bag, foodInfo.slot;
|
return foodInfo.bag, foodInfo.slot;
|
||||||
end
|
end
|
||||||
FOM_LastChoiceReason = nil;
|
FOM_LastChoiceReason = nil;
|
||||||
FOM_Trace("find food result: none")
|
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
@@ -2878,12 +2755,12 @@ end
|
|||||||
function FOM_IsUsefulFood(itemID, quantity)
|
function FOM_IsUsefulFood(itemID, quantity)
|
||||||
local foodName = GetItemInfo(itemID);
|
local foodName = GetItemInfo(itemID);
|
||||||
if (foodName == nil) then
|
if (foodName == nil) then
|
||||||
GFWUtils.DebugLog("Can't get info for item ID "..itemID..", assuming it's OK to eat.");
|
FOM_DebugLog("Can't get info for item ID "..itemID..", assuming it's OK to eat.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
if (FOM_Cooking and FOM_Cooking[FOM_RealmPlayer] and FOM_Cooking[FOM_RealmPlayer][itemID]) then
|
if (FOM_Cooking and FOM_Cooking[FOM_RealmPlayer] and FOM_Cooking[FOM_RealmPlayer][itemID]) then
|
||||||
if (FOM_Cooking[FOM_RealmPlayer][itemID] >= FOM_Config.SaveForCookingLevel) then
|
if (FOM_Cooking[FOM_RealmPlayer][itemID] >= FOM_Config.SaveForCookingLevel) then
|
||||||
GFWUtils.DebugLog("Skipping "..quantity.."x "..foodName.."; is good for cooking.");
|
FOM_DebugLog("Skipping "..quantity.."x "..foodName.."; is good for cooking.");
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2895,19 +2772,19 @@ function FOM_IsUsefulFood(itemID, quantity)
|
|||||||
FOM_Quantity[foodName] = FOM_Quantity[foodName] + quantity;
|
FOM_Quantity[foodName] = FOM_Quantity[foodName] + quantity;
|
||||||
end
|
end
|
||||||
if (FOM_Quantity[foodName] > FOM_QuestFood[FOM_RealmPlayer][foodName]) then
|
if (FOM_Quantity[foodName] > FOM_QuestFood[FOM_RealmPlayer][foodName]) then
|
||||||
GFWUtils.DebugLog("Not skipping "..quantity.."x "..foodName.."; is needed for quest, but we have more than enough.");
|
FOM_DebugLog("Not skipping "..quantity.."x "..foodName.."; is needed for quest, but we have more than enough.");
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
GFWUtils.DebugLog("Skipping "..quantity.."x "..foodName.."; is needed for quest.");
|
FOM_DebugLog("Skipping "..quantity.."x "..foodName.."; is needed for quest.");
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (FOM_Config.AvoidBonusFood and FOM_IsInDiet(itemID, FOM_DIET_BONUS)) then
|
if (FOM_Config.AvoidBonusFood and FOM_IsInDiet(itemID, FOM_DIET_BONUS)) then
|
||||||
GFWUtils.DebugLog("Skipping "..quantity.."x "..foodName.."; has bonus effect when eaten by player.");
|
FOM_DebugLog("Skipping "..quantity.."x "..foodName.."; has bonus effect when eaten by player.");
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
--GFWUtils.DebugLog("Not skipping "..quantity.."x "..foodName.."; doesn't have other uses.");
|
--FOM_DebugLog("Not skipping "..quantity.."x "..foodName.."; doesn't have other uses.");
|
||||||
return false;
|
return false;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2945,7 +2822,7 @@ function FOM_IsInDiet(food, dietList)
|
|||||||
diet = "";
|
diet = "";
|
||||||
end
|
end
|
||||||
if (FOM_Foods[diet] == nil) then
|
if (FOM_Foods[diet] == nil) then
|
||||||
GFWUtils.DebugLog("FOM_Foods[diet] == nil");
|
FOM_DebugLog("FOM_Foods[diet] == nil");
|
||||||
end
|
end
|
||||||
if (FOM_RemovedFoods ~= nil and FOM_RemovedFoods[diet] ~= nil and GFWTable.IndexOf(FOM_RemovedFoods[diet], food) ~= 0) then
|
if (FOM_RemovedFoods ~= nil and FOM_RemovedFoods[diet] ~= nil and GFWTable.IndexOf(FOM_RemovedFoods[diet], food) ~= 0) then
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ FOM_Emotes = {
|
|||||||
["Foxes"] = {
|
["Foxes"] = {
|
||||||
"Clever fox, clever snack choice.",
|
"Clever fox, clever snack choice.",
|
||||||
},
|
},
|
||||||
["Serpents (Cobra)"] = {
|
["Serpents"] = {
|
||||||
"No hissing with your mouth full.",
|
"No hissing with your mouth full.",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,16 +53,6 @@ function GFWUtils_temp_PrintOnce(message, interval, r, g, b)
|
|||||||
GFWUtils.PrintOnceCache[message] = GetTime();
|
GFWUtils.PrintOnceCache[message] = GetTime();
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Prints a message to the chat frame only if Debug is set
|
|
||||||
function GFWUtils_temp_DebugLog(message)
|
|
||||||
if (GFWUtils.Debug) then
|
|
||||||
if MTH and MTH.Print then
|
|
||||||
MTH:Print(message, "debug")
|
|
||||||
else
|
|
||||||
DEFAULT_CHAT_FRAME:AddMessage(message, GFW_DEBUG_COLOR.r, GFW_DEBUG_COLOR.g, GFW_DEBUG_COLOR.b);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Prints a message in yellow to the floating messages frame
|
-- Prints a message in yellow to the floating messages frame
|
||||||
function GFWUtils_temp_Note(message)
|
function GFWUtils_temp_Note(message)
|
||||||
@@ -177,8 +167,6 @@ if (G.Version == nil or (tonumber(G.Version) ~= nil and G.Version < GFWUTILS_THI
|
|||||||
|
|
||||||
-- Constants
|
-- Constants
|
||||||
GFW_FONT_COLOR = {r=0.25, g=1.0, b=1.0};
|
GFW_FONT_COLOR = {r=0.25, g=1.0, b=1.0};
|
||||||
GFW_DEBUG_COLOR = {r=1.0, g=0.75, b=0.25};
|
|
||||||
G.Debug = false;
|
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
G.Hilite = GFWUtils_temp_HiliteText;
|
G.Hilite = GFWUtils_temp_HiliteText;
|
||||||
@@ -187,7 +175,6 @@ if (G.Version == nil or (tonumber(G.Version) ~= nil and G.Version < GFWUTILS_THI
|
|||||||
G.LtY = GFWUtils_temp_LightYellowText;
|
G.LtY = GFWUtils_temp_LightYellowText;
|
||||||
G.Print = GFWUtils_temp_Print;
|
G.Print = GFWUtils_temp_Print;
|
||||||
G.PrintOnce = GFWUtils_temp_PrintOnce;
|
G.PrintOnce = GFWUtils_temp_PrintOnce;
|
||||||
G.DebugLog = GFWUtils_temp_DebugLog;
|
|
||||||
G.Note = GFWUtils_temp_Note;
|
G.Note = GFWUtils_temp_Note;
|
||||||
G.FormatToPattern = GFWUtils_temp_FormatToPattern;
|
G.FormatToPattern = GFWUtils_temp_FormatToPattern;
|
||||||
G.Split = GFWUtils_temp_Split;
|
G.Split = GFWUtils_temp_Split;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
-- Key bindings
|
-- Key bindings
|
||||||
BINDING_HEADER_FEEDOMATIC = "Fizzwidget Feed-O-Matic";
|
-- NOTE: BINDING_HEADER_FEEDOMATIC is defined in api/localization.lua via the MTH_L() system.
|
||||||
BINDING_NAME_FEEDOMATIC = "Feed Pet";
|
BINDING_NAME_FEEDOMATIC = "Feed Pet";
|
||||||
|
|
||||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
||||||
@@ -111,110 +111,6 @@ FOM_OptionsButtonText = {
|
|||||||
};
|
};
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
if (GetLocale() == "frFR") then
|
|
||||||
|
|
||||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
|
||||||
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
|
|
||||||
FOM_DIET_MEAT = "viande";
|
|
||||||
FOM_DIET_FISH = "poisson";
|
|
||||||
FOM_DIET_BREAD = "pain";
|
|
||||||
FOM_DIET_CHEESE = "fromage";
|
|
||||||
FOM_DIET_FRUIT = "fruit";
|
|
||||||
FOM_DIET_FUNGUS = "champignon";
|
|
||||||
|
|
||||||
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons. If these aren't localized, we may not recognize when the player is mounted and still try to feed the pet.
|
|
||||||
FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "loup", "raptor", "steed", "cheval", "bélier", "tigre", "mécanotrotteur", };
|
|
||||||
|
|
||||||
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case. If these aren't localized, we'll just needlessly search your ammo bags for food.
|
|
||||||
FOM_AMMO_POUCH = "Giberne";
|
|
||||||
FOM_QUIVER = "Carquois";
|
|
||||||
|
|
||||||
|
|
||||||
-- From here on down, the localized strings are just for readability... they don't affect whether Feed-O-Matic works.
|
|
||||||
|
|
||||||
-- Two special diets; one is used for tracking food that provides a bonus (or at least, that you don't want to have fed to your pet when the 'savebonus' option is on), and another that's used in the chat-line interface for listing all diets.
|
|
||||||
FOM_DIET_BONUS = "bonus";
|
|
||||||
FOM_DIET_ALL = "tous";
|
|
||||||
|
|
||||||
-- Used in tooltips to indicate food quality.
|
|
||||||
FOM_QUALITY_UNKNOWN = "%s peut le manger, mais n'a jamais essayé.";
|
|
||||||
FOM_QUALITY_UNDER = "%s n'en mange plus désormais.";
|
|
||||||
FOM_QUALITY_MIGHT = "%s en mangera peut-être.";
|
|
||||||
FOM_QUALITY_WILL = "%s en mangera.";
|
|
||||||
FOM_QUALITY_LIKE = "%s aime en manger.";
|
|
||||||
FOM_QUALITY_LOVE = "%s adore en manger.";
|
|
||||||
|
|
||||||
-- User-visible errors
|
|
||||||
FOM_ERROR_NO_PET = "Vous n'avez pas de familier.";
|
|
||||||
FOM_ERROR_PET_DEAD = "Votre familier est mort.";
|
|
||||||
FOM_ERROR_NO_FEEDABLE_PET = "Vous n'avez pas de familier capable de manger.";
|
|
||||||
FOM_ERROR_FOOD_NOT_FOUND = "%s n'a pas trouvé de %s dans votre sac.";
|
|
||||||
FOM_ERROR_NO_FOOD = "%s n'a pas trouvé de nourriture dans votre sac.";
|
|
||||||
|
|
||||||
-- Feeding status messages
|
|
||||||
FOM_FEEDING_EAT_ANOTHER = "%s n'aime pas cette nourriture et va essayer autre chose..."
|
|
||||||
FOM_FEEDING_FEED_ANOTHER = "cherche autre chose à donner à %s...";
|
|
||||||
FOM_FEEDING_EAT = "%s mange un(e) %s.";
|
|
||||||
FOM_FEEDING_FEED = "donne à %s à manger un(e) %s. ";
|
|
||||||
|
|
||||||
-- Beast family names
|
|
||||||
BAT = "Chauve-souris";
|
|
||||||
BEAR = "Ours";
|
|
||||||
BOAR = "Sanglier";
|
|
||||||
CARRION_BIRD = "Charognard";
|
|
||||||
CAT = "Félin";
|
|
||||||
CRAB = "Crabe";
|
|
||||||
CROCOLISK = "Crocilisque";
|
|
||||||
GORILLA = "Gorille";
|
|
||||||
HYENA = "Hyène";
|
|
||||||
OWL = "Chouette";
|
|
||||||
RAPTOR = "Raptor";
|
|
||||||
SCORPID = "Scorpide";
|
|
||||||
SPIDER = "Araignée";
|
|
||||||
TALLSTRIDER = "Haut-trotteur";
|
|
||||||
TURTLE = "Tortue";
|
|
||||||
WIND_SERPENT = "Serpent des vents";
|
|
||||||
WOLF = "Loup";
|
|
||||||
|
|
||||||
FOM_PET_HUNGRY = "%s a faim!";
|
|
||||||
FOM_PET_VERY_HUNGRY = "%s a très faim!";
|
|
||||||
|
|
||||||
FOM_OPTIONS_HEADER = "Feed-O-Matic Options";
|
|
||||||
FOM_OPTIONS_GENERAL = "Options générales:";
|
|
||||||
FOM_OPTIONS_FOOD_CHOICE = "Eviter la nourriture utilisée en cuisine:";
|
|
||||||
FOM_OPTIONS_FEED_NOTIFY = "Prévenir lorsque votre familier est nourrit:";
|
|
||||||
FOM_OPTIONS_WARNING = "Avertir quand votre familier a besoin d'être nourrit:";
|
|
||||||
|
|
||||||
FOM_KEEPOPEN = "Essayer de garder au moins";
|
|
||||||
FOM_KEEPOPEN_SLOTS = "emplacements de sac libres";
|
|
||||||
FOM_KEEPOPEN_INFO = "(Le familier choisira la nourriture des piles les plus petites, sans tenir compte de ses préférences.)";
|
|
||||||
|
|
||||||
FOM_OptionsButtonText = {
|
|
||||||
["Tooltip"] = "Afficher l'avis de votre familier concernant la nourriture",
|
|
||||||
["AvoidQuestFood"] = "Eviter la nourriture utile dans les quêtes",
|
|
||||||
["AvoidBonusFood"] = "Eviter la nourriture donnant un bonus",
|
|
||||||
["PreferHigherQuality"] = "Privilégier la nourriture que votre familier préfère",
|
|
||||||
["Fallback"] = "Utiliser la nourriture évitée s'il n'y en a plus d'autres",
|
|
||||||
["SaveForCook_All"] = "Toutes nourritures utilisées pour la cuisine",
|
|
||||||
["SaveForCook_Green"] = "si elle est utilisée dans les recettes |cff3fbf3f\"faciles\"|r ou supérieures",
|
|
||||||
["SaveForCook_Yellow"] = "si elle est utilisée dans les recettes |cffffff00\"moyennes\"|r ou supérieures",
|
|
||||||
["SaveForCook_Orange"] = "si elle est utilisée dans les recettes |cffff7f3f\"difficiles\"|r",
|
|
||||||
["SaveForCook_None"] = "Ne pas éviter la nourriture utilisée en cuisine",
|
|
||||||
["IconWarning"] = "Clignoter l'icône",
|
|
||||||
["TextWarning"] = "Afficher un texte",
|
|
||||||
["AudioWarning"] = "Jouer un son",
|
|
||||||
["AudioWarningBell"] = "Un son de cloche au lieu du cri du familier",
|
|
||||||
["AlertEmote"] = "Via emote (visible par les autres)",
|
|
||||||
["AlertChat"] = "Dans la fenêtre de discussion (visible uniquement par vous)",
|
|
||||||
["AlertNone"] = "Ne pas prévenir",
|
|
||||||
["LevelContent"] = "quand \"content\"",
|
|
||||||
["LevelUnhappy"] = "quand \"mécontent\"",
|
|
||||||
["LevelOff"] = "Ne pas avertir",
|
|
||||||
};
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------------
|
|
||||||
|
|
||||||
if (GetLocale() == "deDE") then
|
if (GetLocale() == "deDE") then
|
||||||
|
|
||||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
||||||
@@ -279,26 +175,4 @@ if (GetLocale() == "deDE") then
|
|||||||
WIND_SERPENT = "Windnatter";
|
WIND_SERPENT = "Windnatter";
|
||||||
-- WOLF = "Wolf"; -- same as enUS
|
-- WOLF = "Wolf"; -- same as enUS
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------------
|
|
||||||
|
|
||||||
if (GetLocale() == "koKR") then
|
|
||||||
|
|
||||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
|
||||||
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
|
|
||||||
-- FOM_DIET_MEAT = "meat";
|
|
||||||
-- FOM_DIET_FISH = "fish";
|
|
||||||
-- FOM_DIET_BREAD = "bread";
|
|
||||||
-- FOM_DIET_CHEESE = "cheese";
|
|
||||||
-- FOM_DIET_FRUIT = "fruit";
|
|
||||||
-- FOM_DIET_FUNGUS = "fungus";
|
|
||||||
|
|
||||||
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons.
|
|
||||||
-- FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "wolf", "raptor", "steed", "horse", "ram", "saber", "mechanostrider" };
|
|
||||||
|
|
||||||
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case.
|
|
||||||
-- FOM_AMMO_POUCH = "Ammo Pouch";
|
|
||||||
FOM_QUIVER = "화살통";
|
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
local MTH_FeedOMatic = {
|
local MTH_FeedOMatic = {
|
||||||
name = "feedomatic",
|
name = "feedomatic",
|
||||||
enabled = false,
|
enabled = false,
|
||||||
version = "1.1.0",
|
|
||||||
events = {
|
events = {
|
||||||
"VARIABLES_LOADED",
|
"VARIABLES_LOADED",
|
||||||
"MERCHANT_SHOW",
|
"MERCHANT_SHOW",
|
||||||
@@ -32,7 +31,7 @@ local MTH_FeedOMatic = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local MTH_PETL_HOOK_BOUNDARY_KEY = "pet-lifecycle-hooks"
|
local MTH_PETL_HOOK_BOUNDARY_KEY = "pet-lifecycle-hooks"
|
||||||
local MTH_FeedOMatic_MerchantProbeFrame = nil
|
local MTH_FOM_MerchantProbe = nil
|
||||||
|
|
||||||
function MTH_FeedOMatic_OnUpdate(elapsed)
|
function MTH_FeedOMatic_OnUpdate(elapsed)
|
||||||
if not elapsed then
|
if not elapsed then
|
||||||
@@ -47,7 +46,7 @@ function MTH_FeedOMatic_OnUpdate(elapsed)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FeedOMatic_GetRuntimeFrame()
|
local function MTH_FeedOMatic_GetRuntimeFrame()
|
||||||
return getglobal("Frame_GFW_FeedOMatic")
|
return getglobal("MTH_FOM_OnUpdateFrame")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FeedOMatic_CaptureHookBoundary()
|
local function MTH_FeedOMatic_CaptureHookBoundary()
|
||||||
@@ -112,10 +111,6 @@ local function MTH_FeedOMatic_CallLegacyOnEvent(evt, a1, a2, a3, a4, a5, a6, a7,
|
|||||||
event = oldEvent
|
event = oldEvent
|
||||||
arg1, arg2, arg3, arg4, arg5 = oldArg1, oldArg2, oldArg3, oldArg4, oldArg5
|
arg1, arg2, arg3, arg4, arg5 = oldArg1, oldArg2, oldArg3, oldArg4, oldArg5
|
||||||
arg6, arg7, arg8, arg9 = oldArg6, oldArg7, oldArg8, oldArg9
|
arg6, arg7, arg8, arg9 = oldArg6, oldArg7, oldArg8, oldArg9
|
||||||
|
|
||||||
if not ok and MTH and MTH.DebugPrint then
|
|
||||||
MTH:DebugPrint("FeedOMatic legacy OnEvent call failed for event: " .. tostring(evt))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FeedOMatic_EnsureVariablesLoaded(module)
|
local function MTH_FeedOMatic_EnsureVariablesLoaded(module)
|
||||||
@@ -166,8 +161,7 @@ end
|
|||||||
|
|
||||||
local function MTH_FeedOMatic_Log(message, severity)
|
local function MTH_FeedOMatic_Log(message, severity)
|
||||||
if type(MTH_Log) == "function" then
|
if type(MTH_Log) == "function" then
|
||||||
local logSeverity = severity or "debug"
|
MTH_Log("[FeedOMatic] " .. tostring(message or ""), severity)
|
||||||
MTH_Log("[FeedOMatic] " .. tostring(message or ""), logSeverity)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -198,10 +192,8 @@ local function MTH_FeedOMatic_DebugMerchantScan(sourceEvent)
|
|||||||
if type(rows) == "table" then
|
if type(rows) == "table" then
|
||||||
dietCount = table.getn(rows)
|
dietCount = table.getn(rows)
|
||||||
end
|
end
|
||||||
MTH_FeedOMatic_Log("diet " .. tostring(dietName) .. ": " .. tostring(dietCount) .. " item(s)", "debug")
|
|
||||||
if type(rows) == "table" then
|
if type(rows) == "table" then
|
||||||
for _, row in rows do
|
for _, row in rows do
|
||||||
MTH_FeedOMatic_Log(" - [" .. tostring(row.id) .. "] " .. tostring(row.name) .. " (slot=" .. tostring(row.index) .. ")", "debug")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -209,34 +201,31 @@ local function MTH_FeedOMatic_DebugMerchantScan(sourceEvent)
|
|||||||
|
|
||||||
if unknownCount > 0 and type(merchantFoods.unknown) == "table" then
|
if unknownCount > 0 and type(merchantFoods.unknown) == "table" then
|
||||||
for _, row in merchantFoods.unknown do
|
for _, row in merchantFoods.unknown do
|
||||||
MTH_FeedOMatic_Log("unknown map: [" .. tostring(row.id) .. "] " .. tostring(row.name) .. " (slot=" .. tostring(row.index) .. ")", "debug")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
|
local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
|
||||||
if not enabled then
|
if not enabled then
|
||||||
if MTH_FeedOMatic_MerchantProbeFrame then
|
if MTH_FOM_MerchantProbe then
|
||||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_SHOW")
|
MTH_FOM_MerchantProbe:UnregisterEvent("MERCHANT_SHOW")
|
||||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_UPDATE")
|
MTH_FOM_MerchantProbe:UnregisterEvent("MERCHANT_UPDATE")
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not MTH_FeedOMatic_MerchantProbeFrame then
|
if not MTH_FOM_MerchantProbe then
|
||||||
MTH_FeedOMatic_MerchantProbeFrame = CreateFrame("Frame", "MTH_FeedOMatic_MerchantProbeFrame")
|
MTH_FOM_MerchantProbe = CreateFrame("Frame", "MTH_FOM_MerchantProbe")
|
||||||
MTH_FeedOMatic_MerchantProbeFrame:SetScript("OnEvent", function()
|
MTH_FOM_MerchantProbe:SetScript("OnEvent", function()
|
||||||
local evt = event
|
local evt = event
|
||||||
if evt == "MERCHANT_SHOW" or evt == "MERCHANT_UPDATE" then
|
if evt == "MERCHANT_SHOW" or evt == "MERCHANT_UPDATE" then
|
||||||
MTH_FeedOMatic_Log("probe event received: " .. tostring(evt), "debug")
|
|
||||||
MTH_FeedOMatic_DebugMerchantScan(evt)
|
MTH_FeedOMatic_DebugMerchantScan(evt)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_SHOW")
|
MTH_FOM_MerchantProbe:RegisterEvent("MERCHANT_SHOW")
|
||||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_UPDATE")
|
MTH_FOM_MerchantProbe:RegisterEvent("MERCHANT_UPDATE")
|
||||||
MTH_FeedOMatic_Log("merchant probe enabled", "debug")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_FeedOMatic:init()
|
function MTH_FeedOMatic:init()
|
||||||
@@ -277,8 +266,8 @@ function MTH_FeedOMatic:setEnabled(enabled)
|
|||||||
MTH_FeedOMatic_SyncSavedVariables()
|
MTH_FeedOMatic_SyncSavedVariables()
|
||||||
MTH_FeedOMatic_EnsureVariablesLoaded(self)
|
MTH_FeedOMatic_EnsureVariablesLoaded(self)
|
||||||
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
||||||
if FOM_FeedButton then
|
if MTH_FOM_FeedButton then
|
||||||
FOM_FeedButton:Show()
|
MTH_FOM_FeedButton:Show()
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- Disable FeedOMatic functionality
|
-- Disable FeedOMatic functionality
|
||||||
@@ -287,8 +276,8 @@ function MTH_FeedOMatic:setEnabled(enabled)
|
|||||||
FOM_State.ShouldFeed = false
|
FOM_State.ShouldFeed = false
|
||||||
end
|
end
|
||||||
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
||||||
if FOM_FeedButton then
|
if MTH_FOM_FeedButton then
|
||||||
FOM_FeedButton:Hide()
|
MTH_FOM_FeedButton:Hide()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -316,8 +305,8 @@ function MTH_FeedOMatic:cleanup()
|
|||||||
FOM_State.ShouldFeed = false
|
FOM_State.ShouldFeed = false
|
||||||
end
|
end
|
||||||
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
||||||
if FOM_FeedButton then
|
if MTH_FOM_FeedButton then
|
||||||
FOM_FeedButton:Hide();
|
MTH_FOM_FeedButton:Hide();
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ FeedOMatic Runtime Frame Loader (MetaHunt)
|
|||||||
Minimal runtime XML without legacy options window definitions.
|
Minimal runtime XML without legacy options window definitions.
|
||||||
-->
|
-->
|
||||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\..\..\FrameXML\UI.xsd">
|
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\..\..\FrameXML\UI.xsd">
|
||||||
<Frame name="Frame_GFW_FeedOMatic">
|
<Frame name="MTH_FOM_OnUpdateFrame">
|
||||||
<Scripts>
|
<Scripts>
|
||||||
<OnUpdate>
|
<OnUpdate>
|
||||||
if (MTH_FOM_OnUpdate) then
|
if (MTH_FOM_OnUpdate) then
|
||||||
@@ -15,7 +15,7 @@ Minimal runtime XML without legacy options window definitions.
|
|||||||
</Scripts>
|
</Scripts>
|
||||||
</Frame>
|
</Frame>
|
||||||
|
|
||||||
<GameTooltip name="FOMTooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate">
|
<GameTooltip name="MTH_FOM_Tooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate">
|
||||||
<Scripts>
|
<Scripts>
|
||||||
<OnLoad>
|
<OnLoad>
|
||||||
this:SetOwner(UIParent, "ANCHOR_NONE");
|
this:SetOwner(UIParent, "ANCHOR_NONE");
|
||||||
|
|||||||
+1127
-1127
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@
|
|||||||
local MTH_ICU = {
|
local MTH_ICU = {
|
||||||
name = "icu",
|
name = "icu",
|
||||||
enabled = false,
|
enabled = false,
|
||||||
version = "1.1.0",
|
|
||||||
events = {
|
events = {
|
||||||
"VARIABLES_LOADED",
|
"VARIABLES_LOADED",
|
||||||
},
|
},
|
||||||
|
|||||||
+822
-774
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,9 @@ MTH_SA_MANAGED_HOOKS = true
|
|||||||
local MTH_SmartAmmo = {
|
local MTH_SmartAmmo = {
|
||||||
name = "smartammo",
|
name = "smartammo",
|
||||||
enabled = true,
|
enabled = true,
|
||||||
version = "1.1.0",
|
|
||||||
events = {
|
events = {
|
||||||
"VARIABLES_LOADED",
|
"VARIABLES_LOADED",
|
||||||
"PLAYER_ENTERING_WORLD",
|
-- PLAYER_ENTERING_WORLD handled by engine's own frame
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-24
@@ -6,7 +6,6 @@
|
|||||||
local MTH_Tooltips = {
|
local MTH_Tooltips = {
|
||||||
name = "tooltips",
|
name = "tooltips",
|
||||||
enabled = true,
|
enabled = true,
|
||||||
version = "1.1.0",
|
|
||||||
events = {
|
events = {
|
||||||
"UPDATE_MOUSEOVER_UNIT",
|
"UPDATE_MOUSEOVER_UNIT",
|
||||||
"UNIT_NAME_UPDATE",
|
"UNIT_NAME_UPDATE",
|
||||||
@@ -1389,7 +1388,6 @@ local function MTH_TT_AddPetActionNotLearnedHint()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local ownerName = MTH_TT_GetTooltipOwnerName()
|
|
||||||
local ownerMatch = MTH_TT_IsPetActionTooltipOwner()
|
local ownerMatch = MTH_TT_IsPetActionTooltipOwner()
|
||||||
local barMatch = MTH_TT_IsSpellOnPetActionBar(spellName)
|
local barMatch = MTH_TT_IsSpellOnPetActionBar(spellName)
|
||||||
if not ownerMatch and not barMatch then
|
if not ownerMatch and not barMatch then
|
||||||
@@ -1406,11 +1404,13 @@ local function MTH_TT_AddPetActionNotLearnedHint()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local canonicalLower = MTH_TT_Lower(canonical)
|
local canonicalLower = MTH_TT_Lower(canonical)
|
||||||
local known = MTH_TT_HunterKnowsAbility(canonicalLower, rankNumber)
|
local hunterKnown = MTH_TT_HunterKnowsAbility(canonicalLower, rankNumber)
|
||||||
if not known then
|
-- Only fall back to petKnown for ranked abilities: rankless abilities have no rank
|
||||||
known = MTH_TT_CurrentPetKnowsAbility(canonicalLower, rankNumber)
|
-- filter in CurrentPetKnowsAbility, so they always match on name alone -> false positive.
|
||||||
end
|
local petKnown = (not hunterKnown)
|
||||||
if known then
|
and MTH_TT_AbilityHasPositiveRanks(canonical)
|
||||||
|
and MTH_TT_CurrentPetKnowsAbility(canonicalLower, rankNumber)
|
||||||
|
if hunterKnown or petKnown then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1510,8 +1510,10 @@ local function MTH_TT_AddTooltip(unit)
|
|||||||
MTH_TT_Log("vendor tooltip added: unit='" .. tostring(name) .. "'")
|
MTH_TT_Log("vendor tooltip added: unit='" .. tostring(name) .. "'")
|
||||||
end
|
end
|
||||||
|
|
||||||
if row then
|
local abilitiesSource = row and row.abilities or nil
|
||||||
local abilities = MTH_TT_ParseAbilities(row.abilities)
|
|
||||||
|
if abilitiesSource then
|
||||||
|
local abilities = MTH_TT_ParseAbilities(abilitiesSource)
|
||||||
if table.getn(abilities) == 0 then
|
if table.getn(abilities) == 0 then
|
||||||
MTH_TT_StateSet("skip-no-abilities", name, normalized)
|
MTH_TT_StateSet("skip-no-abilities", name, normalized)
|
||||||
MTH_TT_Log("skip: beast has no abilities ('" .. tostring(name) .. "')")
|
MTH_TT_Log("skip: beast has no abilities ('" .. tostring(name) .. "')")
|
||||||
@@ -1545,19 +1547,18 @@ local function MTH_TT_EnsureInjectFrame()
|
|||||||
if MTH_Tooltips.injectFrame then
|
if MTH_Tooltips.injectFrame then
|
||||||
return MTH_Tooltips.injectFrame
|
return MTH_Tooltips.injectFrame
|
||||||
end
|
end
|
||||||
local frame = CreateFrame("Frame", "MTH_TooltipsInjectFrame")
|
local frame = CreateFrame("Frame", "MTH_TooltipsInject")
|
||||||
frame.pending = false
|
frame.pending = false
|
||||||
frame.onUpdate = function(self)
|
frame.onUpdate = function()
|
||||||
self = self or this
|
if not this then
|
||||||
if not self then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not self.pending then
|
if not this.pending then
|
||||||
self:SetScript("OnUpdate", nil)
|
this:SetScript("OnUpdate", nil)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self.pending = false
|
this.pending = false
|
||||||
self:SetScript("OnUpdate", nil)
|
this:SetScript("OnUpdate", nil)
|
||||||
if MTH_Tooltips and MTH_Tooltips.enabled then
|
if MTH_Tooltips and MTH_Tooltips.enabled then
|
||||||
MTH_TT_AddTooltip("mouseover")
|
MTH_TT_AddTooltip("mouseover")
|
||||||
end
|
end
|
||||||
@@ -1581,14 +1582,13 @@ local function MTH_TT_EnsurePollFrame()
|
|||||||
return MTH_Tooltips.pollFrame
|
return MTH_Tooltips.pollFrame
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame", "MTH_TooltipsPollFrame")
|
local frame = CreateFrame("Frame", "MTH_TooltipsPoll")
|
||||||
frame:SetScript("OnUpdate", function(_, elapsed)
|
frame:SetScript("OnUpdate", function()
|
||||||
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
elapsed = elapsed or arg1
|
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (arg1 or 0)
|
||||||
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (elapsed or 0)
|
|
||||||
if MTH_Tooltips.hintElapsed >= 0.25 then
|
if MTH_Tooltips.hintElapsed >= 0.25 then
|
||||||
MTH_Tooltips.hintElapsed = 0
|
MTH_Tooltips.hintElapsed = 0
|
||||||
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
|
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
|
||||||
@@ -1648,13 +1648,12 @@ local function MTH_TT_SetRuntimeActive(active)
|
|||||||
local pollFrame = MTH_Tooltips.pollFrame
|
local pollFrame = MTH_Tooltips.pollFrame
|
||||||
if pollFrame then
|
if pollFrame then
|
||||||
if active then
|
if active then
|
||||||
pollFrame:SetScript("OnUpdate", pollFrame:GetScript("OnUpdate") or function(_, elapsed)
|
pollFrame:SetScript("OnUpdate", pollFrame:GetScript("OnUpdate") or function()
|
||||||
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
if not (MTH_Tooltips and MTH_Tooltips.enabled) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
elapsed = elapsed or arg1
|
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (arg1 or 0)
|
||||||
MTH_Tooltips.hintElapsed = (MTH_Tooltips.hintElapsed or 0) + (elapsed or 0)
|
|
||||||
if MTH_Tooltips.hintElapsed >= 0.25 then
|
if MTH_Tooltips.hintElapsed >= 0.25 then
|
||||||
MTH_Tooltips.hintElapsed = 0
|
MTH_Tooltips.hintElapsed = 0
|
||||||
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
|
if GameTooltip and GameTooltip.IsShown and GameTooltip:IsShown() then
|
||||||
|
|||||||
@@ -37,13 +37,6 @@ local function ZHunterMod_RunButtonInit(frame, onEventFunc)
|
|||||||
event = oldEvent
|
event = oldEvent
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ZHunterMod_LogDeferred(msg)
|
|
||||||
local deferredDebug = _G and _G["MTH_ZH_DEFERRED_DEBUG"]
|
|
||||||
if not (MTH and MTH.debug and deferredDebug) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
MTH_ZH_Print("[ZHUNTER] " .. tostring(msg), "error")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ZHunterMod_EnsureButtonFrame(buttonName)
|
local function ZHunterMod_EnsureButtonFrame(buttonName)
|
||||||
local frame = getglobal(buttonName)
|
local frame = getglobal(buttonName)
|
||||||
@@ -74,10 +67,11 @@ local function ZHunterMod_EnsureButtonFrame(buttonName)
|
|||||||
created:SetPoint("TOP", UIParent, "TOP", 0, -464)
|
created:SetPoint("TOP", UIParent, "TOP", 0, -464)
|
||||||
elseif buttonName == "zButtonToys" then
|
elseif buttonName == "zButtonToys" then
|
||||||
created:SetPoint("TOP", UIParent, "TOP", 0, -518)
|
created:SetPoint("TOP", UIParent, "TOP", 0, -518)
|
||||||
|
elseif buttonName == "zButtonCraft" then
|
||||||
|
created:SetPoint("TOP", UIParent, "TOP", 0, -572)
|
||||||
else
|
else
|
||||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||||
end
|
end
|
||||||
ZHunterMod_LogDeferred("DeferredInit: created missing frame " .. tostring(buttonName))
|
|
||||||
end
|
end
|
||||||
return created
|
return created
|
||||||
end
|
end
|
||||||
@@ -93,16 +87,7 @@ function ZHunterMod_DeferredInit()
|
|||||||
local mounts = ZHunterMod_EnsureButtonFrame("zButtonMounts")
|
local mounts = ZHunterMod_EnsureButtonFrame("zButtonMounts")
|
||||||
local companions = ZHunterMod_EnsureButtonFrame("zButtonCompanions")
|
local companions = ZHunterMod_EnsureButtonFrame("zButtonCompanions")
|
||||||
local toys = ZHunterMod_EnsureButtonFrame("zButtonToys")
|
local toys = ZHunterMod_EnsureButtonFrame("zButtonToys")
|
||||||
|
local craft = ZHunterMod_EnsureButtonFrame("zButtonCraft")
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Pet=" .. tostring(pet ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Aspect=" .. tostring(aspect ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Track=" .. tostring(track ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Trap=" .. tostring(trap ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Ranged=" .. tostring(ranged ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Ammo=" .. tostring(ammo ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Mounts=" .. tostring(mounts ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Companions=" .. tostring(companions ~= nil))
|
|
||||||
ZHunterMod_LogDeferred("DeferredInit: Toys=" .. tostring(toys ~= nil))
|
|
||||||
|
|
||||||
-- Continue with all frames that exist; do not hard-abort when one optional frame is missing.
|
-- Continue with all frames that exist; do not hard-abort when one optional frame is missing.
|
||||||
local missing = {}
|
local missing = {}
|
||||||
@@ -115,12 +100,13 @@ function ZHunterMod_DeferredInit()
|
|||||||
if not mounts then table.insert(missing, "Mounts") end
|
if not mounts then table.insert(missing, "Mounts") end
|
||||||
if not companions then table.insert(missing, "Companions") end
|
if not companions then table.insert(missing, "Companions") end
|
||||||
if not toys then table.insert(missing, "Toys") end
|
if not toys then table.insert(missing, "Toys") end
|
||||||
|
if not craft then table.insert(missing, "Craft") end
|
||||||
|
|
||||||
if table.getn(missing) > 0 then
|
if table.getn(missing) > 0 then
|
||||||
MTH_ZH_Print("[ZHUNTER] Warning: missing frames: " .. table.concat(missing, ", ") .. ". Continuing with available buttons.", "error")
|
MTH_ZH_Print("[ZHUNTER] Warning: missing frames: " .. table.concat(missing, ", ") .. ". Continuing with available buttons.", "error")
|
||||||
end
|
end
|
||||||
|
|
||||||
if not (pet or aspect or track or trap or ranged or ammo or mounts or companions or toys) then
|
if not (pet or aspect or track or trap or ranged or ammo or mounts or companions or toys or craft) then
|
||||||
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -195,6 +181,12 @@ function ZHunterMod_DeferredInit()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if craft and zButtonCraft_OnEvent then
|
||||||
|
if ZHunterMod_SafeRunButtonInit(craft, zButtonCraft_OnEvent, "zButtonCraft") then
|
||||||
|
initialized = initialized + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if initialized <= 0 then
|
if initialized <= 0 then
|
||||||
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
||||||
return
|
return
|
||||||
@@ -202,7 +194,7 @@ function ZHunterMod_DeferredInit()
|
|||||||
|
|
||||||
if type(MTH_ZH_OnDeferredInitComplete) == "function" then
|
if type(MTH_ZH_OnDeferredInitComplete) == "function" then
|
||||||
local ok, err = pcall(MTH_ZH_OnDeferredInitComplete)
|
local ok, err = pcall(MTH_ZH_OnDeferredInitComplete)
|
||||||
if not ok and MTH_DebugFrame and MTH_DebugFrame.AddError then
|
if not ok then
|
||||||
MTH_ZH_Print("[ZHUNTER] DeferredInit callback error: " .. tostring(err), "error")
|
MTH_ZH_Print("[ZHUNTER] DeferredInit callback error: " .. tostring(err), "error")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ ZHUNTER_TRACK_GIANTS = "Track Giants"
|
|||||||
ZHUNTER_TRACK_MINERALS = "Find Minerals"
|
ZHUNTER_TRACK_MINERALS = "Find Minerals"
|
||||||
ZHUNTER_TRACK_HERBS = "Find Herbs"
|
ZHUNTER_TRACK_HERBS = "Find Herbs"
|
||||||
ZHUNTER_TRACK_TREASURE = "Find Treasure"
|
ZHUNTER_TRACK_TREASURE = "Find Treasure"
|
||||||
|
ZHUNTER_TRACK_TREES = "Find Trees"
|
||||||
|
|
||||||
ZHUNTER_TRAP_FREEZING = "Freezing Trap"
|
ZHUNTER_TRAP_FREEZING = "Freezing Trap"
|
||||||
ZHUNTER_TRAP_FROST = "Frost Trap"
|
ZHUNTER_TRAP_FROST = "Frost Trap"
|
||||||
|
|||||||
+171
-217
@@ -1,217 +1,171 @@
|
|||||||
if not ZHunterMod_Saved then
|
if not ZHunterMod_Saved then
|
||||||
ZHunterMod_Saved = {}
|
ZHunterMod_Saved = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
BINDING_HEADER_ZAspectHeader = "ZAspect Buttons"
|
BINDING_HEADER_ZAspectHeader = "ZAspect Buttons"
|
||||||
BINDING_HEADER_ZTrackHeader = "ZTrack Buttons"
|
BINDING_HEADER_ZTrackHeader = "ZTrack Buttons"
|
||||||
BINDING_HEADER_ZTrapHeader = "ZTrap Buttons"
|
BINDING_HEADER_ZTrapHeader = "ZTrap Buttons"
|
||||||
BINDING_HEADER_ZPetHeader = "ZPet Buttons"
|
BINDING_HEADER_ZPetHeader = "ZPet Buttons"
|
||||||
BINDING_HEADER_ZAmmoHeader = "ZAmmo Buttons"
|
BINDING_HEADER_ZAmmoHeader = "ZAmmo Buttons"
|
||||||
BINDING_HEADER_ZMountsHeader = "ZMounts Buttons"
|
BINDING_HEADER_ZMountsHeader = "ZMounts Buttons"
|
||||||
BINDING_HEADER_ZCompanionsHeader = "ZCompanions Buttons"
|
BINDING_HEADER_ZCompanionsHeader = "ZCompanions Buttons"
|
||||||
BINDING_HEADER_ZToysHeader = "ZToys Buttons"
|
BINDING_HEADER_ZToysHeader = "ZToys Buttons"
|
||||||
|
|
||||||
ZHunterModTooltip = CreateFrame("GameTooltip", "ZHunterModScan", nil, "GameTooltipTemplate")
|
ZHunterModTooltip = CreateFrame("GameTooltip", "MTH_ZH_AbilityProbe", nil, "GameTooltipTemplate")
|
||||||
ZHunterModTooltipTextLeft1 = getglobal("ZHunterModScanTextLeft1")
|
ZHunterModTooltipTextLeft1 = getglobal("MTH_ZH_AbilityProbeTextLeft1")
|
||||||
|
|
||||||
MTH_ZH_TRACE_ENABLED = false
|
|
||||||
|
local function MTH_ZH_DescribePoint(frame)
|
||||||
local function MTH_ZH_DescribePoint(frame)
|
if not (frame and frame.GetPoint) then
|
||||||
if not (frame and frame.GetPoint) then
|
return "<no-frame>"
|
||||||
return "<no-frame>"
|
end
|
||||||
end
|
local point, relTo, relPoint, x, y = frame:GetPoint()
|
||||||
local point, relTo, relPoint, x, y = frame:GetPoint()
|
local relName = "nil"
|
||||||
local relName = "nil"
|
if type(relTo) == "table" and relTo.GetName then
|
||||||
if type(relTo) == "table" and relTo.GetName then
|
relName = tostring(relTo:GetName() or "<anon>")
|
||||||
relName = tostring(relTo:GetName() or "<anon>")
|
elseif relTo then
|
||||||
elseif relTo then
|
relName = tostring(relTo)
|
||||||
relName = tostring(relTo)
|
end
|
||||||
end
|
return tostring(point or "nil")
|
||||||
return tostring(point or "nil")
|
.. "->" .. relName
|
||||||
.. "->" .. relName
|
.. ":" .. tostring(relPoint or "nil")
|
||||||
.. ":" .. tostring(relPoint or "nil")
|
.. " @(" .. tostring(x) .. "," .. tostring(y) .. ")"
|
||||||
.. " @(" .. tostring(x) .. "," .. tostring(y) .. ")"
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function MTH_ZH_Trace(msg)
|
|
||||||
if not MTH_ZH_TRACE_ENABLED then
|
|
||||||
return
|
function MTH_ZH_IsModuleEnabled()
|
||||||
end
|
if not (MTH and MTH.IsModuleEnabled) then
|
||||||
if MTH and MTH.Print then
|
return true
|
||||||
MTH:Print("[ZHTRACE] " .. tostring(msg), "debug")
|
end
|
||||||
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
return MTH:IsModuleEnabled("zhunter", true)
|
||||||
DEFAULT_CHAT_FRAME:AddMessage("[ZHTRACE] " .. tostring(msg))
|
end
|
||||||
end
|
|
||||||
end
|
function MTH_ZH_GetSavedRoot()
|
||||||
|
if type(ZHunterMod_Saved) ~= "table" then
|
||||||
function MTH_ZH_TraceButtonPoint(frame, reason)
|
ZHunterMod_Saved = {}
|
||||||
if not MTH_ZH_TRACE_ENABLED then
|
end
|
||||||
return
|
return ZHunterMod_Saved
|
||||||
end
|
end
|
||||||
if not frame then
|
|
||||||
MTH_ZH_Trace("point " .. tostring(reason or "") .. " frame=nil")
|
function MTH_ZH_GetSavedTable(key)
|
||||||
return
|
local root = MTH_ZH_GetSavedRoot()
|
||||||
end
|
if type(key) ~= "string" or key == "" then
|
||||||
local name = frame.GetName and frame:GetName() or "<unnamed>"
|
return root
|
||||||
MTH_ZH_Trace("point " .. tostring(reason or "") .. " " .. tostring(name) .. " " .. MTH_ZH_DescribePoint(frame))
|
end
|
||||||
end
|
if type(root[key]) ~= "table" then
|
||||||
|
root[key] = {}
|
||||||
function MTH_ZH_TraceAllButtonPoints(reason)
|
end
|
||||||
if not MTH_ZH_TRACE_ENABLED then
|
return root[key]
|
||||||
return
|
end
|
||||||
end
|
|
||||||
local names = {
|
local function MTH_ZH_MigrateButtonSavedKeys_Replace()
|
||||||
"zButtonAspect",
|
local root = MTH_ZH_GetSavedRoot()
|
||||||
"zButtonAmmo",
|
if type(root) ~= "table" then
|
||||||
"zButtonTrack",
|
return
|
||||||
"zButtonTrap",
|
end
|
||||||
"zButtonRanged",
|
|
||||||
"zButtonPet",
|
local mapping = {
|
||||||
"zButtonMounts",
|
{"ZHunterButtonAspect", "zButtonAspect"},
|
||||||
"zButtonCompanions",
|
{"ZHunterButtonTrack", "zButtonTrack"},
|
||||||
"zButtonToys",
|
{"ZHunterButtonTrap", "zButtonTrap"},
|
||||||
}
|
{"ZHunterButtonAmmo", "zButtonAmmo"},
|
||||||
MTH_ZH_Trace("snapshot begin reason=" .. tostring(reason or ""))
|
{"ZHunterButtonPet", "zButtonPet"},
|
||||||
for i = 1, table.getn(names) do
|
{"ZHunterButtonMounts", "zButtonMounts"},
|
||||||
local frame = getglobal(names[i])
|
{"ZHunterButtonCompanions", "zButtonCompanions"},
|
||||||
MTH_ZH_TraceButtonPoint(frame, tostring(reason or "") .. ":" .. tostring(names[i]))
|
{"ZHunterButtonToys", "zButtonToys"},
|
||||||
end
|
}
|
||||||
MTH_ZH_Trace("snapshot end reason=" .. tostring(reason or ""))
|
|
||||||
end
|
for i = 1, table.getn(mapping) do
|
||||||
|
local oldKey = mapping[i][1]
|
||||||
function MTH_ZH_IsModuleEnabled()
|
local newKey = mapping[i][2]
|
||||||
if not (MTH and MTH.IsModuleEnabled) then
|
if root[oldKey] ~= nil then
|
||||||
return true
|
root[newKey] = root[oldKey]
|
||||||
end
|
root[oldKey] = nil
|
||||||
return MTH:IsModuleEnabled("zhunter", true)
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
function MTH_ZH_GetSavedRoot()
|
|
||||||
if type(ZHunterMod_Saved) ~= "table" then
|
MTH_ZH_MigrateButtonSavedKeys_Replace()
|
||||||
ZHunterMod_Saved = {}
|
|
||||||
end
|
function MTH_ZH_Print(message, severity)
|
||||||
return ZHunterMod_Saved
|
if type(MTH_Log) == "function" then
|
||||||
end
|
MTH_Log(message, severity)
|
||||||
|
return
|
||||||
function MTH_ZH_GetSavedTable(key)
|
end
|
||||||
local root = MTH_ZH_GetSavedRoot()
|
if MTH and MTH.Print then
|
||||||
if type(key) ~= "string" or key == "" then
|
MTH:Print(message, severity)
|
||||||
return root
|
return
|
||||||
end
|
end
|
||||||
if type(root[key]) ~= "table" then
|
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||||
root[key] = {}
|
DEFAULT_CHAT_FRAME:AddMessage("[MetaHunt] " .. tostring(message or ""), 1, 0.9, 0.3)
|
||||||
end
|
end
|
||||||
return root[key]
|
end
|
||||||
end
|
|
||||||
|
function MTH_ZH_HandleDisabledSlash(message, tableKey, fieldKey)
|
||||||
local function MTH_ZH_MigrateButtonSavedKeys_Replace()
|
if MTH_ZH_IsModuleEnabled() then
|
||||||
local root = MTH_ZH_GetSavedRoot()
|
return false
|
||||||
if type(root) ~= "table" then
|
end
|
||||||
return
|
|
||||||
end
|
if type(tableKey) == "string" and tableKey ~= "" then
|
||||||
|
if fieldKey then
|
||||||
local mapping = {
|
local tbl = MTH_ZH_GetSavedTable(tableKey)
|
||||||
{"ZHunterButtonAspect", "zButtonAspect"},
|
tbl[fieldKey] = nil
|
||||||
{"ZHunterButtonTrack", "zButtonTrack"},
|
else
|
||||||
{"ZHunterButtonTrap", "zButtonTrap"},
|
local root = MTH_ZH_GetSavedRoot()
|
||||||
{"ZHunterButtonAmmo", "zButtonAmmo"},
|
root[tableKey] = nil
|
||||||
{"ZHunterButtonPet", "zButtonPet"},
|
end
|
||||||
{"ZHunterButtonMounts", "zButtonMounts"},
|
end
|
||||||
{"ZHunterButtonCompanions", "zButtonCompanions"},
|
|
||||||
{"ZHunterButtonToys", "zButtonToys"},
|
if message then
|
||||||
}
|
MTH_ZH_Print(message)
|
||||||
|
end
|
||||||
for i = 1, table.getn(mapping) do
|
|
||||||
local oldKey = mapping[i][1]
|
return true
|
||||||
local newKey = mapping[i][2]
|
end
|
||||||
if root[oldKey] ~= nil then
|
|
||||||
root[newKey] = root[oldKey]
|
function ZHunterMod_AlignButtons()
|
||||||
root[oldKey] = nil
|
zButtonAmmo:ClearAllPoints()
|
||||||
end
|
zButtonAmmo:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15)
|
||||||
end
|
zButtonTrack:ClearAllPoints()
|
||||||
end
|
zButtonTrack:SetPoint("TOP", zButtonAmmo, "BOTTOM", 0, -15)
|
||||||
|
zButtonTrap:ClearAllPoints()
|
||||||
MTH_ZH_MigrateButtonSavedKeys_Replace()
|
zButtonTrap:SetPoint("TOP", zButtonTrack, "BOTTOM", 0, -15)
|
||||||
|
zButtonPet:ClearAllPoints()
|
||||||
function MTH_ZH_Print(message, severity)
|
zButtonPet:SetPoint("TOP", zButtonTrap, "BOTTOM", 0, -15)
|
||||||
if type(MTH_Log) == "function" then
|
zButtonMounts:ClearAllPoints()
|
||||||
MTH_Log(message, severity)
|
zButtonMounts:SetPoint("TOP", zButtonPet, "BOTTOM", 0, -15)
|
||||||
return
|
zButtonCompanions:ClearAllPoints()
|
||||||
end
|
zButtonCompanions:SetPoint("TOP", zButtonMounts, "BOTTOM", 0, -15)
|
||||||
if MTH and MTH.Print then
|
zButtonToys:ClearAllPoints()
|
||||||
MTH:Print(message, severity)
|
zButtonToys:SetPoint("TOP", zButtonCompanions, "BOTTOM", 0, -15)
|
||||||
return
|
if AutoStripDisplay then
|
||||||
end
|
AutoStripDisplay:ClearAllPoints()
|
||||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
AutoStripDisplay:SetPoint("TOP", zButtonToys, "BOTTOM", 0, -10)
|
||||||
DEFAULT_CHAT_FRAME:AddMessage("[MetaHunt] " .. tostring(message or ""), 1, 0.9, 0.3)
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
function ZMarkTarget()
|
||||||
function MTH_ZH_HandleDisabledSlash(message, tableKey, fieldKey)
|
if not MTH_ZH_IsModuleEnabled() then
|
||||||
if MTH_ZH_IsModuleEnabled() then
|
return
|
||||||
return false
|
end
|
||||||
end
|
|
||||||
|
if not UnitExists("target") then return end
|
||||||
if type(tableKey) == "string" and tableKey ~= "" then
|
for i=1, 40 do
|
||||||
if fieldKey then
|
if not UnitDebuff("target", i) then break end
|
||||||
local tbl = MTH_ZH_GetSavedTable(tableKey)
|
ZHunterModTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||||
tbl[fieldKey] = nil
|
ZHunterModTooltip:SetUnitDebuff("target", i)
|
||||||
else
|
local spell = ZHunterModTooltipTextLeft1:GetText()
|
||||||
local root = MTH_ZH_GetSavedRoot()
|
if spell == ZHUNTER_HUNTERSMARK then
|
||||||
root[tableKey] = nil
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
CastSpellByName(ZHUNTER_HUNTERSMARK)
|
||||||
if message then
|
return 1
|
||||||
MTH_ZH_Print(message)
|
end
|
||||||
end
|
|
||||||
|
SLASH_ZHunterMod1 = "/zhunter"
|
||||||
return true
|
SlashCmdList["ZHunterMod"] = function(msg)
|
||||||
end
|
MTH_ZH_Print("Possible Slash Commands: \"/zammo\", \"/zaspect\", \"/ztrack\", \"/ztrap\", \"/zpet\", \"/zmounts\", \"/zcompanions\", \"/zminipets\", \"/ztoys\", \"/zstrip\", \"/zantidaze\"")
|
||||||
|
end
|
||||||
function ZHunterMod_AlignButtons()
|
|
||||||
MTH_ZH_TraceAllButtonPoints("AlignButtons:before")
|
|
||||||
zButtonAmmo:ClearAllPoints()
|
|
||||||
zButtonAmmo:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15)
|
|
||||||
zButtonTrack:ClearAllPoints()
|
|
||||||
zButtonTrack:SetPoint("TOP", zButtonAmmo, "BOTTOM", 0, -15)
|
|
||||||
zButtonTrap:ClearAllPoints()
|
|
||||||
zButtonTrap:SetPoint("TOP", zButtonTrack, "BOTTOM", 0, -15)
|
|
||||||
zButtonPet:ClearAllPoints()
|
|
||||||
zButtonPet:SetPoint("TOP", zButtonTrap, "BOTTOM", 0, -15)
|
|
||||||
zButtonMounts:ClearAllPoints()
|
|
||||||
zButtonMounts:SetPoint("TOP", zButtonPet, "BOTTOM", 0, -15)
|
|
||||||
zButtonCompanions:ClearAllPoints()
|
|
||||||
zButtonCompanions:SetPoint("TOP", zButtonMounts, "BOTTOM", 0, -15)
|
|
||||||
zButtonToys:ClearAllPoints()
|
|
||||||
zButtonToys:SetPoint("TOP", zButtonCompanions, "BOTTOM", 0, -15)
|
|
||||||
if AutoStripDisplay then
|
|
||||||
AutoStripDisplay:ClearAllPoints()
|
|
||||||
AutoStripDisplay:SetPoint("TOP", zButtonToys, "BOTTOM", 0, -10)
|
|
||||||
end
|
|
||||||
MTH_ZH_TraceAllButtonPoints("AlignButtons:after")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ZMarkTarget()
|
|
||||||
if not MTH_ZH_IsModuleEnabled() then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not UnitExists("target") then return end
|
|
||||||
for i=1, 40 do
|
|
||||||
if not UnitDebuff("target", i) then break end
|
|
||||||
ZHunterModTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
|
||||||
ZHunterModTooltip:SetUnitDebuff("target", i)
|
|
||||||
local spell = ZHunterModTooltipTextLeft1:GetText()
|
|
||||||
if spell == ZHUNTER_HUNTERSMARK then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
CastSpellByName(ZHUNTER_HUNTERSMARK)
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
SLASH_ZHunterMod1 = "/zhunter"
|
|
||||||
SlashCmdList["ZHunterMod"] = function(msg)
|
|
||||||
MTH_ZH_Print("Possible Slash Commands: \"/zammo\", \"/zaspect\", \"/ztrack\", \"/ztrap\", \"/zpet\", \"/zmounts\", \"/zcompanions\", \"/zminipets\", \"/ztoys\", \"/zstrip\", \"/zantidaze\"")
|
|
||||||
end
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user