Add files via upload
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Eric Mauser (Shagu)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,145 @@
|
||||
# ShaguTweaks
|
||||
|
||||
<img src="screenshots/menu.jpg" float="right" align="right">
|
||||
|
||||
> **A small World of Warcraft (1.12.1 / 2.4.3) AddOn for those, who don't want to use any AddOns at all.**
|
||||
|
||||
The goal of ShaguTweaks is to be non-intrusive to the default appearance, but also giving the user the choice to change additional settings if desired. The pre-selected defaults of ShaguTweaks only add those quality of life changes to the game, that are preserving the look and feel of the original interface. It's up to everyones own preferences to enable more or even disable some more.
|
||||
|
||||
All tweaks are made to the default interface and might not take effect if you already replaced some of the elements with other addons.
|
||||
|
||||
All addon settings can be controlled in game via the "Advanced Options" button on the Main Menu (*Esc*).
|
||||
Every of the listed features below, can be completely disabled in that menu in case you don't like it.
|
||||
|
||||
**Notice:**
|
||||
*This Addon or a superior and maintained version of it, is already included in [pfUI](https://github.com/shagu.pfUI). If using this in combination with pfUI you might get bad results or up to performance regressions.*
|
||||
|
||||
## Installation (Vanilla, 1.12)
|
||||
1. Download **[Latest Version](https://github.com/shagu/ShaguTweaks/archive/master.zip)**
|
||||
2. Unpack the Zip file
|
||||
3. Rename the folder "ShaguTweaks-master" to "ShaguTweaks"
|
||||
4. Copy "ShaguTweaks" into Wow-Directory\Interface\AddOns
|
||||
5. Restart Wow
|
||||
|
||||
## Installation (The Burning Crusade, 2.4.3)
|
||||
1. Download **[Latest Version](https://github.com/shagu/ShaguTweaks/archive/master.zip)**
|
||||
2. Unpack the Zip file
|
||||
3. Rename the folder "ShaguTweaks-master" to "ShaguTweaks-tbc"
|
||||
4. Copy "ShaguTweaks-tbc" into Wow-Directory\Interface\AddOns
|
||||
5. Restart Wow
|
||||
|
||||
## Features
|
||||
|
||||

|
||||
|
||||
- **Auto Dismount**
|
||||
*Automatically dismounts whenever a spell is casted.*
|
||||
|
||||
- **Auto Stance**
|
||||
*Automatically switch to the required warrior or druid stance on spell cast.*
|
||||
|
||||
- **Blue Shaman Class Colors**
|
||||
*Changes the class color code of shamans to blue, as known from TBC+.*
|
||||
|
||||
- **Chat Hyperlinks**
|
||||
*Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links.*
|
||||
|
||||
- **Chat Tweaks**
|
||||
*Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up.*
|
||||
|
||||
- **Cooldown Numbers**
|
||||
*Display the remaining duration as text on every cooldown.*
|
||||
|
||||
- **Darkened UI**
|
||||
*Turns the entire interface into darker colors.*
|
||||
|
||||
- **Equip Compare**
|
||||
*Shows currently equipped items on tooltips while the shift key is pressed.*
|
||||
|
||||
- **Unit Frame Health Colors**
|
||||
*Change health text color based on its value.*
|
||||
|
||||
- **Real Health Numbers**
|
||||
*Estimates health numbers, and shows numbers on player, pet and target unit frames.*
|
||||
|
||||
- **Hide Errors**
|
||||
*Hides and ignores all Lua errors produced by broken addons.*
|
||||
|
||||
- **Hide Gryphons**
|
||||
*Hides the gryphons left and right of the action bar.*
|
||||
|
||||
- **Item Rarity Borders**
|
||||
*Show item rarity as the border color on bags, bank, character and inspect frames.*
|
||||
|
||||
- **MiniMap Clock**
|
||||
*Adds a small 24h clock to the mini map.*
|
||||
|
||||
- **MiniMap Square**
|
||||
*Draw the mini map in a squared shape instead of a round one.*
|
||||
|
||||
- **MiniMap Tweaks**
|
||||
*Hides unnecessary mini map buttons and allows to zoom using the mouse wheel.*
|
||||
|
||||
- **Movable Unit Frames**
|
||||
*Player and Target unit frames can be moved while "Shift" and "Ctrl" are pressed together.*
|
||||
|
||||
- **Nameplate Castbar**
|
||||
*Adds a castbar to the nameplate based on combat log estimations.*
|
||||
|
||||
- **Nameplate Class Colors**
|
||||
*Changes the nameplate health bar color to the class color.*
|
||||
|
||||
- **Nameplate Scale**
|
||||
*Makes all nameplates honor the UI-Scale setting.*
|
||||
|
||||
- **Reduced Actionbar Size**
|
||||
*Reduces the actionbar size by removing several items such as the bag panel and microbar*
|
||||
|
||||
- **Sell Junk**
|
||||
*Adds a “Sell Junk” button to every merchant window, that sells all grey items.*
|
||||
|
||||
- **Social Colors**
|
||||
*Show class colors in Who, Guild, Friends and Chat.*
|
||||
|
||||
- **Enemy Castbars**
|
||||
*Shows an enemy castbar on target unit frame.*
|
||||
|
||||
- **Debuff Timer**
|
||||
*Show debuff durations on the target unit frame.*
|
||||
|
||||
- **Tooltip Details**
|
||||
*Display health, class color, guild name, guild rank and current target on unit tooltips.*
|
||||
|
||||
- **Unit Frame Big Health**
|
||||
*Increases the healthbar of the player and target unitframe.*
|
||||
|
||||
- **Unit Frame Class Colors**
|
||||
*Adds class colors to the player, target and party unit frames.*
|
||||
|
||||
- **Unit Frame Class Portraits**
|
||||
*Replace unitframe portraits with class icons.*
|
||||
|
||||
- **Vendor Values**
|
||||
*Shows the vendor sell values on all item tooltips.*
|
||||
|
||||
- **WorldMap Class Colors**
|
||||
*Show class colored circles on world and battlefield map.*
|
||||
|
||||
- **WorldMap Coordinates**
|
||||
*Adds coordinates to the bottom of the World Map.*
|
||||
|
||||
- **WorldMap Window**
|
||||
*Turns the world map into a movable window. The map can be scaled with "Ctrl" + Mousewheel.*
|
||||
|
||||
## Screenshots
|
||||

|
||||
*All options enabled, except for squared minimap.*
|
||||
|
||||

|
||||
*Target Frame Castbars*
|
||||
|
||||

|
||||
*Big Healthbar, Class Portraits, Darkened UI*
|
||||
|
||||

|
||||
*Debuff Timers & Mob Health*
|
||||
@@ -0,0 +1,77 @@
|
||||
## Interface: 20400
|
||||
## Title: |cffffcc00Shagu|cffffffffTweaks |cffff5555[BETA]
|
||||
## Author: Shagu
|
||||
## Notes: A collection of tweaks and enhancements to the Default UI
|
||||
## Notes-ruRU: Коллекция настроек и улучшений для стандартного пользовательского интерфейса.
|
||||
## Version: GIT
|
||||
## SavedVariablesPerCharacter: ShaguTweaks_config, ShaguTweaks_cache
|
||||
|
||||
# locales
|
||||
locales\locales_deDE.lua
|
||||
locales\locales_enUS.lua
|
||||
locales\locales_esES.lua
|
||||
locales\locales_frFR.lua
|
||||
locales\locales_koKR.lua
|
||||
locales\locales_ruRU.lua
|
||||
locales\locales_zhCN.lua
|
||||
|
||||
# translations
|
||||
locales\translations_deDE.lua
|
||||
locales\translations_enUS.lua
|
||||
locales\translations_esES.lua
|
||||
locales\translations_frFR.lua
|
||||
locales\translations_koKR.lua
|
||||
locales\translations_ruRU.lua
|
||||
locales\translations_zhCN.lua
|
||||
locales\translations_zhTW.lua
|
||||
|
||||
# basic
|
||||
main.lua
|
||||
helpers.lua
|
||||
config.lua
|
||||
|
||||
# libraries
|
||||
libs\libtipscan.lua
|
||||
libs\libspell.lua
|
||||
libs\libcast.lua
|
||||
libs\libdebuff.lua
|
||||
libs\libunitscan.lua
|
||||
libs\libhealth.lua
|
||||
libs\libnameplate.lua
|
||||
|
||||
# custom
|
||||
mods\custom.lua
|
||||
|
||||
# modules
|
||||
mods\dark-ui-elements.lua
|
||||
mods\equip-compare.lua
|
||||
mods\minimap-clock.lua
|
||||
mods\minimap-square.lua
|
||||
mods\minimap-tweaks.lua
|
||||
mods\nameplate-scale.lua
|
||||
mods\sell-junk.lua
|
||||
mods\unitframes-classcolor.lua
|
||||
mods\vendor-values.lua
|
||||
mods\worldmap-coordinates.lua
|
||||
mods\worldmap-window.lua
|
||||
mods\blue-shaman.lua
|
||||
mods\nameplate-classcolor.lua
|
||||
mods\move-unitframes.lua
|
||||
mods\target-castbar.lua
|
||||
mods\target-debufftimer.lua
|
||||
mods\social-colors.lua
|
||||
mods\item-colors.lua
|
||||
mods\chat-links.lua
|
||||
mods\health-numbers.lua
|
||||
mods\health-color.lua
|
||||
mods\auto-dismount.lua
|
||||
mods\auto-stance.lua
|
||||
mods\tooltip-details.lua
|
||||
mods\hide-errors.lua
|
||||
mods\chat-tweaks.lua
|
||||
mods\hide-gryphons.lua
|
||||
mods\worldmap-colors.lua
|
||||
mods\unitframes-bighealth.lua
|
||||
mods\unitframes-classportrait.lua
|
||||
mods\cooldown-numbers.lua
|
||||
mods\reduced-actionbar.lua
|
||||
@@ -0,0 +1,90 @@
|
||||
## Interface: 11200
|
||||
## Title: |cffffcc00Shagu|cffffffffTweaks
|
||||
## Author: Shagu
|
||||
## Notes: A collection of tweaks and enhancements to the Default UI
|
||||
## Notes-ruRU: Коллекция настроек и улучшений для стандартного пользовательского интерфейса.
|
||||
## Version: GIT
|
||||
## SavedVariablesPerCharacter: ShaguTweaks_config, ShaguTweaks_cache
|
||||
|
||||
# locales
|
||||
locales\locales_deDE.lua
|
||||
locales\locales_enUS.lua
|
||||
locales\locales_esES.lua
|
||||
locales\locales_frFR.lua
|
||||
locales\locales_koKR.lua
|
||||
locales\locales_ruRU.lua
|
||||
locales\locales_zhCN.lua
|
||||
|
||||
# translations
|
||||
locales\translations_deDE.lua
|
||||
locales\translations_enUS.lua
|
||||
locales\translations_esES.lua
|
||||
locales\translations_frFR.lua
|
||||
locales\translations_koKR.lua
|
||||
locales\translations_ruRU.lua
|
||||
locales\translations_zhCN.lua
|
||||
locales\translations_zhTW.lua
|
||||
|
||||
# basic
|
||||
main.lua
|
||||
helpers.lua
|
||||
config.lua
|
||||
|
||||
# libraries
|
||||
libs\libtipscan.lua
|
||||
libs\libspell.lua
|
||||
libs\libcast.lua
|
||||
libs\libdebuff.lua
|
||||
libs\libunitscan.lua
|
||||
libs\libhealth.lua
|
||||
libs\libnameplate.lua
|
||||
libs\libpredict.lua
|
||||
|
||||
# custom
|
||||
mods\custom.lua
|
||||
|
||||
# modules
|
||||
mods\dark-ui-elements.lua
|
||||
mods\equip-compare.lua
|
||||
mods\minimap-clock.lua
|
||||
mods\minimap-square.lua
|
||||
mods\minimap-tweaks.lua
|
||||
mods\minimap-clean.lua
|
||||
mods\minimap-zoom.lua
|
||||
mods\free-slots.lua
|
||||
mods\xpbar-text.lua
|
||||
mods\nameplate-scale.lua
|
||||
mods\sell-junk.lua
|
||||
mods\unitframes-classcolor.lua
|
||||
mods\vendor-values.lua
|
||||
mods\worldmap-coordinates.lua
|
||||
mods\worldmap-window.lua
|
||||
mods\blue-shaman.lua
|
||||
mods\nameplate-classcolor.lua
|
||||
mods\nameplate-castbar.lua
|
||||
mods\move-unitframes.lua
|
||||
mods\target-castbar.lua
|
||||
mods\target-debufftimer.lua
|
||||
mods\social-colors.lua
|
||||
mods\item-colors.lua
|
||||
mods\chat-links.lua
|
||||
mods\health-numbers.lua
|
||||
mods\health-color.lua
|
||||
mods\auto-dismount.lua
|
||||
mods\auto-stance.lua
|
||||
mods\tooltip-details.lua
|
||||
mods\hide-errors.lua
|
||||
mods\chat-tweaks.lua
|
||||
mods\chat-levels.lua
|
||||
mods\hide-gryphons.lua
|
||||
mods\worldmap-colors.lua
|
||||
mods\unitframes-bighealth.lua
|
||||
mods\unitframes-classportrait.lua
|
||||
mods\unitframes-energy-tick.lua
|
||||
mods\cooldown-numbers.lua
|
||||
mods\newmap.lua
|
||||
mods\turtle-wow.lua
|
||||
mods\superwow.lua
|
||||
mods\reduced-actionbar.lua
|
||||
mods\no-toggle.lua
|
||||
mods\loot-cursor.lua
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local mod = math.mod or mod
|
||||
|
||||
local current_config = {}
|
||||
local max_width = 500
|
||||
local max_height = 680
|
||||
|
||||
local settings = CreateFrame("Frame", "AdvancedSettingsGUI", UIParent)
|
||||
settings:Hide()
|
||||
|
||||
table.insert(UISpecialFrames, "AdvancedSettingsGUI")
|
||||
settings:SetScript("OnHide", function()
|
||||
ShowUIPanel(GameMenuFrame)
|
||||
UpdateMicroButtons()
|
||||
end)
|
||||
|
||||
settings:SetPoint("CENTER", UIParent, "CENTER", 0, 32)
|
||||
settings:SetWidth(max_width)
|
||||
settings:SetMovable(true)
|
||||
settings:EnableMouse(true)
|
||||
settings:RegisterForDrag("LeftButton")
|
||||
settings:SetScript("OnDragStart", function() this:StartMoving() end)
|
||||
settings:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
|
||||
settings:SetFrameStrata("DIALOG")
|
||||
|
||||
settings:SetBackdrop({
|
||||
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
|
||||
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
||||
tile = true, tileSize = 32, edgeSize = 32,
|
||||
insets = { left = 11, right = 12, top = 12, bottom = 11 }
|
||||
})
|
||||
|
||||
settings.scrollframe = CreateFrame('ScrollFrame', 'AdvancedSettingsGUIScrollframe', settings, 'UIPanelScrollFrameTemplate')
|
||||
settings.scrollframe:SetWidth(max_width - 50)
|
||||
settings.scrollframe:SetPoint('CENTER', settings, -16, 15)
|
||||
settings.scrollframe:Hide()
|
||||
|
||||
settings.container = CreateFrame("Frame", "AdvancedSettingsGUIContainer", settings)
|
||||
|
||||
settings.title = CreateFrame("Frame", "AdvancedSettingsGUITtitle", settings)
|
||||
settings.title:SetPoint("TOP", settings, "TOP", 0, 12)
|
||||
settings.title:SetWidth(256)
|
||||
settings.title:SetHeight(64)
|
||||
|
||||
settings.title.tex = settings.title:CreateTexture(nil, "MEDIUM")
|
||||
settings.title.tex:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
|
||||
settings.title.tex:SetAllPoints()
|
||||
|
||||
settings.title.text = settings.title:CreateFontString(nil, "HIGH", "GameFontNormal")
|
||||
settings.title.text:SetText(T["Advanced Options"])
|
||||
settings.title.text:SetPoint("TOP", 0, -14)
|
||||
|
||||
settings.cancel = CreateFrame("Button", "AdvancedSettingsGUICancel", settings, "GameMenuButtonTemplate")
|
||||
settings.cancel:SetWidth(90)
|
||||
settings.cancel:SetPoint("BOTTOMRIGHT", settings, "BOTTOMRIGHT", -17, 17)
|
||||
settings.cancel:SetText(CANCEL)
|
||||
settings.cancel:SetScript("OnClick", function()
|
||||
current_config = {}
|
||||
settings:Hide()
|
||||
end)
|
||||
|
||||
settings.okay = CreateFrame("Button", "AdvancedSettingsGUIOkay", settings, "GameMenuButtonTemplate")
|
||||
settings.okay:SetWidth(90)
|
||||
settings.okay:SetPoint("RIGHT", settings.cancel, "LEFT", 0, 0)
|
||||
settings.okay:SetText(OKAY)
|
||||
settings.okay:SetScript("OnClick", function()
|
||||
local reload
|
||||
|
||||
-- save temporary config to real config
|
||||
for k, v in pairs(current_config) do
|
||||
if k ~= "overwrites" then
|
||||
-- check if reload is required
|
||||
if current_config[k] ~= ShaguTweaks_config[k] then
|
||||
reload = true
|
||||
end
|
||||
|
||||
-- set new config
|
||||
ShaguTweaks_config[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
-- save slider overwrite values
|
||||
if current_config.overwrites then
|
||||
ShaguTweaks_config.overwrites = ShaguTweaks_config.overwrites or {}
|
||||
for k, v in pairs(current_config.overwrites) do
|
||||
if ShaguTweaks_config.overwrites[k] ~= v then
|
||||
reload = true
|
||||
end
|
||||
ShaguTweaks_config.overwrites[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
-- reload the UI if required
|
||||
if reload then
|
||||
Minimap:SetMaskTexture("Textures\\MinimapMask")
|
||||
ReloadUI()
|
||||
end
|
||||
|
||||
settings:Hide()
|
||||
end)
|
||||
|
||||
settings.defaults = CreateFrame("Button", "AdvancedSettingsGUICancel", settings, "GameMenuButtonTemplate")
|
||||
settings.defaults:SetWidth(90)
|
||||
settings.defaults:SetPoint("BOTTOMLEFT", settings, "BOTTOMLEFT", 17, 17)
|
||||
settings.defaults:SetText(DEFAULTS)
|
||||
settings.defaults:SetScript("OnClick", function()
|
||||
settings:defaults()
|
||||
end)
|
||||
|
||||
settings.load = function(self)
|
||||
-- never use more than 3/4 of the screen size
|
||||
max_height = math.min(UIParent:GetHeight()/UIParent:GetScale()*0.75, 680)
|
||||
|
||||
-- update window sizing according to screen
|
||||
settings:SetHeight(max_height)
|
||||
settings.scrollframe:SetHeight(max_height - 80)
|
||||
settings.container:SetHeight(max_height - 30)
|
||||
|
||||
settings.entries = settings.entries or {}
|
||||
local expansion = ShaguTweaks:GetExpansion()
|
||||
|
||||
-- sort all configs into categories
|
||||
local gui = {}
|
||||
for title, module in pairs(ShaguTweaks.mods) do
|
||||
if module.expansions[expansion] then
|
||||
local category = module.category or T["General"]
|
||||
gui[category] = gui[category] or {}
|
||||
gui[category][title] = module
|
||||
end
|
||||
end
|
||||
|
||||
local topspace = 10
|
||||
local required_height = topspace
|
||||
local entrysize = 22
|
||||
local previous = nil
|
||||
|
||||
local sortGeneralFirst = function(a, b)
|
||||
if a == T["General"] then return true end
|
||||
if b == T["General"] then return false end
|
||||
return a < b
|
||||
end
|
||||
|
||||
for category, entries in ShaguTweaks.spairs(gui, sortGeneralFirst) do
|
||||
local entry, spacing = 1, 22
|
||||
local height = 0
|
||||
|
||||
-- add category background
|
||||
settings.category = settings.category or {}
|
||||
settings.category[category] = settings.category[category] or CreateFrame("Frame", nil, settings.container)
|
||||
|
||||
if not previous then
|
||||
settings.category[category]:SetPoint("TOPLEFT", settings.container, "TOPLEFT", spacing, -spacing - topspace)
|
||||
settings.category[category]:SetPoint("TOPRIGHT", settings.container, "TOPRIGHT", -spacing, -spacing - topspace)
|
||||
else
|
||||
settings.category[category]:SetPoint("TOPLEFT", previous, "BOTTOMLEFT", 0, -spacing)
|
||||
settings.category[category]:SetPoint("TOPRIGHT", previous, "BOTTOMRIGHT", 0, -spacing)
|
||||
end
|
||||
|
||||
previous = settings.category[category]
|
||||
|
||||
-- create category title collapse button
|
||||
local collapse = function(frame, expand)
|
||||
local parent = frame or this.parent
|
||||
|
||||
if expand then
|
||||
local height = parent.collapse or parent:GetHeight()
|
||||
parent.collapse = height
|
||||
end
|
||||
|
||||
if not parent.collapse then
|
||||
local height = parent:GetHeight()
|
||||
parent.collapse = height
|
||||
parent:SetHeight(1)
|
||||
|
||||
for button in pairs(parent.buttons) do button:Hide() end
|
||||
parent.button:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
|
||||
parent.button:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down")
|
||||
parent.button:SetDisabledTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Disabled")
|
||||
parent.button:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight")
|
||||
parent:SetAlpha(0)
|
||||
else
|
||||
local height = parent.collapse
|
||||
parent.collapse = nil
|
||||
parent:SetHeight(height)
|
||||
|
||||
for button in pairs(parent.buttons) do button:Show() end
|
||||
parent.button:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up")
|
||||
parent.button:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down")
|
||||
parent.button:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled")
|
||||
parent.button:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight")
|
||||
parent:SetAlpha(1)
|
||||
end
|
||||
end
|
||||
|
||||
settings.category[category].button = settings.category[category].button or CreateFrame("Button", nil, settings.container)
|
||||
settings.category[category].button:SetPoint("TOPLEFT", settings.category[category], "TOPLEFT", 0, entrysize-4)
|
||||
settings.category[category].button:SetWidth(22)
|
||||
settings.category[category].button:SetHeight(22)
|
||||
settings.category[category].button.parent = settings.category[category]
|
||||
settings.category[category].button:SetScript("OnClick", collapse)
|
||||
|
||||
settings.category[category].title = settings.category[category].title or CreateFrame("Button", nil, settings.container)
|
||||
settings.category[category].title:SetPoint("TOPLEFT", settings.category[category], "TOPLEFT", 22, entrysize-4)
|
||||
settings.category[category].title:SetWidth(200)
|
||||
settings.category[category].title:SetHeight(entrysize)
|
||||
settings.category[category].title.parent = settings.category[category]
|
||||
settings.category[category].title:SetScript("OnClick", collapse)
|
||||
|
||||
settings.category[category]:SetBackdrop({
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
})
|
||||
|
||||
if ShaguTweaks.DarkMode then
|
||||
settings.category[category]:SetBackdropColor(.1,.1,.1,1)
|
||||
settings.category[category]:SetBackdropBorderColor(.2,.2,.2,1)
|
||||
else
|
||||
settings.category[category]:SetBackdropColor(.2,.2,.2,1)
|
||||
settings.category[category]:SetBackdropBorderColor(.5,.5,.5,1)
|
||||
end
|
||||
|
||||
-- add category title
|
||||
settings.category[category].text = settings.category[category].text or settings.category[category].title:CreateFontString(nil, "HIGH", "GameFontHighlightSmall")
|
||||
settings.category[category].text:SetJustifyH("LEFT")
|
||||
settings.category[category].text:SetAllPoints()
|
||||
settings.category[category].text:SetText(category)
|
||||
|
||||
for title, module in ShaguTweaks.spairs(entries) do
|
||||
if not settings.entries[title] then
|
||||
settings.entries[title] = CreateFrame("CheckButton", "AdvancedSettingsGUI" .. title, settings.category[category], "OptionsCheckButtonTemplate")
|
||||
settings.entries[title]:SetHeight(24)
|
||||
settings.entries[title]:SetWidth(24)
|
||||
end
|
||||
|
||||
local button = _G["AdvancedSettingsGUI" .. title]
|
||||
local text = _G["AdvancedSettingsGUI" .. title .. "Text"]
|
||||
|
||||
settings.category[category].buttons = settings.category[category].buttons or {}
|
||||
settings.category[category].buttons[button] = true
|
||||
|
||||
button.title = title
|
||||
button:SetChecked(current_config[title] == 1 and true or nil)
|
||||
button:SetPoint("TOPLEFT", settings.category[category], "TOPLEFT", mod(entry, 2) == 1 and 17 or 17+200, math.ceil(entry/2-1)*-entrysize-spacing/2)
|
||||
|
||||
-- add another row to height
|
||||
if mod(entry, 2) == 1 then height = height + entrysize end
|
||||
|
||||
local title = module.title
|
||||
local description = module.description
|
||||
button:SetScript("OnEnter", function()
|
||||
GameTooltip:SetOwner(this, "ANCHOR_TOPLEFT");
|
||||
GameTooltip:SetText(title, nil, nil, nil, nil, 1)
|
||||
GameTooltip:AddLine(description, 1, 1, 1, 1, 1)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
|
||||
button:SetScript("OnHide", function()
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
|
||||
button:SetScript("OnClick", function()
|
||||
if this:GetChecked() then
|
||||
current_config[this.title] = 1
|
||||
else
|
||||
current_config[this.title] = 0
|
||||
end
|
||||
end)
|
||||
text:SetText(title)
|
||||
entry = entry + 1
|
||||
end
|
||||
|
||||
-- render sliders declared by modules in this category
|
||||
local sliderHeight = 36
|
||||
for title, smod in ShaguTweaks.spairs(entries) do
|
||||
if smod.sliders then
|
||||
for sidx, sdef in ipairs(smod.sliders) do
|
||||
local sliderKey = "slider:" .. sdef.key
|
||||
local safeName = "AdvancedSettingsGUISlider" .. string.gsub(sdef.key, "[^%w]", "_")
|
||||
|
||||
if not settings.entries[sliderKey] then
|
||||
settings.entries[sliderKey] = CreateFrame("Slider", safeName, settings.category[category], "OptionsSliderTemplate")
|
||||
end
|
||||
|
||||
local slider = settings.entries[sliderKey]
|
||||
settings.category[category].buttons[slider] = true
|
||||
|
||||
local yOffset = -(height + spacing / 2 + 16 + (sidx - 1) * sliderHeight)
|
||||
slider:SetWidth(max_width - 90)
|
||||
slider:SetPoint("TOPLEFT", settings.category[category], "TOPLEFT", 17, yOffset)
|
||||
slider:SetMinMaxValues(sdef.min, sdef.max)
|
||||
slider:SetValueStep(sdef.step or 1)
|
||||
|
||||
local curVal = (current_config.overwrites and current_config.overwrites[sdef.key])
|
||||
or (ShaguTweaks_config.overwrites and ShaguTweaks_config.overwrites[sdef.key])
|
||||
or sdef.default or sdef.min
|
||||
|
||||
local labelText = sdef.label or sdef.key
|
||||
local titleLabel = _G[safeName .. "Text"]
|
||||
local lowLabel = _G[safeName .. "Low"]
|
||||
local highLabel = _G[safeName .. "High"]
|
||||
if lowLabel then lowLabel:SetText(sdef.min) end
|
||||
if highLabel then highLabel:SetText(sdef.max) end
|
||||
if titleLabel then titleLabel:SetText(labelText .. ": " .. curVal) end
|
||||
|
||||
local key = sdef.key
|
||||
slider:SetScript("OnValueChanged", function()
|
||||
local val = math.floor(this:GetValue() + 0.5)
|
||||
if titleLabel then titleLabel:SetText(labelText .. ": " .. val) end
|
||||
current_config.overwrites = current_config.overwrites or {}
|
||||
current_config.overwrites[key] = val
|
||||
end)
|
||||
slider:SetValue(curVal)
|
||||
|
||||
height = height + sliderHeight
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
collapse(settings.category[category], true)
|
||||
|
||||
height = height + spacing
|
||||
settings.category[category]:SetHeight(height)
|
||||
|
||||
required_height = required_height + height + spacing
|
||||
end
|
||||
|
||||
-- set container size to required height
|
||||
settings.container:SetHeight(required_height)
|
||||
|
||||
if required_height < max_height then
|
||||
-- reduce base frame if possible
|
||||
settings:SetHeight(required_height + 60)
|
||||
settings.container:SetParent(settings)
|
||||
settings.container:ClearAllPoints()
|
||||
settings.container:SetPoint("CENTER", settings, 0, 20)
|
||||
settings.container:SetWidth(max_width - 20)
|
||||
|
||||
settings.scrollframe:Hide()
|
||||
elseif required_height > max_height then
|
||||
-- set up scrollframe when needed
|
||||
settings.container:SetParent(settings.scrollframe)
|
||||
settings.container:SetHeight(settings.scrollframe:GetHeight())
|
||||
settings.container:SetWidth(settings.scrollframe:GetWidth() + 20)
|
||||
|
||||
settings.scrollframe:SetScrollChild(settings.container)
|
||||
settings.scrollframe:Show()
|
||||
end
|
||||
end
|
||||
|
||||
settings.defaults = function()
|
||||
-- read default settings from modules
|
||||
for title, mod in pairs(ShaguTweaks.mods) do
|
||||
current_config[title] = mod.enabled and 1 or 0
|
||||
end
|
||||
|
||||
-- reset slider overwrite values to module defaults
|
||||
current_config.overwrites = {}
|
||||
for title, mod in pairs(ShaguTweaks.mods) do
|
||||
if mod.config then
|
||||
for k, v in pairs(mod.config) do
|
||||
current_config.overwrites[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
settings:load()
|
||||
end
|
||||
|
||||
settings:SetScript("OnShow", function()
|
||||
-- read current config to temporary config
|
||||
for k, v in pairs(ShaguTweaks_config) do
|
||||
current_config[k] = v
|
||||
end
|
||||
-- copy overwrites into a separate table so Cancel discards slider changes
|
||||
current_config.overwrites = {}
|
||||
for k, v in pairs(ShaguTweaks_config.overwrites or {}) do
|
||||
current_config.overwrites[k] = v
|
||||
end
|
||||
|
||||
settings:load()
|
||||
end)
|
||||
|
||||
-- Add "Advanced Settings" Button to the Game Menu
|
||||
GameMenuFrame:SetWidth(GameMenuFrame:GetWidth() - 10)
|
||||
GameMenuFrame:SetHeight(GameMenuFrame:GetHeight() + 10)
|
||||
local advanced = CreateFrame("Button", "GameMenuButtonAdvancedOptions", GameMenuFrame, "GameMenuButtonTemplate")
|
||||
advanced:SetPoint("TOP", GameMenuButtonUIOptions, "BOTTOM", 0, -1)
|
||||
advanced:SetText(T["Advanced Options"] .. "|cffffff00*")
|
||||
advanced:SetScript("OnClick", function()
|
||||
HideUIPanel(GameMenuFrame)
|
||||
settings:Show()
|
||||
end)
|
||||
|
||||
GameMenuButtonKeybindings:ClearAllPoints()
|
||||
GameMenuButtonKeybindings:SetPoint("TOP", advanced, "BOTTOM", 0, -1)
|
||||
+384
@@ -0,0 +1,384 @@
|
||||
local gfind = string.gmatch or string.gfind
|
||||
|
||||
ShaguTweaks.GetExpansion = function()
|
||||
local _, _, _, client = GetBuildInfo()
|
||||
client = client or 11200
|
||||
|
||||
-- detect client expansion
|
||||
if client >= 20000 and client <= 20400 then
|
||||
return "tbc"
|
||||
elseif client >= 30000 and client <= 30300 then
|
||||
return "wotlk"
|
||||
else
|
||||
return "vanilla"
|
||||
end
|
||||
end
|
||||
|
||||
ShaguTweaks.GetGlobalEnv = function()
|
||||
if ShaguTweaks.GetExpansion() == 'vanilla' then
|
||||
return getfenv(0)
|
||||
else
|
||||
return _G or getfenv(0)
|
||||
end
|
||||
end
|
||||
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
|
||||
local gradientcolors = {}
|
||||
ShaguTweaks.GetColorGradient = function(perc)
|
||||
perc = perc > 1 and 1 or perc
|
||||
perc = perc < 0 and 0 or perc
|
||||
perc = floor(perc*100)/100
|
||||
|
||||
local index = perc
|
||||
if not gradientcolors[index] then
|
||||
local r1, g1, b1, r2, g2, b2
|
||||
|
||||
if perc <= 0.5 then
|
||||
perc = perc * 2
|
||||
r1, g1, b1 = 1, 0, 0
|
||||
r2, g2, b2 = 1, 1, 0
|
||||
else
|
||||
perc = perc * 2 - 1
|
||||
r1, g1, b1 = 1, 1, 0
|
||||
r2, g2, b2 = 0, 1, 0
|
||||
end
|
||||
|
||||
local r = ShaguTweaks.round(r1 + (r2 - r1) * perc, 4)
|
||||
local g = ShaguTweaks.round(g1 + (g2 - g1) * perc, 4)
|
||||
local b = ShaguTweaks.round(b1 + (b2 - b1) * perc, 4)
|
||||
local h = ShaguTweaks.rgbhex(r,g,b)
|
||||
|
||||
gradientcolors[index] = {}
|
||||
gradientcolors[index].r = r
|
||||
gradientcolors[index].g = g
|
||||
gradientcolors[index].b = b
|
||||
gradientcolors[index].h = h
|
||||
end
|
||||
|
||||
return gradientcolors[index].r,
|
||||
gradientcolors[index].g,
|
||||
gradientcolors[index].b,
|
||||
gradientcolors[index].h
|
||||
end
|
||||
|
||||
ShaguTweaks.HookScript = function(f, script, func)
|
||||
local prev = f:GetScript(script)
|
||||
f:SetScript(script, function(a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
if prev then prev(a1,a2,a3,a4,a5,a6,a7,a8,a9) end
|
||||
func(a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
end)
|
||||
end
|
||||
|
||||
ShaguTweaks.HookAddonOrVariable = function(addon, func)
|
||||
local lurker = CreateFrame("Frame", nil)
|
||||
lurker.func = func
|
||||
lurker:RegisterEvent("ADDON_LOADED")
|
||||
lurker:RegisterEvent("VARIABLES_LOADED")
|
||||
lurker:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
lurker:SetScript("OnEvent",function()
|
||||
if IsAddOnLoaded(addon) or _G[addon] then
|
||||
this:func()
|
||||
this:UnregisterAllEvents()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local hooks = {}
|
||||
ShaguTweaks.hooksecurefunc = function(tbl, name, func, prepend)
|
||||
if type(tbl) == "string" then
|
||||
prepend, func, name, tbl = func, name, tbl, _G
|
||||
end
|
||||
|
||||
if not tbl or not tbl[name] then return end
|
||||
|
||||
hooks[tostring(func)] = {}
|
||||
hooks[tostring(func)]["old"] = tbl[name]
|
||||
hooks[tostring(func)]["new"] = func
|
||||
|
||||
if prepend then
|
||||
hooks[tostring(func)]["function"] = function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
|
||||
hooks[tostring(func)]["new"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
|
||||
return hooks[tostring(func)]["old"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
|
||||
end
|
||||
else
|
||||
hooks[tostring(func)]["function"] = function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
|
||||
local r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16 = hooks[tostring(func)]["old"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
|
||||
hooks[tostring(func)]["new"](a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16)
|
||||
return r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16
|
||||
end
|
||||
end
|
||||
|
||||
tbl[name] = hooks[tostring(func)]["function"]
|
||||
end
|
||||
|
||||
local sanitize_cache = {}
|
||||
ShaguTweaks.SanitizePattern = function(pattern)
|
||||
if not sanitize_cache[pattern] then
|
||||
local ret = pattern
|
||||
-- escape magic characters
|
||||
ret = gsub(ret, "([%+%-%*%(%)%?%[%]%^])", "%%%1")
|
||||
-- remove capture indexes
|
||||
ret = gsub(ret, "%d%$","")
|
||||
-- catch all characters
|
||||
ret = gsub(ret, "(%%%a)","%(%1+%)")
|
||||
-- convert all %s to .+
|
||||
ret = gsub(ret, "%%s%+",".+")
|
||||
-- set priority to numbers over strings
|
||||
ret = gsub(ret, "%(.%+%)%(%%d%+%)","%(.-%)%(%%d%+%)")
|
||||
-- cache it
|
||||
sanitize_cache[pattern] = ret
|
||||
end
|
||||
|
||||
return sanitize_cache[pattern]
|
||||
end
|
||||
|
||||
local capture_cache = {}
|
||||
ShaguTweaks.GetCaptures = function(pat)
|
||||
local r = capture_cache
|
||||
|
||||
if not r[pat] then
|
||||
for a, b, c, d, e in gfind(gsub(pat, "%((.+)%)", "%1"), gsub(pat, "%d%$", "%%(.-)$")) do
|
||||
r[pat] = { a, b, c, d, e}
|
||||
end
|
||||
|
||||
r[pat] = r[pat] or {}
|
||||
end
|
||||
|
||||
return r[pat][1], r[pat][2], r[pat][3], r[pat][4], r[pat][5]
|
||||
end
|
||||
|
||||
ShaguTweaks.cmatch = function(str, pat)
|
||||
-- read capture indexes
|
||||
local a,b,c,d,e = ShaguTweaks.GetCaptures(pat)
|
||||
local _, _, va, vb, vc, vd, ve = string.find(str, ShaguTweaks.SanitizePattern(pat))
|
||||
|
||||
-- put entries into the proper return values
|
||||
local ra, rb, rc, rd, re
|
||||
ra = e == "1" and ve or d == "1" and vd or c == "1" and vc or b == "1" and vb or va
|
||||
rb = e == "2" and ve or d == "2" and vd or c == "2" and vc or a == "2" and va or vb
|
||||
rc = e == "3" and ve or d == "3" and vd or a == "3" and va or b == "3" and vb or vc
|
||||
rd = e == "4" and ve or a == "4" and va or c == "4" and vc or b == "4" and vb or vd
|
||||
re = a == "5" and va or d == "5" and vd or c == "5" and vc or b == "5" and vb or ve
|
||||
|
||||
return ra, rb, rc, rd, re
|
||||
end
|
||||
|
||||
local timer
|
||||
ShaguTweaks.QueueFunction = function(a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
if not timer then
|
||||
timer = CreateFrame("Frame")
|
||||
timer.queue = {}
|
||||
timer.interval = TOOLTIP_UPDATE_TIME
|
||||
timer.DeQueue = function()
|
||||
local item = table.remove(timer.queue,1)
|
||||
if item then
|
||||
item[1](item[2],item[3],item[4],item[5],item[6],item[7],item[8],item[9])
|
||||
end
|
||||
if table.getn(timer.queue) == 0 then
|
||||
timer:Hide() -- no need to run the OnUpdate when the queue is empty
|
||||
end
|
||||
end
|
||||
timer:SetScript("OnUpdate",function()
|
||||
this.sinceLast = (this.sinceLast or 0) + arg1
|
||||
while (this.sinceLast > this.interval) do
|
||||
this.DeQueue()
|
||||
this.sinceLast = this.sinceLast - this.interval
|
||||
end
|
||||
end)
|
||||
end
|
||||
table.insert(timer.queue,{a1,a2,a3,a4,a5,a6,a7,a8,a9})
|
||||
timer:Show() -- start the OnUpdate
|
||||
end
|
||||
|
||||
ShaguTweaks.strsplit = function(delimiter, subject)
|
||||
if not subject then return nil end
|
||||
local delimiter, fields = delimiter or ":", {}
|
||||
local pattern = string.format("([^%s]+)", delimiter)
|
||||
string.gsub(subject, pattern, function(c) fields[table.getn(fields)+1] = c end)
|
||||
return unpack(fields)
|
||||
end
|
||||
|
||||
ShaguTweaks.rgbhex = function(r, g, b, a)
|
||||
if type(r) == "table" then
|
||||
if r.r then
|
||||
_r, _g, _b, _a = r.r, r.g, r.b, (r.a or 1)
|
||||
elseif table.getn(r) >= 3 then
|
||||
_r, _g, _b, _a = r[1], r[2], r[3], (r[4] or 1)
|
||||
end
|
||||
elseif tonumber(r) then
|
||||
_r, _g, _b, _a = r, g, b, (a or 1)
|
||||
end
|
||||
|
||||
if _r and _g and _b and _a then
|
||||
-- limit values to 0-1
|
||||
_r = _r + 0 > 1 and 1 or _r + 0
|
||||
_g = _g + 0 > 1 and 1 or _g + 0
|
||||
_b = _b + 0 > 1 and 1 or _b + 0
|
||||
_a = _a + 0 > 1 and 1 or _a + 0
|
||||
return string.format("|c%02x%02x%02x%02x", _a*255, _r*255, _g*255, _b*255)
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
local border = {
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 16,
|
||||
insets = { left = 0, right = 0, top = 0, bottom = 0 }
|
||||
}
|
||||
ShaguTweaks.AddBorder = function(frame, inset, color)
|
||||
if not frame then return end
|
||||
if frame.ShaguTweaks_border then return frame.ShaguTweaks_border end
|
||||
|
||||
local top, right, bottom, left
|
||||
|
||||
if type(inset) == "table" then
|
||||
top, right, bottom, left = unpack((inset))
|
||||
left, bottom = -left, -bottom
|
||||
end
|
||||
|
||||
if not frame.ShaguTweaks_border then
|
||||
frame.ShaguTweaks_border = CreateFrame("Frame", nil, frame)
|
||||
frame.ShaguTweaks_border:SetPoint("TOPLEFT", frame, "TOPLEFT", (left or -inset), (top or inset))
|
||||
frame.ShaguTweaks_border:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", (right or inset), (bottom or -inset))
|
||||
frame.ShaguTweaks_border:SetBackdrop(border)
|
||||
|
||||
if color then
|
||||
frame.ShaguTweaks_border:SetBackdropBorderColor(color.r, color.g, color.b, 1)
|
||||
end
|
||||
end
|
||||
|
||||
return frame.ShaguTweaks_border
|
||||
end
|
||||
|
||||
ShaguTweaks.round = function(input, places)
|
||||
if not places then places = 0 end
|
||||
if type(input) == "number" and type(places) == "number" then
|
||||
local pow = 1
|
||||
for i = 1, places do pow = pow * 10 end
|
||||
return floor(input * pow + 0.5) / pow
|
||||
end
|
||||
end
|
||||
|
||||
ShaguTweaks.Abbreviate = function(number, eachk)
|
||||
local sign = number < 0 and -1 or 1
|
||||
number = math.abs(number)
|
||||
|
||||
if number > 1000000 then
|
||||
return ShaguTweaks.round(number/1000000*sign,2) .. "m"
|
||||
elseif not eachk and number > 10000 then
|
||||
return ShaguTweaks.round(number/1000*sign,2) .. "k"
|
||||
elseif eachk and number > 1000 then
|
||||
return ShaguTweaks.round(number/1000*sign,2) .. "k"
|
||||
end
|
||||
|
||||
return number
|
||||
end
|
||||
|
||||
ShaguTweaks.TimeConvert = function(remaining)
|
||||
local color = "|cffffffff"
|
||||
|
||||
if remaining < 5 then
|
||||
color = "|cffff5555"
|
||||
elseif remaining < 10 then
|
||||
color = "|cffffff55"
|
||||
end
|
||||
|
||||
if remaining < 60 then
|
||||
return color..ceil(remaining)
|
||||
elseif remaining < 3600 then
|
||||
return color..ceil(remaining/60).."m"
|
||||
elseif remaining < 86400 then
|
||||
return color..ceil(remaining/3600).."h"
|
||||
else
|
||||
return color..ceil(remaining/86400).."d"
|
||||
end
|
||||
end
|
||||
|
||||
-- http://lua-users.org/wiki/SortedIteration
|
||||
local function __genOrderedIndex(t, sortFunc)
|
||||
local orderedIndex = {}
|
||||
for key in pairs(t) do
|
||||
table.insert( orderedIndex, key )
|
||||
end
|
||||
table.sort(orderedIndex, sortFunc)
|
||||
return orderedIndex
|
||||
end
|
||||
|
||||
local function orderedNext(t, state)
|
||||
local key = nil
|
||||
if state == nil then
|
||||
key = t.__orderedIndex[1]
|
||||
else
|
||||
for i = 1,table.getn(t.__orderedIndex) do
|
||||
if t.__orderedIndex[i] == state then
|
||||
key = t.__orderedIndex[i+1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if key then
|
||||
return key, t[key]
|
||||
end
|
||||
|
||||
t.__orderedIndex = nil
|
||||
return
|
||||
end
|
||||
|
||||
ShaguTweaks.spairs = function(t, sortFunc)
|
||||
t.__orderedIndex = __genOrderedIndex(t, sortFunc)
|
||||
return orderedNext, t, nil
|
||||
end
|
||||
|
||||
ShaguTweaks.GetItemIDFromLink = function(itemLink)
|
||||
if not itemLink then
|
||||
return
|
||||
end
|
||||
|
||||
local foundID, _ , itemID = string.find(itemLink, "item:(%d+)")
|
||||
if not foundID then
|
||||
return
|
||||
end
|
||||
|
||||
return tonumber(itemID)
|
||||
end
|
||||
|
||||
|
||||
ShaguTweaks.GetItemCount = function(itemName)
|
||||
local count = 0
|
||||
for bag = 4, 0, -1 do
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
local _, itemCount = GetContainerItemInfo(bag, slot)
|
||||
if itemCount then
|
||||
local itemLink = GetContainerItemLink(bag,slot)
|
||||
local itemID = ShaguTweaks.GetItemIDFromLink(itemLink)
|
||||
local queryName = GetItemInfo(itemID)
|
||||
if queryName and queryName ~= "" then
|
||||
if queryName == itemName then
|
||||
count = count + itemCount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
local itemLinkByNameCache = {}
|
||||
ShaguTweaks.GetItemLinkByName = function(name)
|
||||
if itemLinkByNameCache[name] then
|
||||
return itemLinkByNameCache[name]
|
||||
end
|
||||
|
||||
for itemID = 1, 25818 do
|
||||
local itemName, itemLink, itemQuality = GetItemInfo(itemID)
|
||||
if (itemName and itemName == name) then
|
||||
local _, _, _, hex = GetItemQualityColor(tonumber(itemQuality))
|
||||
local hyperLink = hex.. "|H".. itemLink .."|h["..itemName.."]|h" .. FONT_COLOR_CODE_CLOSE
|
||||
itemLinkByNameCache[name] = hyperLink
|
||||
return hyperLink
|
||||
end
|
||||
end
|
||||
end
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,409 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local L = ShaguTweaks.L
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local libtipscan = ShaguTweaks.libtipscan
|
||||
local libspell = ShaguTweaks.libspell
|
||||
local hooksecurefunc = ShaguTweaks.hooksecurefunc
|
||||
local cmatch = ShaguTweaks.cmatch
|
||||
|
||||
-- return instantly if we're not on a vanilla client
|
||||
if GetExpansion() ~= "vanilla" then return end
|
||||
|
||||
local valid_units = {}
|
||||
valid_units["pet"] = true
|
||||
valid_units["player"] = true
|
||||
valid_units["target"] = true
|
||||
valid_units["mouseover"] = true
|
||||
|
||||
valid_units["pettarget"] = true
|
||||
valid_units["playertarget"] = true
|
||||
valid_units["targettarget"] = true
|
||||
valid_units["mouseovertarget"] = true
|
||||
valid_units["targettargettarget"] = true
|
||||
|
||||
for i=1,4 do valid_units["party" .. i] = true end
|
||||
for i=1,4 do valid_units["partypet" .. i] = true end
|
||||
for i=1,40 do valid_units["raid" .. i] = true end
|
||||
for i=1,40 do valid_units["raidpet" .. i] = true end
|
||||
|
||||
for i=1,4 do valid_units["party" .. i .. "target"] = true end
|
||||
for i=1,4 do valid_units["partypet" .. i .. "target"] = true end
|
||||
for i=1,40 do valid_units["raid" .. i .. "target"] = true end
|
||||
for i=1,40 do valid_units["raidpet" .. i .. "target"] = true end
|
||||
|
||||
local lastcasttex, lastrank, _
|
||||
local scanner = libtipscan:GetScanner("libcast")
|
||||
|
||||
local libcast = CreateFrame("Frame", "ShaguTweaksEnemyCast")
|
||||
local player = UnitName("player")
|
||||
|
||||
ShaguTweaks.UnitChannelInfo = _G.UnitChannelInfo or function(unit)
|
||||
-- convert to name if unitstring was given
|
||||
unit = valid_units[unit] and UnitName(unit) or unit
|
||||
|
||||
local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill
|
||||
local db = libcast.db[unit]
|
||||
|
||||
-- clean legacy values
|
||||
if db and db.cast and db.start + db.casttime / 1000 > GetTime() then
|
||||
if not db.channel then return end
|
||||
cast = db.cast
|
||||
nameSubtext = db.rank
|
||||
text = ""
|
||||
texture = db.icon
|
||||
startTime = db.start * 1000
|
||||
endTime = startTime + db.casttime
|
||||
isTradeSkill = nil
|
||||
elseif db then
|
||||
-- remove cast action to the database
|
||||
db.cast = nil
|
||||
db.rank = nil
|
||||
db.start = nil
|
||||
db.casttime = nil
|
||||
db.icon = nil
|
||||
db.channel = nil
|
||||
end
|
||||
|
||||
return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill
|
||||
end
|
||||
|
||||
ShaguTweaks.UnitCastingInfo = _G.UnitCastingInfo or function(unit)
|
||||
-- convert to name if unitstring was given
|
||||
unit = valid_units[unit] and UnitName(unit) or unit
|
||||
|
||||
local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill
|
||||
local db = libcast.db[unit]
|
||||
|
||||
-- clean legacy values
|
||||
if db and db.cast and db.start + db.casttime / 1000 > GetTime() then
|
||||
if db.channel then return end
|
||||
cast = db.cast
|
||||
nameSubtext = db.rank or ""
|
||||
text = ""
|
||||
texture = db.icon
|
||||
startTime = db.start * 1000
|
||||
endTime = startTime + db.casttime
|
||||
isTradeSkill = nil
|
||||
elseif db then
|
||||
-- remove cast action to the database
|
||||
db.cast = nil
|
||||
db.rank = nil
|
||||
db.start = nil
|
||||
db.casttime = nil
|
||||
db.icon = nil
|
||||
db.channel = nil
|
||||
end
|
||||
|
||||
return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill
|
||||
end
|
||||
|
||||
function libcast:AddAction(mob, spell, channel)
|
||||
if not mob or not spell then return nil end
|
||||
|
||||
if L["spells"][spell] ~= nil then
|
||||
local casttime = L["spells"][spell].t
|
||||
local icon = L["spells"][spell].icon and string.format("%s%s", "Interface\\Icons\\", L["spells"][spell].icon) or nil
|
||||
|
||||
-- add cast action to the database
|
||||
if not self.db[mob] then self.db[mob] = {} end
|
||||
self.db[mob].cast = spell
|
||||
self.db[mob].rank = nil
|
||||
self.db[mob].start = GetTime()
|
||||
self.db[mob].casttime = casttime
|
||||
self.db[mob].icon = icon
|
||||
self.db[mob].channel = channel
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function libcast:RemoveAction(mob, spell)
|
||||
if self.db[mob] and ( L["interrupts"][spell] ~= nil or spell == "INTERRUPT" ) then
|
||||
|
||||
-- remove cast action to the database
|
||||
self.db[mob].cast = nil
|
||||
self.db[mob].rank = nil
|
||||
self.db[mob].start = nil
|
||||
self.db[mob].casttime = nil
|
||||
self.db[mob].icon = nil
|
||||
self.db[mob].channel = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- main data
|
||||
libcast.db = { [player] = {} }
|
||||
|
||||
-- environmental casts
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE")
|
||||
libcast:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF")
|
||||
|
||||
-- player spells
|
||||
libcast:RegisterEvent("SPELLCAST_START")
|
||||
libcast:RegisterEvent("SPELLCAST_STOP")
|
||||
libcast:RegisterEvent("SPELLCAST_FAILED")
|
||||
libcast:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||
libcast:RegisterEvent("SPELLCAST_DELAYED")
|
||||
libcast:RegisterEvent("SPELLCAST_CHANNEL_START")
|
||||
libcast:RegisterEvent("SPELLCAST_CHANNEL_STOP")
|
||||
libcast:RegisterEvent("SPELLCAST_CHANNEL_UPDATE")
|
||||
|
||||
libcast:SetScript("OnEvent", function()
|
||||
-- Fill database with player casts
|
||||
if event == "SPELLCAST_START" then
|
||||
local icon = L["spells"][arg1] and L["spells"][arg1].icon and string.format("%s%s", "Interface\\Icons\\", L["spells"][arg1].icon) or lastcasttex
|
||||
-- add cast action to the database
|
||||
this.db[player].cast = arg1
|
||||
this.db[player].rank = lastrank
|
||||
this.db[player].start = GetTime()
|
||||
this.db[player].casttime = arg2
|
||||
this.db[player].icon = icon
|
||||
this.db[player].channel = nil
|
||||
if not L["spells"][arg1] or not L["spells"][arg1].icon or not L["spells"][arg1].t then
|
||||
L["spells"][arg1] = L["spells"][arg1] or { }
|
||||
L["spells"][arg1].icon = L["spells"][arg1].icon or icon
|
||||
L["spells"][arg1].t = L["spells"][arg1].t or arg2
|
||||
end
|
||||
lastcasttex, lastrank = nil, nil
|
||||
elseif event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" then
|
||||
if this.db[player] and not this.db[player].channel then
|
||||
-- remove cast action to the database
|
||||
this.db[player].cast = nil
|
||||
this.db[player].rank = nil
|
||||
this.db[player].rank = nil
|
||||
this.db[player].start = nil
|
||||
this.db[player].casttime = nil
|
||||
this.db[player].icon = nil
|
||||
this.db[player].channel = nil
|
||||
else
|
||||
lastcasttex, lastrank = nil, nil
|
||||
end
|
||||
elseif event == "SPELLCAST_DELAYED" then
|
||||
if this.db[player].cast then
|
||||
this.db[player].start = this.db[player].start + arg1/1000
|
||||
end
|
||||
elseif event == "SPELLCAST_CHANNEL_START" then
|
||||
-- add cast action to the database
|
||||
this.db[player].cast = arg2
|
||||
this.db[player].rank = lastrank
|
||||
this.db[player].start = GetTime()
|
||||
this.db[player].casttime = arg1
|
||||
this.db[player].icon = L["spells"][arg2] and L["spells"][arg2].icon and string.format("%s%s", "Interface\\Icons\\", L["spells"][arg2].icon) or lastcasttex
|
||||
this.db[player].channel = true
|
||||
lastcasttex, lastrank = nil, nil
|
||||
elseif event == "SPELLCAST_CHANNEL_STOP" then
|
||||
if this.db[player] and this.db[player].channel then
|
||||
-- remove cast action to the database
|
||||
this.db[player].cast = nil
|
||||
this.db[player].rank = nil
|
||||
this.db[player].start = nil
|
||||
this.db[player].casttime = nil
|
||||
this.db[player].icon = nil
|
||||
this.db[player].channel = nil
|
||||
end
|
||||
elseif event == "SPELLCAST_CHANNEL_UPDATE" then
|
||||
if this.db[player].cast then
|
||||
this.db[player].start = -this.db[player].casttime/1000 + GetTime() + arg1/1000
|
||||
end
|
||||
-- Fill database with environmental casts
|
||||
elseif arg1 then
|
||||
local mob, spell, _
|
||||
|
||||
-- (.+) begins to cast (.+).
|
||||
mob, spell = cmatch(arg1, SPELLCASTOTHERSTART)
|
||||
if libcast:AddAction(mob, spell) then return end
|
||||
|
||||
-- (.+) begins to perform (.+).
|
||||
mob, spell = cmatch(arg1, SPELLPERFORMOTHERSTART)
|
||||
if libcast:AddAction(mob, spell) then return end
|
||||
|
||||
-- (.+) gains (.+).
|
||||
mob, spell = cmatch(arg1, AURAADDEDOTHERHELPFUL)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- (.+) is afflicted by (.+).
|
||||
mob, spell = cmatch(arg1, AURAADDEDOTHERHARMFUL)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- Your (.+) hits (.+) for (%d+).
|
||||
spell, mob = cmatch(arg1, SPELLLOGSELFOTHER)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- Your (.+) crits (.+) for (%d+).
|
||||
spell, mob = cmatch(arg1, SPELLLOGCRITSELFOTHER)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- (.+)'s (.+) %a hits (.+) for (%d+).
|
||||
_, spell, mob = cmatch(arg1, SPELLLOGOTHEROTHER)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- (.+)'s (.+) %a crits (.+) for (%d+).
|
||||
_, spell, mob = cmatch(arg1, SPELLLOGCRITOTHEROTHER)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- You interrupt (.+)'s (.+).
|
||||
mob, spell = cmatch(arg1, SPELLINTERRUPTSELFOTHER)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
|
||||
-- (.+) interrupts (.+)'s (.+).
|
||||
_, mob, spell = cmatch(arg1, SPELLINTERRUPTOTHEROTHER)
|
||||
if libcast:RemoveAction(mob, spell) then return end
|
||||
end
|
||||
end)
|
||||
|
||||
--[[ Custom Casts
|
||||
Enable Castbars for spells that don't have a castbar by default
|
||||
(e.g Multi-Shot and Aimed Shot)
|
||||
]]--
|
||||
local aimedshot = L["customcast"]["AIMEDSHOT"]
|
||||
local multishot = L["customcast"]["MULTISHOT"]
|
||||
|
||||
libcast.customcast = {}
|
||||
libcast.customcast[strlower(aimedshot)] = function(begin, duration)
|
||||
if begin then
|
||||
local duration = duration or 3000
|
||||
|
||||
for i=1,32 do
|
||||
if UnitBuff("player", i) == "Interface\\Icons\\Racial_Troll_Berserk" then
|
||||
local berserk = 0.3
|
||||
if((UnitHealth("player")/UnitHealthMax("player")) >= 0.40) then
|
||||
berserk = (1.30 - (UnitHealth("player") / UnitHealthMax("player"))) / 3
|
||||
end
|
||||
duration = duration / (1 + berserk)
|
||||
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Hunter_RunningShot" then
|
||||
duration = duration / 1.4
|
||||
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Warrior_InnerRage" then
|
||||
duration = duration / 1.3
|
||||
elseif UnitBuff("player", i) == "Interface\\Icons\\Inv_Trinket_Naxxramas04" then
|
||||
duration = duration / 1.2
|
||||
end
|
||||
end
|
||||
|
||||
local _,_, lag = GetNetStats()
|
||||
local start = GetTime() + lag/1000
|
||||
|
||||
-- add cast action to the database
|
||||
libcast.db[player].cast = aimedshot
|
||||
libcast.db[player].rank = lastrank
|
||||
libcast.db[player].start = start
|
||||
libcast.db[player].casttime = duration
|
||||
libcast.db[player].icon = "Interface\\Icons\\Inv_spear_07"
|
||||
libcast.db[player].channel = nil
|
||||
else
|
||||
-- remove cast action to the database
|
||||
libcast.db[player].cast = nil
|
||||
libcast.db[player].rank = nil
|
||||
libcast.db[player].start = nil
|
||||
libcast.db[player].casttime = nil
|
||||
libcast.db[player].icon = nil
|
||||
libcast.db[player].channel = nil
|
||||
end
|
||||
end
|
||||
|
||||
libcast.customcast[strlower(multishot)] = function(begin, duration)
|
||||
if begin then
|
||||
local duration = duration or 500
|
||||
|
||||
for i=1,32 do
|
||||
if UnitBuff("player", i) == "Interface\\Icons\\Racial_Troll_Berserk" then
|
||||
local berserk = 0.3
|
||||
if((UnitHealth("player")/UnitHealthMax("player")) >= 0.40) then
|
||||
berserk = (1.30 - (UnitHealth("player") / UnitHealthMax("player"))) / 3
|
||||
end
|
||||
duration = duration / (1 + berserk)
|
||||
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Hunter_RunningShot" then
|
||||
duration = duration / 1.4
|
||||
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Warrior_InnerRage" then
|
||||
duration = duration / 1.3
|
||||
elseif UnitBuff("player", i) == "Interface\\Icons\\Inv_Trinket_Naxxramas04" then
|
||||
duration = duration / 1.2
|
||||
end
|
||||
end
|
||||
|
||||
local _,_, lag = GetNetStats()
|
||||
local start = GetTime() + lag/1000
|
||||
|
||||
-- add cast action to the database
|
||||
libcast.db[player].cast = multishot
|
||||
libcast.db[player].rank = lastrank
|
||||
libcast.db[player].start = start
|
||||
libcast.db[player].casttime = duration
|
||||
libcast.db[player].icon = "Interface\\Icons\\Ability_upgrademoonglaive"
|
||||
libcast.db[player].channel = nil
|
||||
else
|
||||
-- remove cast action to the database
|
||||
libcast.db[player].cast = nil
|
||||
libcast.db[player].rank = nil
|
||||
libcast.db[player].start = nil
|
||||
libcast.db[player].casttime = nil
|
||||
libcast.db[player].icon = nil
|
||||
libcast.db[player].channel = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function CastCustom(spell)
|
||||
if not spell then return end
|
||||
if not ShaguTweaks.UnitCastingInfo(UnitName("player")) then
|
||||
for custom, func in pairs(libcast.customcast) do
|
||||
if strfind(strlower(spell), custom) or strlower(spell) == custom then
|
||||
func(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hooksecurefunc("UseContainerItem", function(id, index)
|
||||
lastcasttex = GetContainerItemInfo(id, index)
|
||||
end)
|
||||
|
||||
hooksecurefunc("CastSpell", function(id, bookType)
|
||||
_, lastrank = libspell.GetSpellInfo(id, bookType)
|
||||
lastcasttex = GetSpellTexture(id, bookType)
|
||||
|
||||
if GetSpellCooldown(id, bookType) ~= 0 then
|
||||
local spellName = GetSpellName(id, bookType)
|
||||
CastCustom(spellName)
|
||||
end
|
||||
end)
|
||||
|
||||
hooksecurefunc("CastSpellByName", function(spell, target)
|
||||
_, lastrank = libspell.GetSpellInfo(spell)
|
||||
|
||||
for i=1,120 do
|
||||
-- detect if any cast is ongoing
|
||||
if IsCurrentAction(i) then
|
||||
CastCustom(spell)
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hooksecurefunc("UseAction", function(slot, target, button)
|
||||
scanner:SetAction(slot)
|
||||
local spellName, rank = scanner:Line(1)
|
||||
|
||||
lastcasttex = GetActionTexture(slot)
|
||||
lastrank = rank
|
||||
|
||||
if GetActionText(slot) or not IsCurrentAction(slot) then return end
|
||||
CastCustom(spellName)
|
||||
end)
|
||||
|
||||
ShaguTweaks.libcast = libcast
|
||||
@@ -0,0 +1,279 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local L = ShaguTweaks.L
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local libtipscan = ShaguTweaks.libtipscan
|
||||
local libspell = ShaguTweaks.libspell
|
||||
local hooksecurefunc = ShaguTweaks.hooksecurefunc
|
||||
local QueueFunction = ShaguTweaks.QueueFunction
|
||||
local cmatch = ShaguTweaks.cmatch
|
||||
|
||||
-- return instantly if we're not on a vanilla client
|
||||
if GetExpansion() ~= "vanilla" then return end
|
||||
|
||||
-- fix a typo (missing $) in ruRU capture index
|
||||
if GetLocale() == "ruRU" then
|
||||
SPELLREFLECTSELFOTHER = gsub(SPELLREFLECTSELFOTHER, "%%2s", "%%2%$s")
|
||||
end
|
||||
|
||||
local libdebuff = CreateFrame("Frame", "ShaguTweaksDebuffsScanner", UIParent)
|
||||
local scanner = libtipscan:GetScanner("libdebuff")
|
||||
local _, class = UnitClass("player")
|
||||
local lastspell
|
||||
|
||||
function libdebuff:GetDuration(effect, rank)
|
||||
if L["debuffs"][effect] then
|
||||
local rank = rank and tonumber((string.gsub(rank, RANK .. " ", ""))) or 0
|
||||
local rank = L["debuffs"][effect][rank] and rank or libdebuff:GetMaxRank(effect)
|
||||
local duration = L["debuffs"][effect][rank]
|
||||
|
||||
if effect == L["dyndebuffs"]["Rupture"] then
|
||||
-- Rupture: +2 sec per combo point
|
||||
duration = duration + GetComboPoints()*2
|
||||
elseif effect == L["dyndebuffs"]["Kidney Shot"] then
|
||||
-- Kidney Shot: +1 sec per combo point
|
||||
duration = duration + GetComboPoints()*1
|
||||
elseif effect == L["dyndebuffs"]["Demoralizing Shout"] then
|
||||
-- Booming Voice: 10% per talent
|
||||
local _,_,_,_,count = GetTalentInfo(2,1)
|
||||
if count and count > 0 then duration = duration + ( duration / 100 * (count*10)) end
|
||||
elseif effect == L["dyndebuffs"]["Shadow Word: Pain"] then
|
||||
-- Improved Shadow Word: Pain: +3s per talent
|
||||
local _,_,_,_,count = GetTalentInfo(3,4)
|
||||
if count and count > 0 then duration = duration + count * 3 end
|
||||
elseif effect == L["dyndebuffs"]["Frostbolt"] then
|
||||
-- Permafrost: +1s per talent
|
||||
local _,_,_,_,count = GetTalentInfo(3,7)
|
||||
if count and count > 0 then duration = duration + count end
|
||||
elseif effect == L["dyndebuffs"]["Gouge"] then
|
||||
-- Improved Gouge: +.5s per talent
|
||||
local _,_,_,_,count = GetTalentInfo(2,1)
|
||||
if count and count > 0 then duration = duration + (count*.5) end
|
||||
end
|
||||
return duration
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function libdebuff:UpdateDuration(unit, unitlevel, effect, duration)
|
||||
if not unit or not effect or not duration then return end
|
||||
unitlevel = unitlevel or 0
|
||||
|
||||
if libdebuff.objects[unit] and libdebuff.objects[unit][unitlevel] and libdebuff.objects[unit][unitlevel][effect] then
|
||||
libdebuff.objects[unit][unitlevel][effect].duration = duration
|
||||
end
|
||||
end
|
||||
|
||||
function libdebuff:GetMaxRank(effect)
|
||||
local max = 0
|
||||
for id in pairs(L["debuffs"][effect]) do
|
||||
if id > max then max = id end
|
||||
end
|
||||
return max
|
||||
end
|
||||
|
||||
function libdebuff:UpdateUnits()
|
||||
TargetDebuffButton_Update()
|
||||
end
|
||||
|
||||
function libdebuff:AddPending(unit, unitlevel, effect, duration)
|
||||
if not unit then return end
|
||||
if not L["debuffs"][effect] then return end
|
||||
|
||||
if duration > 0 and libdebuff.pending[3] ~= effect then
|
||||
libdebuff.pending[1] = unit
|
||||
libdebuff.pending[2] = unitlevel or 0
|
||||
libdebuff.pending[3] = effect
|
||||
libdebuff.pending[4] = duration or libdebuff:GetDuration(effect)
|
||||
end
|
||||
end
|
||||
|
||||
function libdebuff:RemovePending()
|
||||
libdebuff.pending[1] = nil
|
||||
libdebuff.pending[2] = nil
|
||||
libdebuff.pending[3] = nil
|
||||
libdebuff.pending[4] = nil
|
||||
end
|
||||
|
||||
function libdebuff:PersistPending(effect)
|
||||
if not libdebuff.pending[3] then return end
|
||||
if libdebuff.pending[3] == effect or ( effect == nil and libdebuff.pending[3] ) then
|
||||
libdebuff:AddEffect(libdebuff.pending[1], libdebuff.pending[2], libdebuff.pending[3], libdebuff.pending[4])
|
||||
libdebuff:RemovePending()
|
||||
end
|
||||
end
|
||||
|
||||
function libdebuff:RevertLastAction()
|
||||
lastspell.start = lastspell.start_old
|
||||
lastspell.start_old = nil
|
||||
libdebuff:UpdateUnits()
|
||||
end
|
||||
|
||||
function libdebuff:AddEffect(unit, unitlevel, effect, duration)
|
||||
if not unit or not effect then return end
|
||||
unitlevel = unitlevel or 0
|
||||
if not libdebuff.objects[unit] then libdebuff.objects[unit] = {} end
|
||||
if not libdebuff.objects[unit][unitlevel] then libdebuff.objects[unit][unitlevel] = {} end
|
||||
if not libdebuff.objects[unit][unitlevel][effect] then libdebuff.objects[unit][unitlevel][effect] = {} end
|
||||
|
||||
-- save current effect as lastspell
|
||||
lastspell = libdebuff.objects[unit][unitlevel][effect]
|
||||
|
||||
libdebuff.objects[unit][unitlevel][effect].effect = effect
|
||||
libdebuff.objects[unit][unitlevel][effect].start_old = libdebuff.objects[unit][unitlevel][effect].start
|
||||
libdebuff.objects[unit][unitlevel][effect].start = GetTime()
|
||||
libdebuff.objects[unit][unitlevel][effect].duration = duration or libdebuff:GetDuration(effect)
|
||||
|
||||
libdebuff:UpdateUnits()
|
||||
end
|
||||
|
||||
-- scan for debuff application
|
||||
libdebuff:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE")
|
||||
libdebuff:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
|
||||
libdebuff:RegisterEvent("CHAT_MSG_SPELL_FAILED_LOCALPLAYER")
|
||||
libdebuff:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
|
||||
libdebuff:RegisterEvent("PLAYER_TARGET_CHANGED")
|
||||
libdebuff:RegisterEvent("SPELLCAST_STOP")
|
||||
libdebuff:RegisterEvent("UNIT_AURA")
|
||||
|
||||
-- register seal handler
|
||||
if class == "PALADIN" then
|
||||
libdebuff:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS")
|
||||
end
|
||||
|
||||
-- Remove Pending
|
||||
libdebuff.rp = { SPELLIMMUNESELFOTHER, IMMUNEDAMAGECLASSSELFOTHER,
|
||||
SPELLMISSSELFOTHER, SPELLRESISTSELFOTHER, SPELLEVADEDSELFOTHER,
|
||||
SPELLDODGEDSELFOTHER, SPELLDEFLECTEDSELFOTHER, SPELLREFLECTSELFOTHER,
|
||||
SPELLPARRIEDSELFOTHER, SPELLLOGABSORBSELFOTHER }
|
||||
|
||||
libdebuff.objects = {}
|
||||
libdebuff.pending = {}
|
||||
|
||||
-- Gather Data by Events
|
||||
libdebuff:SetScript("OnEvent", function()
|
||||
-- paladin seal refresh
|
||||
if event == "CHAT_MSG_COMBAT_SELF_HITS" then
|
||||
local hit = cmatch(arg1, COMBATHITSELFOTHER)
|
||||
local crit = cmatch(arg1, COMBATHITCRITSELFOTHER)
|
||||
if hit or crit then
|
||||
for seal in L["judgements"] do
|
||||
local name = UnitName("target")
|
||||
local level = UnitLevel("target")
|
||||
if name and libdebuff.objects[name] then
|
||||
if level and libdebuff.objects[name][level] and libdebuff.objects[name][level][seal] then
|
||||
libdebuff:AddEffect(name, level, seal)
|
||||
elseif libdebuff.objects[name][0] and libdebuff.objects[name][0][seal] then
|
||||
libdebuff:AddEffect(name, 0, seal)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add Combat Log
|
||||
elseif event == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE" or event == "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE" then
|
||||
local unit, effect = cmatch(arg1, AURAADDEDOTHERHARMFUL)
|
||||
if unit and effect then
|
||||
local unitlevel = UnitName("target") == unit and UnitLevel("target") or 0
|
||||
if not libdebuff.objects[unit] or not libdebuff.objects[unit][unitlevel] or not libdebuff.objects[unit][unitlevel][effect] then
|
||||
libdebuff:AddEffect(unit, unitlevel, effect)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add Missing Buffs by Iteration
|
||||
elseif ( event == "UNIT_AURA" and arg1 == "target" ) or event == "PLAYER_TARGET_CHANGED" then
|
||||
for i=1, 16 do
|
||||
local effect, rank, texture, stacks, dtype, duration, timeleft = libdebuff:UnitDebuff("target", i)
|
||||
|
||||
-- abort when no further debuff was found
|
||||
if not texture then return end
|
||||
|
||||
if texture and effect and effect ~= "" then
|
||||
-- don't overwrite existing timers
|
||||
local unitlevel = UnitLevel("target") or 0
|
||||
local unit = UnitName("target")
|
||||
if not libdebuff.objects[unit] or not libdebuff.objects[unit][unitlevel] or not libdebuff.objects[unit][unitlevel][effect] then
|
||||
libdebuff:AddEffect(unit, unitlevel, effect)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Update Pending Spells
|
||||
elseif event == "CHAT_MSG_SPELL_FAILED_LOCALPLAYER" or event == "CHAT_MSG_SPELL_SELF_DAMAGE" then
|
||||
-- Remove pending spell
|
||||
for _, msg in pairs(libdebuff.rp) do
|
||||
local effect = cmatch(arg1, msg)
|
||||
if effect and libdebuff.pending[3] == effect then
|
||||
-- instant removal of the pending spell
|
||||
libdebuff:RemovePending()
|
||||
return
|
||||
elseif effect and lastspell and lastspell.start_old and lastspell.effect == effect then
|
||||
-- late removal of debuffs (e.g hunter arrows as they hit late)
|
||||
libdebuff:RevertLastAction()
|
||||
return
|
||||
end
|
||||
end
|
||||
elseif event == "SPELLCAST_STOP" then
|
||||
QueueFunction(libdebuff.PersistPending)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Gather Data by User Actions
|
||||
hooksecurefunc("CastSpell", function(id, bookType)
|
||||
local effect = GetSpellName(id, bookType)
|
||||
local _, rank = libspell.GetSpellInfo(id, bookType)
|
||||
local duration = libdebuff:GetDuration(effect, rank)
|
||||
libdebuff:AddPending(UnitName("target"), UnitLevel("target"), effect, duration)
|
||||
end)
|
||||
|
||||
hooksecurefunc("CastSpellByName", function(effect, target)
|
||||
local _, rank = libspell.GetSpellInfo(effect)
|
||||
local duration = libdebuff:GetDuration(effect, rank)
|
||||
libdebuff:AddPending(UnitName("target"), UnitLevel("target"), effect, duration)
|
||||
end)
|
||||
|
||||
hooksecurefunc("UseAction", function(slot, target, button)
|
||||
if GetActionText(slot) or not IsCurrentAction(slot) then return end
|
||||
scanner:SetAction(slot)
|
||||
local effect, rank = scanner:Line(1)
|
||||
local duration = libdebuff:GetDuration(effect, rank)
|
||||
libdebuff:AddPending(UnitName("target"), UnitLevel("target"), effect, duration)
|
||||
end)
|
||||
|
||||
function libdebuff:UnitDebuff(unit, id)
|
||||
local unitname = UnitName(unit)
|
||||
local unitlevel = UnitLevel(unit)
|
||||
local texture, stacks, dtype = UnitDebuff(unit, id)
|
||||
local duration, timeleft = nil, -1
|
||||
local rank = nil -- no backport
|
||||
local effect
|
||||
|
||||
if texture then
|
||||
scanner:SetUnitDebuff(unit, id)
|
||||
effect = scanner:Line(1) or ""
|
||||
end
|
||||
|
||||
if libdebuff.objects[unitname] and libdebuff.objects[unitname][unitlevel] and libdebuff.objects[unitname][unitlevel][effect] then
|
||||
-- clean up cache
|
||||
if libdebuff.objects[unitname][unitlevel][effect].duration and libdebuff.objects[unitname][unitlevel][effect].duration + libdebuff.objects[unitname][unitlevel][effect].start < GetTime() then
|
||||
libdebuff.objects[unitname][unitlevel][effect] = nil
|
||||
else
|
||||
duration = libdebuff.objects[unitname][unitlevel][effect].duration
|
||||
timeleft = duration + libdebuff.objects[unitname][unitlevel][effect].start - GetTime()
|
||||
end
|
||||
|
||||
-- no level data
|
||||
elseif libdebuff.objects[unitname] and libdebuff.objects[unitname][0] and libdebuff.objects[unitname][0][effect] then
|
||||
-- clean up cache
|
||||
if libdebuff.objects[unitname][0][effect].duration and libdebuff.objects[unitname][0][effect].duration + libdebuff.objects[unitname][0][effect].start < GetTime() then
|
||||
libdebuff.objects[unitname][0][effect] = nil
|
||||
else
|
||||
duration = libdebuff.objects[unitname][0][effect].duration
|
||||
timeleft = duration + libdebuff.objects[unitname][0][effect].start - GetTime()
|
||||
end
|
||||
end
|
||||
|
||||
return effect, rank, texture, stacks, dtype, duration, timeleft
|
||||
end
|
||||
|
||||
ShaguTweaks.libdebuff = libdebuff
|
||||
@@ -0,0 +1,108 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local L = ShaguTweaks.L
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
|
||||
local mobdb = {}
|
||||
local target, dmg, perc, diff = nil, 0, 0, 0, 0
|
||||
local UnitHealth, UnitHealthMax
|
||||
local libhealth = CreateFrame("Frame")
|
||||
libhealth.enabled = true
|
||||
libhealth.reqhit = 4
|
||||
libhealth.reqdmg = 5
|
||||
libhealth:RegisterEvent("UNIT_HEALTH")
|
||||
libhealth:RegisterEvent("UNIT_COMBAT")
|
||||
libhealth:RegisterEvent("PLAYER_TARGET_CHANGED")
|
||||
libhealth:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
libhealth:SetScript("OnEvent", function()
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
-- create initial health cache tables
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["libhealth"] = ShaguTweaks_cache["libhealth"] or {}
|
||||
mobdb = ShaguTweaks_cache["libhealth"]
|
||||
|
||||
-- load enable state and set functions
|
||||
libhealth.enabled = true
|
||||
libhealth.reqhit = 2
|
||||
libhealth.reqdmg = 10
|
||||
end
|
||||
|
||||
-- return as we're not supposed to be here
|
||||
if not libhealth.enabled then this:UnregisterAllEvents() return end
|
||||
|
||||
-- try to estimate mob health based on combat and health events
|
||||
if event == "PLAYER_TARGET_CHANGED" then
|
||||
dmg, perc = 0, _G.UnitHealth("target")
|
||||
if UnitName("target") and UnitLevel("target") and _G.UnitHealthMax("target") == 100 then
|
||||
target = string.format("%s:%d",UnitName("target"), UnitLevel("target"))
|
||||
else
|
||||
target = nil
|
||||
end
|
||||
elseif target and event == "UNIT_COMBAT" and arg1 == "target" then
|
||||
if arg2 and arg2 == "HEAL" then return end
|
||||
dmg = dmg + arg4
|
||||
elseif target and event == "UNIT_HEALTH" and arg1 == "target" then
|
||||
diff = perc-_G.UnitHealth("target")
|
||||
if dmg > 0 and diff > 0 then
|
||||
mobdb[target] = mobdb[target] or {}
|
||||
if not mobdb[target][2] or diff > mobdb[target][2] then
|
||||
mobdb[target][1] = ceil(dmg / diff * 100)
|
||||
mobdb[target][2] = diff
|
||||
mobdb[target][3] = mobdb[target][3] and mobdb[target][3] + 1 or 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- core function to query the generated database
|
||||
local unit, level, cur, max, dbstring
|
||||
local function GetUnitHealth(self, unitstr)
|
||||
unit = UnitName(unitstr)
|
||||
level = UnitLevel(unitstr)
|
||||
cur = _G.UnitHealth(unitstr)
|
||||
max = _G.UnitHealthMax(unitstr)
|
||||
|
||||
-- return raw values if another addon is replacing global API calls
|
||||
if cur > 100 or max > 100 or max < 100 then
|
||||
return cur, max, true
|
||||
end
|
||||
|
||||
-- return raw values if no unit data could be found (unlikely but happened...)
|
||||
if not unit or not level then
|
||||
return cur, max
|
||||
end
|
||||
|
||||
-- query the database for known values
|
||||
dbstring = string.format("%s:%s", unit, level)
|
||||
if mobdb[dbstring] and mobdb[dbstring][1] and mobdb[dbstring][2] > libhealth.reqdmg and (not mobdb[dbstring][3] or mobdb[dbstring][3] > libhealth.reqhit) then
|
||||
return ceil(mobdb[dbstring][1]/100*cur), mobdb[dbstring][1], true
|
||||
end
|
||||
|
||||
-- return raw values as fallback
|
||||
return cur, max
|
||||
end
|
||||
|
||||
local function GetUnitHealthByName(self, unit, level, cur, max)
|
||||
-- return raw values if another addon is replacing global API calls
|
||||
if cur > 100 or max > 100 or max < 100 then
|
||||
return cur, max, true
|
||||
end
|
||||
|
||||
-- return raw values if no unit data could be found (unlikely but happened...)
|
||||
if not unit or not level then
|
||||
return cur, max
|
||||
end
|
||||
|
||||
-- query the database for known values
|
||||
dbstring = string.format("%s:%s", unit, level)
|
||||
if mobdb[dbstring] and mobdb[dbstring][1] and mobdb[dbstring][2] > libhealth.reqdmg and (not mobdb[dbstring][3] or mobdb[dbstring][3] > libhealth.reqhit) then
|
||||
return ceil(mobdb[dbstring][1]/100*cur), mobdb[dbstring][1], true
|
||||
end
|
||||
|
||||
-- return raw values as fallback
|
||||
return cur, max
|
||||
end
|
||||
|
||||
-- add api calls to global tree
|
||||
ShaguTweaks.libhealth = libhealth
|
||||
ShaguTweaks.libhealth.GetUnitHealth = GetUnitHealth
|
||||
ShaguTweaks.libhealth.GetUnitHealthByName = GetUnitHealthByName
|
||||
@@ -0,0 +1,75 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local GetUnitData = ShaguTweaks.GetUnitData
|
||||
|
||||
local NAMEPLATE_OBJECTORDER = { "border", "glow", "name", "level", "levelicon", "raidicon" }
|
||||
local NAMEPLATE_TYPE = "Button"
|
||||
if GetExpansion() == "tbc" then
|
||||
NAMEPLATE_OBJECTORDER = { "border", "castborder", "casticon", "glow", "name", "level", "levelicon", "raidicon" }
|
||||
NAMEPLATE_TYPE = "Frame"
|
||||
end
|
||||
|
||||
local function IsNamePlate(frame)
|
||||
if frame:GetObjectType() ~= NAMEPLATE_TYPE then return nil end
|
||||
regions = frame:GetRegions()
|
||||
|
||||
if not regions then return nil end
|
||||
if not regions.GetObjectType then return nil end
|
||||
if not regions.GetTexture then return nil end
|
||||
|
||||
if regions:GetObjectType() ~= "Texture" then return nil end
|
||||
return regions:GetTexture() == "Interface\\Tooltips\\Nameplate-Border" or nil
|
||||
end
|
||||
|
||||
local registry = {}
|
||||
local initialized = 0
|
||||
local parentcount, childs, plate
|
||||
ShaguTweaks.libnameplate = CreateFrame("Frame", nil, UIParent)
|
||||
ShaguTweaks.libnameplate.OnInit = {}
|
||||
ShaguTweaks.libnameplate.OnShow = {}
|
||||
ShaguTweaks.libnameplate.OnUpdate = {}
|
||||
ShaguTweaks.libnameplate:SetScript("OnUpdate", function()
|
||||
parentcount = WorldFrame:GetNumChildren()
|
||||
if initialized < parentcount then
|
||||
childs = { WorldFrame:GetChildren() }
|
||||
for i = initialized + 1, parentcount do
|
||||
plate = childs[i]
|
||||
|
||||
if IsNamePlate(plate) and not registry[plate] then
|
||||
plate.healthbar = plate:GetChildren()
|
||||
for i, object in pairs({plate:GetRegions()}) do
|
||||
if plate and NAMEPLATE_OBJECTORDER[i] then
|
||||
plate[NAMEPLATE_OBJECTORDER[i]] = object
|
||||
end
|
||||
end
|
||||
|
||||
-- run OnInit functions
|
||||
for id, func in pairs(ShaguTweaks.libnameplate.OnInit) do
|
||||
func(plate)
|
||||
end
|
||||
|
||||
-- register OnUpdate functions
|
||||
local oldUpdate = plate:GetScript("OnUpdate")
|
||||
plate:SetScript("OnUpdate", function(self, elapsed)
|
||||
if oldUpdate then oldUpdate(self, elapsed) end
|
||||
for id, func in pairs(ShaguTweaks.libnameplate.OnUpdate) do
|
||||
func(self, elapsed)
|
||||
end
|
||||
end)
|
||||
|
||||
-- register OnShow functions
|
||||
local oldShow = plate:GetScript("OnShow")
|
||||
plate:SetScript("OnShow", function(self)
|
||||
if oldShow then oldShow(self) end
|
||||
for id, func in pairs(ShaguTweaks.libnameplate.OnShow) do
|
||||
func(self)
|
||||
end
|
||||
end)
|
||||
|
||||
registry[plate] = plate
|
||||
end
|
||||
end
|
||||
|
||||
initialized = parentcount
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,469 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local L = ShaguTweaks.L
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local libtipscan = ShaguTweaks.libtipscan
|
||||
local libspell = ShaguTweaks.libspell
|
||||
local hooksecurefunc = ShaguTweaks.hooksecurefunc
|
||||
local strsplit = ShaguTweaks.strsplit
|
||||
local cmatch = ShaguTweaks.cmatch
|
||||
|
||||
local senttarget
|
||||
local heals, ress, events = {}, {}, {}
|
||||
|
||||
local PRAYER_OF_HEALING
|
||||
do -- Prayer of Healing
|
||||
local locales = {
|
||||
["deDE"] = "Gebet der Heilung",
|
||||
["enUS"] = "Prayer of Healing",
|
||||
["esES"] = "Rezo de curación",
|
||||
["frFR"] = "Prière de soins",
|
||||
["koKR"] = "치유의 기원",
|
||||
["ruRU"] = "Молитва исцеления",
|
||||
["zhCN"] = "治疗祷言",
|
||||
}
|
||||
|
||||
PRAYER_OF_HEALING = locales[GetLocale()] or locales["enUS"]
|
||||
end
|
||||
|
||||
local libpredict = CreateFrame("Frame")
|
||||
libpredict:RegisterEvent("UNIT_HEALTH")
|
||||
libpredict:RegisterEvent("CHAT_MSG_ADDON")
|
||||
libpredict:RegisterEvent("PLAYER_TARGET_CHANGED")
|
||||
libpredict:SetScript("OnEvent", function()
|
||||
if event == "CHAT_MSG_ADDON" and (arg1 == "HealComm" or arg1 == "CTRA") then
|
||||
this:ParseChatMessage(arg4, arg2, arg1)
|
||||
elseif event == "UNIT_HEALTH" then
|
||||
local name = UnitName(arg1)
|
||||
if ress[name] and not UnitIsDeadOrGhost(arg1) then
|
||||
ress[UnitName(arg1)] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
libpredict:SetScript("OnUpdate", function()
|
||||
-- update on timeout events
|
||||
for timestamp, targets in pairs(events) do
|
||||
if GetTime() >= timestamp then
|
||||
events[timestamp] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function libpredict:ParseComm(sender, msg)
|
||||
local msgtype, target, heal, time
|
||||
|
||||
if msg == "Healstop" or msg == "GrpHealstop" then
|
||||
msgtype = "Stop"
|
||||
elseif msg == "Resurrection/stop/" then
|
||||
msgtype = "RessStop"
|
||||
elseif msg then
|
||||
local msgobj = {strsplit("/", msg)}
|
||||
|
||||
if msgobj and msgobj[1] and msgobj[2] then
|
||||
-- legacy healcomm object
|
||||
if msgobj[1] == "GrpHealdelay" or msgobj[1] == "Healdelay" then
|
||||
msgtype, time = "Delay", msgobj[2]
|
||||
end
|
||||
|
||||
if msgobj[1] and msgobj[1] == "Resurrection" and msgobj[2] then
|
||||
msgtype, target = "Ress", msgobj[2]
|
||||
end
|
||||
|
||||
if msgobj[1] == "Heal" and msgobj[2] then
|
||||
msgtype, target, heal, time = "Heal", msgobj[2], msgobj[3], msgobj[4]
|
||||
end
|
||||
|
||||
if msgobj[1] == "GrpHeal" and msgobj[2] then
|
||||
msgtype, target, heal, time = "Heal", {}, msgobj[2], msgobj[3]
|
||||
for i=4,8 do
|
||||
if msgobj[i] then table.insert(target, msgobj[i]) end
|
||||
end
|
||||
end
|
||||
elseif select and UnitCastingInfo then
|
||||
-- latest healcomm
|
||||
msgtype = tonumber(string.sub(msg, 1, 3))
|
||||
if not msgtype then return end
|
||||
|
||||
if msgtype == 0 then
|
||||
msgtype = "Heal"
|
||||
heal = tonumber(string.sub(msg, 4, 8))
|
||||
target = string.sub(msg,9, -1)
|
||||
|
||||
local starttime = select(5, UnitCastingInfo(sender))
|
||||
local endtime = select(6, UnitCastingInfo(sender))
|
||||
if not starttime or not endtime then return end
|
||||
time = endtime - starttime
|
||||
elseif msgtype == 1 then
|
||||
msgtype = "Stop"
|
||||
elseif msgtype == 2 then
|
||||
msgtype = "Heal"
|
||||
heal = tonumber(string.sub(msg,4, 8))
|
||||
target = {strsplit(":", string.sub(msg,9, -1))}
|
||||
local starttime = select(5, UnitCastingInfo(sender))
|
||||
local endtime = select(6, UnitCastingInfo(sender))
|
||||
if not starttime or not endtime then return end
|
||||
time = endtime - starttime
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return msgtype, target, heal, time
|
||||
end
|
||||
|
||||
function libpredict:ParseChatMessage(sender, msg, comm)
|
||||
local msgtype, target, heal, time
|
||||
|
||||
if comm == "HealComm" then
|
||||
msgtype, target, heal, time = libpredict:ParseComm(sender, msg)
|
||||
elseif comm == "CTRA" then
|
||||
local _, _, cmd, ctratarget = string.find(msg, "(%a+)%s?([^#]*)")
|
||||
if cmd and ctratarget and cmd == "RES" and ctratarget ~= "" and ctratarget ~= UNKNOWN then
|
||||
msgtype = "Ress"
|
||||
target = ctratarget
|
||||
end
|
||||
end
|
||||
|
||||
if msgtype == "Stop" and sender then
|
||||
libpredict:HealStop(sender)
|
||||
return
|
||||
elseif ( msg == "RessStop" or msg == "RESNO" ) and sender then
|
||||
libpredict:RessStop(sender)
|
||||
return
|
||||
elseif msgtype == "Delay" and time then
|
||||
libpredict:HealDelay(sender, time)
|
||||
elseif msgtype == "Heal" and target and heal and time then
|
||||
if type(target) == "table" then
|
||||
for _, name in pairs(target) do
|
||||
libpredict:Heal(sender, name, heal, time)
|
||||
end
|
||||
else
|
||||
libpredict:Heal(sender, target, heal, time)
|
||||
end
|
||||
elseif msgtype == "Ress" then
|
||||
libpredict:Ress(sender, target)
|
||||
end
|
||||
end
|
||||
|
||||
function libpredict:AddEvent(time, target)
|
||||
events[time] = events[time] or {}
|
||||
table.insert(events[time], target)
|
||||
end
|
||||
|
||||
function libpredict:Heal(sender, target, amount, duration)
|
||||
if not sender or not target or not amount or not duration then
|
||||
return
|
||||
end
|
||||
|
||||
local timeout = duration/1000 + GetTime()
|
||||
heals[target] = heals[target] or {}
|
||||
heals[target][sender] = { amount, timeout }
|
||||
libpredict:AddEvent(timeout, target)
|
||||
end
|
||||
|
||||
function libpredict:HealStop(sender)
|
||||
for ttarget, t in pairs(heals) do
|
||||
for tsender in pairs(heals[ttarget]) do
|
||||
if sender == tsender then
|
||||
heals[ttarget][tsender] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function libpredict:HealDelay(sender, delay)
|
||||
local delay = delay/1000
|
||||
for target, t in pairs(heals) do
|
||||
for tsender, amount in pairs(heals[target]) do
|
||||
if sender == tsender then
|
||||
amount[2] = amount[2] + delay
|
||||
libpredict:AddEvent(amount[2], target)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function libpredict:Ress(sender, target)
|
||||
ress[target] = ress[target] or {}
|
||||
ress[target][sender] = true
|
||||
end
|
||||
|
||||
function libpredict:RessStop(sender)
|
||||
for ttarget, t in pairs(ress) do
|
||||
for tsender in pairs(ress[ttarget]) do
|
||||
if sender == tsender then
|
||||
ress[ttarget][tsender] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function libpredict:UnitGetIncomingHeals(unit)
|
||||
if not unit or not UnitName(unit) then return 0 end
|
||||
if UnitIsDeadOrGhost(unit) then return 0 end
|
||||
local name = UnitName(unit)
|
||||
|
||||
local sumheal = 0
|
||||
if not heals[name] then
|
||||
return sumheal
|
||||
else
|
||||
for sender, amount in pairs(heals[name]) do
|
||||
if amount[2] <= GetTime() then
|
||||
heals[name][sender] = nil
|
||||
else
|
||||
sumheal = sumheal + amount[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
return sumheal
|
||||
end
|
||||
|
||||
function libpredict:UnitHasIncomingResurrection(unit)
|
||||
if not unit or not UnitName(unit) then return nil end
|
||||
local name = UnitName(unit)
|
||||
|
||||
if not ress[name] then
|
||||
return nil
|
||||
else
|
||||
for sender, val in pairs(ress[name]) do
|
||||
if val == true then
|
||||
return val
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local spell_queue = { "DUMMY", "DUMMYRank 9", "TARGET" }
|
||||
local realm = GetRealmName()
|
||||
local player = UnitName("player")
|
||||
local cache, gear_string = {}, ""
|
||||
local resetcache = CreateFrame("Frame")
|
||||
resetcache:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
resetcache:RegisterEvent("SKILL_LINES_CHANGED")
|
||||
resetcache:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||
resetcache:SetScript("OnEvent", function()
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
-- load and initialize previous caches of spell amounts
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["prediction"] = ShaguTweaks_cache["prediction"] or {}
|
||||
ShaguTweaks_cache["prediction"][realm] = ShaguTweaks_cache["prediction"][realm] or {}
|
||||
ShaguTweaks_cache["prediction"][realm][player] = ShaguTweaks_cache["prediction"][realm][player] or {}
|
||||
ShaguTweaks_cache["prediction"][realm][player]["heals"] = ShaguTweaks_cache["prediction"][realm][player]["heals"] or {}
|
||||
cache = ShaguTweaks_cache["prediction"][realm][player]["heals"]
|
||||
return
|
||||
end
|
||||
|
||||
if event == "UNIT_INVENTORY_CHANGED" then
|
||||
-- skip non-player events
|
||||
if arg1 and arg1 ~= "player" then return end
|
||||
|
||||
local gear = ""
|
||||
for id = 1, 18 do
|
||||
gear = gear .. (GetInventoryItemLink("player",id) or "")
|
||||
end
|
||||
|
||||
-- abort when inventory didn't change
|
||||
if gear == gear_string then return end
|
||||
gear_string = gear
|
||||
end
|
||||
|
||||
-- flag all cached heals for renewal
|
||||
for k in pairs(cache) do
|
||||
if type(cache[k]) == "number" or type(cache[k]) == "string" then
|
||||
-- migrate old data
|
||||
local oldval = cache[k]
|
||||
cache[k] = { [1] = oldval }
|
||||
end
|
||||
|
||||
-- flag for reset
|
||||
cache[k][2] = true
|
||||
end
|
||||
end)
|
||||
|
||||
local function UpdateCache(spell, heal, crit)
|
||||
if not spell or not heal then return end
|
||||
local heal = tonumber(heal)
|
||||
|
||||
if not cache[spell] or cache[spell][2] then
|
||||
-- skills or equipment changed, save whatever is detected
|
||||
cache[spell] = cache[spell] or {}
|
||||
cache[spell][1] = crit and heal*2/3 or heal
|
||||
cache[spell][2] = crit
|
||||
elseif not crit and cache[spell][1] < heal then
|
||||
-- safe the best heal we can get
|
||||
cache[spell][1] = heal
|
||||
cache[spell][2] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Gather Data by User Actions
|
||||
hooksecurefunc("CastSpell", function(id, bookType)
|
||||
if not libpredict.sender.enabled then return end
|
||||
local effect, rank = libspell.GetSpellInfo(id, bookType)
|
||||
if not effect then return end
|
||||
spell_queue[1] = effect
|
||||
spell_queue[2] = effect.. ( rank or "" )
|
||||
spell_queue[3] = UnitName("target") and UnitCanAssist("player", "target") and UnitName("target") or UnitName("player")
|
||||
end)
|
||||
|
||||
hooksecurefunc("CastSpellByName", function(effect, target)
|
||||
if not libpredict.sender.enabled then return end
|
||||
local effect, rank = libspell.GetSpellInfo(effect)
|
||||
if not effect then return end
|
||||
spell_queue[1] = effect
|
||||
spell_queue[2] = effect.. ( rank or "" )
|
||||
spell_queue[3] = UnitName("target") and UnitCanAssist("player", "target") and UnitName("target") or UnitName("player")
|
||||
end)
|
||||
|
||||
local scanner = libtipscan:GetScanner("prediction")
|
||||
hooksecurefunc("UseAction", function(slot, target, selfcast)
|
||||
if not libpredict.sender.enabled then return end
|
||||
if GetActionText(slot) or not IsCurrentAction(slot) then return end
|
||||
scanner:SetAction(slot)
|
||||
local effect, rank = scanner:Line(1)
|
||||
if not effect then return end
|
||||
spell_queue[1] = effect
|
||||
spell_queue[2] = effect.. ( rank or "" )
|
||||
spell_queue[3] = selfcast and UnitName("player") or UnitName("target") and UnitCanAssist("player", "target") and UnitName("target") or UnitName("player")
|
||||
end)
|
||||
|
||||
libpredict.sender = CreateFrame("Frame", "ShaguTweaksPredictionSender", UIParent)
|
||||
libpredict.sender.enabled = true
|
||||
libpredict.sender.SendHealCommMsg = function(self, msg)
|
||||
SendAddonMessage("HealComm", msg, "RAID")
|
||||
SendAddonMessage("HealComm", msg, "BATTLEGROUND")
|
||||
end
|
||||
libpredict.sender.SendResCommMsg = function(self, msg)
|
||||
SendAddonMessage("CTRA", msg, "RAID")
|
||||
SendAddonMessage("CTRA", msg, "BATTLEGROUND")
|
||||
end
|
||||
|
||||
-- tbc
|
||||
libpredict.sender:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
||||
libpredict.sender:RegisterEvent("UNIT_SPELLCAST_START")
|
||||
libpredict.sender:RegisterEvent("UNIT_SPELLCAST_STOP")
|
||||
libpredict.sender:RegisterEvent("UNIT_SPELLCAST_FAILED")
|
||||
libpredict.sender:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
|
||||
libpredict.sender:RegisterEvent("UNIT_SPELLCAST_SENT")
|
||||
|
||||
-- vanilla
|
||||
libpredict.sender:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF")
|
||||
libpredict.sender:RegisterEvent("SPELLCAST_START")
|
||||
libpredict.sender:RegisterEvent("SPELLCAST_STOP")
|
||||
libpredict.sender:RegisterEvent("SPELLCAST_FAILED")
|
||||
libpredict.sender:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||
libpredict.sender:RegisterEvent("SPELLCAST_DELAYED")
|
||||
|
||||
-- force cache updates
|
||||
libpredict.sender:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||
libpredict.sender:RegisterEvent("SKILL_LINES_CHANGED")
|
||||
|
||||
libpredict.sender:SetScript("OnEvent", function()
|
||||
if event == "CHAT_MSG_SPELL_SELF_BUFF" then -- vanilla
|
||||
local spell, _, heal = cmatch(arg1, HEALEDSELFOTHER) -- "Your %s heals %s for %d."
|
||||
if spell and heal then
|
||||
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal) end
|
||||
return
|
||||
end
|
||||
|
||||
local spell, heal = cmatch(arg1, HEALEDSELFSELF) -- "Your %s heals you for %d."
|
||||
if spell and heal then
|
||||
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal) end
|
||||
return
|
||||
end
|
||||
|
||||
local spell, heal = cmatch(arg1, HEALEDCRITSELFOTHER) -- "Your %s critically heals %s for %d."
|
||||
if spell and heal then
|
||||
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal, true) end
|
||||
return
|
||||
end
|
||||
|
||||
local spell, _, heal = cmatch(arg1, HEALEDCRITSELFSELF) -- "Your %s critically heals you for %d."
|
||||
if spell and heal then
|
||||
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal, true) end
|
||||
return
|
||||
end
|
||||
elseif event == "COMBAT_LOG_EVENT_UNFILTERED" and arg2 == "SPELL_HEAL" and arg4 == player then -- tbc
|
||||
local spell, heal, crit = arg10, arg12, arg13
|
||||
if spell and heal and crit then
|
||||
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal, true) end
|
||||
elseif spell and heal then
|
||||
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal) end
|
||||
end
|
||||
elseif event == "UNIT_SPELLCAST_SENT" and arg4 then -- fix tbc mouseover macros
|
||||
senttarget = arg4
|
||||
elseif strfind(event, "SPELLCAST_START", 1) then
|
||||
local spell, time = arg1, arg2
|
||||
|
||||
if strfind(event, "UNIT_", 1) then -- tbc
|
||||
if arg1 ~= "player" then return end
|
||||
local spellname, _, _, _, starttime, endtime = UnitCastingInfo("player")
|
||||
spell, time = spellname, endtime - starttime
|
||||
end
|
||||
|
||||
if spell_queue[1] == spell and cache[spell_queue[2]] then
|
||||
local sender = player
|
||||
local target = senttarget or spell_queue[3]
|
||||
local amount = cache[spell_queue[2]][1]
|
||||
local casttime = time
|
||||
|
||||
if spell == PRAYER_OF_HEALING then
|
||||
target = sender
|
||||
|
||||
for i=1,4 do
|
||||
if CheckInteractDistance("party"..i, 4) then
|
||||
libpredict:Heal(player, UnitName("party"..i), amount, casttime)
|
||||
if GetExpansion() == "vanilla" then -- vanilla
|
||||
libpredict.sender:SendHealCommMsg("Heal/" .. UnitName("party"..i) .. "/" .. amount .. "/" .. casttime .. "/")
|
||||
else -- tbc
|
||||
libpredict.sender:SendHealCommMsg(string.format("002%05d%s", math.min(amount, 99999), UnitName("party"..i)))
|
||||
end
|
||||
libpredict.sender.healing = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
libpredict:Heal(player, target, amount, casttime)
|
||||
if GetExpansion() == "vanilla" then -- vanilla
|
||||
libpredict.sender:SendHealCommMsg("Heal/" .. target .. "/" .. amount .. "/" .. casttime .. "/")
|
||||
else -- tbc
|
||||
libpredict.sender:SendHealCommMsg(string.format("002%05d%s", math.min(amount, 99999), target))
|
||||
end
|
||||
libpredict.sender.healing = true
|
||||
|
||||
elseif spell_queue[1] == spell and L["resurrections"][spell] then
|
||||
local target = senttarget or spell_queue[3]
|
||||
libpredict:Ress(player, target)
|
||||
libpredict.sender:SendHealCommMsg("Resurrection/" .. target .. "/start/")
|
||||
libpredict.sender:SendResCommMsg("RES " .. target)
|
||||
libpredict.sender.resurrecting = true
|
||||
end
|
||||
elseif strfind(event, "SPELLCAST_FAILED", 1) or strfind(event, "SPELLCAST_INTERRUPTED", 1) then
|
||||
if strfind(event, "UNIT_", 1) and arg1 ~= "player" then return end
|
||||
if libpredict.sender.healing then
|
||||
libpredict:HealStop(player)
|
||||
if GetExpansion() == "vanilla" then -- vanilla
|
||||
libpredict.sender:SendHealCommMsg("HealStop")
|
||||
else -- tbc
|
||||
libpredict.sender:SendHealCommMsg("001F")
|
||||
end
|
||||
libpredict.sender.healing = nil
|
||||
elseif libpredict.sender.resurrecting then
|
||||
local target = senttarget or spell_queue[3]
|
||||
libpredict:RessStop(player)
|
||||
libpredict.sender:SendHealCommMsg("Resurrection/stop/")
|
||||
libpredict.sender:SendResCommMsg("RESNO " .. target)
|
||||
libpredict.sender.resurrecting = nil
|
||||
end
|
||||
elseif event == "SPELLCAST_DELAYED" then
|
||||
if libpredict.sender.healing then
|
||||
libpredict:HealDelay(player, arg1)
|
||||
libpredict.sender:SendHealCommMsg("Healdelay/" .. arg1 .. "/")
|
||||
end
|
||||
elseif strfind(event, "SPELLCAST_STOP", 1) then
|
||||
if strfind(event, "UNIT_", 1) and arg1 ~= "player" then return end
|
||||
libpredict:HealStop(player)
|
||||
end
|
||||
end)
|
||||
|
||||
ShaguTweaks.libpredict = libpredict
|
||||
@@ -0,0 +1,129 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local libtipscan = ShaguTweaks.libtipscan
|
||||
|
||||
local scanner = libtipscan:GetScanner("libspell")
|
||||
local libspell = {}
|
||||
|
||||
-- [ GetSpellMaxRank ]
|
||||
-- Returns the maximum rank of a players spell.
|
||||
-- 'name' [string] spellname to query
|
||||
-- return: [string],[number] maximum rank in characters and the number
|
||||
-- e.g "Rank 1" and "1"
|
||||
local spellmaxrank = {}
|
||||
function libspell.GetSpellMaxRank(name)
|
||||
local cache = spellmaxrank[name]
|
||||
if cache then return cache[1], cache[2] end
|
||||
|
||||
local rank = { 0, nil}
|
||||
for i = 1, GetNumSpellTabs() do
|
||||
local _, _, offset, num = GetSpellTabInfo(i)
|
||||
local bookType = BOOKTYPE_SPELL
|
||||
for id = offset + 1, offset + num do
|
||||
local spellName, spellRank = GetSpellName(id, bookType)
|
||||
if spellName == name then
|
||||
if not rank[2] then rank[2] = spellRank end
|
||||
|
||||
local _, _, numRank = string.find(spellRank, " (%d+)$")
|
||||
if numRank and tonumber(numRank) > rank[1] then
|
||||
rank = { tonumber(numRank), spellRank}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
spellmaxrank[name] = { rank[2], rank[1] }
|
||||
return rank[2], rank[1]
|
||||
end
|
||||
|
||||
-- [ GetSpellIndex ]
|
||||
-- Returns the spellbook index and bookid of the given spell.
|
||||
-- 'name' [string] spellname to query
|
||||
-- 'rank' [string] rank to query (optional)
|
||||
-- return: [number],[string] spell index and spellbook id
|
||||
local spellindex = {}
|
||||
function libspell.GetSpellIndex(name, rank)
|
||||
if not name then return end
|
||||
local cache = spellindex[name..(rank or "")]
|
||||
if cache then return cache[1], cache[2] end
|
||||
|
||||
if not rank then rank = libspell.GetSpellMaxRank(name) end
|
||||
|
||||
for i = 1, GetNumSpellTabs() do
|
||||
local _, _, offset, num = GetSpellTabInfo(i)
|
||||
local bookType = BOOKTYPE_SPELL
|
||||
for id = offset + 1, offset + num do
|
||||
local spellName, spellRank = GetSpellName(id, bookType)
|
||||
if rank and rank == spellRank and name == spellName then
|
||||
spellindex[name..rank] = { id, bookType }
|
||||
return id, bookType
|
||||
elseif not rank and name == spellName then
|
||||
spellindex[name] = { id, bookType }
|
||||
return id, bookType
|
||||
end
|
||||
end
|
||||
end
|
||||
spellindex[name..(rank or "")] = { nil }
|
||||
return nil
|
||||
end
|
||||
|
||||
-- [ GetSpellInfo ]
|
||||
-- Returns several information about a spell.
|
||||
-- 'index' [string/number] Spellname or Index of a spell in the spellbook
|
||||
-- 'bookType' [string] Type of spellbook (optional)
|
||||
-- return:
|
||||
-- [string] Name of the spell
|
||||
-- [string] Secondary text associated with the spell
|
||||
-- (e.g."Rank 5", "Racial", etc.)
|
||||
-- [string] Path to an icon texture for the spell
|
||||
-- [number] Casting time of the spell in milliseconds
|
||||
-- [number] Minimum range from the target required to cast the spell
|
||||
-- [number] Maximum range from the target at which you can cast the spell
|
||||
local spellinfo = {}
|
||||
function libspell.GetSpellInfo(index, bookType)
|
||||
local cache = spellinfo[index]
|
||||
if cache then return cache[1], cache[2], cache[3], cache[4], cache[5], cache[6] end
|
||||
|
||||
local name, rank, id
|
||||
local icon = ""
|
||||
local castingTime = 0
|
||||
local minRange = 0
|
||||
local maxRange = 0
|
||||
|
||||
if type(index) == "string" then
|
||||
local _, _, sname, srank = string.find(index, '(.+)%((.+)%)')
|
||||
name = sname or index
|
||||
rank = srank or libspell.GetSpellMaxRank(name)
|
||||
id, bookType = libspell.GetSpellIndex(name, rank)
|
||||
else
|
||||
name, rank = GetSpellName(index, bookType)
|
||||
id, bookType = libspell.GetSpellIndex(name, rank)
|
||||
end
|
||||
|
||||
if name and id then
|
||||
icon = GetSpellTexture(id, bookType)
|
||||
end
|
||||
|
||||
if id then
|
||||
scanner:SetSpell(id, bookType)
|
||||
local _, sec = scanner:Find(gsub(SPELL_CAST_TIME_SEC, "%%.3g", "%(.+%)"))
|
||||
local _, min = scanner:Find(gsub(SPELL_CAST_TIME_MIN, "%%.3g", "%(.+%)"))
|
||||
local _, range = scanner:Find(gsub(SPELL_RANGE, "%%s", "%(.+%)"))
|
||||
castingTime = (tonumber(sec) or tonumber(min) or 0) * 1000
|
||||
if range then
|
||||
local _, _, min, max = string.find(range, "(.+)-(.+)")
|
||||
if min and max then
|
||||
minRange = tonumber(min)
|
||||
maxRange = tonumber(max)
|
||||
else
|
||||
minRange = 0
|
||||
maxRange = tonumber(range)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
spellinfo[index] = { name, rank, icon, castingTime, minRange, maxRange }
|
||||
return name, rank, icon, castingTime, minRange, maxRange
|
||||
end
|
||||
|
||||
ShaguTweaks.libspell = libspell
|
||||
@@ -0,0 +1,169 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local libtipscan = {}
|
||||
local baseName = "ShaguTweaksTooltip"
|
||||
local methods = {
|
||||
"SetBagItem", "SetAction", "SetAuctionItem", "SetAuctionSellItem", "SetBuybackItem",
|
||||
"SetCraftItem", "SetCraftSpell", "SetHyperlink", "SetInboxItem", "SetInventoryItem",
|
||||
"SetLootItem", "SetLootRollItem", "SetMerchantItem", "SetPetAction", "SetPlayerBuff",
|
||||
"SetQuestItem", "SetQuestLogItem", "SetQuestRewardSpell", "SetSendMailItem", "SetShapeshift",
|
||||
"SetSpell", "SetTalent", "SetTrackingSpell", "SetTradePlayerItem", "SetTradeSkillItem", "SetTradeTargetItem",
|
||||
"SetTrainerService", "SetUnit", "SetUnitBuff", "SetUnitDebuff",
|
||||
}
|
||||
local extra_methods = {
|
||||
"Find", "Line", "Text", "List",
|
||||
}
|
||||
|
||||
local getFontString = function(obj)
|
||||
local name = obj:GetName()
|
||||
local r, g, b, color, a
|
||||
local text, segment
|
||||
|
||||
for i=1, obj:NumLines() do
|
||||
local left = _G[string.format("%sTextLeft%d",name,i)]
|
||||
segment = left and left:IsVisible() and left:GetText()
|
||||
segment = segment and segment ~= "" and segment or nil
|
||||
if segment then
|
||||
r, g, b, a = left:GetTextColor()
|
||||
segment = rgbhex(r,g,b) .. segment .. "|r"
|
||||
text = text and text .. "\n" .. segment or segment
|
||||
end
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
local getText = function(obj)
|
||||
local name = obj:GetName()
|
||||
local text = {}
|
||||
for i=1, obj:NumLines() do
|
||||
local left, right = _G[string.format("%sTextLeft%d",name,i)], _G[string.format("%sTextRight%d",name,i)]
|
||||
left = left and left:IsVisible() and left:GetText()
|
||||
right = right and right:IsVisible() and right:GetText()
|
||||
left = left and left ~= "" and left or nil
|
||||
right = right and right ~= "" and right or nil
|
||||
if left or right then
|
||||
text[i] = {left, right}
|
||||
end
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
local findText = function(obj, text, exact)
|
||||
local name = obj:GetName()
|
||||
for i=1, obj:NumLines() do
|
||||
local left, right = _G[string.format("%sTextLeft%d",name,i)], _G[string.format("%sTextRight%d",name,i)]
|
||||
left = left and left:IsVisible() and left:GetText()
|
||||
right = right and right:IsVisible() and right:GetText()
|
||||
if exact then
|
||||
if (left and left == text) or (right and right == text) then
|
||||
return i, text
|
||||
end
|
||||
else
|
||||
if left then
|
||||
local found,_,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10 = string.find(left, text)
|
||||
if found then
|
||||
return i, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
|
||||
end
|
||||
end
|
||||
if right then
|
||||
local found,_,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10 = string.find(right, text)
|
||||
if found then
|
||||
return i, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local lineText = function(obj, line)
|
||||
local name = obj:GetName()
|
||||
if line <= obj:NumLines() then
|
||||
local left, right = _G[string.format("%sTextLeft%d",name,line)], _G[string.format("%sTextRight%d",name,line)]
|
||||
left = left and left:IsVisible() and left:GetText()
|
||||
right = right and right:IsVisible() and right:GetText()
|
||||
|
||||
if left or right then
|
||||
return left, right
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local findColor = function(obj, r,g,b)
|
||||
local name = obj:GetName()
|
||||
if type(r) == "table" then
|
||||
r,g,b = r.r or r[1], r.g or r[2], r.b or r[3]
|
||||
end
|
||||
for i=1, obj:NumLines() do
|
||||
local tr, tg, tb
|
||||
local left, right = _G[string.format("%sTextLeft%d",name,i)], _G[string.format("%sTextRight%d",name,i)]
|
||||
if left and left:IsVisible() then
|
||||
tr, tg, tb = left:GetTextColor()
|
||||
tr, tg, tb = round(tr,1), round(tg,1), round(tb,1)
|
||||
end
|
||||
if tr and (tr == r and tg == g and tb == b) then
|
||||
return i
|
||||
end
|
||||
if right and right:IsVisible() then
|
||||
tr, tg, tb = right:GetTextColor()
|
||||
tr, tg, tb = round(tr,1), round(tg,1), round(tb,1)
|
||||
end
|
||||
if tr and (tr == r and tg == g and tb == b) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
libtipscan._registry = setmetatable({},{__index = function(t,k)
|
||||
local v = CreateFrame("GameTooltip", string.format("%s%s",baseName,k), nil, "GameTooltipTemplate")
|
||||
v:SetOwner(WorldFrame,"ANCHOR_NONE")
|
||||
v:SetScript("OnHide", function ()
|
||||
this:SetOwner(WorldFrame,"ANCHOR_NONE")
|
||||
end)
|
||||
function v:Text()
|
||||
return getText(self)
|
||||
end
|
||||
function v:FontString()
|
||||
return getFontString(self)
|
||||
end
|
||||
function v:Find(text, exact)
|
||||
return findText(self, text, exact)
|
||||
end
|
||||
function v:Color(r,g,b)
|
||||
return findColor(self,r,g,b)
|
||||
end
|
||||
function v:Line(line)
|
||||
return lineText(self, line)
|
||||
end
|
||||
for _,method in ipairs(methods) do
|
||||
local method = method
|
||||
local old = v[method]
|
||||
v[method] = function(v, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
v:ClearLines()
|
||||
return old(v, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
end
|
||||
end
|
||||
function v:List()
|
||||
table.sort(methods)
|
||||
for _,method in ipairs(methods) do
|
||||
print(method)
|
||||
end
|
||||
for _,method in ipairs(extra_methods) do
|
||||
print(method)
|
||||
end
|
||||
end
|
||||
rawset(t,k,v)
|
||||
return v
|
||||
end})
|
||||
|
||||
function libtipscan:GetScanner(type)
|
||||
local scanner = self._registry[type]
|
||||
scanner:ClearLines()
|
||||
return scanner
|
||||
end
|
||||
|
||||
function libtipscan:List()
|
||||
for name, scanner in pairs(self._registry) do
|
||||
print(name)
|
||||
end
|
||||
end
|
||||
|
||||
ShaguTweaks.libtipscan = libtipscan
|
||||
@@ -0,0 +1,144 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local L = ShaguTweaks.L
|
||||
|
||||
local units = { players = {}, mobs = {} }
|
||||
local queue = { }
|
||||
|
||||
local libunitscan = CreateFrame("Frame", "ShaguTweaksUnitScan", UIParent)
|
||||
|
||||
function ShaguTweaks.GetUnitData(name, active)
|
||||
if units["players"][name] then
|
||||
local ret = units["players"][name]
|
||||
return ret.class, ret.level, ret.elite, true
|
||||
elseif units["mobs"][name] then
|
||||
local ret = units["mobs"][name]
|
||||
return ret.class, ret.level, ret.elite, nil
|
||||
elseif active then
|
||||
queue[name] = true
|
||||
libunitscan:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function AddData(db, name, class, level, elite)
|
||||
if not name then return end
|
||||
units[db][name] = units[db][name] or {}
|
||||
units[db][name].class = class or units[db][name].class
|
||||
units[db][name].level = level or units[db][name].level
|
||||
units[db][name].elite = elite or units[db][name].elite
|
||||
queue[name] = nil
|
||||
end
|
||||
|
||||
libunitscan:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
libunitscan:RegisterEvent("FRIENDLIST_UPDATE")
|
||||
libunitscan:RegisterEvent("GUILD_ROSTER_UPDATE")
|
||||
libunitscan:RegisterEvent("RAID_ROSTER_UPDATE")
|
||||
libunitscan:RegisterEvent("PARTY_MEMBERS_CHANGED")
|
||||
libunitscan:RegisterEvent("PLAYER_TARGET_CHANGED")
|
||||
libunitscan:RegisterEvent("WHO_LIST_UPDATE")
|
||||
libunitscan:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||
libunitscan:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
|
||||
libunitscan:SetScript("OnEvent", function()
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
-- load database
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["players"] = ShaguTweaks_cache["players"] or {}
|
||||
units.players = ShaguTweaks_cache["players"]
|
||||
|
||||
-- update own character details
|
||||
local name = UnitName("player")
|
||||
local _, class = UnitClass("player")
|
||||
local level = UnitLevel("player")
|
||||
AddData("players", name, class, level)
|
||||
|
||||
elseif event == "FRIENDLIST_UPDATE" then
|
||||
local name, class, level
|
||||
for i = 1, GetNumFriends() do
|
||||
name, level, class = GetFriendInfo(i)
|
||||
class = L["class"][class] or nil
|
||||
-- friendlist updates due to friend going off-line return level 0, let's not overwrite good older values
|
||||
level = level > 0 and level or nil
|
||||
AddData("players", name, class, level)
|
||||
end
|
||||
|
||||
elseif event == "GUILD_ROSTER_UPDATE" then
|
||||
local name, class, level, _
|
||||
for i = 1, GetNumGuildMembers() do
|
||||
name, _, _, level, class = GetGuildRosterInfo(i)
|
||||
class = L["class"][class] or nil
|
||||
AddData("players", name, class, level)
|
||||
end
|
||||
|
||||
elseif event == "RAID_ROSTER_UPDATE" then
|
||||
local name, class, SubGroup, level, _
|
||||
for i = 1, GetNumRaidMembers() do
|
||||
name, _, SubGroup, level, class = GetRaidRosterInfo(i)
|
||||
class = L["class"][class] or nil
|
||||
AddData("players", name, class, level)
|
||||
end
|
||||
|
||||
elseif event == "PARTY_MEMBERS_CHANGED" then
|
||||
local name, class, level, unit, _
|
||||
for i = 1, GetNumPartyMembers() do
|
||||
unit = "party" .. i
|
||||
_, class = UnitClass(unit)
|
||||
name = UnitName(unit)
|
||||
level = UnitLevel(unit)
|
||||
AddData("players", name, class, level)
|
||||
end
|
||||
|
||||
elseif event == "WHO_LIST_UPDATE" or event == "CHAT_MSG_SYSTEM" then
|
||||
local name, class, level, _
|
||||
for i = 1, GetNumWhoResults() do
|
||||
name, _, level, _, class, _ = GetWhoInfo(i)
|
||||
class = L["class"][class] or nil
|
||||
AddData("players", name, class, level)
|
||||
end
|
||||
|
||||
elseif event == "UPDATE_MOUSEOVER_UNIT" or event == "PLAYER_TARGET_CHANGED" then
|
||||
local scan = event == "PLAYER_TARGET_CHANGED" and "target" or "mouseover"
|
||||
local name, class, level, elite, _
|
||||
if UnitIsPlayer(scan) then
|
||||
_, class = UnitClass(scan)
|
||||
level = UnitLevel(scan)
|
||||
name = UnitName(scan)
|
||||
AddData("players", name, class, level)
|
||||
else
|
||||
_, class = UnitClass(scan)
|
||||
elite = UnitClassification(scan)
|
||||
level = UnitLevel(scan)
|
||||
name = UnitName(scan)
|
||||
AddData("mobs", name, class, level, elite)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- since TargetByName can only be triggered within vanilla,
|
||||
-- we can't auto-scan targets on further expansions.
|
||||
if GetExpansion() == "vanilla" then
|
||||
-- setup sound function switches
|
||||
local SoundOn = PlaySound
|
||||
local SoundOff = function() return end
|
||||
|
||||
libunitscan:SetScript("OnUpdate", function()
|
||||
-- don't scan when another unit is in target
|
||||
if UnitExists("target") or UnitName("target") then return end
|
||||
|
||||
local name = next(queue)
|
||||
if name then
|
||||
-- disable sound
|
||||
_G.PlaySound = SoundOff
|
||||
|
||||
-- try to target the unknown unit
|
||||
TargetByName(name, true)
|
||||
ClearTarget()
|
||||
|
||||
-- enable sound again
|
||||
_G.PlaySound = SoundOn
|
||||
|
||||
queue[name] = nil
|
||||
end
|
||||
|
||||
this:Hide()
|
||||
end)
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["deDE"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = nil,
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = nil,
|
||||
["Adds a small 24h clock to the mini map."] = nil,
|
||||
["Adds class colors to the player, target and party unit frames."] = nil,
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = nil,
|
||||
["Adds coordinates to the bottom of the World Map."] = nil,
|
||||
["Advanced Options"] = nil,
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = nil,
|
||||
["Auto Dismount"] = nil,
|
||||
["Automatically dismounts whenever a spell is casted."] = nil,
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = nil,
|
||||
["Auto Stance"] = nil,
|
||||
["Blue Shaman Class Colors"] = nil,
|
||||
["Change health text color based on its value."] = nil,
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = nil,
|
||||
["Changes the nameplate health bar color to the class color."] = nil,
|
||||
["Chat Hyperlinks"] = nil,
|
||||
["Chat Tweaks"] = nil,
|
||||
["Clock"] = nil,
|
||||
["Cooldown Numbers"] = nil,
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = nil,
|
||||
["Cursor"] = nil,
|
||||
["Darkened UI"] = nil,
|
||||
["Debuff Timer"] = nil,
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = nil,
|
||||
["Display the remaining duration as text on every cooldown."] = nil,
|
||||
["Draw the mini map in a squared shape instead of a round one."] = nil,
|
||||
["Enemy Castbars"] = nil,
|
||||
["Equip Compare"] = nil,
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = nil,
|
||||
["General"] = nil,
|
||||
["Hide Errors"] = nil,
|
||||
["Hide Gryphons"] = nil,
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = nil,
|
||||
["Hides the gryphons left and right of the action bar."] = nil,
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = nil,
|
||||
["Increases the healthbar of the player and target unitframe."] = nil,
|
||||
["Item Rarity Borders"] = nil,
|
||||
["Localtime"] = nil,
|
||||
["Makes all nameplates honor the UI-Scale setting."] = nil,
|
||||
["MiniMap Clock"] = nil,
|
||||
["MiniMap Square"] = nil,
|
||||
["MiniMap Tweaks"] = nil,
|
||||
["Movable Unit Frames"] = nil,
|
||||
["N/A"] = nil,
|
||||
["Nameplate Castbar"] = nil,
|
||||
["Nameplate Class Colors"] = nil,
|
||||
["Nameplate Scale"] = nil,
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = nil,
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = nil,
|
||||
["Real Health Numbers"] = nil,
|
||||
["Reduced Actionbar Size"] = nil,
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = nil,
|
||||
["Replace unitframe portraits with class icons."] = nil,
|
||||
["Sell Grey Items"] = nil,
|
||||
["Sell Junk"] = nil,
|
||||
["Servertime"] = nil,
|
||||
["Show class colored circles on world and battlefield map."] = nil,
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = nil,
|
||||
["Show debuff durations on the target unit frame."] = nil,
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = nil,
|
||||
["Shows an enemy castbar on target unit frame."] = nil,
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = nil,
|
||||
["Shows the vendor sell values on all item tooltips."] = nil,
|
||||
["Social & Chat"] = nil,
|
||||
["Social Colors"] = nil,
|
||||
["Tooltip Details"] = nil,
|
||||
["Tooltip & Items"] = nil,
|
||||
["Turns the entire interface into darker colors."] = nil,
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = nil,
|
||||
["Turtle WoW Compatibility"] = nil,
|
||||
["Unit Frame Big Health"] = nil,
|
||||
["Unit Frame Class Colors"] = nil,
|
||||
["Unit Frame Class Portraits"] = nil,
|
||||
["Unit Frame Health Colors"] = nil,
|
||||
["Unit Frames"] = nil,
|
||||
["Vendor Values"] = nil,
|
||||
["WorldMap Class Colors"] = nil,
|
||||
["WorldMap Coordinates"] = nil,
|
||||
["WorldMap Window"] = nil,
|
||||
["World & MiniMap"] = nil,
|
||||
["Your vendor trash has been sold and you earned"] = nil,
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["enUS"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = nil,
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = nil,
|
||||
["Adds a small 24h clock to the mini map."] = nil,
|
||||
["Adds class colors to the player, target and party unit frames."] = nil,
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = nil,
|
||||
["Adds coordinates to the bottom of the World Map."] = nil,
|
||||
["Advanced Options"] = nil,
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = nil,
|
||||
["Auto Dismount"] = nil,
|
||||
["Automatically dismounts whenever a spell is casted."] = nil,
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = nil,
|
||||
["Auto Stance"] = nil,
|
||||
["Blue Shaman Class Colors"] = nil,
|
||||
["Change health text color based on its value."] = nil,
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = nil,
|
||||
["Changes the nameplate health bar color to the class color."] = nil,
|
||||
["Chat Hyperlinks"] = nil,
|
||||
["Chat Tweaks"] = nil,
|
||||
["Clock"] = nil,
|
||||
["Cooldown Numbers"] = nil,
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = nil,
|
||||
["Cursor"] = nil,
|
||||
["Darkened UI"] = nil,
|
||||
["Debuff Timer"] = nil,
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = nil,
|
||||
["Display the remaining duration as text on every cooldown."] = nil,
|
||||
["Draw the mini map in a squared shape instead of a round one."] = nil,
|
||||
["Enemy Castbars"] = nil,
|
||||
["Equip Compare"] = nil,
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = nil,
|
||||
["General"] = nil,
|
||||
["Hide Errors"] = nil,
|
||||
["Hide Gryphons"] = nil,
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = nil,
|
||||
["Hides the gryphons left and right of the action bar."] = nil,
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = nil,
|
||||
["Increases the healthbar of the player and target unitframe."] = nil,
|
||||
["Item Rarity Borders"] = nil,
|
||||
["Localtime"] = nil,
|
||||
["Makes all nameplates honor the UI-Scale setting."] = nil,
|
||||
["MiniMap Clock"] = nil,
|
||||
["MiniMap Square"] = nil,
|
||||
["MiniMap Tweaks"] = nil,
|
||||
["Movable Unit Frames"] = nil,
|
||||
["N/A"] = nil,
|
||||
["Nameplate Castbar"] = nil,
|
||||
["Nameplate Class Colors"] = nil,
|
||||
["Nameplate Scale"] = nil,
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = nil,
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = nil,
|
||||
["Real Health Numbers"] = nil,
|
||||
["Reduced Actionbar Size"] = nil,
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = nil,
|
||||
["Replace unitframe portraits with class icons."] = nil,
|
||||
["Sell Grey Items"] = nil,
|
||||
["Sell Junk"] = nil,
|
||||
["Servertime"] = nil,
|
||||
["Show class colored circles on world and battlefield map."] = nil,
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = nil,
|
||||
["Show debuff durations on the target unit frame."] = nil,
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = nil,
|
||||
["Shows an enemy castbar on target unit frame."] = nil,
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = nil,
|
||||
["Shows the vendor sell values on all item tooltips."] = nil,
|
||||
["Social & Chat"] = nil,
|
||||
["Social Colors"] = nil,
|
||||
["Tooltip Details"] = nil,
|
||||
["Tooltip & Items"] = nil,
|
||||
["Turns the entire interface into darker colors."] = nil,
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = nil,
|
||||
["Turtle WoW Compatibility"] = nil,
|
||||
["Unit Frame Big Health"] = nil,
|
||||
["Unit Frame Class Colors"] = nil,
|
||||
["Unit Frame Class Portraits"] = nil,
|
||||
["Unit Frame Health Colors"] = nil,
|
||||
["Unit Frames"] = nil,
|
||||
["Vendor Values"] = nil,
|
||||
["WorldMap Class Colors"] = nil,
|
||||
["WorldMap Coordinates"] = nil,
|
||||
["WorldMap Window"] = nil,
|
||||
["World & MiniMap"] = nil,
|
||||
["Your vendor trash has been sold and you earned"] = nil,
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["esES"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = nil,
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = nil,
|
||||
["Adds a small 24h clock to the mini map."] = nil,
|
||||
["Adds class colors to the player, target and party unit frames."] = nil,
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = nil,
|
||||
["Adds coordinates to the bottom of the World Map."] = nil,
|
||||
["Advanced Options"] = nil,
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = nil,
|
||||
["Auto Dismount"] = nil,
|
||||
["Automatically dismounts whenever a spell is casted."] = nil,
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = nil,
|
||||
["Auto Stance"] = nil,
|
||||
["Blue Shaman Class Colors"] = nil,
|
||||
["Change health text color based on its value."] = nil,
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = nil,
|
||||
["Changes the nameplate health bar color to the class color."] = nil,
|
||||
["Chat Hyperlinks"] = nil,
|
||||
["Chat Tweaks"] = nil,
|
||||
["Clock"] = nil,
|
||||
["Cooldown Numbers"] = nil,
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = nil,
|
||||
["Cursor"] = nil,
|
||||
["Darkened UI"] = nil,
|
||||
["Debuff Timer"] = nil,
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = nil,
|
||||
["Display the remaining duration as text on every cooldown."] = nil,
|
||||
["Draw the mini map in a squared shape instead of a round one."] = nil,
|
||||
["Enemy Castbars"] = nil,
|
||||
["Equip Compare"] = nil,
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = nil,
|
||||
["General"] = nil,
|
||||
["Hide Errors"] = nil,
|
||||
["Hide Gryphons"] = nil,
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = nil,
|
||||
["Hides the gryphons left and right of the action bar."] = nil,
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = nil,
|
||||
["Increases the healthbar of the player and target unitframe."] = nil,
|
||||
["Item Rarity Borders"] = nil,
|
||||
["Localtime"] = nil,
|
||||
["Makes all nameplates honor the UI-Scale setting."] = nil,
|
||||
["MiniMap Clock"] = nil,
|
||||
["MiniMap Square"] = nil,
|
||||
["MiniMap Tweaks"] = nil,
|
||||
["Movable Unit Frames"] = nil,
|
||||
["N/A"] = nil,
|
||||
["Nameplate Castbar"] = nil,
|
||||
["Nameplate Class Colors"] = nil,
|
||||
["Nameplate Scale"] = nil,
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = nil,
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = nil,
|
||||
["Real Health Numbers"] = nil,
|
||||
["Reduced Actionbar Size"] = nil,
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = nil,
|
||||
["Replace unitframe portraits with class icons."] = nil,
|
||||
["Sell Grey Items"] = nil,
|
||||
["Sell Junk"] = nil,
|
||||
["Servertime"] = nil,
|
||||
["Show class colored circles on world and battlefield map."] = nil,
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = nil,
|
||||
["Show debuff durations on the target unit frame."] = nil,
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = nil,
|
||||
["Shows an enemy castbar on target unit frame."] = nil,
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = nil,
|
||||
["Shows the vendor sell values on all item tooltips."] = nil,
|
||||
["Social & Chat"] = nil,
|
||||
["Social Colors"] = nil,
|
||||
["Tooltip Details"] = nil,
|
||||
["Tooltip & Items"] = nil,
|
||||
["Turns the entire interface into darker colors."] = nil,
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = nil,
|
||||
["Turtle WoW Compatibility"] = nil,
|
||||
["Unit Frame Big Health"] = nil,
|
||||
["Unit Frame Class Colors"] = nil,
|
||||
["Unit Frame Class Portraits"] = nil,
|
||||
["Unit Frame Health Colors"] = nil,
|
||||
["Unit Frames"] = nil,
|
||||
["Vendor Values"] = nil,
|
||||
["WorldMap Class Colors"] = nil,
|
||||
["WorldMap Coordinates"] = nil,
|
||||
["WorldMap Window"] = nil,
|
||||
["World & MiniMap"] = nil,
|
||||
["Your vendor trash has been sold and you earned"] = nil,
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["frFR"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = nil,
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = nil,
|
||||
["Adds a small 24h clock to the mini map."] = nil,
|
||||
["Adds class colors to the player, target and party unit frames."] = nil,
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = nil,
|
||||
["Adds coordinates to the bottom of the World Map."] = nil,
|
||||
["Advanced Options"] = nil,
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = nil,
|
||||
["Auto Dismount"] = nil,
|
||||
["Automatically dismounts whenever a spell is casted."] = nil,
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = nil,
|
||||
["Auto Stance"] = nil,
|
||||
["Blue Shaman Class Colors"] = nil,
|
||||
["Change health text color based on its value."] = nil,
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = nil,
|
||||
["Changes the nameplate health bar color to the class color."] = nil,
|
||||
["Chat Hyperlinks"] = nil,
|
||||
["Chat Tweaks"] = nil,
|
||||
["Clock"] = nil,
|
||||
["Cooldown Numbers"] = nil,
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = nil,
|
||||
["Cursor"] = nil,
|
||||
["Darkened UI"] = nil,
|
||||
["Debuff Timer"] = nil,
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = nil,
|
||||
["Display the remaining duration as text on every cooldown."] = nil,
|
||||
["Draw the mini map in a squared shape instead of a round one."] = nil,
|
||||
["Enemy Castbars"] = nil,
|
||||
["Equip Compare"] = nil,
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = nil,
|
||||
["General"] = nil,
|
||||
["Hide Errors"] = nil,
|
||||
["Hide Gryphons"] = nil,
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = nil,
|
||||
["Hides the gryphons left and right of the action bar."] = nil,
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = nil,
|
||||
["Increases the healthbar of the player and target unitframe."] = nil,
|
||||
["Item Rarity Borders"] = nil,
|
||||
["Localtime"] = nil,
|
||||
["Makes all nameplates honor the UI-Scale setting."] = nil,
|
||||
["MiniMap Clock"] = nil,
|
||||
["MiniMap Square"] = nil,
|
||||
["MiniMap Tweaks"] = nil,
|
||||
["Movable Unit Frames"] = nil,
|
||||
["N/A"] = nil,
|
||||
["Nameplate Castbar"] = nil,
|
||||
["Nameplate Class Colors"] = nil,
|
||||
["Nameplate Scale"] = nil,
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = nil,
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = nil,
|
||||
["Real Health Numbers"] = nil,
|
||||
["Reduced Actionbar Size"] = nil,
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = nil,
|
||||
["Replace unitframe portraits with class icons."] = nil,
|
||||
["Sell Grey Items"] = nil,
|
||||
["Sell Junk"] = nil,
|
||||
["Servertime"] = nil,
|
||||
["Show class colored circles on world and battlefield map."] = nil,
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = nil,
|
||||
["Show debuff durations on the target unit frame."] = nil,
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = nil,
|
||||
["Shows an enemy castbar on target unit frame."] = nil,
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = nil,
|
||||
["Shows the vendor sell values on all item tooltips."] = nil,
|
||||
["Social & Chat"] = nil,
|
||||
["Social Colors"] = nil,
|
||||
["Tooltip Details"] = nil,
|
||||
["Tooltip & Items"] = nil,
|
||||
["Turns the entire interface into darker colors."] = nil,
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = nil,
|
||||
["Turtle WoW Compatibility"] = nil,
|
||||
["Unit Frame Big Health"] = nil,
|
||||
["Unit Frame Class Colors"] = nil,
|
||||
["Unit Frame Class Portraits"] = nil,
|
||||
["Unit Frame Health Colors"] = nil,
|
||||
["Unit Frames"] = nil,
|
||||
["Vendor Values"] = nil,
|
||||
["WorldMap Class Colors"] = nil,
|
||||
["WorldMap Coordinates"] = nil,
|
||||
["WorldMap Window"] = nil,
|
||||
["World & MiniMap"] = nil,
|
||||
["Your vendor trash has been sold and you earned"] = nil,
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["koKR"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = nil,
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = nil,
|
||||
["Adds a small 24h clock to the mini map."] = nil,
|
||||
["Adds class colors to the player, target and party unit frames."] = nil,
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = nil,
|
||||
["Adds coordinates to the bottom of the World Map."] = nil,
|
||||
["Advanced Options"] = nil,
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = nil,
|
||||
["Auto Dismount"] = nil,
|
||||
["Automatically dismounts whenever a spell is casted."] = nil,
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = nil,
|
||||
["Auto Stance"] = nil,
|
||||
["Blue Shaman Class Colors"] = nil,
|
||||
["Change health text color based on its value."] = nil,
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = nil,
|
||||
["Changes the nameplate health bar color to the class color."] = nil,
|
||||
["Chat Hyperlinks"] = nil,
|
||||
["Chat Tweaks"] = nil,
|
||||
["Clock"] = nil,
|
||||
["Cooldown Numbers"] = nil,
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = nil,
|
||||
["Cursor"] = nil,
|
||||
["Darkened UI"] = nil,
|
||||
["Debuff Timer"] = nil,
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = nil,
|
||||
["Display the remaining duration as text on every cooldown."] = nil,
|
||||
["Draw the mini map in a squared shape instead of a round one."] = nil,
|
||||
["Enemy Castbars"] = nil,
|
||||
["Equip Compare"] = nil,
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = nil,
|
||||
["General"] = nil,
|
||||
["Hide Errors"] = nil,
|
||||
["Hide Gryphons"] = nil,
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = nil,
|
||||
["Hides the gryphons left and right of the action bar."] = nil,
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = nil,
|
||||
["Increases the healthbar of the player and target unitframe."] = nil,
|
||||
["Item Rarity Borders"] = nil,
|
||||
["Localtime"] = nil,
|
||||
["Makes all nameplates honor the UI-Scale setting."] = nil,
|
||||
["MiniMap Clock"] = nil,
|
||||
["MiniMap Square"] = nil,
|
||||
["MiniMap Tweaks"] = nil,
|
||||
["Movable Unit Frames"] = nil,
|
||||
["N/A"] = nil,
|
||||
["Nameplate Castbar"] = nil,
|
||||
["Nameplate Class Colors"] = nil,
|
||||
["Nameplate Scale"] = nil,
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = nil,
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = nil,
|
||||
["Real Health Numbers"] = nil,
|
||||
["Reduced Actionbar Size"] = nil,
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = nil,
|
||||
["Replace unitframe portraits with class icons."] = nil,
|
||||
["Sell Grey Items"] = nil,
|
||||
["Sell Junk"] = nil,
|
||||
["Servertime"] = nil,
|
||||
["Show class colored circles on world and battlefield map."] = nil,
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = nil,
|
||||
["Show debuff durations on the target unit frame."] = nil,
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = nil,
|
||||
["Shows an enemy castbar on target unit frame."] = nil,
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = nil,
|
||||
["Shows the vendor sell values on all item tooltips."] = nil,
|
||||
["Social & Chat"] = nil,
|
||||
["Social Colors"] = nil,
|
||||
["Tooltip Details"] = nil,
|
||||
["Tooltip & Items"] = nil,
|
||||
["Turns the entire interface into darker colors."] = nil,
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = nil,
|
||||
["Turtle WoW Compatibility"] = nil,
|
||||
["Unit Frame Big Health"] = nil,
|
||||
["Unit Frame Class Colors"] = nil,
|
||||
["Unit Frame Class Portraits"] = nil,
|
||||
["Unit Frame Health Colors"] = nil,
|
||||
["Unit Frames"] = nil,
|
||||
["Vendor Values"] = nil,
|
||||
["WorldMap Class Colors"] = nil,
|
||||
["WorldMap Coordinates"] = nil,
|
||||
["WorldMap Window"] = nil,
|
||||
["World & MiniMap"] = nil,
|
||||
["Your vendor trash has been sold and you earned"] = nil,
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["ruRU"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = "Добавляет панель применения к индикатору здоровья на основе оценок журнала боя.",
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = "Добавляет кнопку «Продать серые предметы» в каждое окно торговца, в котором продаются все серые предметы.",
|
||||
["Adds a small 24h clock to the mini map."] = "Добавляет небольшие 24-часовые часы на мини-карту.",
|
||||
["Adds class colors to the player, target and party unit frames."] = "Добавить цвета классов к окнам игрока, цели и отряда группы.",
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = "Добавляет совместимость с пользовательскими изменениями Turtle WoW.",
|
||||
["Adds coordinates to the bottom of the World Map."] = "Добавляет координаты внизу карты мира.",
|
||||
["Advanced Options"] = "Расширенные настройки",
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = "Позволяет прокручивать колесо мыши, включает закрепленные каналы чата и повторяет сообщение при нажатии стрелки вверх.",
|
||||
["Auto Dismount"] = "Авто-спешивание",
|
||||
["Automatically dismounts whenever a spell is casted."] = "Автоматическое спешивание при каждом произнесении заклинания.",
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = "Автоматически переключаться на нужную стойку воина или друида при произнесении заклинания.",
|
||||
["Auto Stance"] = "Авто-стойка",
|
||||
["Blue Shaman Class Colors"] = "Синий класс шамана",
|
||||
["Change health text color based on its value."] = "Изменить цвет текста о состоянии здоровья в зависимости от его значения.",
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = "Изменяет цветовой код класса шаманов на синий, как известно из TBC+.",
|
||||
["Changes the nameplate health bar color to the class color."] = "Изменяет цвет индикатора здоровья на цвет класса.",
|
||||
["Chat Hyperlinks"] = "Гиперссылки чата",
|
||||
["Chat Tweaks"] = "Улучшения чата",
|
||||
["Clock"] = "Часы",
|
||||
["Cooldown Numbers"] = "Продолжительность перезарядки",
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = "Копирование URL-адреса веб-сайтов из чата, преобразование CLINKов в реальные предметы и обрабатывание ссылок на квесты и игроков.",
|
||||
["Cursor"] = "Курсор",
|
||||
["Darkened UI"] = "Затемненный интерфейс",
|
||||
["Debuff Timer"] = "Таймер дебаффов",
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = "Отображение здоровья, цвета класса, названия гильдии, ранга гильдии и текущей цели во всплывающих подсказках юнитов.",
|
||||
["Display the remaining duration as text on every cooldown."] = "Отображать оставшуюся продолжительность в виде текста при перезарядке.",
|
||||
["Draw the mini map in a squared shape instead of a round one."] = "Мини-карта квадратной формы вместо круглой.",
|
||||
["Enemy Castbars"] = "Панель применения противника",
|
||||
["Equip Compare"] = "Сравнение экипировки",
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = "Оценивает количество здоровья и показывает цифры на окнах игрока, питомца и цели.",
|
||||
["General"] = "Общие",
|
||||
["Hide Errors"] = "Скрыть ошибки",
|
||||
["Hide Gryphons"] = "Спрятать грифонов",
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = "Скрывает и игнорирует все ошибки Lua, вызванные неработающими аддонами.",
|
||||
["Hides the gryphons left and right of the action bar."] = "Скрывает грифонов слева и справа от панели действий.",
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = "Скрывает ненужные кнопки мини-карты и позволяет масштабировать ее с помощью колеса мыши.",
|
||||
["Increases the healthbar of the player and target unitframe."] = "Увеличивает полосу здоровья игрока и цели.",
|
||||
["Item Rarity Borders"] = "Границы редкости предметов",
|
||||
["Localtime"] = "Местное время",
|
||||
["Makes all nameplates honor the UI-Scale setting."] = "Все индикаторы здоровья будут соответствовать настройке UI-Scale.",
|
||||
["MiniMap Clock"] = "Часы на мини-карте",
|
||||
["MiniMap Square"] = "Квадратная мини-карта",
|
||||
["MiniMap Tweaks"] = "Улучшения мини-карты",
|
||||
["Movable Unit Frames"] = "Передвижные окна",
|
||||
["N/A"] = "Н/Д",
|
||||
["Nameplate Castbar"] = "Панель применения индикатора здоровья",
|
||||
["Nameplate Class Colors"] = "Классы индикатора здоровья",
|
||||
["Nameplate Scale"] = "Масштаб индикаторов здоровья",
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = "Игрок",
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = "Окна игрока и цели можно перемещать, удерживая клавиши <Shift> и <Ctrl> вместе.",
|
||||
["Real Health Numbers"] = "Реальные цифры здоровья",
|
||||
["Reduced Actionbar Size"] = "Уменьшить панель действий",
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = "Уменьшает размер панели действий за счет удаления нескольких элементов, таких как панель сумки и микропанель.",
|
||||
["Replace unitframe portraits with class icons."] = "Заменить портреты окон юнитов значками классов.",
|
||||
["Sell Grey Items"] = "Продать серые предметы",
|
||||
["Sell Junk"] = "Продать серые предметы",
|
||||
["Servertime"] = "Серверное время",
|
||||
["Show class colored circles on world and battlefield map."] = "Показать цветные круги классов на карте мира и поле боя.",
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = "Показать цвета классов в разделах «Кто», «Гильдия», «Друзья» и «Чат».",
|
||||
["Show debuff durations on the target unit frame."] = "Показать продолжительность дебаффов в окне цели.",
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = "Показать редкость предмета в качестве цвета рамки на сумках, банке, окне персонажа и осмотра.",
|
||||
["Shows an enemy castbar on target unit frame."] = "Показать панель применения противника в окне юнита цели.",
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = "Показывает экипированные в данный момент предметы во всплывающих подсказках, пока нажата клавиша Shift.",
|
||||
["Shows the vendor sell values on all item tooltips."] = "Показывает стоимость продажи продавцу во всплывающих подсказках ко всем предметам.",
|
||||
["Social & Chat"] = "Общение и чат",
|
||||
["Social Colors"] = "Социальные цвета",
|
||||
["Tooltip Details"] = "Подробные подсказки",
|
||||
["Tooltip & Items"] = "Подсказки и предметы",
|
||||
["Turns the entire interface into darker colors."] = "Меняет весь интерфейс в более темные цвета.",
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = "Превращает карту мира в подвижное окно. Карту можно масштабировать с помощью <Ctrl> + Колесо мыши.",
|
||||
["Turtle WoW Compatibility"] = "Совместимость с Turtle WoW",
|
||||
["Unit Frame Big Health"] = "Большое здоровье",
|
||||
["Unit Frame Class Colors"] = "Цветные классы",
|
||||
["Unit Frame Class Portraits"] = "Классовые портреты",
|
||||
["Unit Frame Health Colors"] = "Цветное здоровье",
|
||||
["Unit Frames"] = "Окна юнитов",
|
||||
["Vendor Values"] = "Стоимость продажи",
|
||||
["WorldMap Class Colors"] = "Классы на карте мира",
|
||||
["WorldMap Coordinates"] = "Координаты на карте мира",
|
||||
["WorldMap Window"] = "Окно карты мира",
|
||||
["World & MiniMap"] = "Карта мира и мини-карта",
|
||||
["Your vendor trash has been sold and you earned"] = "Ваш хлам продан, и вы заработали",
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["zhCN"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = "添加基于战斗日志的施法条。",
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = "商人窗口添加:“出售垃圾”按钮,将灰色物品出售给商人。",
|
||||
["Adds a small 24h clock to the mini map."] = "添加一个24小时的时钟到小地图。",
|
||||
["Adds class colors to the player, target and party unit frames."] = "添加玩家、目标和队伍单位的职业颜色。",
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = "添加乌龟服的兼容修改。",
|
||||
["Adds coordinates to the bottom of the World Map."] = "添加坐标到世界地图的底部。",
|
||||
["Advanced Options"] = "高级选项",
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = "允许使用鼠标滚轮,启用粘性频道,向上箭头重复消息。",
|
||||
["Auto Dismount"] = "自动下坐骑",
|
||||
["Automatically dismounts whenever a spell is casted."] = "当施放任何法术时自动取消坐骑。",
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = "自动切换技能所需姿态(战士/德鲁伊)。",
|
||||
["Auto Stance"] = "自动切换姿态",
|
||||
["Blue Shaman Class Colors"] = "蓝色萨满职业颜色",
|
||||
["Change health text color based on its value."] = "根据值改变血量文本颜色。",
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = "修改了萨满职业的颜色为蓝色,与TBC+相同。",
|
||||
["Changes the nameplate health bar color to the class color."] = "修改姓名板的血量条颜色为职业颜色。",
|
||||
["Chat Hyperlinks"] = "聊天超链接",
|
||||
["Chat Tweaks"] = "聊天增强",
|
||||
["Clock"] = "时钟",
|
||||
["Cooldown Numbers"] = "冷却倒计时",
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = "复制聊天中的网址,将CLINK转换为实际的物品、任务和玩家链接。",
|
||||
["Cursor"] = "鼠标指针",
|
||||
["Darkened UI"] = "黑暗风格UI",
|
||||
["Debuff Timer"] = "Debuff计时",
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = "提示框显示当前目标血量、职业颜色、公会名称、公会等级、荣誉排名。",
|
||||
["Display the remaining duration as text on every cooldown."] = "显示剩余时间的文本,如:10s,1m,1h,1d。",
|
||||
["Draw the mini map in a squared shape instead of a round one."] = "小地图以方形显示,而不是圆形。",
|
||||
["Enemy Castbars"] = "敌对目标施法条",
|
||||
["Equip Compare"] = "装备比较",
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = "显示玩家、宠物和目标单位的血量。",
|
||||
["General"] = "常规",
|
||||
["Hide Errors"] = "隐藏LUA错误",
|
||||
["Hide Gryphons"] = "隐藏动作条狮鹫",
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = "隐藏并忽略所有插件脚本产生的LUA错误。",
|
||||
["Hides the gryphons left and right of the action bar."] = "隐藏动作条左右两边狮鹫。",
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = "隐藏小地图缩放按钮,改用使用鼠标滚轮进行缩放。",
|
||||
["Increases the healthbar of the player and target unitframe."] = "增加玩家和目标单位的血量条的宽度。",
|
||||
["Item Rarity Borders"] = "物品品质边框着色",
|
||||
["Localtime"] = "本地时间",
|
||||
["Makes all nameplates honor the UI-Scale setting."] = "名字板跟随UI缩放设置。",
|
||||
["MiniMap Clock"] = "小地图时钟",
|
||||
["MiniMap Square"] = "方形小地图",
|
||||
["MiniMap Tweaks"] = "小地图增强",
|
||||
["Movable Unit Frames"] = "头像框架可移动",
|
||||
["N/A"] = "N/A",
|
||||
["Nameplate Castbar"] = "姓名板施法条",
|
||||
["Nameplate Class Colors"] = "姓名板职业着色",
|
||||
["Nameplate Scale"] = "姓名板缩放",
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = "玩家",
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = "当<Shift>和<Ctrl>键同时按下时,玩家与目标单位的头像可移动。",
|
||||
["Real Health Numbers"] = "显示预估生命值",
|
||||
["Reduced Actionbar Size"] = "减少动作条大小",
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = "减少底部动作条大小,移除动作条上的按钮。",
|
||||
["Replace unitframe portraits with class icons."] = "单位头像替换为职业图标。",
|
||||
["Sell Grey Items"] = "售卖灰色物品",
|
||||
["Sell Junk"] = "售卖垃圾物品",
|
||||
["Servertime"] = "服务器时间",
|
||||
["Show class colored circles on world and battlefield map."] = "在世界地图和战场地图上显示团队成员职业颜色的圆圈。",
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = "显示职业颜色在Who、公会、好友和聊天等列表中。",
|
||||
["Show debuff durations on the target unit frame."] = "目标单位显示debuff的持续时间。",
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = "在背包、银行、角色、查看窗口中显示物品品质边框颜色。",
|
||||
["Shows an enemy castbar on target unit frame."] = "显示敌对目标单位的施法条。",
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = "按下<Shift>键时与当前与装备物品在进行比较。",
|
||||
["Shows the vendor sell values on all item tooltips."] = "物品的提示框中显示物品的售价。",
|
||||
["Social & Chat"] = "社交&聊天",
|
||||
["Social Colors"] = "显示职业颜色",
|
||||
["Tooltip Details"] = "提示框详情",
|
||||
["Tooltip & Items"] = "提示框&物品",
|
||||
["Turns the entire interface into darker colors."] = "将整个用户界面元素改为暗黑向。",
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = "让世界地图窗口可移动,可以按住<Ctrl>并滚动鼠标滚轮进行缩放。",
|
||||
["Turtle WoW Compatibility"] = "乌龟服兼容修改",
|
||||
["Unit Frame Big Health"] = "单位框架大生命文本",
|
||||
["Unit Frame Class Colors"] = "单位框架职业着色",
|
||||
["Unit Frame Class Portraits"] = "单位框架职业图标头像",
|
||||
["Unit Frame Health Colors"] = "单位框架血条颜色",
|
||||
["Unit Frames"] = "单位框架",
|
||||
["Vendor Values"] = "售卖价格",
|
||||
["WorldMap Class Colors"] = "世界地图职业着色",
|
||||
["WorldMap Coordinates"] = "世界地图显示坐标",
|
||||
["WorldMap Window"] = "世界地图窗口",
|
||||
["World & MiniMap"] = "地图&小地图",
|
||||
["Your vendor trash has been sold and you earned"] = "你的垃圾物品已出售,你获得了:",
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
ShaguTweaks_translation = ShaguTweaks_translation or {}
|
||||
ShaguTweaks_translation["zhTW"] = {
|
||||
["Adds a castbar to the nameplate based on combat log estimations."] = nil,
|
||||
["Adds a “Sell Junk” button to every merchant window, that sells all grey items."] = nil,
|
||||
["Adds a small 24h clock to the mini map."] = nil,
|
||||
["Adds class colors to the player, target and party unit frames."] = nil,
|
||||
["Adds compatibility to Turtle WoW's custom changes."] = nil,
|
||||
["Adds coordinates to the bottom of the World Map."] = nil,
|
||||
["Advanced Options"] = nil,
|
||||
["Allows to scroll using the mouse wheel, enables sticky chat channels and repeats message on arrow up."] = nil,
|
||||
["Auto Dismount"] = nil,
|
||||
["Automatically dismounts whenever a spell is casted."] = nil,
|
||||
["Automatically switch to the required warrior or druid stance on spell cast."] = nil,
|
||||
["Auto Stance"] = nil,
|
||||
["Blue Shaman Class Colors"] = nil,
|
||||
["Change health text color based on its value."] = nil,
|
||||
["Changes the class color code of shamans to blue, as known from TBC+."] = nil,
|
||||
["Changes the nameplate health bar color to the class color."] = nil,
|
||||
["Chat Hyperlinks"] = nil,
|
||||
["Chat Tweaks"] = nil,
|
||||
["Clock"] = nil,
|
||||
["Cooldown Numbers"] = nil,
|
||||
["Copy website URLs from the chat, transforms CLINKs into real items and handles quest and player links."] = nil,
|
||||
["Cursor"] = nil,
|
||||
["Darkened UI"] = nil,
|
||||
["Debuff Timer"] = nil,
|
||||
["Display health, class color, guild name, guild rank and current target on unit tooltips."] = nil,
|
||||
["Display the remaining duration as text on every cooldown."] = nil,
|
||||
["Draw the mini map in a squared shape instead of a round one."] = nil,
|
||||
["Enemy Castbars"] = nil,
|
||||
["Equip Compare"] = nil,
|
||||
["Estimates health numbers, and shows numbers on player, pet and target unit frames."] = nil,
|
||||
["General"] = nil,
|
||||
["Hide Errors"] = nil,
|
||||
["Hide Gryphons"] = nil,
|
||||
["Hides and ignores all Lua errors produced by broken addons."] = nil,
|
||||
["Hides the gryphons left and right of the action bar."] = nil,
|
||||
["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."] = nil,
|
||||
["Increases the healthbar of the player and target unitframe."] = nil,
|
||||
["Item Rarity Borders"] = nil,
|
||||
["Localtime"] = nil,
|
||||
["Makes all nameplates honor the UI-Scale setting."] = nil,
|
||||
["MiniMap Clock"] = nil,
|
||||
["MiniMap Square"] = nil,
|
||||
["MiniMap Tweaks"] = nil,
|
||||
["Movable Unit Frames"] = nil,
|
||||
["N/A"] = nil,
|
||||
["Nameplate Castbar"] = nil,
|
||||
["Nameplate Class Colors"] = nil,
|
||||
["Nameplate Scale"] = nil,
|
||||
["Nameplates"] = nil,
|
||||
["Player"] = nil,
|
||||
["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."] = nil,
|
||||
["Real Health Numbers"] = nil,
|
||||
["Reduced Actionbar Size"] = nil,
|
||||
["Reduces the actionbar size by removing several items such as the bag panel and microbar"] = nil,
|
||||
["Replace unitframe portraits with class icons."] = nil,
|
||||
["Sell Grey Items"] = nil,
|
||||
["Sell Junk"] = nil,
|
||||
["Servertime"] = nil,
|
||||
["Show class colored circles on world and battlefield map."] = nil,
|
||||
["Show class colors in Who, Guild, Friends and Chat."] = nil,
|
||||
["Show debuff durations on the target unit frame."] = nil,
|
||||
["Show item rarity as the border color on bags, bank, character and inspect frames."] = nil,
|
||||
["Shows an enemy castbar on target unit frame."] = nil,
|
||||
["Shows currently equipped items on tooltips while the shift key is pressed."] = nil,
|
||||
["Shows the vendor sell values on all item tooltips."] = nil,
|
||||
["Social & Chat"] = nil,
|
||||
["Social Colors"] = nil,
|
||||
["Tooltip Details"] = nil,
|
||||
["Tooltip & Items"] = nil,
|
||||
["Turns the entire interface into darker colors."] = nil,
|
||||
["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."] = nil,
|
||||
["Turtle WoW Compatibility"] = nil,
|
||||
["Unit Frame Big Health"] = nil,
|
||||
["Unit Frame Class Colors"] = nil,
|
||||
["Unit Frame Class Portraits"] = nil,
|
||||
["Unit Frame Health Colors"] = nil,
|
||||
["Unit Frames"] = nil,
|
||||
["Vendor Values"] = nil,
|
||||
["WorldMap Class Colors"] = nil,
|
||||
["WorldMap Coordinates"] = nil,
|
||||
["WorldMap Window"] = nil,
|
||||
["World & MiniMap"] = nil,
|
||||
["Your vendor trash has been sold and you earned"] = nil,
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
local _G = _G or getfenv(0)
|
||||
|
||||
SLASH_RELOAD1 = '/rl'
|
||||
function SlashCmdList.RELOAD(msg, editbox) ReloadUI() end
|
||||
|
||||
message = function(msg)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffff00" .. ( msg or "nil" ))
|
||||
end
|
||||
print = print or message
|
||||
|
||||
error = function(msg)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000".. (msg or "nil" ))
|
||||
end
|
||||
seterrorhandler(error)
|
||||
|
||||
ShaguTweaks = CreateFrame("Frame")
|
||||
ShaguTweaks.mods = {}
|
||||
ShaguTweaks.overwrites = {}
|
||||
|
||||
-- flag official modules
|
||||
local official = true
|
||||
|
||||
-- load translation tables
|
||||
ShaguTweaks.L = (ShaguTweaks_locale[GetLocale()] or ShaguTweaks_locale["enUS"])
|
||||
ShaguTweaks.T = (ShaguTweaks_translation[GetLocale()] or ShaguTweaks_translation["enUS"])
|
||||
|
||||
-- use table index key as translation fallback
|
||||
ShaguTweaks.T = setmetatable(ShaguTweaks.T, { __index = function(tab,key)
|
||||
local value = tostring(key)
|
||||
rawset(tab, key, value)
|
||||
return value
|
||||
end})
|
||||
|
||||
ShaguTweaks:RegisterEvent("ADDON_LOADED")
|
||||
ShaguTweaks:RegisterEvent("VARIABLES_LOADED")
|
||||
ShaguTweaks:SetScript("OnEvent", function()
|
||||
-- flag all external modules as unofficial
|
||||
if event == "ADDON_LOADED" then
|
||||
ShaguTweaks.provider = nil
|
||||
official = false
|
||||
return
|
||||
end
|
||||
|
||||
-- load current expansion
|
||||
local expansion = ShaguTweaks:GetExpansion()
|
||||
|
||||
-- initialize empty config
|
||||
if not ShaguTweaks_config then ShaguTweaks_config = {} end
|
||||
|
||||
-- initialize overwrites
|
||||
ShaguTweaks_config.overwrites = ShaguTweaks_config.overwrites or {}
|
||||
|
||||
-- read all registered mods
|
||||
for title, mod in pairs(ShaguTweaks.mods) do
|
||||
-- write initial default config
|
||||
if not ShaguTweaks_config[title] then
|
||||
ShaguTweaks_config[title] = mod.enabled and 1 or 0
|
||||
end
|
||||
|
||||
-- load possible overwrites
|
||||
if mod.config then
|
||||
for name, value in pairs(mod.config) do
|
||||
ShaguTweaks.overwrites[name] = value
|
||||
end
|
||||
end
|
||||
|
||||
-- apply custom overwrites
|
||||
if mod.config and ShaguTweaks_config.overwrites then
|
||||
for name, value in pairs(ShaguTweaks_config.overwrites) do
|
||||
ShaguTweaks.overwrites[name] = value
|
||||
mod.config[name] = value
|
||||
end
|
||||
end
|
||||
|
||||
-- load enabled mods
|
||||
if mod.expansions[expansion] and ShaguTweaks_config[title] == 1 then
|
||||
mod:enable()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
ShaguTweaks.register = function(self, mod)
|
||||
-- add fallback captions and providers to categories
|
||||
local provider = ShaguTweaks.provider or "|cffFF5555Mods:|r"
|
||||
local category = mod.category or ShaguTweaks.T["General"]
|
||||
mod.category = official and category or provider .. " " .. category
|
||||
|
||||
-- register mod
|
||||
ShaguTweaks.mods[mod.title] = mod
|
||||
return ShaguTweaks.mods[mod.title]
|
||||
end
|
||||
|
||||
local GetConfigValue = function(conf)
|
||||
if type(conf) == "table" and conf.r and conf.g and conf.b then
|
||||
return string.format("%s,%s,%s,%s", conf.r, conf.g, conf.b, (conf.a or 1))
|
||||
elseif type(conf) == "number" or type(conf) == "string" then
|
||||
return conf
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
-- print message without applied hooks
|
||||
local originalAddMessage = DEFAULT_CHAT_FRAME.AddMessage
|
||||
local stdout = function(msg)
|
||||
originalAddMessage(DEFAULT_CHAT_FRAME, msg)
|
||||
end
|
||||
|
||||
-- add /st slash command for custom config overwrites
|
||||
SLASH_STWEAKS1, SLASH_STWEAKS2, SLASH_STWEAKS3 = "/st", "/stweaks", "/shagutweaks"
|
||||
SlashCmdList["STWEAKS"] = function(msg)
|
||||
local cmd = { ShaguTweaks.strsplit(" ", msg) }
|
||||
if cmd[1] == "reset" then
|
||||
ShaguTweaks_config.overwrites = {}
|
||||
ReloadUI()
|
||||
elseif cmd[1] then
|
||||
local index = cmd[1]
|
||||
local input = cmd[2] or ""
|
||||
|
||||
-- detect best value format
|
||||
local value
|
||||
local rgba, _, r, g, b, a = string.find(input, "(.+),(.+),(.+),(.+)")
|
||||
|
||||
value = rgba and { r = r, g = g, b = b, a = a }
|
||||
value = value or tonumber(input) and tonumber(input)
|
||||
value = value or input
|
||||
|
||||
-- validate input and set config
|
||||
if not ShaguTweaks.overwrites[index] then
|
||||
local text = "|cffff5555Error:|r Overwrite |cffffcc00%s|r does not exists.|r"
|
||||
stdout(string.format(text, index), 1, 1, 1, 1)
|
||||
elseif type(ShaguTweaks.overwrites[index]) ~= type(value) then
|
||||
local text = "|cffff5555Error:|r Overwrite |cffffcc00%s|r requires to be type: |cffffcc00%s|r"
|
||||
stdout(string.format(text, index, type(ShaguTweaks.overwrites[index])), 1, 1, 1, 1)
|
||||
else
|
||||
ShaguTweaks_config.overwrites[index] = value
|
||||
local text = "Overwrite |cffffcc00%s|r is now set to: |cffffcc00%s|r"
|
||||
stdout(string.format(text, index, input), 1, 1, 1, 1)
|
||||
end
|
||||
else
|
||||
stdout("|cffffcc00Shagu|rTweaks overwrites:", 1, 1, 1, 1)
|
||||
stdout("|cffffcc00|r", 1, 1, 1, 1)
|
||||
stdout("|cffff5555Warning:|r This is for experienced users only. Do not change values unless you know what you're doing. Use '/st reset' before submitting any bug.", 1, .8, .8, 1)
|
||||
stdout("|cffffcc00|r", 1, 1, 1, 1)
|
||||
for name, value in ShaguTweaks.spairs(ShaguTweaks.overwrites) do
|
||||
stdout(" |cffaaaaaa/st|r " .. name .. " |cffffcc00" .. GetConfigValue(value), 1, 1, 1, 1)
|
||||
end
|
||||
stdout(" |cffaaaaaa/st|r reset", 1, 1, 1, 1)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Auto Dismount"],
|
||||
description = T["Automatically dismounts whenever a spell is casted."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local dismount = CreateFrame("Frame")
|
||||
ShaguTweaks.dismount = dismount
|
||||
|
||||
-- mount tooltip texts
|
||||
dismount.strings = {
|
||||
-- deDE
|
||||
"^Erhöht Tempo um (.+)%%",
|
||||
-- enUS
|
||||
"^Increases speed by (.+)%%",
|
||||
-- esES
|
||||
"^Aumenta la velocidad en un (.+)%%",
|
||||
-- frFR
|
||||
"^Augmente la vitesse de (.+)%%",
|
||||
-- ruRU
|
||||
"^Скорость увеличена на (.+)%%",
|
||||
-- koKR
|
||||
"^이동 속도 (.+)%%만큼 증가",
|
||||
-- zhCN
|
||||
"^速度提高(.+)%%",
|
||||
-- turtle-wow
|
||||
"speed based on", "Slow and steady...", "Riding",
|
||||
"Lento y constante...", "Aumenta la velocidad según tu habilidad de Montar.",
|
||||
"根据您的骑行技能提高速度。", "根据骑术技能提高速度。", "又慢又稳......",
|
||||
}
|
||||
|
||||
-- shapeshift buff icons
|
||||
dismount.shapeshifts = {
|
||||
"ability_racial_bearform", "ability_druid_catform", "ability_druid_travelform",
|
||||
"spell_nature_forceofnature", "ability_druid_aquaticform", "spell_nature_spiritwolf"
|
||||
}
|
||||
|
||||
-- errors that indicate mount/shapeshift
|
||||
dismount.errors = { SPELL_FAILED_NOT_MOUNTED, ERR_ATTACK_MOUNTED, ERR_TAXIPLAYERALREADYMOUNTED,
|
||||
SPELL_FAILED_NOT_SHAPESHIFT, SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED, SPELL_NOT_SHAPESHIFTED,
|
||||
SPELL_NOT_SHAPESHIFTED_NOSPACE, ERR_CANT_INTERACT_SHAPESHIFTED, ERR_NOT_WHILE_SHAPESHIFTED,
|
||||
ERR_NO_ITEMS_WHILE_SHAPESHIFTED, ERR_TAXIPLAYERSHAPESHIFTED,ERR_MOUNT_SHAPESHIFTED }
|
||||
|
||||
dismount.scanner = ShaguTweaks.libtipscan:GetScanner("dismount")
|
||||
|
||||
dismount:RegisterEvent("UI_ERROR_MESSAGE")
|
||||
dismount:SetScript("OnEvent", function()
|
||||
-- stand up
|
||||
if arg1 == SPELL_FAILED_NOT_STANDING then
|
||||
SitOrStand()
|
||||
return
|
||||
end
|
||||
|
||||
-- scan through buffs and cancel shapeshift/mount
|
||||
for id, errorstring in pairs(dismount.errors) do
|
||||
if arg1 == errorstring then
|
||||
for i=0, 31 do
|
||||
-- detect mounts based on tooltip text
|
||||
dismount.scanner:SetPlayerBuff(i)
|
||||
for _, str in pairs(dismount.strings) do
|
||||
if dismount.scanner:Find(str) then
|
||||
CancelPlayerBuff(i)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- detect shapeshift based on texture
|
||||
local buff = GetPlayerBuffTexture(i)
|
||||
if buff then
|
||||
for id, bufftype in pairs(dismount.shapeshifts) do
|
||||
if string.find(string.lower(buff), bufftype) then
|
||||
CancelPlayerBuff(i)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local strsplit = ShaguTweaks.strsplit
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Auto Stance"],
|
||||
description = T["Automatically switch to the required warrior or druid stance on spell cast."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local stancedance = CreateFrame("Frame", "ShaguTweaksStancedance")
|
||||
stancedance.scanString = string.gsub(SPELL_FAILED_ONLY_SHAPESHIFT, "%%s", "(.+)")
|
||||
stancedance:RegisterEvent("UI_ERROR_MESSAGE")
|
||||
stancedance:SetScript("OnEvent", function()
|
||||
for stances in string.gfind(arg1, stancedance.scanString) do
|
||||
for _, stance in pairs({ strsplit(",", stances)}) do
|
||||
CastSpellByName(string.gsub(stance,"^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Blue Shaman Class Colors"],
|
||||
description = T["Changes the class color code of shamans to blue, as known from TBC+."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Social & Chat"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
-- update table to get unknown colors and blue shamans for vanilla
|
||||
RAID_CLASS_COLORS = {
|
||||
["WARRIOR"] = { r = 0.78, g = 0.61, b = 0.43, colorStr = "ffc79c6e" },
|
||||
["MAGE"] = { r = 0.41, g = 0.8, b = 0.94, colorStr = "ff69ccf0" },
|
||||
["ROGUE"] = { r = 1, g = 0.96, b = 0.41, colorStr = "fffff569" },
|
||||
["DRUID"] = { r = 1, g = 0.49, b = 0.04, colorStr = "ffff7d0a" },
|
||||
["HUNTER"] = { r = 0.67, g = 0.83, b = 0.45, colorStr = "ffabd473" },
|
||||
["SHAMAN"] = { r = 0.14, g = 0.35, b = 1.0, colorStr = "ff2459ff" },
|
||||
["PRIEST"] = { r = 1, g = 1, b = 1, colorStr = "ffffffff" },
|
||||
["WARLOCK"] = { r = 0.58, g = 0.51, b = 0.79, colorStr = "ff9482c9" },
|
||||
["PALADIN"] = { r = 0.96, g = 0.55, b = 0.73, colorStr = "fff58cba" },
|
||||
}
|
||||
|
||||
RAID_CLASS_COLORS = setmetatable(RAID_CLASS_COLORS, { __index = function(tab,key)
|
||||
return { r = 0.6, g = 0.6, b = 0.6, colorStr = "ff999999" }
|
||||
end})
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local gfind = string.gmatch or string.gfind
|
||||
local rgbhex = ShaguTweaks.rgbhex
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Chat Levels"],
|
||||
description = T["Shows player levels in chat."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Social & Chat"],
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local events = CreateFrame("Frame", nil, UIParent)
|
||||
events:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
events:SetScript("OnEvent", function()
|
||||
if this.loaded then return end
|
||||
this.loaded = true
|
||||
|
||||
local playerdb = ShaguTweaks_cache and ShaguTweaks_cache["players"]
|
||||
|
||||
for i=1, NUM_CHAT_WINDOWS do
|
||||
local frame = _G["ChatFrame"..i]
|
||||
if frame and not frame.HookAddMessageLevel and not Prat then
|
||||
frame.HookAddMessageLevel = frame.AddMessage
|
||||
frame.AddMessage = function(f, text, a1, a2, a3, a4, a5)
|
||||
if text and playerdb then
|
||||
for name in gfind(text, "|Hplayer:(.-)|h") do
|
||||
local data = playerdb[name]
|
||||
if data and data.level then
|
||||
local level = data.level
|
||||
local color = rgbhex(GetDifficultyColor(level))
|
||||
text = string.gsub(text,
|
||||
"|Hplayer:" .. name .. "|h%[" .. name .. "%]|h|r",
|
||||
"|Hplayer:" .. name .. "|h[" .. name .. "]|h|r " .. color .. level .. "|r")
|
||||
end
|
||||
end
|
||||
end
|
||||
frame.HookAddMessageLevel(f, text, a1, a2, a3, a4, a5)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,517 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local L = ShaguTweaks.L
|
||||
local gfind = string.gmatch or string.gfind
|
||||
local GetUnitData = ShaguTweaks.GetUnitData
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local hooksecurefunc = ShaguTweaks.hooksecurefunc
|
||||
local cmatch = ShaguTweaks.cmatch
|
||||
local rgbhex = ShaguTweaks.rgbhex
|
||||
local strsplit = ShaguTweaks.strsplit
|
||||
|
||||
local scrollspeed = 1
|
||||
local friendinfo = gsub(gsub(FRIENDS_LEVEL_TEMPLATE,"%%s","%%s %%s"),"%%d","%%s")
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Chat Tweaks"],
|
||||
description = T["Improves chat with mouse wheel scrolling, sticky channels, arrow-up repeat, shortened names, item link preview, Alt/Ctrl-click to invite/target, right-click ignore, chat history, and class colors."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Social & Chat"],
|
||||
enabled = true,
|
||||
order = 60,
|
||||
})
|
||||
|
||||
-- ============================================================
|
||||
-- URL pattern helpers (from chat-links)
|
||||
-- ============================================================
|
||||
local URLPattern = {
|
||||
WWW = { ["rx"]=" (www%d-)%.([_A-Za-z0-9-]+)%.(%S+)%s?", ["fm"]="%s.%s.%s" },
|
||||
PROTOCOL = { ["rx"]=" (%a+)://(%S+)%s?", ["fm"]="%s://%s" },
|
||||
EMAIL = { ["rx"]=" ([_A-Za-z0-9-%.:]+)@([_A-Za-z0-9-]+)(%.)([_A-Za-z0-9-]+%.?[_A-Za-z0-9-]*)%s?", ["fm"]="%s@%s%s%s" },
|
||||
PORTIP = { ["rx"]=" (%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?):(%d%d?%d?%d?%d?)%s?", ["fm"]="%s.%s.%s.%s:%s" },
|
||||
IP = { ["rx"]=" (%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%s?", ["fm"]="%s.%s.%s.%s" },
|
||||
SHORTURL = { ["rx"]=" (%a+)%.(%a+)/(%S+)%s?", ["fm"]="%s.%s/%s" },
|
||||
URLIP = { ["rx"]=" ([_A-Za-z0-9-]+)%.([_A-Za-z0-9-]+)%.(%S+)%:([_0-9-]+)%s?", ["fm"]="%s.%s.%s:%s" },
|
||||
URL = { ["rx"]=" ([_A-Za-z0-9-]+)%.([_A-Za-z0-9-]+)%.(%S+)%s?", ["fm"]="%s.%s.%s" },
|
||||
}
|
||||
|
||||
local function FormatLink(formatter,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
if not (formatter and a1) then return end
|
||||
local newtext = string.format(formatter,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
local invalidtld
|
||||
for _, arg in pairs({a10,a9,a8,a7,a6,a5,a4,a3,a2,a1}) do
|
||||
if arg then invalidtld = string.find(arg, "(%.%.)$") break end
|
||||
end
|
||||
if (invalidtld) then return newtext end
|
||||
if formatter == URLPattern.EMAIL.fm then
|
||||
local colon = string.find(a1,":")
|
||||
if (colon) and string.len(a1) > colon then
|
||||
if not (string.sub(a1,1,6) == "mailto") then
|
||||
local prefix,address = string.sub(newtext,1,colon),string.sub(newtext,colon+1)
|
||||
return string.format(" %s|cffccccff|Hurl:%s|h[%s]|h|r ",prefix,address,address)
|
||||
end
|
||||
end
|
||||
end
|
||||
return " |cffccccff|Hurl:" .. newtext .. "|h[" .. newtext .. "]|h|r "
|
||||
end
|
||||
|
||||
local URLFuncs = {
|
||||
["WWW"] = function(a1,a2,a3) return FormatLink(URLPattern.WWW.fm,a1,a2,a3) end,
|
||||
["PROTOCOL"] = function(a1,a2) return FormatLink(URLPattern.PROTOCOL.fm,a1,a2) end,
|
||||
["EMAIL"] = function(a1,a2,a3,a4) return FormatLink(URLPattern.EMAIL.fm,a1,a2,a3,a4) end,
|
||||
["PORTIP"] = function(a1,a2,a3,a4,a5) return FormatLink(URLPattern.PORTIP.fm,a1,a2,a3,a4,a5) end,
|
||||
["IP"] = function(a1,a2,a3,a4) return FormatLink(URLPattern.IP.fm,a1,a2,a3,a4) end,
|
||||
["SHORTURL"] = function(a1,a2,a3) return FormatLink(URLPattern.SHORTURL.fm,a1,a2,a3) end,
|
||||
["URLIP"] = function(a1,a2,a3,a4) return FormatLink(URLPattern.URLIP.fm,a1,a2,a3,a4) end,
|
||||
["URL"] = function(a1,a2,a3) return FormatLink(URLPattern.URL.fm,a1,a2,a3) end,
|
||||
}
|
||||
|
||||
local function HandleLink(text)
|
||||
text = string.gsub(text, URLPattern.WWW.rx, URLFuncs.WWW)
|
||||
text = string.gsub(text, URLPattern.PROTOCOL.rx, URLFuncs.PROTOCOL)
|
||||
text = string.gsub(text, URLPattern.EMAIL.rx, URLFuncs.EMAIL)
|
||||
text = string.gsub(text, URLPattern.PORTIP.rx, URLFuncs.PORTIP)
|
||||
text = string.gsub(text, URLPattern.IP.rx, URLFuncs.IP)
|
||||
text = string.gsub(text, URLPattern.SHORTURL.rx, URLFuncs.SHORTURL)
|
||||
text = string.gsub(text, URLPattern.URLIP.rx, URLFuncs.URLIP)
|
||||
text = string.gsub(text, URLPattern.URL.rx, URLFuncs.URL)
|
||||
return text
|
||||
end
|
||||
|
||||
-- URL copy dialog
|
||||
local CopyLinkDialog = CreateFrame("Frame", "ShaguTweaksURLCopy", UIParent)
|
||||
CopyLinkDialog:Hide()
|
||||
CopyLinkDialog:SetWidth(300)
|
||||
CopyLinkDialog:SetHeight(90)
|
||||
CopyLinkDialog:SetFrameStrata("FULLSCREEN")
|
||||
CopyLinkDialog:SetPoint("CENTER", 0, 0)
|
||||
CopyLinkDialog:SetBackdrop({
|
||||
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
|
||||
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
||||
tile = true, tileSize = 32, edgeSize = 32,
|
||||
insets = { left = 11, right = 12, top = 12, bottom = 11 }
|
||||
})
|
||||
CopyLinkDialog:SetScript("OnShow", function() this.text:HighlightText() end)
|
||||
|
||||
CopyLinkDialog.text = CreateFrame("EditBox", "ShaguTweaksURLCopyEditBox", CopyLinkDialog)
|
||||
CopyLinkDialog.text:SetTextColor(1,.8,0)
|
||||
CopyLinkDialog.text:SetJustifyH("CENTER")
|
||||
CopyLinkDialog.text:SetBackdrop({
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
})
|
||||
CopyLinkDialog.text:SetBackdropColor(0,0,0,.8)
|
||||
CopyLinkDialog.text:SetBackdropBorderColor(.8,.8,.8,1)
|
||||
CopyLinkDialog.text:SetWidth(260)
|
||||
CopyLinkDialog.text:SetHeight(25)
|
||||
CopyLinkDialog.text:SetPoint("TOP", CopyLinkDialog, "TOP", 0, -20)
|
||||
CopyLinkDialog.text:SetFontObject(GameFontNormal)
|
||||
CopyLinkDialog.text:SetScript("OnEscapePressed", function() CopyLinkDialog:Hide() end)
|
||||
CopyLinkDialog.text:SetScript("OnEditFocusLost", function() CopyLinkDialog:Hide() end)
|
||||
|
||||
CopyLinkDialog.close = CreateFrame("Button", "ShaguTweaksURLCopyClose", CopyLinkDialog, "UIPanelButtonTemplate")
|
||||
CopyLinkDialog.close:SetPoint("BOTTOMRIGHT", CopyLinkDialog, "BOTTOMRIGHT", -20, 20)
|
||||
CopyLinkDialog.close:SetWidth(70)
|
||||
CopyLinkDialog.close:SetHeight(18)
|
||||
CopyLinkDialog.close:SetText(CLOSE)
|
||||
CopyLinkDialog.close:SetScript("OnClick", function() CopyLinkDialog:Hide() end)
|
||||
CopyLinkDialog.CopyText = function(text)
|
||||
CopyLinkDialog.text:SetText(text)
|
||||
CopyLinkDialog:Show()
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Module enable
|
||||
-- ============================================================
|
||||
module.enable = function(self)
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Blue Shaman class colors (vanilla only)
|
||||
-- --------------------------------------------------------
|
||||
if GetExpansion() == "vanilla" then
|
||||
RAID_CLASS_COLORS = {
|
||||
["WARRIOR"] = { r = 0.78, g = 0.61, b = 0.43, colorStr = "ffc79c6e" },
|
||||
["MAGE"] = { r = 0.41, g = 0.8, b = 0.94, colorStr = "ff69ccf0" },
|
||||
["ROGUE"] = { r = 1, g = 0.96, b = 0.41, colorStr = "fffff569" },
|
||||
["DRUID"] = { r = 1, g = 0.49, b = 0.04, colorStr = "ffff7d0a" },
|
||||
["HUNTER"] = { r = 0.67, g = 0.83, b = 0.45, colorStr = "ffabd473" },
|
||||
["SHAMAN"] = { r = 0.14, g = 0.35, b = 1.0, colorStr = "ff2459ff" },
|
||||
["PRIEST"] = { r = 1, g = 1, b = 1, colorStr = "ffffffff" },
|
||||
["WARLOCK"] = { r = 0.58, g = 0.51, b = 0.79, colorStr = "ff9482c9" },
|
||||
["PALADIN"] = { r = 0.96, g = 0.55, b = 0.73, colorStr = "fff58cba" },
|
||||
}
|
||||
RAID_CLASS_COLORS = setmetatable(RAID_CLASS_COLORS, { __index = function(tab,key)
|
||||
return { r = 0.6, g = 0.6, b = 0.6, colorStr = "ff999999" }
|
||||
end})
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Sticky channels & arrow-up repeat
|
||||
-- --------------------------------------------------------
|
||||
ChatTypeInfo.WHISPER.sticky = 1
|
||||
ChatTypeInfo.OFFICER.sticky = 1
|
||||
ChatTypeInfo.RAID_WARNING.sticky = 1
|
||||
ChatTypeInfo.CHANNEL.sticky = 1
|
||||
ChatFrameEditBox:SetAltArrowKeyMode(false)
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Mouse wheel scrolling
|
||||
-- --------------------------------------------------------
|
||||
local function ChatOnMouseWheel()
|
||||
if arg1 > 0 then
|
||||
if IsShiftKeyDown() then this:ScrollToTop()
|
||||
else for i=1,scrollspeed do this:ScrollUp() end end
|
||||
elseif arg1 < 0 then
|
||||
if IsShiftKeyDown() then this:ScrollToBottom()
|
||||
else for i=1,scrollspeed do this:ScrollDown() end end
|
||||
end
|
||||
if this:AtBottom() then
|
||||
_G[this:GetName().."BottomButton"]:Hide()
|
||||
this.scroll = nil
|
||||
else
|
||||
this.scroll = true
|
||||
_G[this:GetName().."BottomButton"]:Show()
|
||||
end
|
||||
end
|
||||
|
||||
for i=1, NUM_CHAT_WINDOWS do
|
||||
_G["ChatFrame"..i]:EnableMouseWheel(true)
|
||||
_G["ChatFrame"..i].scroll = nil
|
||||
_G["ChatFrame"..i]:SetScript("OnMouseWheel", ChatOnMouseWheel)
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Chat history save/restore
|
||||
-- --------------------------------------------------------
|
||||
local realm = GetRealmName()
|
||||
local player = UnitName("player")
|
||||
|
||||
local function SaveChatHistory(id, msg, r, g, b)
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["chathistory"] = ShaguTweaks_cache["chathistory"] or {}
|
||||
ShaguTweaks_cache["chathistory"][realm] = ShaguTweaks_cache["chathistory"][realm] or {}
|
||||
ShaguTweaks_cache["chathistory"][realm][player] = ShaguTweaks_cache["chathistory"][realm][player] or {}
|
||||
ShaguTweaks_cache["chathistory"][realm][player][id] = ShaguTweaks_cache["chathistory"][realm][player][id] or {}
|
||||
if r and g and b then
|
||||
local color = rgbhex(r*.5+.2, g*.5+.2, b*.5+.2)
|
||||
msg = string.gsub(msg, "^", color)
|
||||
msg = string.gsub(msg, "|r", "|r"..color)
|
||||
end
|
||||
local history = ShaguTweaks_cache["chathistory"][realm][player][id]
|
||||
table.insert(history, 1, msg)
|
||||
if history[30] then table.remove(history, 30) end
|
||||
end
|
||||
|
||||
local function GetChatHistory(id)
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["chathistory"] = ShaguTweaks_cache["chathistory"] or {}
|
||||
ShaguTweaks_cache["chathistory"][realm] = ShaguTweaks_cache["chathistory"][realm] or {}
|
||||
ShaguTweaks_cache["chathistory"][realm][player] = ShaguTweaks_cache["chathistory"][realm][player] or {}
|
||||
ShaguTweaks_cache["chathistory"][realm][player][id] = ShaguTweaks_cache["chathistory"][realm][player][id] or {}
|
||||
return ShaguTweaks_cache["chathistory"][realm][player][id]
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Per-frame hooks: history + CLINK cleanup + URLs + class colors
|
||||
-- --------------------------------------------------------
|
||||
for i=1, NUM_CHAT_WINDOWS do
|
||||
local isCombat = 0
|
||||
if _G["ChatFrame"..i] and _G["ChatFrame"..i].messageTypeList then
|
||||
for _, msg in pairs(_G["ChatFrame"..i].messageTypeList) do
|
||||
if strfind(msg,"SPELL",1) or strfind(msg,"COMBAT",1) then
|
||||
isCombat = isCombat + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isCombat <= 5 and _G["ChatFrame"..i] and not _G["ChatFrame"..i].ShaguTweaksChatTweaksHooked then
|
||||
_G["ChatFrame"..i].ShaguTweaksChatTweaksHooked = true
|
||||
|
||||
-- restore history
|
||||
local history = GetChatHistory(i)
|
||||
for j=30,0,-1 do
|
||||
if history[j] then _G["ChatFrame"..i]:AddMessage(history[j], .7,.7,.7) end
|
||||
end
|
||||
|
||||
_G["ChatFrame"..i].ShaguTweaksBaseAddMessage = _G["ChatFrame"..i].AddMessage
|
||||
_G["ChatFrame"..i].AddMessage = function(frame, text, a1, a2, a3, a4, a5)
|
||||
if not text then return end
|
||||
|
||||
-- Remove prat/chatter CLINKs
|
||||
text = gsub(text, "{CLINK:(%x+):([%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
|
||||
text = gsub(text, "{CLINK:(%x+):([%d-]-:[%d-]-:[%d-]-:[%d-]-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
|
||||
text = gsub(text, "{CLINK:item:(%x+):([%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-:[%d-]-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
|
||||
text = gsub(text, "{CLINK:enchant:(%x+):([%d-]-):([^}]-)}", "|c%1|Henchant:%2|h[%3]|h|r")
|
||||
text = gsub(text, "{CLINK:spell:(%x+):([%d-]-):([^}]-)}", "|c%1|Hspell:%2|h[%3]|h|r")
|
||||
text = gsub(text, "{CLINK:quest:(%x+):([%d-]-):([%d-]-):([^}]-)}", "|c%1|Hquest:%2:%3|h[%4]|h|r")
|
||||
|
||||
-- Reduce channel number (e.g. [1. General] -> [1])
|
||||
local channel = string.gsub(text, ".*%[(.-)%]%s+(.*|Hplayer).+", "%1")
|
||||
if string.find(channel, "%d+%. ") then
|
||||
channel = string.gsub(channel, "(%d+)%..*", "%1")
|
||||
text = string.gsub(text, "%[%d+%..-%]%s+(.*|Hplayer)", "[" .. channel .. "] %1")
|
||||
end
|
||||
|
||||
-- URL detection
|
||||
text = HandleLink(text)
|
||||
|
||||
-- Class colors on player links
|
||||
for name in gfind(text, "|Hplayer:(.-)|h") do
|
||||
local real, _ = strsplit(":", name)
|
||||
local color = "|cffaaaaaa"
|
||||
local class = GetUnitData(real)
|
||||
if class and class ~= UNKNOWN then
|
||||
color = rgbhex(RAID_CLASS_COLORS[class])
|
||||
end
|
||||
text = string.gsub(text, "|Hplayer:"..name.."|h%["..real.."%]|h(.-:-)",
|
||||
"|r["..color.."|Hplayer:"..name.."|h"..color..real.."|h|r".."]|r".."%1")
|
||||
end
|
||||
|
||||
SaveChatHistory(frame:GetID(), text, a1, a2, a3)
|
||||
frame:ShaguTweaksBaseAddMessage(text, a1, a2, a3, a4, a5)
|
||||
end
|
||||
|
||||
-- Item link tooltip on mouseover
|
||||
_G["ChatFrame"..i]:SetScript("OnHyperlinkEnter", function()
|
||||
local _, _, linktype = string.find(arg1, "^(.-):(.+)$")
|
||||
if linktype == "item" then
|
||||
GameTooltip:SetOwner(this, "ANCHOR_CURSOR")
|
||||
GameTooltip:SetHyperlink(arg1)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end)
|
||||
_G["ChatFrame"..i]:SetScript("OnHyperlinkLeave", function()
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
|
||||
-- Alt/Ctrl-click player names; URL copy
|
||||
_G["ChatFrame"..i]:SetScript("OnHyperlinkClick", function()
|
||||
local _, _, playerLink = string.find(arg1, "(player:.+)")
|
||||
if playerLink then
|
||||
local _, pname = strsplit(":", playerLink)
|
||||
if IsAltKeyDown() then
|
||||
InviteByName(pname)
|
||||
elseif IsControlKeyDown() then
|
||||
TargetByName(pname, true)
|
||||
else
|
||||
ChatFrame_OnHyperlinkShow(arg1, arg2, arg3)
|
||||
end
|
||||
elseif strsub(arg1,1,3) == "url" then
|
||||
if string.len(arg1) > 4 and string.sub(arg1,1,4) == "url:" then
|
||||
CopyLinkDialog.CopyText(string.sub(arg1, 5))
|
||||
end
|
||||
else
|
||||
ChatFrame_OnHyperlinkShow(arg1, arg2, arg3)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Shorten channel names
|
||||
-- --------------------------------------------------------
|
||||
local left, right = "[", "]"
|
||||
local default = " " .. "%s" .. "|r:" .. "\32"
|
||||
_G.CHAT_CHANNEL_GET = "%s" .. "|r:" .. "\32"
|
||||
_G.CHAT_GUILD_GET = left.."G"..right .. default
|
||||
_G.CHAT_OFFICER_GET = left.."O"..right .. default
|
||||
_G.CHAT_PARTY_GET = left.."P"..right .. default
|
||||
_G.CHAT_RAID_GET = left.."R"..right .. default
|
||||
_G.CHAT_RAID_LEADER_GET = left.."RL"..right .. default
|
||||
_G.CHAT_RAID_WARNING_GET = left.."RW"..right .. default
|
||||
_G.CHAT_BATTLEGROUND_GET = left.."BG"..right .. default
|
||||
_G.CHAT_BATTLEGROUND_LEADER_GET = left.."BL"..right .. default
|
||||
_G.CHAT_SAY_GET = left.."S"..right .. default
|
||||
_G.CHAT_YELL_GET = left.."Y"..right .. default
|
||||
_G.CHAT_WHISPER_GET = "[From]" .. default
|
||||
_G.CHAT_WHISPER_INFORM_GET = "[To]" .. default
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- SetItemRef hook for URL/quest/player links
|
||||
-- --------------------------------------------------------
|
||||
local HookSetItemRef = SetItemRef
|
||||
function _G.SetItemRef(link, text, button)
|
||||
if (strsub(link,1,3) == "url") then
|
||||
if string.len(link) > 4 and string.sub(link,1,4) == "url:" then
|
||||
CopyLinkDialog.CopyText(string.sub(link, 5))
|
||||
end
|
||||
return
|
||||
end
|
||||
local questlink, _, quest_id = string.find(link, "quest:(%d+):.*")
|
||||
local playerlink = strsub(link,1,6) == "player"
|
||||
if ShaguQuest or pfQuest or Questie then questlink = nil end
|
||||
if questlink then
|
||||
local _, _, quest_title = string.find(text, ".*|h%[(.*)%]|h.*")
|
||||
if quest_title then
|
||||
HideUIPanel(ItemRefTooltip)
|
||||
ShowUIPanel(ItemRefTooltip)
|
||||
ItemRefTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE")
|
||||
ItemRefTooltip:AddLine(quest_title, 1,1,0)
|
||||
ItemRefTooltip:AddDoubleLine("Quest ID", quest_id, .6,.6,.6, 1,1,1)
|
||||
ItemRefTooltip:Show()
|
||||
end
|
||||
return
|
||||
elseif playerlink then
|
||||
local name = strsub(link, 8)
|
||||
if name and strlen(name) > 0 then
|
||||
local n, _ = strsplit(":", name)
|
||||
n = gsub(n, "([^%s]*)%s+([^%s]*)%s+([^%s]*)", "%3")
|
||||
n = gsub(n, "([^%s]*)%s+([^%s]*)", "%2")
|
||||
if IsShiftKeyDown() and ChatFrameEditBox:IsVisible() then
|
||||
ChatFrameEditBox:Insert("|cffffffff|Hplayer:"..n.."|h["..n.."]|h|r")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
HookSetItemRef(link, text, button)
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Right-click ignore
|
||||
-- --------------------------------------------------------
|
||||
UnitPopupButtons["IGNORE_PLAYER"] = { text = "Ignore", dist = 0 }
|
||||
for index, value in ipairs(UnitPopupMenus["FRIEND"]) do
|
||||
if value == "GUILD_LEAVE" then
|
||||
table.insert(UnitPopupMenus["FRIEND"], index+1, "IGNORE_PLAYER")
|
||||
end
|
||||
end
|
||||
hooksecurefunc("UnitPopup_OnClick", function(self)
|
||||
if this.value == "IGNORE_PLAYER" then
|
||||
AddIgnore(_G[UIDROPDOWNMENU_INIT_MENU].name)
|
||||
end
|
||||
end)
|
||||
|
||||
-- --------------------------------------------------------
|
||||
-- Social colors: guild, friends, who lists
|
||||
-- --------------------------------------------------------
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["players"] = ShaguTweaks_cache["players"] or {}
|
||||
local playerdb = ShaguTweaks_cache["players"]
|
||||
|
||||
local socialmod = CreateFrame("Frame", "ShaguTweaksSocialMod", UIParent)
|
||||
socialmod:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||
socialmod:SetScript("OnEvent", function()
|
||||
local name = cmatch(arg1, _G.ERR_FRIEND_ONLINE_SS)
|
||||
name = cmatch(arg1, _G.ERR_FRIEND_OFFLINE_S)
|
||||
if name and playerdb[name] and playerdb[name].cname then
|
||||
playerdb[name].lastseen = date("%a %d-%b-%Y")
|
||||
end
|
||||
end)
|
||||
|
||||
hooksecurefunc("GuildStatus_Update", function()
|
||||
local playerzone = GetRealZoneText()
|
||||
local off = FauxScrollFrame_GetOffset(GuildListScrollFrame)
|
||||
local _, _, playerrankindex = GetGuildInfo("player")
|
||||
for i=1, GUILDMEMBERS_TO_DISPLAY do
|
||||
local name, _, rankindex, level, class, zone, _, _, online = GetGuildRosterInfo(off + i)
|
||||
class = L["class"][class]
|
||||
if name then
|
||||
if class then
|
||||
local color = RAID_CLASS_COLORS[class]
|
||||
local alpha = online and 1 or .5
|
||||
_G["GuildFrameButton"..i.."Name"]:SetTextColor(color.r, color.g, color.b, alpha)
|
||||
_G["GuildFrameButton"..i.."Class"]:SetTextColor(color.r, color.g, color.b, alpha)
|
||||
_G["GuildFrameGuildStatusButton"..i.."Name"]:SetTextColor(color.r, color.g, color.b, alpha)
|
||||
end
|
||||
if level then
|
||||
local color = GetDifficultyColor(level)
|
||||
local alpha = online and 1 or .5
|
||||
_G["GuildFrameButton"..i.."Level"]:SetTextColor(color.r+.2, color.g+.2, color.b+.2, alpha)
|
||||
end
|
||||
if zone and zone == playerzone then
|
||||
local alpha = online and 1 or .5
|
||||
_G["GuildFrameButton"..i.."Zone"]:SetTextColor(.5, 1, 1, alpha)
|
||||
end
|
||||
if rankindex and rankindex == playerrankindex then
|
||||
local alpha = online and 1 or .5
|
||||
_G["GuildFrameGuildStatusButton"..i.."Rank"]:SetTextColor(.5, 1, 1, alpha)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local FRIENDS_NAME_LOCATION = GetExpansion() == "vanilla" and "ButtonTextNameLocation" or "ButtonTextLocation"
|
||||
hooksecurefunc("FriendsList_Update", function()
|
||||
if GetNumFriends() == 0 then return end
|
||||
local playerzone = GetRealZoneText()
|
||||
local off = FauxScrollFrame_GetOffset(FriendsFrameFriendsScrollFrame)
|
||||
for i=1, FRIENDS_TO_DISPLAY do
|
||||
local name, level, class, zone, connected, status = GetFriendInfo(off + i)
|
||||
if not name or name == _G.UNKNOWN then break end
|
||||
local friendName = _G["FriendsFrameFriendButton"..i.."ButtonTextName"]
|
||||
local friendLoc = _G["FriendsFrameFriendButton"..i..FRIENDS_NAME_LOCATION]
|
||||
local friendInfo = _G["FriendsFrameFriendButton"..i.."ButtonTextInfo"]
|
||||
local caption = friendName or friendLoc
|
||||
if connected then
|
||||
if not class or class == _G.UNKNOWN then break end
|
||||
local ccolor = RAID_CLASS_COLORS[L["class"][class]] or { 1,1,1 }
|
||||
local lcolor = GetDifficultyColor(tonumber(level)) or { 1,1,1 }
|
||||
zone = (zone == playerzone and "|cffffffff" or "|cffcccccc") .. zone .. "|r"
|
||||
local cname = rgbhex(ccolor) .. name .. "|r"
|
||||
local clevel = rgbhex(lcolor) .. level .. "|r"
|
||||
if playerdb[name] then
|
||||
playerdb[name].lastseen = date("%a %d-%b-%Y")
|
||||
playerdb[name].cname = cname
|
||||
playerdb[name].clevel = clevel
|
||||
playerdb[name].cclass = ccolor
|
||||
end
|
||||
if friendName then
|
||||
friendName:SetText(cname)
|
||||
friendLoc:SetText(format(TEXT(FRIENDS_LIST_TEMPLATE), zone, status))
|
||||
else
|
||||
friendLoc:SetText(format(TEXT(FRIENDS_LIST_TEMPLATE), cname, zone, status))
|
||||
end
|
||||
friendInfo:SetText(format(TEXT(friendinfo), clevel, class, ""))
|
||||
caption:SetVertexColor(1,1,1,.9)
|
||||
friendInfo:SetVertexColor(1,1,1,.9)
|
||||
else
|
||||
if playerdb[name] and playerdb[name].cname and playerdb[name].clevel and playerdb[name].lastseen then
|
||||
caption:SetText(format(TEXT(FRIENDS_LIST_OFFLINE_TEMPLATE), playerdb[name].cname))
|
||||
friendInfo:SetText(format(TEXT(friendinfo), playerdb[name].clevel, playerdb[name].lastseen, ""))
|
||||
else
|
||||
caption:SetText(format(TEXT(FRIENDS_LIST_OFFLINE_TEMPLATE), name.."|r"))
|
||||
friendInfo:SetText(TEXT(UNKNOWN))
|
||||
end
|
||||
caption:SetVertexColor(1,1,1,.4)
|
||||
friendInfo:SetVertexColor(1,1,1,.4)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hooksecurefunc("WhoList_Update", function()
|
||||
local num, max = GetNumWhoResults()
|
||||
local off = FauxScrollFrame_GetOffset(WhoListScrollFrame)
|
||||
local playerzone = GetRealZoneText()
|
||||
local playerrace = UnitRace("player")
|
||||
local playerguild = GetGuildInfo("player")
|
||||
for i=1, WHOS_TO_DISPLAY do
|
||||
local name, guild, level, race, class, zone = GetWhoInfo(off + i)
|
||||
local displayedText = ""
|
||||
if num + 1 >= MAX_WHOS_FROM_SERVER then
|
||||
displayedText = format(WHO_FRAME_SHOWN_TEMPLATE, MAX_WHOS_FROM_SERVER)
|
||||
WhoFrameTotals:SetText("|cffffffff"..format(GetText("WHO_FRAME_TOTAL_TEMPLATE",nil,num),max).." |cffaaaaaa"..displayedText)
|
||||
else
|
||||
displayedText = format(WHO_FRAME_SHOWN_TEMPLATE, num)
|
||||
WhoFrameTotals:SetText("|cffffffff"..format(GetText("WHO_FRAME_TOTAL_TEMPLATE",nil,num),num).." |cffaaaaaa"..displayedText)
|
||||
end
|
||||
class = L["class"][class]
|
||||
_G["WhoFrameButton"..i.."Name"]:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
|
||||
if UIDropDownMenu_GetSelectedID(WhoFrameDropDown) == 1 then
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(zone == playerzone and .5 or 1, 1, 1)
|
||||
elseif UIDropDownMenu_GetSelectedID(WhoFrameDropDown) == 2 then
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(guild == playerguild and .5 or 1, 1, 1)
|
||||
elseif UIDropDownMenu_GetSelectedID(WhoFrameDropDown) == 3 then
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(race == playerrace and .5 or 1, 1, 1)
|
||||
end
|
||||
if class then
|
||||
local color = RAID_CLASS_COLORS[class]
|
||||
_G["WhoFrameButton"..i.."Class"]:SetTextColor(color.r, color.g, color.b, 1)
|
||||
end
|
||||
local color = GetDifficultyColor(level)
|
||||
_G["WhoFrameButton"..i.."Level"]:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,125 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local hooksecurefunc = hooksecurefunc or ShaguTweaks.hooksecurefunc
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local AddBorder = ShaguTweaks.AddBorder
|
||||
local TimeConvert = ShaguTweaks.TimeConvert
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Cooldown Numbers"],
|
||||
description = T["Display the remaining duration as text on every cooldown."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
enabled = true,
|
||||
color = { r = .3, g = .3, b = .3, a = .9}
|
||||
})
|
||||
|
||||
local function CooldownOnUpdate()
|
||||
-- hide frames without parent
|
||||
local parent = this:GetParent()
|
||||
if not parent then this:Hide() end
|
||||
|
||||
if not this.tick then this.tick = GetTime() + .1 end
|
||||
if this.tick > GetTime() then return end
|
||||
this.tick = GetTime() + .1
|
||||
|
||||
-- fix own alpha value (should be inherited, but somehow isn't always)
|
||||
this:SetAlpha(parent:GetAlpha())
|
||||
|
||||
if this.start < GetTime() then
|
||||
-- calculating remaining time as it should be
|
||||
local remaining = this.duration - (GetTime() - this.start)
|
||||
if remaining > 0 then
|
||||
this.text:SetText(TimeConvert(remaining))
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
else
|
||||
-- I have absolutely no idea, but it works:
|
||||
-- https://github.com/Stanzilla/WoWUIBugs/issues/47
|
||||
local time = time()
|
||||
local startupTime = time - GetTime()
|
||||
-- just a simplification of: ((2^32) - (start * 1000)) / 1000
|
||||
local cdTime = (2 ^ 32) / 1000 - this.start
|
||||
local cdStartTime = startupTime - cdTime
|
||||
local cdEndTime = cdStartTime + this.duration
|
||||
local remaining = cdEndTime - time
|
||||
|
||||
if remaining >= 0 then
|
||||
this.text:SetText(TimeConvert(remaining))
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateCoolDown(cooldown, start, duration)
|
||||
local parent = cooldown:GetParent()
|
||||
if not parent then return end
|
||||
|
||||
-- skip already set debuff timers
|
||||
if cooldown.readable then return end
|
||||
|
||||
local parentname = parent and parent.GetName and parent:GetName()
|
||||
parentname = parentname or "UnknownCooldownFrame"
|
||||
|
||||
cooldown.cooldowntext = CreateFrame("Frame", parentname .. "CooldownText", cooldown)
|
||||
cooldown.cooldowntext:SetAllPoints(cooldown)
|
||||
cooldown.cooldowntext:SetFrameLevel(parent:GetFrameLevel() + 1)
|
||||
cooldown.cooldowntext.text = cooldown.cooldowntext:CreateFontString(parentname .. "CooldownTextFont", "OVERLAY")
|
||||
|
||||
-- detect dynamic font size
|
||||
local size = parent:GetHeight() or 0
|
||||
size = size > 0 and size * .64 or 12
|
||||
size = size > 14 and 14 or size
|
||||
|
||||
-- set fonts
|
||||
cooldown.cooldowntext.text:SetFont(STANDARD_TEXT_FONT, size, "OUTLINE")
|
||||
cooldown.cooldowntext.text:SetPoint("CENTER", cooldown.cooldowntext, "CENTER", 0, 0)
|
||||
cooldown.cooldowntext:SetScript("OnUpdate", CooldownOnUpdate)
|
||||
end
|
||||
|
||||
local function SetCooldown(this, start, duration, enable)
|
||||
-- add support for omnicc's disable flag
|
||||
if this.noCooldownCount then return end
|
||||
|
||||
-- skip ShaguPlates-owned frames (nameplates etc.)
|
||||
if this.pfCooldownType then return end
|
||||
|
||||
-- don't draw global cooldowns
|
||||
if not duration or duration < 2 then
|
||||
-- hide if already existing
|
||||
if this.cooldowntext then
|
||||
this.cooldowntext:Hide()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if not this.cooldowntext then
|
||||
CreateCoolDown(this, start, duration)
|
||||
end
|
||||
|
||||
if this.cooldowntext then
|
||||
if start > 0 and duration > 0 and (not enable or enable > 0) then
|
||||
this.cooldowntext:Show()
|
||||
else
|
||||
this.cooldowntext:Hide()
|
||||
end
|
||||
|
||||
this.cooldowntext.start = start
|
||||
this.cooldowntext.duration = duration
|
||||
end
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
if GetExpansion() == "vanilla" then
|
||||
-- vanilla does not have a cooldown frame type, so we hook the
|
||||
-- regular SetTimer function that each one is calling.
|
||||
hooksecurefunc("CooldownFrame_SetTimer", SetCooldown)
|
||||
else
|
||||
-- tbc and later expansion have a cooldown frametype, so we can
|
||||
-- hook directly into the frame creation and add our function there.
|
||||
local methods = getmetatable(CreateFrame('Cooldown', nil, nil, 'CooldownFrameTemplate')).__index
|
||||
hooksecurefunc(methods, 'SetCooldown', SetCooldown)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
-- This module can be used to add your own custom code.
|
||||
-- Make sure to read the comments carefully.
|
||||
|
||||
-- Remove the following line to activate the module:
|
||||
if true then return end
|
||||
|
||||
-- This table holds the meta-data of the module:
|
||||
local module = ShaguTweaks:register({
|
||||
title = "Custom Settings",
|
||||
description = "Custom code: Have a look at mods/custom.lua",
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = nil,
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
-- Global code:
|
||||
-- This is where you can put your most basic variable assignments.
|
||||
-- Code in this scope will *always* run, no matter if the module is enabled or not.
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
|
||||
module.enable = function(self)
|
||||
-- Module code:
|
||||
-- This is where you should put your changes.
|
||||
-- Code in this scope will *only* if the module is enabled.
|
||||
|
||||
-- Example:
|
||||
-- Hide actionbar textures:
|
||||
-- for i = 0, 4 do
|
||||
-- _G["MainMenuMaxLevelBar"..i]:Hide()
|
||||
-- _G["MainMenuBarTexture"..i]:Hide()
|
||||
-- end
|
||||
end
|
||||
@@ -0,0 +1,287 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local HookAddonOrVariable = ShaguTweaks.HookAddonOrVariable
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local AddBorder = ShaguTweaks.AddBorder
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Darkened UI"],
|
||||
description = T["Turns the entire interface into darker colors."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
enabled = nil,
|
||||
config = {
|
||||
["darkmode.color"] = { r = .3, g = .3, b = .3, a = .9 }
|
||||
}
|
||||
})
|
||||
|
||||
local blacklist = {
|
||||
["Solid Texture"] = true,
|
||||
["WHITE8X8"] = true,
|
||||
["StatusBar"] = true,
|
||||
["BarFill"] = true,
|
||||
["Portrait"] = true,
|
||||
["Button"] = true,
|
||||
["Icon"] = true,
|
||||
["AddOns"] = true,
|
||||
["StationeryTest"] = true,
|
||||
["TargetDead"] = true, -- LootFrame Icon
|
||||
["^KeyRing"] = true, -- bag frame
|
||||
["GossipIcon"] = true,
|
||||
["WorldMap\\(.+)\\"] = true,
|
||||
["PetHappiness"] = true,
|
||||
["Elite"] = true,
|
||||
["Rare"] = true,
|
||||
["ColorPickerWheel"] = true,
|
||||
["ComboPoint"] = true,
|
||||
["Skull"] = true,
|
||||
|
||||
-- LFT:
|
||||
["battlenetworking0"] = true,
|
||||
["damage"] = true,
|
||||
["tank"] = true,
|
||||
["healer"] = true,
|
||||
}
|
||||
|
||||
local regionskips = {
|
||||
-- colorpicker gradient
|
||||
["ColorPickerFrame"] = { [15] = true },
|
||||
-- EQL3: background art tiles on the main frame - BookIcon(1), TopLeft(2), Top_Switch_Off(3), BottomLeft(4), Bottom_Switch_Off(5), Top_Switch_On(6), Bottom_Switch_On(7)
|
||||
["EQL3_QuestLogFrame"] = { [1]=true, [2]=true, [3]=true, [4]=true, [5]=true, [6]=true, [7]=true },
|
||||
-- EQL3: parchment tiles on the description panel - TopMiddle(1), TopRight(2), BottomMiddle(3), BottomRight(4)
|
||||
["EQL3_QuestLogFrame_Description"] = { [1]=true, [2]=true, [3]=true, [4]=true },
|
||||
}
|
||||
|
||||
local backgrounds = {
|
||||
["^SpellBookFrame$"] = { 325, 355, 17, -74 },
|
||||
["^ItemTextFrame$"] = { 300, 355, 24, -74 },
|
||||
["^QuestLogDetailScrollFrame$"] = { QuestLogDetailScrollChildFrame:GetWidth(), QuestLogDetailScrollChildFrame:GetHeight(), 0, 0 },
|
||||
["^QuestFrame(.+)Panel$"] = { 300, 330, 24, -82 },
|
||||
["^GossipFrameGreetingPanel$"] = { 300, 330, 24, -82 },
|
||||
}
|
||||
|
||||
local borders = {
|
||||
["ShapeshiftButton"] = 3,
|
||||
["BuffButton"] = 3,
|
||||
["TargetFrameBuff"] = 3,
|
||||
["TempEnchant"] = 3,
|
||||
["SpellButton"] = 3,
|
||||
["SpellBookSkillLineTab"] = 3,
|
||||
["ActionButton%d+$"] = 3,
|
||||
["MultiBar(.+)Button%d+$"] = 3,
|
||||
["KeyRingButton"] = 2,
|
||||
["ActionBarUpButton"] = -3,
|
||||
["ActionBarDownButton"] = -3,
|
||||
["MainMenuBarPerformanceBarFrameButton"] = { -12, -1, -8, 4 },
|
||||
["Character(.+)Slot$"] = 3,
|
||||
["Inspect(.+)Slot$"] = 3,
|
||||
["ContainerFrame(.+)Item"] = 3,
|
||||
["MainMenuBarBackpackButton$"] = 3,
|
||||
["CharacterBag(.+)Slot$"] = 3,
|
||||
["ChatFrame(.+)Button"] = -2,
|
||||
["PetFrameHappiness"] = 2,
|
||||
["MicroButton"] = { -21, 0, 0, 0 },
|
||||
}
|
||||
|
||||
local addonframes = {
|
||||
["Blizzard_TalentUI"] = { "TalentFrame" },
|
||||
["Blizzard_AuctionUI"] = { "AuctionFrame", "AuctionDressUpFrame" },
|
||||
["Blizzard_CraftUI"] = { "CraftFrame" },
|
||||
["Blizzard_InspectUI"] = { "InspectPaperDollFrame", "InspectHonorFrame", "InspectFrameTab1", "InspectFrameTab2" },
|
||||
["Blizzard_MacroUI"] = { "MacroFrame", "MacroPopupFrame" },
|
||||
["Blizzard_RaidUI"] = { "ReadyCheckFrame" },
|
||||
["Blizzard_TalentUI"] = { "TalentFrame" },
|
||||
["Blizzard_TradeSkillUI"] = { "TradeSkillFrame" },
|
||||
["Blizzard_TrainerUI"] = { "ClassTrainerFrame" },
|
||||
}
|
||||
|
||||
-- sizing is a bit different on tbc
|
||||
if GetExpansion() == "tbc" then
|
||||
borders["BuffButton"] = 2
|
||||
borders["TempEnchant"] = 2
|
||||
borders["MicroButton"] = { -21, 0, 0, 0 }
|
||||
end
|
||||
|
||||
local function IsBlacklisted(texture)
|
||||
local name = texture:GetName()
|
||||
local texture = texture:GetTexture()
|
||||
if not texture then return true end
|
||||
|
||||
if name then
|
||||
for entry in pairs(blacklist) do
|
||||
if string.find(name, entry, 1) then return true end
|
||||
end
|
||||
end
|
||||
|
||||
for entry in pairs(blacklist) do
|
||||
if string.find(texture, entry, 1) then return true end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function AddSpecialBackground(frame, w, h, x, y)
|
||||
frame.Material = frame.Material or frame:CreateTexture(nil, "OVERLAY")
|
||||
frame.Material:SetTexture("Interface\\Stationery\\StationeryTest1")
|
||||
frame.Material:SetWidth(w)
|
||||
frame.Material:SetHeight(h)
|
||||
frame.Material:SetPoint("TOPLEFT", frame, x, y)
|
||||
frame.Material:SetVertexColor(.8, .8, .8)
|
||||
end
|
||||
|
||||
local function DarkenFrame(frame, r, g, b, a)
|
||||
-- dont't do anything if disabled
|
||||
if not ShaguTweaks.DarkMode then return end
|
||||
|
||||
-- set defaults
|
||||
if not r and not g and not b then
|
||||
r, g, b, a = module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, module.config["darkmode.color"].a
|
||||
end
|
||||
|
||||
-- iterate through all subframes
|
||||
if frame and frame.GetChildren then
|
||||
for _, frame in pairs({frame:GetChildren()}) do
|
||||
DarkenFrame(frame, r, g, b, a)
|
||||
end
|
||||
end
|
||||
|
||||
-- set vertex on all regions
|
||||
if frame and frame.GetRegions then
|
||||
-- read name
|
||||
local name = frame.GetName and frame:GetName()
|
||||
|
||||
-- set a dark backdrop border color everywhere
|
||||
frame:SetBackdropBorderColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, module.config["darkmode.color"].a)
|
||||
|
||||
-- add special backgrounds to quests and such
|
||||
for pattern, inset in pairs(backgrounds) do
|
||||
if name and string.find(name, pattern) then AddSpecialBackground(frame, inset[1], inset[2], inset[3], inset[4]) end
|
||||
end
|
||||
|
||||
-- add black borders around specified buttons
|
||||
for pattern, inset in pairs(borders) do
|
||||
if name and string.find(name, pattern) then AddBorder(frame, inset, module.config["darkmode.color"]) end
|
||||
end
|
||||
|
||||
-- scan through all regions (textures)
|
||||
for id, region in pairs({frame:GetRegions()}) do
|
||||
if region.SetVertexColor and region:GetObjectType() == "Texture" then
|
||||
if region:GetTexture() and string.find(region:GetTexture(), "UI%-Panel%-Button%-Up") then
|
||||
-- monochrome buttons
|
||||
-- region:SetDesaturated(true)
|
||||
elseif name and id and regionskips[name] and regionskips[name][id] then
|
||||
-- skip special regions
|
||||
elseif region.GetBlendMode and region:GetBlendMode() == "ADD" then
|
||||
-- skip blend over textures
|
||||
elseif IsBlacklisted(region) then
|
||||
-- skip blacklisted texture names
|
||||
else
|
||||
region:SetVertexColor(r,g,b,a)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- register darken frame to global
|
||||
ShaguTweaks.DarkenFrame = DarkenFrame
|
||||
|
||||
module.enable = function(self)
|
||||
ShaguTweaks.DarkMode = true
|
||||
|
||||
local name, original, r, g, b
|
||||
local hookBuffButton_Update = BuffButton_Update
|
||||
function BuffButton_Update(buttonName, index, filter)
|
||||
hookBuffButton_Update(buttonName, index, filter)
|
||||
|
||||
-- tbc passes buttonName and index arguments, vanilla uses "this" context
|
||||
name = buttonName and index and buttonName .. index or this:GetName()
|
||||
original = _G[name.."Border"]
|
||||
|
||||
if original and this.ShaguTweaks_border then
|
||||
r, g, b = original:GetVertexColor()
|
||||
this.ShaguTweaks_border:SetBackdropBorderColor(r, g, b, 1)
|
||||
original:SetAlpha(0)
|
||||
elseif not original and _G[name] then
|
||||
-- tbc buff buttons don't have borders, so we
|
||||
-- need to manually add a dark one.
|
||||
AddBorder(_G[name], 2, module.config["darkmode.color"])
|
||||
end
|
||||
end
|
||||
|
||||
TOOLTIP_DEFAULT_COLOR.r = module.config["darkmode.color"].r
|
||||
TOOLTIP_DEFAULT_COLOR.g = module.config["darkmode.color"].g
|
||||
TOOLTIP_DEFAULT_COLOR.b = module.config["darkmode.color"].b
|
||||
|
||||
TOOLTIP_DEFAULT_BACKGROUND_COLOR.r = module.config["darkmode.color"].r
|
||||
TOOLTIP_DEFAULT_BACKGROUND_COLOR.g = module.config["darkmode.color"].g
|
||||
TOOLTIP_DEFAULT_BACKGROUND_COLOR.b = module.config["darkmode.color"].b
|
||||
|
||||
DarkenFrame(UIParent)
|
||||
DarkenFrame(WorldMapFrame)
|
||||
DarkenFrame(DropDownList1)
|
||||
DarkenFrame(DropDownList2)
|
||||
DarkenFrame(DropDownList3)
|
||||
|
||||
-- align all actionbutton textures
|
||||
local bars = { "Action", "BonusAction", "MultiBarBottomLeft", "MultiBarBottomRight", "MultiBarLeft", "MultiBarRight", "Shapeshift" }
|
||||
for _, prefix in pairs(bars) do
|
||||
for i = 1, NUM_ACTIONBAR_BUTTONS do
|
||||
local button = _G[prefix .. "Button" .. i]
|
||||
local texture = _G[prefix.."Button"..i.."NormalTexture"]
|
||||
|
||||
if button and texture then
|
||||
texture:SetWidth(60)
|
||||
texture:SetHeight(60)
|
||||
texture:SetPoint("CENTER", 0, 0)
|
||||
ShaguTweaks.AddBorder(button, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, button in pairs({ MinimapZoomOut, MinimapZoomIn }) do
|
||||
for _, func in pairs({ "GetNormalTexture", "GetDisabledTexture", "GetPushedTexture" }) do
|
||||
if button[func] then
|
||||
local tex = button[func](button)
|
||||
if tex then
|
||||
tex:SetVertexColor(module.config["darkmode.color"].r+.2, module.config["darkmode.color"].g+.2, module.config["darkmode.color"].b+.2, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
HookAddonOrVariable("Blizzard_AuctionUI", function()
|
||||
for i = 1, 15 do
|
||||
local tex = _G["AuctionFilterButton"..i]:GetNormalTexture()
|
||||
tex:SetVertexColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, 1)
|
||||
end
|
||||
|
||||
for i = 1, 8 do
|
||||
_G["BrowseButton"..i.."Left"]:SetVertexColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, 1)
|
||||
_G["BrowseButton"..i.."Right"]:SetVertexColor(module.config["darkmode.color"].r, module.config["darkmode.color"].g, module.config["darkmode.color"].b, 1)
|
||||
end
|
||||
end)
|
||||
|
||||
for addon, data in pairs(addonframes) do
|
||||
for _, frame in pairs(data) do
|
||||
local frame = frame
|
||||
HookAddonOrVariable(frame, function()
|
||||
DarkenFrame(_G[frame])
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
HookAddonOrVariable("Blizzard_TimeManager", function()
|
||||
DarkenFrame(TimeManagerClockButton)
|
||||
end)
|
||||
|
||||
HookAddonOrVariable("GameTooltipStatusBarBackdrop", function()
|
||||
DarkenFrame(_G["GameTooltipStatusBarBackdrop"])
|
||||
end)
|
||||
|
||||
table.insert(ShaguTweaks.libnameplate.OnUpdate, function()
|
||||
if not this.darkened then
|
||||
this.darkened = true
|
||||
DarkenFrame(this)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,218 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Equip Compare"],
|
||||
description = T["Shows currently equipped items on tooltips while the shift key is pressed."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Tooltip & Items"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local sides = { "Left", "Right" }
|
||||
|
||||
local function AddHeader(tooltip)
|
||||
local name = tooltip:GetName()
|
||||
|
||||
-- shift all entries one line down
|
||||
for i=tooltip:NumLines(), 1, -1 do
|
||||
for _, side in pairs(sides) do
|
||||
local current = _G[name.."Text"..side..i]
|
||||
local below = _G[name.."Text"..side..i+1]
|
||||
|
||||
if current and current:IsShown() then
|
||||
local text = current:GetText()
|
||||
local r, g, b = current:GetTextColor()
|
||||
|
||||
if text and text ~= "" then
|
||||
if tooltip:NumLines() < i+1 then
|
||||
-- add new line if required
|
||||
tooltip:AddLine(text, r, g, b, true)
|
||||
else
|
||||
-- update existing lines
|
||||
below:SetText(text)
|
||||
below:SetTextColor(r, g, b)
|
||||
below:Show()
|
||||
|
||||
-- hide processed line
|
||||
current:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- add label to first line
|
||||
_G[name.."TextLeft1"]:SetTextColor(.5, .5, .5, 1)
|
||||
_G[name.."TextLeft1"]:SetText(CURRENTLY_EQUIPPED)
|
||||
_G[name.."TextLeft1"]:Show()
|
||||
|
||||
-- update tooltip sizes
|
||||
tooltip:Show()
|
||||
end
|
||||
|
||||
local itemtypes = {
|
||||
["deDE"] = {
|
||||
["INVTYPE_WAND"] = "Zauberstab",
|
||||
["INVTYPE_THROWN"] = "Wurfwaffe",
|
||||
["INVTYPE_GUN"] = "Schusswaffe",
|
||||
["INVTYPE_CROSSBOW"] = "Armbrust",
|
||||
["INVTYPE_PROJECTILE"] = "Projektil",
|
||||
},
|
||||
["enUS"] = {
|
||||
["INVTYPE_WAND"] = "Wand",
|
||||
["INVTYPE_THROWN"] = "Thrown",
|
||||
["INVTYPE_GUN"] = "Gun",
|
||||
["INVTYPE_CROSSBOW"] = "Crossbow",
|
||||
["INVTYPE_PROJECTILE"] = "Projectile",
|
||||
},
|
||||
["esES"] = {
|
||||
["INVTYPE_WAND"] = "Varita",
|
||||
["INVTYPE_THROWN"] = "Arma arrojadiza",
|
||||
["INVTYPE_GUN"] = "Arma de fuego",
|
||||
["INVTYPE_CROSSBOW"] = "Ballesta",
|
||||
["INVTYPE_PROJECTILE"] = "Proyectil",
|
||||
},
|
||||
["frFR"] = {
|
||||
["INVTYPE_WAND"] = "Baguette",
|
||||
["INVTYPE_THROWN"] = "Armes de jet",
|
||||
["INVTYPE_GUN"] = "Arme à feu",
|
||||
["INVTYPE_CROSSBOW"] = "Arbalète",
|
||||
["INVTYPE_PROJECTILE"] = "Projectile",
|
||||
},
|
||||
["koKR"] = {
|
||||
["INVTYPE_WAND"] = "마법봉",
|
||||
["INVTYPE_THROWN"] = "투척 무기",
|
||||
["INVTYPE_GUN"] = "총",
|
||||
["INVTYPE_CROSSBOW"] = "석궁",
|
||||
["INVTYPE_PROJECTILE"] = "투사체",
|
||||
},
|
||||
["ruRU"] = {
|
||||
["INVTYPE_WAND"] = "Жезл",
|
||||
["INVTYPE_THROWN"] = "Метательное",
|
||||
["INVTYPE_GUN"] = "Огнестрельное",
|
||||
["INVTYPE_CROSSBOW"] = "Арбалет",
|
||||
["INVTYPE_PROJECTILE"] = "Боеприпасы",
|
||||
},
|
||||
["zhCN"] = {
|
||||
["INVTYPE_WAND"] = "魔杖",
|
||||
["INVTYPE_THROWN"] = "投掷武器",
|
||||
["INVTYPE_GUN"] = "枪械",
|
||||
["INVTYPE_CROSSBOW"] = "弩",
|
||||
["INVTYPE_PROJECTILE"] = "弹药",
|
||||
}
|
||||
}
|
||||
|
||||
-- set globals for all inventory types
|
||||
for key, value in pairs(itemtypes[GetLocale()]) do setglobal(key, value) end
|
||||
INVTYPE_WEAPON_OTHER = INVTYPE_WEAPON.."_other"
|
||||
INVTYPE_FINGER_OTHER = INVTYPE_FINGER.."_other"
|
||||
INVTYPE_TRINKET_OTHER = INVTYPE_TRINKET.."_other"
|
||||
|
||||
local slots = {
|
||||
[INVTYPE_2HWEAPON] = "MainHandSlot",
|
||||
[INVTYPE_BODY] = "ShirtSlot",
|
||||
[INVTYPE_CHEST] = "ChestSlot",
|
||||
[INVTYPE_CLOAK] = "BackSlot",
|
||||
[INVTYPE_FEET] = "FeetSlot",
|
||||
[INVTYPE_FINGER] = "Finger0Slot",
|
||||
[INVTYPE_FINGER_OTHER] = "Finger1Slot",
|
||||
[INVTYPE_HAND] = "HandsSlot",
|
||||
[INVTYPE_HEAD] = "HeadSlot",
|
||||
[INVTYPE_HOLDABLE] = "SecondaryHandSlot",
|
||||
[INVTYPE_LEGS] = "LegsSlot",
|
||||
[INVTYPE_NECK] = "NeckSlot",
|
||||
[INVTYPE_RANGED] = "RangedSlot",
|
||||
[INVTYPE_RELIC] = "RangedSlot",
|
||||
[INVTYPE_ROBE] = "ChestSlot",
|
||||
[INVTYPE_SHIELD] = "SecondaryHandSlot",
|
||||
[INVTYPE_SHOULDER] = "ShoulderSlot",
|
||||
[INVTYPE_TABARD] = "TabardSlot",
|
||||
[INVTYPE_TRINKET] = "Trinket0Slot",
|
||||
[INVTYPE_TRINKET_OTHER] = "Trinket1Slot",
|
||||
[INVTYPE_WAIST] = "WaistSlot",
|
||||
[INVTYPE_WEAPON] = "MainHandSlot",
|
||||
[INVTYPE_WEAPON_OTHER] = "SecondaryHandSlot",
|
||||
[INVTYPE_WEAPONMAINHAND] = "MainHandSlot",
|
||||
[INVTYPE_WEAPONOFFHAND] = "SecondaryHandSlot",
|
||||
[INVTYPE_WRIST] = "WristSlot",
|
||||
[INVTYPE_WAND] = "RangedSlot",
|
||||
[INVTYPE_GUN] = "RangedSlot",
|
||||
[INVTYPE_PROJECTILE] = "AmmoSlot",
|
||||
[INVTYPE_CROSSBOW] = "RangedSlot",
|
||||
[INVTYPE_THROWN] = "RangedSlot",
|
||||
}
|
||||
|
||||
ShoppingTooltip1:SetClampedToScreen(true)
|
||||
ShoppingTooltip2:SetClampedToScreen(true)
|
||||
|
||||
local function ShowCompare(tooltip)
|
||||
-- abort if shift is not pressed
|
||||
if not IsShiftKeyDown() then
|
||||
ShoppingTooltip1:Hide()
|
||||
ShoppingTooltip2:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
for i=1,tooltip:NumLines() do
|
||||
local tmpText = _G[tooltip:GetName() .. "TextLeft"..i]
|
||||
|
||||
for slotType, slotName in pairs(slots) do
|
||||
if tmpText:GetText() == slotType then
|
||||
local slotID = GetInventorySlotInfo(slotName)
|
||||
|
||||
-- determine screen part
|
||||
local x = GetCursorPosition() / UIParent:GetEffectiveScale()
|
||||
local anchor = x < GetScreenWidth() / 2 and "TOPLEFT" or "TOPRIGHT"
|
||||
local relative = x < GetScreenWidth() / 2 and "TOPRIGHT" or "TOPLEFT"
|
||||
|
||||
-- overwrite position for tooltips without owner
|
||||
local pos, parent = tooltip:GetPoint()
|
||||
if parent and parent == UIParent and pos == "TOPRIGHT" then
|
||||
anchor = "TOPRIGHT"
|
||||
relative = "TOPLEFT"
|
||||
end
|
||||
|
||||
-- first tooltip
|
||||
ShoppingTooltip1:SetOwner(tooltip, "ANCHOR_NONE")
|
||||
ShoppingTooltip1:ClearAllPoints()
|
||||
ShoppingTooltip1:SetPoint(anchor, tooltip, relative, 0, 0)
|
||||
ShoppingTooltip1:SetInventoryItem("player", slotID)
|
||||
ShoppingTooltip1:Show()
|
||||
AddHeader(ShoppingTooltip1)
|
||||
|
||||
-- second tooltip
|
||||
if slots[slotType .. "_other"] then
|
||||
local slotID_other = GetInventorySlotInfo(slots[slotType .. "_other"])
|
||||
ShoppingTooltip2:SetOwner(tooltip, "ANCHOR_NONE")
|
||||
ShoppingTooltip2:ClearAllPoints()
|
||||
if ShoppingTooltip1:IsShown() then
|
||||
ShoppingTooltip2:SetPoint(anchor, ShoppingTooltip1, relative, 0, 0)
|
||||
else
|
||||
ShoppingTooltip2:SetPoint(anchor, tooltip, relative, 0, 0)
|
||||
end
|
||||
ShoppingTooltip2:SetInventoryItem("player", slotID_other)
|
||||
ShoppingTooltip2:Show()
|
||||
AddHeader(ShoppingTooltip2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- show item compare on default tooltips
|
||||
local default = CreateFrame("Frame", nil, GameTooltip)
|
||||
default:SetScript("OnUpdate", function()
|
||||
ShowCompare(GameTooltip)
|
||||
end)
|
||||
|
||||
-- show compare on atlas tooltips
|
||||
ShaguTweaks.HookAddonOrVariable("AtlasLoot", function()
|
||||
local atlas = CreateFrame("Frame", nil, AtlasLootTooltip)
|
||||
atlas:SetScript("OnUpdate", function()
|
||||
ShowCompare(AtlasLootTooltip)
|
||||
ShowCompare(AtlasLootTooltip2)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,107 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local L, T = ShaguTweaks.L, ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Free Slot Count"],
|
||||
description = T["Shows free slot counts on the backpack button: class bag slots (top right), reagent bag slots (bottom left), and total free slots (bottom right)."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["General"],
|
||||
enabled = true,
|
||||
order = 31,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local button = MainMenuBarBackpackButton
|
||||
|
||||
button.class = button:CreateFontString("Status", "LOW", "GameFontNormal")
|
||||
button.class:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE")
|
||||
button.class:SetPoint("TOPRIGHT", button, "TOPRIGHT", -2, -4)
|
||||
button.class:SetJustifyH("RIGHT")
|
||||
button.class:SetFontObject(GameFontWhite)
|
||||
local _, playerclass = UnitClass("player")
|
||||
local classcolor = RAID_CLASS_COLORS[playerclass] or { r = .5, g = .5, b = .5, a = 1 }
|
||||
button.class:SetTextColor(classcolor.r, classcolor.g, classcolor.b)
|
||||
|
||||
button.reagent = button:CreateFontString("Status", "LOW", "GameFontNormal")
|
||||
button.reagent:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE")
|
||||
button.reagent:SetPoint("BOTTOMLEFT", button, "BOTTOMLEFT", 2, 4)
|
||||
button.reagent:SetJustifyH("LEFT")
|
||||
button.reagent:SetFontObject(GameFontWhite)
|
||||
button.reagent:SetTextColor(.25, .78, .92)
|
||||
|
||||
button.count = button:CreateFontString("Status", "LOW", "GameFontNormal")
|
||||
button.count:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE")
|
||||
button.count:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 4)
|
||||
button.count:SetJustifyH("RIGHT")
|
||||
button.count:SetFontObject(GameFontWhite)
|
||||
|
||||
-- class-specific bags
|
||||
local soul = { "Core Felcloth Bag", "D'Sak's Small bag", "Felcloth Bag", "Box of Souls", "Small Soul Pouch", "Soul Pouch" }
|
||||
local quiver = { "Ancient Sinew Wrapped Lamina", "Harpy Hide Quiver", "Heavy Quiver", "Quickdraw Quiver", "Quiver of the Night Watch", "Ribbly's Quiver", "Hunting Quiver", "Light Leather Quiver", "Light Quiver", "Medium Quiver", "Small Quiver" }
|
||||
local pouch = { "Gnoll Skin Bandolier", "Bandolier of the Night Watch", "Heavy Leather Ammo Pouch", "Ribbly's Bandolier", "Thick Leather Ammo Pouch", "Hunting Ammo Sack", "Medium Shot Pouch", "Small Ammo Pouch", "Small Leather Ammo Pouch", "Small Shot Pouch" }
|
||||
-- reagent bags
|
||||
local herb = { "Cenarion Herb Bag", "Herb Pouch", "Satchel of Cenarius" }
|
||||
local ench = { "Big Bag of Enchantment", "Enchanted Mageweave Pouch", "Enchanted Runecloth Bag" }
|
||||
|
||||
local freeClass = 0
|
||||
local freeReagent = 0
|
||||
|
||||
local function findName(name, names)
|
||||
for _, bagName in ipairs(names) do
|
||||
if string.find(name, bagName) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function classSlots()
|
||||
local found, free = false, 0
|
||||
for i = 0, 4 do
|
||||
local name = GetBagName(i)
|
||||
if name and (findName(name, soul) or findName(name, quiver) or findName(name, pouch)) then
|
||||
found = true
|
||||
for slot = 1, GetContainerNumSlots(i) do
|
||||
if not GetContainerItemLink(i, slot) then free = free + 1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
freeClass = free
|
||||
button.class:SetText(found and free or "")
|
||||
end
|
||||
|
||||
local function reagentSlots()
|
||||
local found, free = false, 0
|
||||
for i = 0, 4 do
|
||||
local name = GetBagName(i)
|
||||
if name and (findName(name, herb) or findName(name, ench)) then
|
||||
found = true
|
||||
for slot = 1, GetContainerNumSlots(i) do
|
||||
if not GetContainerItemLink(i, slot) then free = free + 1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
freeReagent = free
|
||||
button.reagent:SetText(found and free or "")
|
||||
end
|
||||
|
||||
local function freeSlots()
|
||||
local free = 0
|
||||
for i = 0, 4 do
|
||||
for slot = 1, GetContainerNumSlots(i) do
|
||||
if not GetContainerItemLink(i, slot) then free = free + 1 end
|
||||
end
|
||||
end
|
||||
button.count:SetText(free - freeClass - freeReagent)
|
||||
end
|
||||
|
||||
classSlots()
|
||||
reagentSlots()
|
||||
freeSlots()
|
||||
|
||||
local events = CreateFrame("Frame")
|
||||
events:RegisterEvent("BAG_UPDATE")
|
||||
events:SetScript("OnEvent", function()
|
||||
classSlots()
|
||||
reagentSlots()
|
||||
freeSlots()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local Abbreviate = ShaguTweaks.Abbreviate
|
||||
local GetColorGradient = ShaguTweaks.GetColorGradient
|
||||
local vanilla = ShaguTweaks.GetExpansion() == "vanilla" or nil
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Unit Frame Health Colors"],
|
||||
description = T["Change health text color based on its value."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Unit Frames"],
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local HookUnitFrame_UpdateManaType = UnitFrame_UpdateManaType
|
||||
function UnitFrame_UpdateManaType(uf)
|
||||
HookUnitFrame_UpdateManaType(uf)
|
||||
if not uf then uf = this end
|
||||
local string = uf.manabar and uf.manabar.TextString
|
||||
if not string then return end
|
||||
|
||||
if not strfind(uf.manabar:GetName(), "Health") then
|
||||
local r, g, b = uf.manabar:GetStatusBarColor()
|
||||
string:SetTextColor((r + 2) / 3, (g + 2) / 3, (b + 2) / 3, 1)
|
||||
end
|
||||
end
|
||||
|
||||
local HookTextStatusBar_UpdateTextString = TextStatusBar_UpdateTextString
|
||||
function TextStatusBar_UpdateTextString(sb)
|
||||
if not sb then sb = this end
|
||||
|
||||
HookTextStatusBar_UpdateTextString(sb)
|
||||
local string = sb.TextString
|
||||
|
||||
if string and sb.unit then
|
||||
local min, max = sb:GetMinMaxValues()
|
||||
local cur = sb:GetValue()
|
||||
local percent = max > 0 and floor(cur/max*100) or 0
|
||||
|
||||
if strfind(sb:GetName(), "Health") then
|
||||
local r, g, b = GetColorGradient(percent/100)
|
||||
string:SetTextColor((r + 1) / 2, (g + 1) / 2, (b + 1) / 2, .75)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,87 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local Abbreviate = ShaguTweaks.Abbreviate
|
||||
local GetColorGradient = ShaguTweaks.GetColorGradient
|
||||
local vanilla = ShaguTweaks.GetExpansion() == "vanilla" or nil
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Real Health Numbers"],
|
||||
description = T["Estimates health numbers, and shows numbers on player, pet and target unit frames."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Unit Frames"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
TargetFrame.StatusTexts = CreateFrame("Frame", nil, TargetFrame)
|
||||
TargetFrame.StatusTexts:SetAllPoints(TargetFrame)
|
||||
|
||||
TargetFrameHealthBar.TextString = TargetFrame.StatusTexts:CreateFontString("TargetFrameHealthBarText", "OVERLAY")
|
||||
TargetFrameHealthBar.TextString:SetPoint("TOP", TargetFrameHealthBar, "BOTTOM", -2, 23)
|
||||
|
||||
TargetFrameManaBar.TextString = TargetFrame.StatusTexts:CreateFontString("TargetFrameManaBarText", "OVERLAY")
|
||||
TargetFrameManaBar.TextString:SetPoint("TOP", TargetFrameManaBar, "BOTTOM", -2, 22)
|
||||
|
||||
PetFrameHealthBar.TextString:SetPoint("CENTER", PetFrameHealthBar, "CENTER", -2, 0)
|
||||
PetFrameManaBar.TextString:SetPoint("CENTER", PetFrameManaBar, "CENTER", -2, -2)
|
||||
|
||||
for _, frame in pairs( { TargetFrameHealthBar, TargetFrameManaBar, PlayerFrameHealthBar, PlayerFrameManaBar }) do
|
||||
frame.TextString:SetFontObject("GameFontWhite")
|
||||
frame.TextString:SetFont(STANDARD_TEXT_FONT, 10, "OUTLINE")
|
||||
frame.TextString:SetHeight(32)
|
||||
end
|
||||
|
||||
for _, frame in pairs( { PetFrameHealthBar, PetFrameManaBar }) do
|
||||
frame.TextString:SetFontObject("GameFontWhite")
|
||||
frame.TextString:SetFont(STANDARD_TEXT_FONT, 9, "OUTLINE")
|
||||
frame.TextString:SetHeight(32)
|
||||
frame.TextString:SetJustifyH("LEFT")
|
||||
end
|
||||
|
||||
local HookTextStatusBar_UpdateTextString = TextStatusBar_UpdateTextString
|
||||
function TextStatusBar_UpdateTextString(sb)
|
||||
if not sb then sb = this end
|
||||
|
||||
HookTextStatusBar_UpdateTextString(sb)
|
||||
local string = sb.TextString
|
||||
|
||||
if string and sb.unit then
|
||||
-- hide tbc text string element
|
||||
if not vanilla then
|
||||
TargetFrameHealthBarText:Hide()
|
||||
end
|
||||
|
||||
sb.lockShow = 42
|
||||
sb:Show()
|
||||
|
||||
local min, max = sb:GetMinMaxValues()
|
||||
local cur = sb:GetValue()
|
||||
local percent = max > 0 and floor(cur/max*100) or 0
|
||||
|
||||
if sb:GetName() == "TargetFrameHealthBar" then
|
||||
cur, max = ShaguTweaks.libhealth:GetUnitHealth(sb.unit)
|
||||
end
|
||||
|
||||
if cur == percent and strfind(sb:GetName(), "Health") then
|
||||
string:SetText(percent .. "/" .. percent)
|
||||
elseif sb:GetName() == "TargetFrameHealthBar" and cur < max then
|
||||
string:SetText(Abbreviate(cur) .. "/" .. Abbreviate(max) .. " - " .. percent .. "%")
|
||||
else
|
||||
string:SetText(Abbreviate(cur) .. "/" .. Abbreviate(max))
|
||||
end
|
||||
|
||||
if max == 0 then
|
||||
string:Hide()
|
||||
string:SetText("")
|
||||
elseif sb.unit == "target" and UnitIsDead("target") then
|
||||
string:Hide()
|
||||
string:SetText("")
|
||||
elseif sb.unit == "target" and UnitIsGhost("target") then
|
||||
string:Hide()
|
||||
string:SetText("")
|
||||
else
|
||||
string:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Hide Errors"],
|
||||
description = T["Hides and ignores all Lua errors produced by broken addons."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
error = function() return end
|
||||
seterrorhandler(error)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Hide Gryphons"],
|
||||
description = T["Hides the gryphons left and right of the action bar."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
MainMenuBarLeftEndCap:Hide()
|
||||
MainMenuBarRightEndCap:Hide()
|
||||
end
|
||||
@@ -0,0 +1,222 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local AddBorder = ShaguTweaks.AddBorder
|
||||
local HookAddonOrVariable = ShaguTweaks.HookAddonOrVariable
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Item Rarity Borders"],
|
||||
description = T["Show item rarity as the border color on bags, bank, character and inspect frames."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Tooltip & Items"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
local defcolor = {}
|
||||
|
||||
local paperdoll_slots = {
|
||||
[0] = "AmmoSlot", "HeadSlot",
|
||||
"NeckSlot", "ShoulderSlot",
|
||||
"ShirtSlot", "ChestSlot",
|
||||
"WaistSlot", "LegsSlot",
|
||||
"FeetSlot", "WristSlot",
|
||||
"HandsSlot", "Finger0Slot",
|
||||
"Finger1Slot", "Trinket0Slot",
|
||||
"Trinket1Slot", "BackSlot",
|
||||
"MainHandSlot", "SecondaryHandSlot",
|
||||
"RangedSlot", "TabardSlot",
|
||||
}
|
||||
|
||||
local inspect_slots = {
|
||||
"HeadSlot", "NeckSlot",
|
||||
"ShoulderSlot", "ShirtSlot",
|
||||
"ChestSlot", "WaistSlot",
|
||||
"LegsSlot", "FeetSlot",
|
||||
"WristSlot", "HandsSlot",
|
||||
"Finger0Slot", "Finger1Slot",
|
||||
"Trinket0Slot", "Trinket1Slot",
|
||||
"BackSlot", "MainHandSlot",
|
||||
"SecondaryHandSlot", "RangedSlot",
|
||||
"TabardSlot"
|
||||
}
|
||||
|
||||
module.enable = function(self)
|
||||
do -- paperdoll
|
||||
local refresh_paperdoll = function()
|
||||
for i, slot in pairs(paperdoll_slots) do
|
||||
local button = _G["Character"..slot]
|
||||
if button then
|
||||
local border = button.ShaguTweaks_border
|
||||
|
||||
if not border then
|
||||
border = AddBorder(button, 3, { r = .5, g = .5, b = .5 })
|
||||
end
|
||||
|
||||
if not defcolor["paperdoll"] then
|
||||
defcolor["paperdoll"] = { border:GetBackdropBorderColor() }
|
||||
end
|
||||
|
||||
local quality = GetInventoryItemQuality("player", i)
|
||||
if quality then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
border:SetBackdropBorderColor(r, g, b, 1)
|
||||
else
|
||||
border:SetBackdropBorderColor(defcolor["paperdoll"][1], defcolor["paperdoll"][2], defcolor["paperdoll"][3], 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local paperdoll = CreateFrame("Frame", nil, CharacterFrame)
|
||||
paperdoll:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||
paperdoll:SetScript("OnEvent", refresh_paperdoll)
|
||||
paperdoll:SetScript("OnShow", refresh_paperdoll)
|
||||
end
|
||||
|
||||
do -- inspect
|
||||
local refresh_inspect = function()
|
||||
for i, v in pairs(inspect_slots) do
|
||||
local button = _G["Inspect"..v]
|
||||
local link = GetInventoryItemLink("target", i)
|
||||
local border = button.ShaguTweaks_border
|
||||
|
||||
if not border then
|
||||
border = AddBorder(button, 3, { r = .5, g = .5, b = .5 })
|
||||
end
|
||||
|
||||
if not defcolor["inspect"] then
|
||||
defcolor["inspect"] = { border:GetBackdropBorderColor() }
|
||||
end
|
||||
|
||||
border:SetBackdropBorderColor(defcolor["inspect"][1], defcolor["inspect"][2], defcolor["inspect"][3], 1)
|
||||
if link then
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
local _, _, quality = GetItemInfo(istring)
|
||||
if quality then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
border:SetBackdropBorderColor(r, g, b, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
HookAddonOrVariable("Blizzard_InspectUI", function()
|
||||
local HookInspectPaperDollItemSlotButton_Update = InspectPaperDollItemSlotButton_Update
|
||||
InspectPaperDollItemSlotButton_Update = function(arg)
|
||||
HookInspectPaperDollItemSlotButton_Update(arg)
|
||||
refresh_inspect()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
do -- bags
|
||||
local color = { r = .5, g = .5, b = .46 }
|
||||
|
||||
for i = 0, 3 do
|
||||
AddBorder(_G["CharacterBag"..i.."Slot"], 3, color)
|
||||
end
|
||||
|
||||
for i = 1, 12 do
|
||||
for k = 1, MAX_CONTAINER_ITEMS do
|
||||
AddBorder(_G["ContainerFrame"..i.."Item"..k], 3, color)
|
||||
end
|
||||
end
|
||||
|
||||
local refresh_bags = function()
|
||||
for i = 1, 12 do
|
||||
local frame = _G["ContainerFrame"..i]
|
||||
if frame then
|
||||
local name = frame:GetName()
|
||||
local id = frame:GetID()
|
||||
for i = 1, MAX_CONTAINER_ITEMS do
|
||||
local button = _G[name.."Item"..i]
|
||||
|
||||
if not defcolor["bag"] then
|
||||
defcolor["bag"] = { button.ShaguTweaks_border:GetBackdropBorderColor() }
|
||||
end
|
||||
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(defcolor["bag"][1], defcolor["bag"][2], defcolor["bag"][3], 1)
|
||||
|
||||
local link = GetContainerItemLink(id, button:GetID())
|
||||
if button and button:IsShown() and link then
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
local _, _, quality = GetItemInfo(istring)
|
||||
if quality then
|
||||
local r, g, b = GetItemQualityColor(quality)
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local bags = CreateFrame("Frame", nil, ContainerFrame1)
|
||||
bags:RegisterEvent("BAG_UPDATE")
|
||||
bags:SetScript("OnEvent", refresh_bags)
|
||||
|
||||
local HookContainerFrame_OnShow = ContainerFrame_OnShow
|
||||
function ContainerFrame_OnShow() refresh_bags() HookContainerFrame_OnShow() end
|
||||
|
||||
local HookContainerFrame_OnHide = ContainerFrame_OnHide
|
||||
function ContainerFrame_OnHide() refresh_bags() HookContainerFrame_OnHide() end
|
||||
end
|
||||
|
||||
do -- bank
|
||||
for i = 1, 28 do
|
||||
AddBorder(_G["BankFrameItem"..i], 3, color)
|
||||
end
|
||||
|
||||
local refresh_bank = function()
|
||||
for i = 1, 28 do
|
||||
local button = _G["BankFrameItem"..i]
|
||||
local link = GetContainerItemLink(-1, i)
|
||||
if button then
|
||||
if not defcolor["bank"] then
|
||||
defcolor["bank"] = { button.ShaguTweaks_border:GetBackdropBorderColor() }
|
||||
end
|
||||
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(defcolor["bank"][1], defcolor["bank"][2], defcolor["bank"][3], 1)
|
||||
|
||||
if link then
|
||||
local _, _, istring = string.find(link, "|H(.+)|h")
|
||||
local _, _, q = GetItemInfo(istring)
|
||||
if q and q > 1 then
|
||||
local r, g, b = GetItemQualityColor(q)
|
||||
button.ShaguTweaks_border:SetBackdropBorderColor(r,g,b)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local bank = CreateFrame("Frame", nil, BankFrame)
|
||||
bank:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
|
||||
bank:SetScript("OnEvent", refresh_bank)
|
||||
bank:SetScript("OnShow", refresh_bank)
|
||||
end
|
||||
|
||||
do -- weapon buff
|
||||
AddBorder(TempEnchant1, 3, {.2,.2,.2})
|
||||
AddBorder(TempEnchant2, 3, {.2,.2,.2})
|
||||
|
||||
local hookBuffFrame_Enchant_OnUpdate = BuffFrame_Enchant_OnUpdate
|
||||
function BuffFrame_Enchant_OnUpdate(elapsed)
|
||||
hookBuffFrame_Enchant_OnUpdate(elapsed)
|
||||
|
||||
-- return early without any weapon enchants
|
||||
local mh, _, _, oh = GetWeaponEnchantInfo()
|
||||
if not mh and not oh then return end
|
||||
|
||||
-- update weapon enchant 1
|
||||
local r, g, b = GetItemQualityColor(GetInventoryItemQuality("player", TempEnchant1:GetID()) or 1)
|
||||
TempEnchant1.ShaguTweaks_border:SetBackdropBorderColor(r,g,b,1)
|
||||
TempEnchant1Border:SetAlpha(0)
|
||||
|
||||
-- update weapon enchant 2
|
||||
local r, g, b = GetItemQualityColor(GetInventoryItemQuality("player", TempEnchant2:GetID()) or 1)
|
||||
TempEnchant2.ShaguTweaks_border:SetBackdropBorderColor(r,g,b,1)
|
||||
TempEnchant2Border:SetAlpha(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Loot Cursor"],
|
||||
description = T["Positions the loot window directly under your cursor so you can loot without moving your mouse."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["General"],
|
||||
enabled = true,
|
||||
order = 44,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local loot = CreateFrame("Frame", "ShaguTweaksLoot", LootFrame)
|
||||
|
||||
loot:SetScript("OnUpdate", function()
|
||||
if GetNumLootItems() == 0 then HideUIPanel(LootFrame) return end
|
||||
local x, y = GetCursorPosition()
|
||||
local s = LootFrame:GetEffectiveScale()
|
||||
x, y = x / s, y / s
|
||||
for i = 1, LOOTFRAME_NUMBUTTONS do
|
||||
local button = getglobal("LootButton"..i)
|
||||
if button:IsVisible() then
|
||||
if loot.last_button ~= button then
|
||||
local button_offset = (i-1) * button:GetHeight()
|
||||
LootFrame:ClearAllPoints()
|
||||
LootFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x - 40, y + 100 + button_offset)
|
||||
loot.last_button = button
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
loot:SetScript("OnShow", function()
|
||||
loot.last_button = nil
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,144 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Minimap Clean"],
|
||||
description = T["Hides minimap addon buttons automatically when the cursor leaves the minimap area."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
-- 🛡️ Liste noire : tout ce qu'on ne veut PAS toucher (trackers, blips, boutons systeme...)
|
||||
local ignoreList = {
|
||||
"MiniMapTrackingFrame",
|
||||
"MiniMapMeetingStoneFrame",
|
||||
"MiniMapMailFrame",
|
||||
"MiniMapPing",
|
||||
"MinimapBackdrop",
|
||||
"MinimapZoomIn",
|
||||
"MinimapZoomOut",
|
||||
"BookOfTracksFrame",
|
||||
"GatherNote",
|
||||
"FishingExtravaganzaMini",
|
||||
"MiniNotePOI",
|
||||
"RecipeRadarMinimapIcon",
|
||||
"FWGMinimapPOI",
|
||||
"MBB_MinimapButtonFrame",
|
||||
"MinimapButtonFrame", -- MBB peut nommer sa frame sans le prefixe MBB_ selon les versions
|
||||
"QuestieNote",
|
||||
"MetaMap",
|
||||
"LootLinkMinimapButton",
|
||||
"TimeManagerClockButton",
|
||||
"pfMiniMapPin",
|
||||
"Clock",
|
||||
"Timer",
|
||||
"GameTimeFrame",
|
||||
"MinimapToggleButton",
|
||||
"TWMinimapShopFrame",
|
||||
"LFT_Minimap"
|
||||
}
|
||||
|
||||
local function ShouldIgnore(name)
|
||||
if not name then return true end
|
||||
for _, needle in ipairs(ignoreList) do
|
||||
if string.find(name, needle, 1, true) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function IsAddonButton(child)
|
||||
local name = child:GetName()
|
||||
|
||||
if ShouldIgnore(name) then return false end
|
||||
|
||||
local hasClick = child:HasScript("OnClick") and child:GetScript("OnClick")
|
||||
local hasMouseUp = child:HasScript("OnMouseUp") and child:GetScript("OnMouseUp")
|
||||
local hasMouseDown = child:HasScript("OnMouseDown") and child:GetScript("OnMouseDown")
|
||||
|
||||
-- Parfois, le bouton cliquable est cache dans un enfant de la frame principale
|
||||
if not (hasClick or hasMouseUp or hasMouseDown) then
|
||||
for _, subchild in ipairs({child:GetChildren()}) do
|
||||
if subchild:HasScript("OnClick") and subchild:GetScript("OnClick") then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return hasClick or hasMouseUp or hasMouseDown
|
||||
end
|
||||
|
||||
local function SetButtonsAlpha(alpha)
|
||||
local children = {Minimap:GetChildren()}
|
||||
for _, child in ipairs(children) do
|
||||
-- pcall ici : si un autre addon (MBB, etc.) est en train de detruire/
|
||||
-- reparenter sa frame au meme moment, un appel direct sur un objet
|
||||
-- dans un etat incoherent peut planter le client. On isole l'appel
|
||||
-- pour qu'une frame problematique ne fasse pas tomber tout le module.
|
||||
local ok, isButton = pcall(IsAddonButton, child)
|
||||
if ok and isButton then
|
||||
pcall(child.SetAlpha, child, alpha)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
-- Etat interne stocke sur le module -> propre a chaque enable
|
||||
self.isShown = true
|
||||
self.leaveTime = nil
|
||||
self.elapsed = 0
|
||||
|
||||
local HIDE_DELAY = 3
|
||||
local THROTTLE = 0.1
|
||||
local MARGIN = 30
|
||||
|
||||
self.frame = self.frame or CreateFrame("Frame")
|
||||
|
||||
self.frame:SetScript("OnUpdate", function()
|
||||
-- ⚠️ En vanilla 1.12, OnUpdate ne passe pas "elapsed" en parametre de fonction,
|
||||
-- il faut utiliser la variable globale arg1 !
|
||||
self.elapsed = self.elapsed + arg1
|
||||
if self.elapsed < THROTTLE then return end
|
||||
self.elapsed = 0
|
||||
|
||||
local x, y = GetCursorPosition()
|
||||
local scale = Minimap:GetEffectiveScale()
|
||||
local mx, my = x / scale, y / scale
|
||||
|
||||
local left = Minimap:GetLeft()
|
||||
local right = Minimap:GetRight()
|
||||
local bottom = Minimap:GetBottom()
|
||||
local top = Minimap:GetTop()
|
||||
|
||||
local isOver = left and mx >= (left - MARGIN) and mx <= (right + MARGIN)
|
||||
and my >= (bottom - MARGIN) and my <= (top + MARGIN)
|
||||
|
||||
if isOver then
|
||||
self.leaveTime = nil
|
||||
if not self.isShown then
|
||||
SetButtonsAlpha(1)
|
||||
self.isShown = true
|
||||
end
|
||||
else
|
||||
if self.isShown then
|
||||
if not self.leaveTime then
|
||||
self.leaveTime = GetTime()
|
||||
elseif GetTime() - self.leaveTime >= HIDE_DELAY then
|
||||
SetButtonsAlpha(0)
|
||||
self.isShown = false
|
||||
self.leaveTime = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
module.disable = function(self)
|
||||
if self.frame then
|
||||
self.frame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
-- On remet tous les boutons visibles quand on desactive le module
|
||||
SetButtonsAlpha(1)
|
||||
end
|
||||
@@ -0,0 +1,57 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["MiniMap Clock"],
|
||||
description = T["Adds a small 24h clock to the mini map."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
MinimapClock = CreateFrame("Frame", "Clock", Minimap)
|
||||
MinimapClock:Hide()
|
||||
MinimapClock:SetFrameLevel(64)
|
||||
MinimapClock:SetPoint("BOTTOM", MinimapCluster, "BOTTOM", 8, 18)
|
||||
MinimapClock:SetWidth(50)
|
||||
MinimapClock:SetHeight(23)
|
||||
MinimapClock:SetBackdrop({
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
})
|
||||
MinimapClock:SetBackdropBorderColor(.9,.8,.5,1)
|
||||
MinimapClock:SetBackdropColor(.4,.4,.4,1)
|
||||
|
||||
module.enable = function(self)
|
||||
MinimapClock:Show()
|
||||
MinimapClock:EnableMouse(true)
|
||||
|
||||
MinimapClock.text = MinimapClock:CreateFontString("Status", "LOW", "GameFontNormal")
|
||||
MinimapClock.text:SetFont(STANDARD_TEXT_FONT, 12, "OUTLINE")
|
||||
MinimapClock.text:SetAllPoints(MinimapClock)
|
||||
MinimapClock.text:SetFontObject(GameFontWhite)
|
||||
MinimapClock:SetScript("OnUpdate", function()
|
||||
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + 1 end
|
||||
this.text:SetText(date("%H:%M"))
|
||||
end)
|
||||
|
||||
MinimapClock:SetScript("OnEnter", function()
|
||||
local h, m = GetGameTime()
|
||||
local servertime = string.format("%.2d:%.2d", h, m)
|
||||
local time = date("%H:%M")
|
||||
|
||||
GameTooltip:ClearLines()
|
||||
GameTooltip:SetOwner(this, ANCHOR_BOTTOMLEFT)
|
||||
|
||||
GameTooltip:AddLine(T["Clock"])
|
||||
GameTooltip:AddDoubleLine(T["Localtime"], time, 1,1,1,1,1,1)
|
||||
GameTooltip:AddDoubleLine(T["Servertime"], servertime, 1,1,1,1,1,1)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
|
||||
MinimapClock:SetScript("OnLeave", function()
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["MiniMap Square"],
|
||||
description = T["Draw the mini map in a squared shape instead of a round one."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = nil,
|
||||
config = {
|
||||
["minimap.size"] = 144,
|
||||
},
|
||||
})
|
||||
module.enable = function(self)
|
||||
local size = module.config["minimap.size"]
|
||||
MinimapBorder:SetTexture(nil)
|
||||
Minimap:SetWidth(size)
|
||||
Minimap:SetHeight(size)
|
||||
Minimap:SetPoint("CENTER", MinimapCluster, "TOP", 9, -98)
|
||||
Minimap:SetMaskTexture("Interface\\BUTTONS\\WHITE8X8")
|
||||
Minimap.border = CreateFrame("Frame", nil, Minimap)
|
||||
Minimap.border:SetFrameStrata("BACKGROUND")
|
||||
Minimap.border:SetFrameLevel(1)
|
||||
Minimap.border:SetPoint("TOPLEFT", Minimap, "TOPLEFT", -3, 3)
|
||||
Minimap.border:SetPoint("BOTTOMRIGHT", Minimap, "BOTTOMRIGHT", 3, -3)
|
||||
Minimap.border:SetBackdrop({
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }})
|
||||
Minimap.border:SetBackdropBorderColor(.9,.8,.5,1)
|
||||
Minimap.border:SetBackdropColor(.4,.4,.4,1)
|
||||
|
||||
if _G.MinimapClock then
|
||||
if not self.clockOriginalPoint then
|
||||
local point, relativeTo, relativePoint, x, y = MinimapClock:GetPoint()
|
||||
self.clockOriginalPoint = { point, relativeTo, relativePoint, x, y }
|
||||
end
|
||||
|
||||
MinimapClock:ClearAllPoints()
|
||||
MinimapClock:SetPoint("TOP", Minimap, "BOTTOM", 0, -2)
|
||||
end
|
||||
end
|
||||
|
||||
module.disable = function(self)
|
||||
if _G.MinimapClock and self.clockOriginalPoint then
|
||||
MinimapClock:ClearAllPoints()
|
||||
MinimapClock:SetPoint(unpack(self.clockOriginalPoint))
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["MiniMap Tweaks"],
|
||||
description = T["Hides unnecessary mini map buttons and allows to zoom using the mouse wheel."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
|
||||
-- hide daytime circle
|
||||
GameTimeFrame:Hide()
|
||||
GameTimeFrame:SetScript("OnShow", function() this:Hide() end)
|
||||
|
||||
-- hide minimap zone background
|
||||
MinimapBorderTop:Hide()
|
||||
MinimapToggleButton:Hide()
|
||||
MinimapZoneTextButton:SetPoint("CENTER", 7, 85)
|
||||
|
||||
-- hide zoom buttons and enable mousewheel
|
||||
MinimapZoomIn:Hide()
|
||||
MinimapZoomOut:Hide()
|
||||
Minimap:EnableMouseWheel(true)
|
||||
Minimap:SetScript("OnMouseWheel", function()
|
||||
if(arg1 > 0) then Minimap_ZoomIn() else Minimap_ZoomOut() end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,103 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Enlarged Minimap"],
|
||||
description = T["Increases the minimap size and shifts buff icons left to prevent overlap."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = nil,
|
||||
order = 73,
|
||||
config = {
|
||||
["minimap.scale"] = 1.2,
|
||||
}
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local scale = module.config["minimap.scale"]
|
||||
if scale < 1.0 then scale = 1.0 end
|
||||
if scale > 2.0 then scale = 2.0 end
|
||||
|
||||
MinimapCluster:SetScale(scale)
|
||||
|
||||
-- BuffFrame is anchored to UIParent TOPRIGHT/TOPRIGHT x=-205 y=-13 by vanilla.
|
||||
-- The C engine resets this after every PLAYER_AURAS_CHANGED event, overwriting
|
||||
-- any Lua SetPoint. The only reliable fix is to enforce on every frame via
|
||||
-- OnUpdate, which always runs after the C layout pass for that frame.
|
||||
-- We skip the call when the position is already correct to minimise overhead.
|
||||
|
||||
local extra = MinimapCluster:GetWidth() * (scale - 1.0)
|
||||
local targetX = -205 - extra
|
||||
local targetY = -13
|
||||
|
||||
-- BuffButton16 is the anchor for the player debuff row in vanilla 1.12.
|
||||
-- It sits just to the left of the minimap independently of BuffFrame.
|
||||
-- We calculate its target position to match the same leftward shift.
|
||||
local debuffX = -205 - extra
|
||||
local debuffY = -13 - 70 -- tuned value: one row below buffs without overlap
|
||||
|
||||
-- BuffButton8 ends the top buff row; it is not reanchored by the C engine
|
||||
-- so it can overlap the minimap when scaled up. Pin it one icon height
|
||||
-- above BuffButton16 to keep both rows aligned with the leftward shift.
|
||||
local buffRowX = -205 - extra
|
||||
local buffRowY = debuffY + 26 -- one icon height above the debuff row
|
||||
|
||||
-- TempEnchant1 sits to the right of BuffFrame, TempEnchant2 just below it.
|
||||
-- Both are re-anchored every frame to prevent the C engine from resetting them.
|
||||
|
||||
-- IMPORTANT: enable() can be called multiple times (reload UI, toggling the
|
||||
-- module in ShaguTweaks settings, expansion switch, etc). Without reusing a
|
||||
-- single persistent frame, every call created a brand new anonymous
|
||||
-- CreateFrame("Frame") with its own OnUpdate, and the old ones were never
|
||||
-- released -- they kept running forever in the background, stacking up and
|
||||
-- fighting each other over the same anchors every frame. That's the source
|
||||
-- of the micro-stutter. We now store the enforcer on the module and just
|
||||
-- refresh its OnUpdate closure (with the new target values) if it already
|
||||
-- exists, instead of creating a new frame.
|
||||
if not self.enforcer then
|
||||
self.enforcer = CreateFrame("Frame")
|
||||
end
|
||||
local enforcer = self.enforcer
|
||||
|
||||
enforcer:SetScript("OnUpdate", function()
|
||||
local _, _, _, x, y = BuffFrame:GetPoint(1)
|
||||
if x ~= targetX or y ~= targetY then
|
||||
BuffFrame:ClearAllPoints()
|
||||
BuffFrame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", targetX, targetY)
|
||||
end
|
||||
|
||||
if BuffButton16 then
|
||||
local _, _, _, dx, dy = BuffButton16:GetPoint(1)
|
||||
if dx ~= debuffX or dy ~= debuffY then
|
||||
BuffButton16:ClearAllPoints()
|
||||
BuffButton16:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", debuffX, debuffY)
|
||||
end
|
||||
end
|
||||
|
||||
-- BuffButton8 ends the top buff row; force it leftward to clear the minimap.
|
||||
if BuffButton8 then
|
||||
local _, _, _, bx, by = BuffButton8:GetPoint(1)
|
||||
if bx ~= buffRowX or by ~= buffRowY then
|
||||
BuffButton8:ClearAllPoints()
|
||||
BuffButton8:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", buffRowX, buffRowY)
|
||||
end
|
||||
end
|
||||
|
||||
-- TempEnchant1 to the right of BuffFrame, TempEnchant2 just below it.
|
||||
if TempEnchant1 then
|
||||
TempEnchant1:ClearAllPoints()
|
||||
TempEnchant1:SetPoint("TOPLEFT", BuffFrame, "TOPRIGHT", 5, 0)
|
||||
end
|
||||
|
||||
if TempEnchant2 and TempEnchant1 then
|
||||
TempEnchant2:ClearAllPoints()
|
||||
TempEnchant2:SetPoint("TOP", TempEnchant1, "BOTTOM", 0, -2)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
module.disable = function(self)
|
||||
if self.enforcer then
|
||||
self.enforcer:SetScript("OnUpdate", nil)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,92 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Movable Unit Frames"],
|
||||
description = T["Player and Target unit frames can be moved while <Shift> and <Ctrl> are pressed together."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Unit Frames"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
local movables = { "PlayerFrame", "TargetFrame" }
|
||||
|
||||
module.enable = function(self)
|
||||
local unlocker = CreateFrame("Frame", nil, UIParent)
|
||||
unlocker:SetAllPoints(UIParent)
|
||||
|
||||
for _, frame in pairs(movables) do
|
||||
_G[frame]:SetClampedToScreen(true)
|
||||
end
|
||||
|
||||
unlocker.movable = nil
|
||||
unlocker:SetScript("OnUpdate", function()
|
||||
if IsShiftKeyDown() and IsControlKeyDown() then
|
||||
if not unlocker.movable then
|
||||
for _, frame in pairs(movables) do
|
||||
_G[frame]:SetUserPlaced(true)
|
||||
_G[frame]:SetMovable(true)
|
||||
_G[frame]:EnableMouse(true)
|
||||
_G[frame]:RegisterForDrag("LeftButton")
|
||||
_G[frame]:SetScript("OnDragStart", function() this:StartMoving() end)
|
||||
_G[frame]:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
|
||||
end
|
||||
|
||||
unlocker.movable = true
|
||||
unlocker.grid:Show()
|
||||
end
|
||||
elseif unlocker.movable then
|
||||
for _, frame in pairs(movables) do
|
||||
_G[frame]:SetScript("OnDragStart", function() end)
|
||||
_G[frame]:SetScript("OnDragStop", function() end)
|
||||
_G[frame]:StopMovingOrSizing()
|
||||
end
|
||||
|
||||
unlocker.movable = nil
|
||||
unlocker.grid:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
unlocker.grid = CreateFrame("Frame", nil, WorldFrame)
|
||||
unlocker.grid:SetAllPoints(WorldFrame)
|
||||
unlocker.grid:Hide()
|
||||
|
||||
local size = 1
|
||||
local line = {}
|
||||
|
||||
local width = GetScreenWidth()
|
||||
local height = GetScreenHeight()
|
||||
|
||||
local ratio = width / GetScreenHeight()
|
||||
local rheight = GetScreenHeight() * ratio
|
||||
|
||||
local wStep = width / 64
|
||||
local hStep = rheight / 64
|
||||
|
||||
-- vertical lines
|
||||
for i = 0, 64 do
|
||||
if i == 64 / 2 then
|
||||
line = unlocker.grid:CreateTexture(nil, 'BORDER')
|
||||
line:SetTexture(.8, .6, 0)
|
||||
else
|
||||
line = unlocker.grid:CreateTexture(nil, 'BACKGROUND')
|
||||
line:SetTexture(0, 0, 0, .2)
|
||||
end
|
||||
line:SetPoint("TOPLEFT", unlocker.grid, "TOPLEFT", i*wStep - (size/2), 0)
|
||||
line:SetPoint('BOTTOMRIGHT', unlocker.grid, 'BOTTOMLEFT', i*wStep + (size/2), 0)
|
||||
end
|
||||
|
||||
-- horizontal lines
|
||||
for i = 1, floor(height/hStep) do
|
||||
if i == floor(height/hStep / 2) then
|
||||
line = unlocker.grid:CreateTexture(nil, 'BORDER')
|
||||
line:SetTexture(.8, .6, 0)
|
||||
else
|
||||
line = unlocker.grid:CreateTexture(nil, 'BACKGROUND')
|
||||
line:SetTexture(0, 0, 0, .2)
|
||||
end
|
||||
|
||||
line:SetPoint("TOPLEFT", unlocker.grid, "TOPLEFT", 0, -(i*hStep) + (size/2))
|
||||
line:SetPoint('BOTTOMRIGHT', unlocker.grid, 'TOPRIGHT', 0, -(i*hStep + size/2))
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,118 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local UnitCastingInfo = ShaguTweaks.UnitCastingInfo
|
||||
local UnitChannelInfo = ShaguTweaks.UnitChannelInfo
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Nameplate Castbar"],
|
||||
description = T["Adds a castbar to the nameplate based on combat log estimations."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = false },
|
||||
category = T["Nameplates"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
if ShaguPlates then return end
|
||||
|
||||
local backdrop = {
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 12,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
}
|
||||
|
||||
local function create_castbar(plate)
|
||||
-- create the castbar
|
||||
plate.castbar = CreateFrame("StatusBar", nil, plate)
|
||||
plate.castbar:SetPoint("BOTTOM", plate, "BOTTOM", 8, -11)
|
||||
plate.castbar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
|
||||
plate.castbar:SetStatusBarColor(1, .8, 0, 1)
|
||||
plate.castbar:SetWidth(plate:GetWidth() - 22)
|
||||
plate.castbar:SetHeight(10)
|
||||
|
||||
-- create the spell icon
|
||||
plate.castbar.texture = CreateFrame("Frame", nil, plate.castbar)
|
||||
plate.castbar.texture:SetPoint("RIGHT", plate.castbar, "LEFT", 0, 0)
|
||||
plate.castbar.texture:SetHeight(18)
|
||||
plate.castbar.texture:SetWidth(18)
|
||||
plate.castbar.texture.icon = plate.castbar.texture:CreateTexture(nil, "BACKGROUND")
|
||||
plate.castbar.texture.icon:SetPoint("CENTER", 0, 0)
|
||||
plate.castbar.texture.icon:SetWidth(12)
|
||||
plate.castbar.texture.icon:SetHeight(12)
|
||||
plate.castbar.texture:SetBackdrop(backdrop)
|
||||
plate.castbar.texture:SetBackdropBorderColor(1,.8,0)
|
||||
|
||||
-- castbar background
|
||||
plate.castbar.bg = plate.castbar:CreateTexture(nil, "BACKGROUND")
|
||||
plate.castbar.bg:SetTexture("Interface\\TARGETINGFRAME\\UI-StatusBar")
|
||||
plate.castbar.bg:SetVertexColor(.1, .1, 0, .8)
|
||||
plate.castbar.bg:SetAllPoints(true)
|
||||
|
||||
-- castbar spark
|
||||
plate.castbar.spark = plate.castbar:CreateTexture(nil, "OVERLAY")
|
||||
plate.castbar.spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
|
||||
plate.castbar.spark:SetWidth(20)
|
||||
plate.castbar.spark:SetHeight(20)
|
||||
plate.castbar.spark:SetBlendMode("ADD")
|
||||
|
||||
-- castbar border
|
||||
plate.castbar.backdrop = CreateFrame("Frame", nil, plate.castbar)
|
||||
plate.castbar.backdrop:SetFrameLevel(plate.castbar:GetFrameLevel())
|
||||
plate.castbar.backdrop:SetPoint("TOPLEFT", plate.castbar, "TOPLEFT", -3, 3)
|
||||
plate.castbar.backdrop:SetPoint("BOTTOMRIGHT", plate.castbar, "BOTTOMRIGHT", 3, -3)
|
||||
plate.castbar.backdrop:SetBackdrop(backdrop)
|
||||
plate.castbar.backdrop:SetBackdropBorderColor(1,.8,0)
|
||||
|
||||
-- castbar spellname
|
||||
plate.castbar.text = plate.castbar:CreateFontString(nil, "HIGH", "GameFontWhite")
|
||||
plate.castbar.text:SetPoint("CENTER", plate.castbar, "CENTER", 0, 0)
|
||||
local font, size, opts = plate.castbar.text:GetFont()
|
||||
plate.castbar.text:SetFont(font, size - 3, "THINOUTLINE")
|
||||
|
||||
-- hide castbar by default
|
||||
plate.castbar:Hide()
|
||||
end
|
||||
|
||||
-- scan for casts and show castbar
|
||||
table.insert(ShaguTweaks.libnameplate.OnUpdate, function()
|
||||
-- create castbar if not existing
|
||||
if not this.castbar then create_castbar(this) end
|
||||
|
||||
local name = this.name:GetText()
|
||||
local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(name)
|
||||
|
||||
-- read enemy casts from SuperWoW if enabled
|
||||
if ShaguTweaks.superwow_active then
|
||||
cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(this:GetName(1))
|
||||
end
|
||||
|
||||
if cast then
|
||||
local duration = endTime - startTime
|
||||
local max = duration / 1000
|
||||
local cur = GetTime() - startTime / 1000
|
||||
|
||||
cur = cur > max and max or cur
|
||||
cur = cur < 0 and 0 or cur
|
||||
|
||||
this.castbar:Show()
|
||||
this.castbar:SetMinMaxValues(0, duration / 1000)
|
||||
this.castbar:SetValue(cur)
|
||||
|
||||
local percent = cur / max
|
||||
local x = this.castbar:GetWidth()*percent
|
||||
this.castbar.spark:SetPoint("CENTER", this.castbar, "LEFT", x, 0)
|
||||
|
||||
this.castbar.text:SetText(cast)
|
||||
|
||||
if texture then
|
||||
this.castbar.texture.icon:SetTexture(texture)
|
||||
this.castbar.texture.icon:Show()
|
||||
else
|
||||
this.castbar.texture.icon:Hide()
|
||||
end
|
||||
|
||||
this.castbar:SetAlpha(this:GetAlpha())
|
||||
else
|
||||
this.castbar:Hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local GetUnitData = ShaguTweaks.GetUnitData
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Nameplate Class Colors"],
|
||||
description = T["Changes the nameplate health bar color to the class color."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Nameplates"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
if ShaguPlates then return end
|
||||
|
||||
table.insert(ShaguTweaks.libnameplate.OnUpdate, function()
|
||||
local name = this.name:GetText()
|
||||
local class, _, elite, player = GetUnitData(name, true)
|
||||
if class and player then
|
||||
local color = RAID_CLASS_COLORS[class] or { r = .5, g = .5, b = .5, a = 1 }
|
||||
this.healthbar:SetStatusBarColor(color.r, color.g, color.b, 1)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Nameplate Scale"],
|
||||
description = T["Makes all nameplates honor the UI-Scale setting."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Nameplates"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
if ShaguPlates then return end
|
||||
|
||||
table.insert(ShaguTweaks.libnameplate.OnInit, function(plate)
|
||||
local owidth = plate:GetWidth()
|
||||
local oheight = plate:GetHeight()
|
||||
|
||||
-- create new plate
|
||||
local new = CreateFrame("Frame", nil, plate)
|
||||
plate.new = new
|
||||
|
||||
new:SetScale(UIParent:GetScale())
|
||||
new:SetAllPoints(plate)
|
||||
new.plate = plate
|
||||
|
||||
plate.healthbar:SetParent(new)
|
||||
plate.healthbar:SetFrameLevel(1)
|
||||
|
||||
plate:SetWidth(owidth*UIParent:GetScale())
|
||||
plate:SetHeight(oheight*UIParent:GetScale())
|
||||
|
||||
for i, object in pairs({plate:GetRegions()}) do
|
||||
object:SetParent(new)
|
||||
|
||||
-- adjust level icon position
|
||||
if ShaguTweaks:GetExpansion() == "vanilla" and i == 5 or i == 7 then
|
||||
object:SetPoint("BOTTOMRIGHT", -6, 3)
|
||||
end
|
||||
end
|
||||
|
||||
new:SetScript("OnShow", function()
|
||||
-- adjust sizes
|
||||
this:SetScale(UIParent:GetScale())
|
||||
this.plate:SetWidth(owidth*UIParent:GetScale())
|
||||
this.plate:SetHeight(oheight*UIParent:GetScale())
|
||||
end)
|
||||
end)
|
||||
|
||||
table.insert(ShaguTweaks.libnameplate.OnUpdate, function()
|
||||
this.new:SetAlpha(this:GetAlpha())
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,62 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["No Toggle Auto-Attack"],
|
||||
description = T["Keeps Auto Attack, Auto Shot, and Shoot active when re-pressed, preventing accidental cancellation."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["General"],
|
||||
enabled = true,
|
||||
order = 12,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local attacking, shooting
|
||||
|
||||
local combatFrame = CreateFrame("Frame")
|
||||
combatFrame:RegisterEvent("PLAYER_ENTER_COMBAT")
|
||||
combatFrame:RegisterEvent("PLAYER_LEAVE_COMBAT")
|
||||
combatFrame:SetScript("OnEvent", function()
|
||||
attacking = event == "PLAYER_ENTER_COMBAT"
|
||||
end)
|
||||
|
||||
local shootFrame = CreateFrame("Frame")
|
||||
shootFrame:RegisterEvent("START_AUTOREPEAT_SPELL")
|
||||
shootFrame:RegisterEvent("STOP_AUTOREPEAT_SPELL")
|
||||
shootFrame:SetScript("OnEvent", function()
|
||||
shooting = event == "START_AUTOREPEAT_SPELL"
|
||||
end)
|
||||
|
||||
local function active(name)
|
||||
if not name then return false end
|
||||
name = strlower(name)
|
||||
return (name == "attack" and attacking) or
|
||||
((name == "auto shot" or name == "shoot") and shooting)
|
||||
end
|
||||
|
||||
local origCastSpell = CastSpell
|
||||
function _G.CastSpell(index, booktype)
|
||||
if active(GetSpellName(index, booktype)) then return end
|
||||
return origCastSpell(index, booktype)
|
||||
end
|
||||
|
||||
local origCastSpellByName = CastSpellByName
|
||||
function _G.CastSpellByName(text, onself)
|
||||
if active(text) then return end
|
||||
return origCastSpellByName(text, onself)
|
||||
end
|
||||
|
||||
local tt = CreateFrame("GameTooltip", "ShaguTweaksNoToggleTT", nil, "GameTooltipTemplate")
|
||||
tt:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
|
||||
local origUseAction = UseAction
|
||||
function _G.UseAction(slot, clicked, onself)
|
||||
if HasAction(slot) and not GetActionText(slot) then
|
||||
tt:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
tt:SetAction(slot)
|
||||
local label = _G["ShaguTweaksNoToggleTTTextLeft1"]
|
||||
if label and active(label:GetText()) then return end
|
||||
end
|
||||
return origUseAction(slot, clicked, onself)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,172 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local hooksecurefunc = hooksecurefunc or ShaguTweaks.hooksecurefunc
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Reduced Actionbar Size"],
|
||||
description = T["Reduces the actionbar size by removing several items such as the bag panel and microbar"],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
local function ReplaceBag()
|
||||
local id = this:GetID()
|
||||
if id ~= 0 then
|
||||
id = ContainerIDToInventoryID(id)
|
||||
if CursorHasItem() then
|
||||
PutItemInBag(id)
|
||||
else
|
||||
PickupBagFromSlot(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
-- general function to hide textures and frames
|
||||
local function hide(frame, texture)
|
||||
if not frame then return end
|
||||
|
||||
if texture and texture == 1 and frame.SetTexture then
|
||||
frame:SetTexture("")
|
||||
elseif texture and texture == 2 and frame.SetNormalTexture then
|
||||
frame:SetNormalTexture("")
|
||||
else
|
||||
frame:ClearAllPoints()
|
||||
frame.Show = function() return end
|
||||
frame:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- frames that shall be hidden
|
||||
local frames = {
|
||||
-- actionbar paging
|
||||
MainMenuBarPageNumber, ActionBarUpButton, ActionBarDownButton,
|
||||
-- xp and reputation bar
|
||||
MainMenuXPBarTexture2, MainMenuXPBarTexture3,
|
||||
ReputationWatchBarTexture2, ReputationWatchBarTexture3,
|
||||
-- actionbar backgrounds
|
||||
MainMenuBarTexture2, MainMenuBarTexture3,
|
||||
MainMenuMaxLevelBar2, MainMenuMaxLevelBar3,
|
||||
-- micro button panel
|
||||
CharacterMicroButton, SpellbookMicroButton, TalentMicroButton,
|
||||
QuestLogMicroButton, MainMenuMicroButton, SocialsMicroButton,
|
||||
WorldMapMicroButton, MainMenuBarPerformanceBarFrame, HelpMicroButton,
|
||||
-- bag panel
|
||||
CharacterBag3Slot, CharacterBag2Slot, CharacterBag1Slot,
|
||||
CharacterBag0Slot, MainMenuBarBackpackButton, KeyRingButton,
|
||||
-- shapeshift backgrounds
|
||||
ShapeshiftBarLeft, ShapeshiftBarMiddle, ShapeshiftBarRight,
|
||||
}
|
||||
|
||||
-- textures that shall be set empty
|
||||
local textures = {
|
||||
ReputationWatchBarTexture2, ReputationWatchBarTexture3,
|
||||
ReputationXPBarTexture2, ReputationXPBarTexture3,
|
||||
SlidingActionBarTexture0, SlidingActionBarTexture1,
|
||||
}
|
||||
|
||||
-- button textures that shall be set empty
|
||||
local normtextures = {
|
||||
ShapeshiftButton1, ShapeshiftButton2,
|
||||
ShapeshiftButton3, ShapeshiftButton4,
|
||||
ShapeshiftButton5, ShapeshiftButton6,
|
||||
ShapeshiftButton7, ShapeshiftButton8,
|
||||
ShapeshiftButton9, ShapeshiftButton10,
|
||||
ShapeshiftButton11, ShapeshiftButton12,
|
||||
}
|
||||
|
||||
-- elements that shall be resized to 511px
|
||||
local resizes = {
|
||||
MainMenuBar, MainMenuExpBar, MainMenuBarMaxLevelBar,
|
||||
ReputationWatchBar, ReputationWatchStatusBar,
|
||||
}
|
||||
|
||||
-- hide frames
|
||||
for id, frame in pairs(frames) do hide(frame) end
|
||||
|
||||
-- clear textures
|
||||
for id, frame in pairs(textures) do hide(frame, 1) end
|
||||
for id, frame in pairs(normtextures) do hide(frame, 2) end
|
||||
|
||||
-- resize actionbar
|
||||
for id, frame in pairs(resizes) do frame:SetWidth(511) end
|
||||
|
||||
-- experience bar
|
||||
MainMenuXPBarTexture0:SetPoint("LEFT", MainMenuExpBar, "LEFT")
|
||||
MainMenuXPBarTexture1:SetPoint("RIGHT", MainMenuExpBar, "RIGHT")
|
||||
|
||||
-- reputation bar
|
||||
ReputationWatchBar:SetPoint("BOTTOM", MainMenuExpBar, "TOP", 0, 0)
|
||||
ReputationWatchBarTexture0:SetPoint("LEFT", ReputationWatchBar, "LEFT")
|
||||
ReputationWatchBarTexture1:SetPoint("RIGHT", ReputationWatchBar, "RIGHT")
|
||||
|
||||
-- move menubar texture background
|
||||
MainMenuMaxLevelBar0:SetPoint("LEFT", MainMenuBarArtFrame, "LEFT")
|
||||
MainMenuBarTexture0:SetPoint("LEFT", MainMenuBarArtFrame, "LEFT")
|
||||
MainMenuBarTexture1:SetPoint("RIGHT", MainMenuBarArtFrame, "RIGHT")
|
||||
|
||||
-- move gryphon textures
|
||||
MainMenuBarLeftEndCap:SetPoint("RIGHT", MainMenuBarArtFrame, "LEFT", 29.5, 0)
|
||||
MainMenuBarRightEndCap:SetPoint("LEFT", MainMenuBarArtFrame, "RIGHT", -31.5, 0)
|
||||
|
||||
-- move MultiBarBottomRight ontop of MultiBarBottomLeft
|
||||
MultiBarBottomRight:ClearAllPoints()
|
||||
MultiBarBottomRight:SetPoint("BOTTOM", MultiBarBottomLeft, "TOP", 0, 5)
|
||||
|
||||
-- reload custom frame positions after original frame manage runs
|
||||
local hookUIParent_ManageFramePositions = UIParent_ManageFramePositions
|
||||
UIParent_ManageFramePositions = function(a1, a2, a3)
|
||||
-- run original function
|
||||
hookUIParent_ManageFramePositions(a1, a2, a3)
|
||||
|
||||
-- move top actionbar if xp or reputation is tracked
|
||||
MultiBarBottomLeft:ClearAllPoints()
|
||||
if MainMenuExpBar:IsVisible() or ReputationWatchBar:IsVisible() then
|
||||
local anchor = GetWatchedFactionInfo() and ReputationWatchBar or MainMenuExpBar
|
||||
MultiBarBottomLeft:SetPoint("BOTTOM", anchor, "TOP", 2, 3)
|
||||
else
|
||||
MultiBarBottomLeft:SetPoint("BOTTOM", MainMenuBar, "TOP", 2, -3)
|
||||
end
|
||||
|
||||
-- move pet actionbar above other actionbars
|
||||
PetActionBarFrame:ClearAllPoints()
|
||||
local anchor = MainMenuBarArtFrame
|
||||
anchor = MultiBarBottomLeft:IsVisible() and MultiBarBottomLeft or anchor
|
||||
anchor = MultiBarBottomRight:IsVisible() and MultiBarBottomRight or anchor
|
||||
anchor = ShapeshiftBarFrame:IsVisible() and ShapeshiftBarFrame or anchor
|
||||
PetActionBarFrame:SetPoint("BOTTOMLEFT", anchor, "TOPLEFT", 20, 4)
|
||||
|
||||
-- ShapeshiftBarFrame
|
||||
ShapeshiftBarFrame:ClearAllPoints()
|
||||
local offset = 0
|
||||
local anchor = ActionButton1
|
||||
anchor = MultiBarBottomLeft:IsVisible() and MultiBarBottomLeft or anchor
|
||||
anchor = MultiBarBottomRight:IsVisible() and MultiBarBottomRight or anchor
|
||||
|
||||
offset = anchor == ActionButton1 and ( MainMenuExpBar:IsVisible() or ReputationWatchBar:IsVisible() ) and 6 or 0
|
||||
offset = anchor == ActionButton1 and offset + 4 or offset
|
||||
ShapeshiftBarFrame:SetPoint("BOTTOMLEFT", anchor, "TOPLEFT", 8, 4 + offset)
|
||||
|
||||
-- move castbar ontop of other bars
|
||||
local anchor = MainMenuBarArtFrame
|
||||
anchor = MultiBarBottomLeft:IsVisible() and MultiBarBottomLeft or anchor
|
||||
anchor = MultiBarBottomRight:IsVisible() and MultiBarBottomRight or anchor
|
||||
local pet_offset = PetActionBarFrame:IsVisible() and 40 or 0
|
||||
local stance_offset = ShapeshiftBarFrame:IsVisible() and 40 or 0
|
||||
CastingBarFrame:SetPoint("BOTTOM", anchor, "TOP", 0, 10 + pet_offset + stance_offset)
|
||||
end
|
||||
|
||||
-- restore frame positions when UIParent becomes visible
|
||||
local restore = CreateFrame("Frame", nil, UIParent)
|
||||
restore:SetScript("OnShow", UIParent_ManageFramePositions)
|
||||
|
||||
-- enforce pet actionbar offset after pet actionbar becomes visible
|
||||
hooksecurefunc("ShowPetActionBar", function()
|
||||
PETACTIONBAR_XPOS = 36
|
||||
end)
|
||||
|
||||
-- enable picking up/replacing bags by clicking on the container frame portrait
|
||||
for i = 1, 5 do
|
||||
_G["ContainerFrame" .. i .. "PortraitButton"]:SetScript("OnClick", ReplaceBag)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,175 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local GetItemIDFromLink = ShaguTweaks.GetItemIDFromLink
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Sell Junk"],
|
||||
description = T["Adds a “Sell Junk” button to every merchant window, that sells all grey items."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Tooltip & Items"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
local processed = {}
|
||||
|
||||
local function CreateGoldString(money)
|
||||
if type(money) ~= "number" then return "-" end
|
||||
|
||||
local gold = floor(money/ 100 / 100)
|
||||
local silver = floor(mod((money/100),100))
|
||||
local copper = floor(mod(money,100))
|
||||
|
||||
local string = ""
|
||||
if gold > 0 then string = string .. "|cffffffff" .. gold .. "|cffffd700g" end
|
||||
if silver > 0 or gold > 0 then string = string .. "|cffffffff " .. silver .. "|cffc7c7cfs" end
|
||||
string = string .. "|cffffffff " .. copper .. "|cffeda55fc"
|
||||
|
||||
return string
|
||||
end
|
||||
|
||||
local function HasGreyItems()
|
||||
for bag = 0, 4, 1 do
|
||||
for slot = 1, GetContainerNumSlots(bag), 1 do
|
||||
local name = GetContainerItemLink(bag,slot)
|
||||
if name and string.find(name,"ff9d9d9d") then return true end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function GetNextGreyItem()
|
||||
for bag = 0, 4, 1 do
|
||||
for slot = 1, GetContainerNumSlots(bag), 1 do
|
||||
local name = GetContainerItemLink(bag,slot)
|
||||
if name and string.find(name,"ff9d9d9d") and not processed[bag.."x"..slot] then
|
||||
processed[bag.."x"..slot] = true
|
||||
return bag, slot
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
local autovendor = CreateFrame("Frame", nil, nil)
|
||||
autovendor:Hide()
|
||||
|
||||
autovendor:SetScript("OnShow", function()
|
||||
processed = {}
|
||||
this.price = 0
|
||||
this.count = 0
|
||||
end)
|
||||
|
||||
autovendor:SetScript("OnHide", function()
|
||||
if this.count > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(T["Your vendor trash has been sold and you earned"] .. " " .. CreateGoldString(this.price))
|
||||
end
|
||||
end)
|
||||
|
||||
autovendor:SetScript("OnUpdate", function()
|
||||
-- throttle to to one item per .1 second
|
||||
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + .1 end
|
||||
|
||||
-- scan for the next grey item
|
||||
local bag, slot = GetNextGreyItem()
|
||||
if not bag or not slot then
|
||||
this:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
-- double check to only sell grey
|
||||
local name = GetContainerItemLink(bag,slot)
|
||||
if not name or not string.find(name,"ff9d9d9d") then
|
||||
return
|
||||
end
|
||||
|
||||
-- get value
|
||||
local _, icount = GetContainerItemInfo(bag, slot)
|
||||
local itemID = GetItemIDFromLink(GetContainerItemLink(bag, slot))
|
||||
local price = ShaguTweaks.SellValueDB[itemID] or 0
|
||||
if this.price then
|
||||
this.price = this.price + ( price * ( icount or 1 ) )
|
||||
this.count = this.count + 1
|
||||
end
|
||||
|
||||
-- abort if the merchant window disappeared
|
||||
if not this.merchant then return end
|
||||
|
||||
-- clear cursor and sell the item
|
||||
ClearCursor()
|
||||
UseContainerItem(bag, slot)
|
||||
end)
|
||||
|
||||
autovendor:RegisterEvent("MERCHANT_SHOW")
|
||||
autovendor:RegisterEvent("MERCHANT_CLOSED")
|
||||
autovendor:RegisterEvent("MERCHANT_UPDATE")
|
||||
autovendor:SetScript("OnEvent", function()
|
||||
autovendor.button:Update()
|
||||
|
||||
if event == "MERCHANT_CLOSED" then
|
||||
autovendor.merchant = nil
|
||||
autovendor:Hide()
|
||||
elseif event == "MERCHANT_SHOW" then
|
||||
autovendor.merchant = true
|
||||
autovendor.button:Show()
|
||||
end
|
||||
|
||||
MerchantRepairText:SetText("")
|
||||
if MerchantRepairItemButton:IsShown() then
|
||||
autovendor.button:ClearAllPoints()
|
||||
autovendor.button:SetPoint("RIGHT", MerchantRepairItemButton, "LEFT", -4, 0)
|
||||
else
|
||||
autovendor.button:ClearAllPoints()
|
||||
autovendor.button:SetPoint("RIGHT", MerchantBuyBackItemItemButton, "LEFT", -14, 0)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Setup Autosell button
|
||||
autovendor.button = CreateFrame("Button", nil, MerchantFrame)
|
||||
autovendor.button:SetWidth(36)
|
||||
autovendor.button:SetHeight(36)
|
||||
autovendor.button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
|
||||
autovendor.button:SetNormalTexture("Interface\\Icons\\Spell_Shadow_SacrificialShield")
|
||||
autovendor.button:SetScript("OnEnter", function()
|
||||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
||||
GameTooltip:SetText(T["Sell Grey Items"])
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
|
||||
autovendor.button:SetScript("OnLeave", function()
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
|
||||
autovendor.button:SetScript("OnClick", function()
|
||||
autovendor:Show()
|
||||
end)
|
||||
|
||||
autovendor.button.Update = function()
|
||||
if not autovendor:IsVisible() then
|
||||
if HasGreyItems() then
|
||||
autovendor.button:Enable()
|
||||
autovendor.button:GetNormalTexture():SetDesaturated(false)
|
||||
else
|
||||
autovendor.button:Disable()
|
||||
autovendor.button:GetNormalTexture():SetDesaturated(true)
|
||||
end
|
||||
else
|
||||
autovendor.button:Disable()
|
||||
autovendor.button:GetNormalTexture():SetDesaturated(true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Hook MerchantFrame_Update
|
||||
if not HookMerchantFrame_Update then
|
||||
local HookMerchantFrame_Update = MerchantFrame_Update
|
||||
function _G.MerchantFrame_Update()
|
||||
if MerchantFrame.selectedTab == 1 then
|
||||
autovendor.button:Show()
|
||||
else
|
||||
autovendor.button:Hide()
|
||||
end
|
||||
HookMerchantFrame_Update()
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,228 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local L = ShaguTweaks.L
|
||||
local gfind = string.gmatch or string.gfind
|
||||
local GetUnitData = ShaguTweaks.GetUnitData
|
||||
local hooksecurefunc = ShaguTweaks.hooksecurefunc
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local cmatch = ShaguTweaks.cmatch
|
||||
local rgbhex = ShaguTweaks.rgbhex
|
||||
local strsplit = ShaguTweaks.strsplit
|
||||
local friendinfo = gsub(gsub(FRIENDS_LEVEL_TEMPLATE,"%%s","%%s %%s"),"%%d","%%s")
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Social Colors"],
|
||||
description = T["Show class colors in Who, Guild, Friends and Chat."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Social & Chat"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
do -- add class colors to chat
|
||||
for i=1,NUM_CHAT_WINDOWS do
|
||||
if _G["ChatFrame"..i] and not _G["ChatFrame"..i].HookAddMessageColor and not Prat then
|
||||
_G["ChatFrame"..i].HookAddMessageColor = _G["ChatFrame"..i].AddMessage
|
||||
_G["ChatFrame"..i].AddMessage = function(frame, text, a1, a2, a3, a4, a5)
|
||||
if text then
|
||||
for name in gfind(text, "|Hplayer:(.-)|h") do
|
||||
local real = strsplit(":", name)
|
||||
local class = GetUnitData(real)
|
||||
if class and class ~= UNKNOWN then
|
||||
local color = rgbhex(RAID_CLASS_COLORS[class])
|
||||
text = string.gsub(text,
|
||||
"|Hplayer:"..name.."|h%["..real.."%]|h(.-:-)",
|
||||
"|r["..color.."|Hplayer:"..name.."|h"..color..real.."|h|r]|r%1")
|
||||
end
|
||||
end
|
||||
end
|
||||
_G["ChatFrame"..i].HookAddMessageColor(frame, text, a1, a2, a3, a4, a5)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ShaguTweaks_cache = ShaguTweaks_cache or {}
|
||||
ShaguTweaks_cache["players"] = ShaguTweaks_cache["players"] or {}
|
||||
|
||||
local playerdb = ShaguTweaks_cache["players"]
|
||||
local socialmod = CreateFrame("Frame", "ShaguTweaksSocialMod", UIParent)
|
||||
socialmod:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||
socialmod:SetScript("OnEvent", function()
|
||||
local name = cmatch(arg1, _G.ERR_FRIEND_ONLINE_SS)
|
||||
name = cmatch(arg1, _G.ERR_FRIEND_OFFLINE_S)
|
||||
if name and playerdb[name] and playerdb[name].cname then
|
||||
playerdb[name].lastseen = date("%a %d-%b-%Y")
|
||||
end
|
||||
end)
|
||||
|
||||
do -- add colors to guild list
|
||||
hooksecurefunc("GuildStatus_Update", function()
|
||||
local playerzone = GetRealZoneText()
|
||||
local off = FauxScrollFrame_GetOffset(GuildListScrollFrame)
|
||||
local _, _, playerrankindex = GetGuildInfo("player")
|
||||
|
||||
for i=1, GUILDMEMBERS_TO_DISPLAY, 1 do
|
||||
local name, _, rankindex, level, class, zone, _, _, online = GetGuildRosterInfo(off + i)
|
||||
|
||||
class = L["class"][class]
|
||||
|
||||
if name then
|
||||
if class then
|
||||
local color = RAID_CLASS_COLORS[class]
|
||||
if online then
|
||||
_G["GuildFrameButton"..i.."Name"]:SetTextColor(color.r,color.g,color.b,1)
|
||||
_G["GuildFrameButton"..i.."Class"]:SetTextColor(color.r,color.g,color.b,1)
|
||||
_G["GuildFrameGuildStatusButton"..i.."Name"]:SetTextColor(color.r,color.g,color.b,1)
|
||||
else
|
||||
_G["GuildFrameButton"..i.."Name"]:SetTextColor(color.r,color.g,color.b,.5)
|
||||
_G["GuildFrameButton"..i.."Class"]:SetTextColor(color.r,color.g,color.b,.5)
|
||||
_G["GuildFrameGuildStatusButton"..i.."Name"]:SetTextColor(color.r,color.g,color.b,.5)
|
||||
end
|
||||
end
|
||||
|
||||
if level then
|
||||
local color = GetDifficultyColor(level)
|
||||
if online then
|
||||
_G["GuildFrameButton"..i.."Level"]:SetTextColor(color.r + .2, color.g + .2, color.b + .2, 1)
|
||||
else
|
||||
_G["GuildFrameButton"..i.."Level"]:SetTextColor(color.r + .2, color.g + .2, color.b + .2, .5)
|
||||
end
|
||||
end
|
||||
|
||||
if zone and zone == playerzone then
|
||||
if online then
|
||||
_G["GuildFrameButton"..i.."Zone"]:SetTextColor(.5, 1, 1, 1)
|
||||
else
|
||||
_G["GuildFrameButton"..i.."Zone"]:SetTextColor(.5, 1, 1, .5)
|
||||
end
|
||||
end
|
||||
|
||||
if rankindex and rankindex == playerrankindex then
|
||||
if online then
|
||||
_G["GuildFrameGuildStatusButton"..i.."Rank"]:SetTextColor(.5, 1, 1, 1)
|
||||
else
|
||||
_G["GuildFrameGuildStatusButton"..i.."Rank"]:SetTextColor(.5, 1, 1, .5)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
do -- add colors to friend list
|
||||
local FRIENDS_NAME_LOCATION = GetExpansion() == "vanilla" and "ButtonTextNameLocation" or "ButtonTextLocation"
|
||||
hooksecurefunc("FriendsList_Update", function()
|
||||
if GetNumFriends() == 0 then return end
|
||||
|
||||
local playerzone = GetRealZoneText()
|
||||
local off = FauxScrollFrame_GetOffset(FriendsFrameFriendsScrollFrame)
|
||||
|
||||
for i=1, FRIENDS_TO_DISPLAY do
|
||||
local name, level, class, zone, connected, status = GetFriendInfo(off + i)
|
||||
if not name or name == _G.UNKNOWN then break end
|
||||
local friendName = _G["FriendsFrameFriendButton"..i.."ButtonTextName"]
|
||||
local friendLoc = _G["FriendsFrameFriendButton"..i..FRIENDS_NAME_LOCATION]
|
||||
local friendInfo = _G["FriendsFrameFriendButton"..i.."ButtonTextInfo"]
|
||||
local caption = friendName or friendLoc
|
||||
|
||||
if connected then
|
||||
if not class or class == _G.UNKNOWN then break end
|
||||
local ccolor = RAID_CLASS_COLORS[L["class"][class]] or { 1, 1, 1 }
|
||||
local lcolor = GetDifficultyColor(tonumber(level)) or { 1, 1, 1 }
|
||||
|
||||
zone = ( zone == playerzone and "|cffffffff" or "|cffcccccc" ) .. zone .. "|r"
|
||||
local cname = rgbhex(ccolor) .. name .. "|r"
|
||||
local clevel = rgbhex(lcolor) .. level .. "|r"
|
||||
|
||||
if playerdb[name] then
|
||||
playerdb[name].lastseen = date("%a %d-%b-%Y")
|
||||
playerdb[name].cname = cname
|
||||
playerdb[name].clevel = clevel
|
||||
playerdb[name].cclass = ccolor
|
||||
end
|
||||
|
||||
if friendName then
|
||||
friendName:SetText(cname)
|
||||
friendLoc:SetText(format(TEXT(FRIENDS_LIST_TEMPLATE), zone, status))
|
||||
else
|
||||
friendLoc:SetText(format(TEXT(FRIENDS_LIST_TEMPLATE), cname, zone, status))
|
||||
end
|
||||
|
||||
friendInfo:SetText(format(TEXT(friendinfo), clevel, class, ""))
|
||||
caption:SetVertexColor(1,1,1,.9)
|
||||
friendInfo:SetVertexColor(1,1,1,.9)
|
||||
else
|
||||
if playerdb[name] and playerdb[name].cname and playerdb[name].clevel and playerdb[name].lastseen then
|
||||
caption:SetText(format(TEXT(FRIENDS_LIST_OFFLINE_TEMPLATE), playerdb[name].cname))
|
||||
friendInfo:SetText(format(TEXT(friendinfo), playerdb[name].clevel, playerdb[name].lastseen, ""))
|
||||
else
|
||||
caption:SetText(format(TEXT(FRIENDS_LIST_OFFLINE_TEMPLATE), name.."|r"))
|
||||
friendInfo:SetText(TEXT(UNKNOWN))
|
||||
end
|
||||
|
||||
caption:SetVertexColor(1,1,1,.4)
|
||||
friendInfo:SetVertexColor(1,1,1,.4)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
do -- add colors to who list
|
||||
hooksecurefunc("WhoList_Update", function()
|
||||
local num, max = GetNumWhoResults()
|
||||
local off = FauxScrollFrame_GetOffset(WhoListScrollFrame)
|
||||
|
||||
local playerzone = GetRealZoneText()
|
||||
local playerrace = UnitRace("player")
|
||||
local playerguild = GetGuildInfo("player")
|
||||
|
||||
for i=1, WHOS_TO_DISPLAY do
|
||||
local name, guild, level, race, class, zone = GetWhoInfo(off + i)
|
||||
local displayedText = ""
|
||||
|
||||
if num + 1 >= MAX_WHOS_FROM_SERVER then
|
||||
displayedText = format(WHO_FRAME_SHOWN_TEMPLATE, MAX_WHOS_FROM_SERVER)
|
||||
WhoFrameTotals:SetText("|cffffffff" .. format(GetText("WHO_FRAME_TOTAL_TEMPLATE", nil, num), max).." |cffaaaaaa"..displayedText)
|
||||
else
|
||||
displayedText = format(WHO_FRAME_SHOWN_TEMPLATE, num)
|
||||
WhoFrameTotals:SetText("|cffffffff" .. format(GetText("WHO_FRAME_TOTAL_TEMPLATE", nil, num), num).." |cffaaaaaa"..displayedText)
|
||||
end
|
||||
|
||||
class = L["class"][class]
|
||||
|
||||
_G["WhoFrameButton"..i.."Name"]:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
|
||||
|
||||
if (UIDropDownMenu_GetSelectedID(WhoFrameDropDown) == 1) then
|
||||
if (zone == playerzone) then
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(.5, 1, 1)
|
||||
else
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(1, 1, 1)
|
||||
end
|
||||
|
||||
elseif (UIDropDownMenu_GetSelectedID(WhoFrameDropDown) == 2) then
|
||||
if (guild == playerguild) then
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(.5, 1, 1)
|
||||
else
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(1, 1, 1)
|
||||
end
|
||||
|
||||
elseif (UIDropDownMenu_GetSelectedID(WhoFrameDropDown) == 3) then
|
||||
if (race == playerrace) then
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(.5, 1, 1)
|
||||
else
|
||||
_G["WhoFrameButton"..i.."Variable"]:SetTextColor(1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
if class then
|
||||
local color = RAID_CLASS_COLORS[class]
|
||||
_G["WhoFrameButton"..i.."Class"]:SetTextColor(color.r,color.g,color.b,1)
|
||||
end
|
||||
|
||||
local color = GetDifficultyColor(level)
|
||||
_G["WhoFrameButton"..i.."Level"]:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,71 @@
|
||||
-- SuperWoW compatibility
|
||||
--
|
||||
-- https://github.com/balakethelock/SuperWoW
|
||||
--
|
||||
-- This module adds GUID based cast and channel data to the
|
||||
-- libcast library that is used to query enemy casting infos.
|
||||
|
||||
-- Skip module initialization if SuperWoW is not running.
|
||||
if not GetPlayerBuffID or not CombatLogAdd or not SpellInfo then return end
|
||||
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Super WoW Compatibility"],
|
||||
description = T["Adds compatibility for the SuperWoW client mod."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = false },
|
||||
category = T["General"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local libcast = ShaguTweaks.libcast
|
||||
|
||||
local unitcast = CreateFrame("Frame")
|
||||
unitcast:RegisterEvent("UNIT_CASTEVENT")
|
||||
unitcast:SetScript("OnEvent", function()
|
||||
if arg3 == "START" or arg3 == "CAST" or arg3 == "CHANNEL" then
|
||||
-- human readable argument list
|
||||
local guid = arg1
|
||||
local target = arg2
|
||||
local event_type = arg3
|
||||
local spell_id = arg4
|
||||
local timer = arg5
|
||||
local start = GetTime()
|
||||
|
||||
-- get spell info from spell id
|
||||
local spell, icon, _
|
||||
if SpellInfo and SpellInfo(spell_id) then
|
||||
spell, _, icon = SpellInfo(spell_id)
|
||||
end
|
||||
|
||||
-- set fallback values
|
||||
spell = spell or UNKNOWN
|
||||
icon = icon or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
|
||||
-- add cast action to the database
|
||||
if not libcast.db[guid] then libcast.db[guid] = {} end
|
||||
libcast.db[guid].cast = spell
|
||||
libcast.db[guid].rank = nil
|
||||
libcast.db[guid].start = GetTime()
|
||||
libcast.db[guid].casttime = timer
|
||||
libcast.db[guid].icon = icon
|
||||
libcast.db[guid].channel = event_type == "CHANNEL" or false
|
||||
|
||||
-- write state variable
|
||||
ShaguTweaks.superwow_active = true
|
||||
elseif arg3 == "FAIL" then
|
||||
local guid = arg1
|
||||
|
||||
-- delete all cast entries of guid
|
||||
if libcast.db[guid] then
|
||||
libcast.db[guid].cast = nil
|
||||
libcast.db[guid].rank = nil
|
||||
libcast.db[guid].start = nil
|
||||
libcast.db[guid].casttime = nil
|
||||
libcast.db[guid].icon = nil
|
||||
libcast.db[guid].channel = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,144 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local GetExpansion = ShaguTweaks.GetExpansion
|
||||
local UnitCastingInfo = ShaguTweaks.UnitCastingInfo
|
||||
local UnitChannelInfo = ShaguTweaks.UnitChannelInfo
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Enemy Castbars"],
|
||||
description = T["Shows an enemy castbar on target unit frame."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Unit Frames"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
local castbar = CreateFrame("StatusBar", "ShaguTargetCastbar", TargetFrame)
|
||||
castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -4)
|
||||
castbar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
|
||||
castbar:SetStatusBarColor(1, .8, 0, 1)
|
||||
castbar:SetWidth(140)
|
||||
castbar:SetHeight(10)
|
||||
castbar:Hide()
|
||||
|
||||
castbar.texture = CreateFrame("Frame", nil, castbar)
|
||||
castbar.texture:SetPoint("RIGHT", castbar, "LEFT", -2, 0)
|
||||
castbar.texture:SetHeight(20)
|
||||
castbar.texture:SetWidth(20)
|
||||
|
||||
castbar.texture.icon = castbar.texture:CreateTexture(nil, "BACKGROUND")
|
||||
castbar.texture.icon:SetPoint("CENTER", 0, 0)
|
||||
castbar.texture.icon:SetWidth(16)
|
||||
castbar.texture.icon:SetHeight(16)
|
||||
castbar.texture:SetBackdrop({
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 12,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
})
|
||||
|
||||
castbar.bg = castbar:CreateTexture(nil, "BACKGROUND")
|
||||
castbar.bg:SetTexture("Interface\\TARGETINGFRAME\\UI-StatusBar")
|
||||
castbar.bg:SetVertexColor(.1, .1, 0, .8)
|
||||
castbar.bg:SetAllPoints(true)
|
||||
|
||||
castbar.spark = castbar:CreateTexture(nil, "OVERLAY")
|
||||
castbar.spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
|
||||
castbar.spark:SetWidth(20)
|
||||
castbar.spark:SetHeight(20)
|
||||
castbar.spark:SetBlendMode("ADD")
|
||||
|
||||
castbar.backdrop = CreateFrame("Frame", nil, castbar)
|
||||
castbar.backdrop:SetFrameStrata("BACKGROUND")
|
||||
castbar.backdrop:SetPoint("TOPLEFT", castbar, "TOPLEFT", -3, 3)
|
||||
castbar.backdrop:SetPoint("BOTTOMRIGHT", castbar, "BOTTOMRIGHT", 3, -3)
|
||||
castbar.backdrop:SetBackdrop({
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 12,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
})
|
||||
|
||||
castbar.text = castbar:CreateFontString(nil, "HIGH", "GameFontWhite")
|
||||
castbar.text:SetPoint("CENTER", castbar, "CENTER", 0, 0)
|
||||
local font, size, opts = castbar.text:GetFont()
|
||||
castbar.text:SetFont(font, size - 2, "THINOUTLINE")
|
||||
|
||||
module.enable = function(self)
|
||||
local oldUpdate = TargetFrame:GetScript("OnUpdate")
|
||||
TargetFrame:SetScript("OnUpdate", function(arg)
|
||||
if oldUpdate then oldUpdate(arg) end
|
||||
|
||||
local query = this.unit
|
||||
local channel = false
|
||||
|
||||
-- try to read cast and guid from SuperWoW (except for self casts)
|
||||
if ShaguTweaks.superwow_active and this.unit and not UnitIsUnit(this.unit, 'player') then
|
||||
local _, guid = UnitExists(this.unit)
|
||||
query = guid or query
|
||||
end
|
||||
|
||||
local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(query)
|
||||
if not cast then
|
||||
-- scan for channel spells if no cast was found
|
||||
channel, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitChannelInfo(query)
|
||||
cast = channel
|
||||
end
|
||||
|
||||
if cast then
|
||||
local channel = UnitChannelInfo(this.unit)
|
||||
local duration = endTime - startTime
|
||||
local max = duration / 1000
|
||||
local cur = GetTime() - startTime / 1000
|
||||
|
||||
if channel then
|
||||
cur = max + startTime/1000 - GetTime()
|
||||
end
|
||||
|
||||
cur = cur > max and max or cur
|
||||
cur = cur < 0 and 0 or cur
|
||||
|
||||
castbar:Show()
|
||||
castbar:SetMinMaxValues(0, duration / 1000)
|
||||
castbar:SetValue(cur)
|
||||
|
||||
local percent = cur / max
|
||||
local x = castbar:GetWidth()*percent
|
||||
castbar.spark:SetPoint("CENTER", castbar, "LEFT", x, 0)
|
||||
|
||||
castbar.text:SetText(cast)
|
||||
|
||||
if texture then
|
||||
castbar.texture.icon:SetTexture(texture)
|
||||
castbar.texture.icon:Show()
|
||||
else
|
||||
castbar.texture.icon:Hide()
|
||||
end
|
||||
|
||||
castbar:ClearAllPoints()
|
||||
castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -4)
|
||||
|
||||
local targetOfTarget = TargetofTargetFrame and TargetofTargetFrame:IsShown()
|
||||
local debuff11 = TargetFrameDebuff11 and TargetFrameDebuff11:IsShown()
|
||||
local debuff7 = TargetFrameDebuff7 and TargetFrameDebuff7:IsShown()
|
||||
local buff1 = TargetFrameBuff1 and TargetFrameBuff1:IsShown()
|
||||
|
||||
if targetOfTarget then
|
||||
castbar:ClearAllPoints()
|
||||
castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -24)
|
||||
if debuff11 then
|
||||
castbar:ClearAllPoints()
|
||||
castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -45)
|
||||
if buff1 then
|
||||
castbar:ClearAllPoints()
|
||||
castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -65)
|
||||
end
|
||||
end
|
||||
else
|
||||
if debuff7 then
|
||||
castbar:ClearAllPoints()
|
||||
castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -24)
|
||||
end
|
||||
end
|
||||
else
|
||||
castbar:Hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,96 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Debuff Timer"],
|
||||
description = T["Show debuff durations on the target unit frame."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Unit Frames"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
local libdebuff = ShaguTweaks.libdebuff
|
||||
local UnitDebuff = libdebuff and libdebuff.UnitDebuff
|
||||
local TimeConvert = ShaguTweaks.TimeConvert
|
||||
|
||||
local function CreateTextCooldown(cooldown)
|
||||
if cooldown.readable then return end
|
||||
|
||||
cooldown.readable = CreateFrame("Frame", "pfCooldownFrame", cooldown:GetParent())
|
||||
cooldown.readable:SetAllPoints(cooldown)
|
||||
cooldown.readable:SetFrameLevel(cooldown:GetParent():GetFrameLevel() + 1)
|
||||
cooldown.readable.text = cooldown.readable:CreateFontString("pfCooldownFrameText", "OVERLAY")
|
||||
|
||||
cooldown.readable.text:SetFont(STANDARD_TEXT_FONT, 10, "OUTLINE")
|
||||
cooldown.readable.text:SetPoint("CENTER", cooldown.readable, "CENTER", 0, 0)
|
||||
cooldown.readable:SetScript("OnUpdate", function()
|
||||
parent = this:GetParent()
|
||||
if not parent then this:Hide() end
|
||||
|
||||
if not this.next then this.next = GetTime() + .1 end
|
||||
if this.next > GetTime() then return end
|
||||
this.next = GetTime() + .1
|
||||
|
||||
-- fix own alpha value (should be inherited, but somehow isn't always)
|
||||
this:SetAlpha(parent:GetAlpha())
|
||||
|
||||
local remaining = this.duration - (GetTime() - this.start)
|
||||
if remaining >= 0 then
|
||||
this.text:SetText(TimeConvert(remaining))
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
local HookTargetDebuffButton_Update = TargetDebuffButton_Update
|
||||
TargetDebuffButton_Update = function()
|
||||
HookTargetDebuffButton_Update()
|
||||
|
||||
for i=1, MAX_TARGET_DEBUFFS do
|
||||
local effect, rank, texture, stacks, dtype, duration, timeleft = libdebuff:UnitDebuff("target", i)
|
||||
local button = _G["TargetFrameDebuff"..i]
|
||||
|
||||
if button and not button.cd then
|
||||
button.cd = CreateFrame("Model", "TargetFrameDebuff"..i.."Cooldown", button, "CooldownFrameTemplate")
|
||||
button.cd.noCooldownCount = true
|
||||
button.cd:SetAllPoints()
|
||||
button.cd:SetScale(.6)
|
||||
button.cd:SetAlpha(.8)
|
||||
end
|
||||
|
||||
local dCount = _G["TargetFrameDebuff" .. i .. "Count"]
|
||||
if button and dCount then
|
||||
if not dCount.fixup then
|
||||
dCount.fixup = true
|
||||
dCount:SetPoint("BOTTOMRIGHT", "TargetFrameDebuff" .. i, "BOTTOMRIGHT", 6, -3)
|
||||
end
|
||||
if stacks and stacks > 1 then
|
||||
dCount:SetText("|c0000ff3b" .. stacks)
|
||||
dCount:Show()
|
||||
else
|
||||
dCount:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local dBorder = _G["TargetFrameDebuff" .. i .. "Border"]
|
||||
if button and dBorder then
|
||||
local color = dtype and DebuffTypeColor[dtype] or DebuffTypeColor["none"]
|
||||
dBorder:SetVertexColor(color.r, color.g, color.b)
|
||||
end
|
||||
|
||||
if button and effect and duration and timeleft then
|
||||
local start = GetTime() + timeleft - duration
|
||||
CreateTextCooldown(button.cd)
|
||||
CooldownFrame_SetTimer(button.cd, start, duration, 1)
|
||||
button.cd.readable.start = start
|
||||
button.cd.readable.duration = duration
|
||||
button.cd.readable:Show()
|
||||
button.cd:Show()
|
||||
elseif button then
|
||||
CooldownFrame_SetTimer(button.cd,0,0,0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local L = ShaguTweaks.L
|
||||
local round = ShaguTweaks.round
|
||||
local rgbhex = ShaguTweaks.rgbhex
|
||||
local Abbreviate = ShaguTweaks.Abbreviate
|
||||
|
||||
local units = { "mouseover", "player", "pet", "target", "party", "partypet", "raid", "raidpet" }
|
||||
local current_unit = "none"
|
||||
|
||||
local function GetUnit()
|
||||
current_unit = "none"
|
||||
for i, unit in pairs(units) do
|
||||
if unit == "party" or unit == "partypet" then
|
||||
for i=1,4 do
|
||||
if UnitExists(unit .. i) and ( UnitName(unit .. i) == GameTooltipTextLeft1:GetText() or UnitPVPName(unit .. i) == GameTooltipTextLeft1:GetText() ) then
|
||||
current_unit = unit .. i
|
||||
return current_unit
|
||||
end
|
||||
end
|
||||
elseif unit == "raid" or unit == "raidpet" then
|
||||
for i=1,40 do
|
||||
if UnitExists(unit .. i) and ( UnitName(unit .. i) == GameTooltipTextLeft1:GetText() or UnitPVPName(unit .. i) == GameTooltipTextLeft1:GetText() ) then
|
||||
current_unit = unit .. i
|
||||
return current_unit
|
||||
end
|
||||
end
|
||||
else
|
||||
if UnitExists(unit) and ( UnitName(unit) == GameTooltipTextLeft1:GetText() or UnitPVPName(unit) == GameTooltipTextLeft1:GetText() ) then
|
||||
current_unit = unit
|
||||
return current_unit
|
||||
end
|
||||
end
|
||||
end
|
||||
return current_unit
|
||||
end
|
||||
|
||||
local updating = false
|
||||
|
||||
local function UpdateTooltip()
|
||||
if updating then return end
|
||||
updating = true
|
||||
|
||||
local unit = GetUnit()
|
||||
if unit == "none" then
|
||||
updating = false
|
||||
return
|
||||
end
|
||||
|
||||
local pvpname = UnitPVPName(unit)
|
||||
local name = UnitName(unit)
|
||||
local target = UnitName(unit .. "target")
|
||||
local _, targetClass = UnitClass(unit .. "target")
|
||||
local targetReaction = UnitReaction("player", unit .. "target")
|
||||
local _, class = UnitClass(unit)
|
||||
local guild = GetGuildInfo(unit)
|
||||
local reaction = UnitReaction(unit, "player")
|
||||
local pvptitle = gsub(pvpname or name, " " .. name, "", 1)
|
||||
|
||||
if name then
|
||||
if UnitIsPlayer(unit) and class then
|
||||
local color = RAID_CLASS_COLORS[class]
|
||||
GameTooltipStatusBar:SetStatusBarColor_orig(color.r, color.g, color.b)
|
||||
GameTooltipStatusBar.bg:SetVertexColor(color.r * 0.15, color.g * 0.15, color.b * 0.15, 0.8)
|
||||
if color and color.r then
|
||||
GameTooltipTextLeft1:SetText(rgbhex(color.r, color.g, color.b, color.a) .. name)
|
||||
else
|
||||
GameTooltipTextLeft1:SetText("|cff999999" .. name)
|
||||
end
|
||||
elseif reaction then
|
||||
local color = UnitReactionColor[reaction]
|
||||
GameTooltipStatusBar:SetStatusBarColor_orig(color.r, color.g, color.b)
|
||||
GameTooltipStatusBar.bg:SetVertexColor(color.r * 0.15, color.g * 0.15, color.b * 0.15, 0.8)
|
||||
end
|
||||
|
||||
if pvptitle ~= name then
|
||||
GameTooltip:AppendText(" |cff666666[" .. pvptitle .. "]|r")
|
||||
end
|
||||
end
|
||||
|
||||
-- Guild name only (no rank)
|
||||
if guild then
|
||||
local guildAlready = false
|
||||
for i = 2, GameTooltip:NumLines() do
|
||||
local left = _G["GameTooltipTextLeft" .. i]
|
||||
if left and left:GetText() == "<" .. guild .. ">" then
|
||||
guildAlready = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not guildAlready then
|
||||
GameTooltip:AddLine("<" .. guild .. ">", 0.3, 1, 0.5)
|
||||
end
|
||||
end
|
||||
|
||||
-- Current target, colored by class or reaction
|
||||
-- Check tooltip lines to avoid duplicating the target line
|
||||
local alreadyAdded = false
|
||||
for i = 2, GameTooltip:NumLines() do
|
||||
local left = _G["GameTooltipTextLeft" .. i]
|
||||
if left and left:GetText() == target then
|
||||
alreadyAdded = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if target and not alreadyAdded then
|
||||
if UnitIsPlayer(unit .. "target") and targetClass then
|
||||
local color = RAID_CLASS_COLORS[targetClass]
|
||||
GameTooltip:AddLine(target, color.r, color.g, color.b)
|
||||
elseif targetReaction then
|
||||
local color = UnitReactionColor[targetReaction]
|
||||
if color then
|
||||
GameTooltip:AddLine(target, color.r, color.g, color.b)
|
||||
else
|
||||
GameTooltip:AddLine(target, .5, .5, .5)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
GameTooltip:Show()
|
||||
updating = false
|
||||
end
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Tooltip Details"],
|
||||
description = T["Enriches unit tooltips with health, class color, guild name, rank, and current target."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["General"],
|
||||
enabled = true,
|
||||
order = 50,
|
||||
})
|
||||
|
||||
local backdrop = {
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 12,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
}
|
||||
|
||||
module.enable = function(self)
|
||||
GameTooltipStatusBar:SetHeight(10)
|
||||
GameTooltipStatusBar:ClearAllPoints()
|
||||
GameTooltipStatusBar:SetPoint("BOTTOMLEFT", GameTooltip, "TOPLEFT", 4, 2)
|
||||
GameTooltipStatusBar:SetPoint("BOTTOMRIGHT", GameTooltip, "TOPRIGHT", -4, 2)
|
||||
|
||||
GameTooltipStatusBar.bg = GameTooltipStatusBar:CreateTexture(nil, "BACKGROUND")
|
||||
GameTooltipStatusBar.bg:SetTexture("Interface\\TARGETINGFRAME\\UI-StatusBar")
|
||||
GameTooltipStatusBar.bg:SetVertexColor(.1, .1, 0, .8)
|
||||
GameTooltipStatusBar.bg:SetAllPoints(true)
|
||||
|
||||
GameTooltipStatusBar.backdrop = CreateFrame("Frame", "GameTooltipStatusBarBackdrop", GameTooltipStatusBar)
|
||||
GameTooltipStatusBar.backdrop:SetPoint("TOPLEFT", GameTooltipStatusBar, "TOPLEFT", -3, 3)
|
||||
GameTooltipStatusBar.backdrop:SetPoint("BOTTOMRIGHT", GameTooltipStatusBar, "BOTTOMRIGHT", 3, -3)
|
||||
GameTooltipStatusBar.backdrop:SetBackdrop(backdrop)
|
||||
GameTooltipStatusBar.backdrop:SetBackdropBorderColor(.8,.8,.8,1)
|
||||
|
||||
GameTooltipStatusBar.backdrop.health = GameTooltipStatusBar.backdrop:CreateFontString("Status", "DIALOG", "GameFontWhite")
|
||||
GameTooltipStatusBar.backdrop.health:SetFont(STANDARD_TEXT_FONT, 12, "OUTLINE")
|
||||
GameTooltipStatusBar.backdrop.health:SetPoint("TOP", 0, 4)
|
||||
GameTooltipStatusBar.backdrop.health:SetNonSpaceWrap(false)
|
||||
|
||||
GameTooltipStatusBar.SetStatusBarColor_orig = GameTooltipStatusBar.SetStatusBarColor
|
||||
GameTooltipStatusBar.SetStatusBarColor = function() return end
|
||||
|
||||
-- update tooltip whenever it gets shown
|
||||
local details = CreateFrame("Frame", nil, GameTooltip)
|
||||
details:SetScript("OnShow", UpdateTooltip)
|
||||
|
||||
-- refresh current name and level
|
||||
local statusbar = CreateFrame('Frame', nil, GameTooltipStatusBar)
|
||||
statusbar:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
|
||||
statusbar:SetScript("OnEvent", function()
|
||||
this.name = UnitName("mouseover")
|
||||
this.level = UnitLevel("mouseover")
|
||||
UpdateTooltip()
|
||||
end)
|
||||
|
||||
-- update health text
|
||||
statusbar:SetScript("OnUpdate", function()
|
||||
local hp = GameTooltipStatusBar:GetValue()
|
||||
local _, hpmax = GameTooltipStatusBar:GetMinMaxValues()
|
||||
local rhp, rhpmax, estimated
|
||||
|
||||
if hpmax > 100 or (round(hpmax/100*hp) ~= hp) then
|
||||
rhp, rhpmax = hp, hpmax
|
||||
else
|
||||
rhp, rhpmax, estimated = ShaguTweaks.libhealth:GetUnitHealthByName(this.name, this.level, tonumber(hp), tonumber(hpmax))
|
||||
end
|
||||
|
||||
if ( estimated or hpmax > 100 or round(hpmax/100*hp) ~= hp ) then
|
||||
GameTooltipStatusBar.backdrop.health:SetText(string.format("%s / %s", Abbreviate(rhp, true), Abbreviate(rhpmax, true)))
|
||||
elseif hpmax > 0 then
|
||||
GameTooltipStatusBar.backdrop.health:SetText(string.format("%s%%", ceil(hp/hpmax*100)))
|
||||
else
|
||||
GameTooltipStatusBar.backdrop.health:SetText("")
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
+3092
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,113 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Unit Frame Big Health"],
|
||||
description = T["Increases the healthbar of the player and target unitframe."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Unit Frames"],
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
|
||||
local addonpath
|
||||
local tocs = { "", "-master", "-tbc", "-wotlk" }
|
||||
for _, name in pairs(tocs) do
|
||||
local current = string.format("ShaguTweaks%s", name)
|
||||
local _, title = GetAddOnInfo(current)
|
||||
if title then
|
||||
addonpath = "Interface\\AddOns\\" .. current
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
PlayerFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame")
|
||||
PlayerFrameHealthBar:SetPoint("TOPLEFT", 106, -22)
|
||||
PlayerFrameHealthBar:SetHeight(30)
|
||||
|
||||
PlayerStatusTexture:SetTexture(addonpath .. "\\img\\UI-Player-Status")
|
||||
|
||||
TargetFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame")
|
||||
TargetFrameHealthBar:SetPoint("TOPRIGHT", -106, -22)
|
||||
TargetFrameHealthBar:SetHeight(30)
|
||||
|
||||
|
||||
local original = TargetFrame_CheckClassification
|
||||
function TargetFrame_CheckClassification()
|
||||
local classification = UnitClassification("target")
|
||||
if ( classification == "worldboss" ) then
|
||||
TargetFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame-Elite")
|
||||
elseif ( classification == "rareelite" ) then
|
||||
TargetFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame-Elite")
|
||||
elseif ( classification == "elite" ) then
|
||||
TargetFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame-Elite")
|
||||
elseif ( classification == "rare" ) then
|
||||
TargetFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame-Rare")
|
||||
else
|
||||
TargetFrameTexture:SetTexture(addonpath .. "\\img\\UI-TargetingFrame")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local wait = CreateFrame("Frame")
|
||||
wait:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
wait:SetScript("OnEvent", function()
|
||||
-- apply darkmode if required
|
||||
ShaguTweaks.DarkenFrame(PlayerFrameTexture)
|
||||
ShaguTweaks.DarkenFrame(TargetFrameTexture)
|
||||
|
||||
-- adjust healthbar colors to frame colors
|
||||
local original = TargetFrame_CheckFaction
|
||||
function TargetFrame_CheckFaction(self)
|
||||
original(self)
|
||||
|
||||
if TargetFrameHealthBar._SetStatusBarColor then
|
||||
local r, g, b, a = TargetFrameNameBackground:GetVertexColor()
|
||||
TargetFrameHealthBar:_SetStatusBarColor(r, g, b, a)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- delay to first draw
|
||||
wait:SetScript("OnUpdate", function()
|
||||
-- move text strings a bit higher
|
||||
if PlayerFrameHealthBar.TextString then
|
||||
PlayerFrameHealthBar.TextString:SetPoint("TOP", PlayerFrameHealthBar, "BOTTOM", 0, 23)
|
||||
end
|
||||
|
||||
if TargetFrameHealthBar.TextString then
|
||||
TargetFrameHealthBar.TextString:SetPoint("TOP", TargetFrameHealthBar, "BOTTOM", -2, 23)
|
||||
end
|
||||
|
||||
-- use class color for player (if enabled)
|
||||
if PlayerFrameNameBackground then
|
||||
-- disable vanilla ui color restore functions
|
||||
PlayerFrameHealthBar._SetStatusBarColor = PlayerFrameHealthBar.SetStatusBarColor
|
||||
PlayerFrameHealthBar.SetStatusBarColor = function() return end
|
||||
|
||||
-- set player healthbar to class color
|
||||
local r, g, b, a = PlayerFrameNameBackground:GetVertexColor()
|
||||
PlayerFrameHealthBar:_SetStatusBarColor(r, g, b, a)
|
||||
|
||||
-- hide status textures
|
||||
PlayerFrameNameBackground:Hide()
|
||||
PlayerFrameNameBackground.Show = function() return end
|
||||
end
|
||||
|
||||
-- use frame color for target frame
|
||||
if TargetFrameNameBackground then
|
||||
-- disable vanilla ui color restore functions
|
||||
TargetFrameHealthBar._SetStatusBarColor = TargetFrameHealthBar.SetStatusBarColor
|
||||
TargetFrameHealthBar.SetStatusBarColor = function() return end
|
||||
|
||||
-- hide status textures
|
||||
TargetFrameNameBackground.Show = function() return end
|
||||
TargetFrameNameBackground:Hide()
|
||||
end
|
||||
|
||||
TargetFrame_CheckFaction(PlayerFrame)
|
||||
wait:UnregisterAllEvents()
|
||||
wait:Hide()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,78 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Unit Frame Class Colors"],
|
||||
description = T["Adds class colors to the player, target and party unit frames."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Unit Frames"],
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
local partycolors = function()
|
||||
for id = 1, MAX_PARTY_MEMBERS do
|
||||
local name = _G['PartyMemberFrame'..id..'Name']
|
||||
local _, class = UnitClass("party" .. id)
|
||||
local class = RAID_CLASS_COLORS[class] or { r = .5, g = .5, b = .5, a = 1 }
|
||||
if name then name:SetTextColor(class.r, class.g, class.b, 1) end
|
||||
end
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
-- enable class color backgrounds
|
||||
local original = TargetFrame_CheckFaction
|
||||
function TargetFrame_CheckFaction(self)
|
||||
original(self)
|
||||
|
||||
local reaction = UnitReaction("target", "player")
|
||||
|
||||
if UnitIsPlayer("target") then
|
||||
local _, class = UnitClass("target")
|
||||
local class = RAID_CLASS_COLORS[class] or { r = .5, g = .5, b = .5, a = 1 }
|
||||
TargetFrameNameBackground:SetVertexColor(class.r, class.g, class.b, 1)
|
||||
TargetFrameNameBackground:Show()
|
||||
elseif reaction and reaction > 4 then
|
||||
TargetFrameNameBackground:Hide()
|
||||
else
|
||||
TargetFrameNameBackground:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local _, class = UnitClass("player")
|
||||
local class = RAID_CLASS_COLORS[class] or { r = .5, g = .5, b = .5, a = 1 }
|
||||
|
||||
-- add name background to player frame
|
||||
PlayerFrameNameBackground = PlayerFrame:CreateTexture(nil, "BACKGROUND")
|
||||
PlayerFrameNameBackground:SetTexture("Interface\\TargetingFrame\\UI-TargetingFrame-LevelBackground")
|
||||
PlayerFrameNameBackground:SetWidth(119)
|
||||
PlayerFrameNameBackground:SetHeight(19)
|
||||
PlayerFrameNameBackground:SetPoint("TOPLEFT", 106, -22)
|
||||
PlayerFrameNameBackground:SetVertexColor(class.r, class.g, class.b, 1)
|
||||
|
||||
local wait = CreateFrame("Frame")
|
||||
wait:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
wait:SetScript("OnEvent", function()
|
||||
local _, class = UnitClass("player")
|
||||
local class = RAID_CLASS_COLORS[class] or { r = .5, g = .5, b = .5, a = 1 }
|
||||
PlayerFrameNameBackground:SetVertexColor(class.r, class.g, class.b, 1)
|
||||
this:UnregisterAllEvents()
|
||||
|
||||
-- make sure to keep name background above frame shadow
|
||||
PlayerFrameNameBackground:SetDrawLayer("BORDER")
|
||||
TargetFrameNameBackground:SetDrawLayer("BORDER")
|
||||
end)
|
||||
|
||||
-- add font outline
|
||||
local font, size = PlayerFrame.name:GetFont()
|
||||
PlayerFrame.name:SetFont(font, size, "NONE")
|
||||
TargetFrame.name:SetFont(font, size, "NONE")
|
||||
|
||||
-- add party frame class colors
|
||||
local HookPartyMemberFrame_UpdateMember = PartyMemberFrame_UpdateMember
|
||||
PartyMemberFrame_UpdateMember = function(self)
|
||||
HookPartyMemberFrame_UpdateMember(self)
|
||||
partycolors()
|
||||
end
|
||||
|
||||
partycolors()
|
||||
end
|
||||
@@ -0,0 +1,80 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local addonpath
|
||||
local tocs = { "", "-master", "-tbc", "-wotlk" }
|
||||
for _, name in pairs(tocs) do
|
||||
local current = string.format("ShaguTweaks%s", name)
|
||||
local _, title = GetAddOnInfo(current)
|
||||
if title then
|
||||
addonpath = "Interface\\AddOns\\" .. current
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local CLASS_ICON_TCOORDS = {
|
||||
["WARRIOR"] = { 0, 0.25, 0, 0.25 },
|
||||
["MAGE"] = { 0.25, 0.49609375, 0, 0.25 },
|
||||
["ROGUE"] = { 0.49609375, 0.7421875, 0, 0.25 },
|
||||
["DRUID"] = { 0.7421875, 0.98828125, 0, 0.25 },
|
||||
["HUNTER"] = { 0, 0.25, 0.25, 0.5 },
|
||||
["SHAMAN"] = { 0.25, 0.49609375, 0.25, 0.5 },
|
||||
["PRIEST"] = { 0.49609375, 0.7421875, 0.25, 0.5 },
|
||||
["WARLOCK"] = { 0.7421875, 0.98828125, 0.25, 0.5 },
|
||||
["PALADIN"] = { 0, 0.25, 0.5, 0.75 },
|
||||
["DEATHKNIGHT"] = { 0.25, .5, 0.5, .75 },
|
||||
}
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Unit Frame Class Portraits"],
|
||||
description = T["Replace unitframe portraits with class icons."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["Unit Frames"],
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
local function UpdatePortraits(frame)
|
||||
-- detect unit class or remove for non-player units
|
||||
local _, class = UnitClass(frame.unit)
|
||||
class = UnitIsPlayer(frame.unit) and class or nil
|
||||
|
||||
-- update class icon if possible
|
||||
if class and frame.portrait then
|
||||
local iconCoords = CLASS_ICON_TCOORDS[class]
|
||||
frame.portrait:SetTexture(addonpath .. "\\img\\UI-Classes-Circles")
|
||||
frame.portrait:SetTexCoord(unpack(iconCoords))
|
||||
elseif not class and frame.portrait then
|
||||
frame.portrait:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
end
|
||||
|
||||
module.enable = function(self)
|
||||
-- overwrite portraits set by the game
|
||||
local original = UnitFrame_Update
|
||||
UnitFrame_Update = function(arg1, arg2, arg3)
|
||||
original(arg1, arg2, arg3)
|
||||
UpdatePortraits(this)
|
||||
end
|
||||
|
||||
-- handle portrait update events
|
||||
local events = CreateFrame("Frame")
|
||||
events:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
events:RegisterEvent("UNIT_PORTRAIT_UPDATE")
|
||||
events:SetScript("OnEvent", function()
|
||||
-- reload player portrait
|
||||
UpdatePortraits(PlayerFrame)
|
||||
UpdatePortraits(TargetFrame)
|
||||
|
||||
-- reload party portraits
|
||||
UpdatePortraits(PartyMemberFrame1)
|
||||
UpdatePortraits(PartyMemberFrame2)
|
||||
UpdatePortraits(PartyMemberFrame3)
|
||||
UpdatePortraits(PartyMemberFrame4)
|
||||
end)
|
||||
|
||||
-- update target of target
|
||||
local tot = CreateFrame("Frame", nil, TargetFrame)
|
||||
tot:SetScript("OnUpdate", function()
|
||||
UpdatePortraits(TargetofTargetFrame)
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,85 @@
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["Unit Frame Energy & Mana Tick"],
|
||||
description = T["Adds an energy & mana tick to the player frame."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = nil },
|
||||
category = T["Unit Frames"],
|
||||
enabled = nil,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local energytick = CreateFrame("Frame", nil, PlayerFrameManaBar)
|
||||
energytick:SetAllPoints(PlayerFrameManaBar)
|
||||
energytick:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
energytick:RegisterEvent("UNIT_DISPLAYPOWER")
|
||||
energytick:RegisterEvent("UNIT_ENERGY")
|
||||
energytick:RegisterEvent("UNIT_MANA")
|
||||
energytick:SetScript("OnEvent", function()
|
||||
if UnitPowerType("player") == 0 then
|
||||
this.mode = "MANA"
|
||||
-- hide if full mana and not in combat
|
||||
if (UnitMana("player") == UnitManaMax("player")) and (not UnitAffectingCombat("player")) then
|
||||
this:Hide()
|
||||
else
|
||||
this:Show()
|
||||
end
|
||||
elseif UnitPowerType("player") == 3 then
|
||||
this.mode = "ENERGY"
|
||||
this:Show()
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
this.lastMana = UnitMana("player")
|
||||
end
|
||||
|
||||
if (this.mode == "ENERGY") or ((event == "UNIT_MANA" or event == "UNIT_ENERGY") and arg1 == "player") then
|
||||
this.currentMana = UnitMana("player")
|
||||
local diff = 0
|
||||
if this.lastMana then
|
||||
diff = this.currentMana - this.lastMana
|
||||
end
|
||||
|
||||
if this.mode == "MANA" and diff < 0 then
|
||||
this.target = 5
|
||||
elseif this.mode == "MANA" and diff > 0 then
|
||||
if this.max ~= 5 and diff > (this.badtick and this.badtick*1.2 or 5) then
|
||||
this.target = 2
|
||||
else
|
||||
this.badtick = diff
|
||||
end
|
||||
elseif this.mode == "ENERGY" and diff >= 0 then
|
||||
this.target = 2
|
||||
end
|
||||
this.lastMana = this.currentMana
|
||||
end
|
||||
end)
|
||||
|
||||
local pheight, pwidth = PlayerFrameManaBar:GetHeight(), PlayerFrameManaBar:GetWidth()
|
||||
energytick:SetScript("OnUpdate", function()
|
||||
if this.target then
|
||||
this.start, this.max = GetTime(), this.target
|
||||
this.target = nil
|
||||
end
|
||||
|
||||
if not this.start then return end
|
||||
|
||||
this.current = GetTime() - this.start
|
||||
|
||||
if this.current > this.max then
|
||||
this.start, this.max, this.current = GetTime(), 2, 0
|
||||
end
|
||||
|
||||
local pos = (pwidth ~= "-1" and pwidth or width) * (this.current / this.max)
|
||||
if not pheight then return end
|
||||
this.spark:SetPoint("LEFT", pos-((pheight+5)/2), 0)
|
||||
end)
|
||||
|
||||
energytick.spark = energytick:CreateTexture(nil, 'OVERLAY')
|
||||
energytick.spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
|
||||
energytick.spark:SetHeight(pheight + 10)
|
||||
energytick.spark:SetWidth(pheight + 4)
|
||||
energytick.spark:SetBlendMode('ADD')
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,107 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["WorldMap Class Colors"],
|
||||
description = T["Show class colored circles on world and battlefield map."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
local addonpath
|
||||
local tocs = { "", "-master", "-tbc", "-wotlk" }
|
||||
for _, name in pairs(tocs) do
|
||||
local current = string.format("ShaguTweaks%s", name)
|
||||
local _, title = GetAddOnInfo(current)
|
||||
if title then
|
||||
addonpath = "Interface\\AddOns\\" .. current
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local function SetAllPointsOffset(frame, parent, offset)
|
||||
frame:SetPoint("TOPLEFT", parent, "TOPLEFT", offset, -offset)
|
||||
frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -offset, offset)
|
||||
end
|
||||
|
||||
local function UpdateWorldMapColors()
|
||||
-- throttle to to one item per .1 second
|
||||
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + .1 end
|
||||
|
||||
local frame, icon
|
||||
|
||||
-- initialize all button names
|
||||
if not this.buttons then
|
||||
this.buttons = {}
|
||||
|
||||
for i = 1, 4 do
|
||||
icon = string.format("WorldMapParty%d", i)
|
||||
this.buttons[icon] = string.format("party%d", i)
|
||||
end
|
||||
|
||||
for i = 1, 4 do
|
||||
icon = string.format("BattlefieldMinimapParty%d", i)
|
||||
this.buttons[icon] = string.format("party%d", i)
|
||||
end
|
||||
|
||||
for i = 1, 40 do
|
||||
icon = string.format("BattlefieldMinimapRaid%d", i)
|
||||
this.buttons[icon] = string.format("raid%d", i)
|
||||
end
|
||||
|
||||
for i = 1, 40 do
|
||||
icon = string.format("WorldMapRaid%d", i)
|
||||
this.buttons[icon] = string.format("raid%d", i)
|
||||
end
|
||||
end
|
||||
|
||||
-- update all available buttons
|
||||
local ingroup
|
||||
for name, unitstr in pairs(this.buttons) do
|
||||
frame = _G[name]
|
||||
|
||||
if frame and UnitExists(unitstr) then
|
||||
icon = _G[name.."Icon"]
|
||||
icon:SetTexture()
|
||||
|
||||
-- create icon if not yet existing
|
||||
if not frame.texture then
|
||||
frame.texture = frame:CreateTexture(nil, "OVERLAY")
|
||||
SetAllPointsOffset(frame.texture, frame, 12, 12)
|
||||
end
|
||||
|
||||
-- check if unit is in same group
|
||||
ingroup = nil
|
||||
for i=1,5 do -- check if unit is in group
|
||||
if UnitName(string.format("party%d", i)) == UnitName(unitstr) then
|
||||
ingroup = true
|
||||
end
|
||||
end
|
||||
|
||||
-- update texture according to raid/group state
|
||||
if ingroup and frame.texture.ingroup ~= "PARTY" then
|
||||
frame.texture:SetTexture(addonpath .. "\\img\\circleparty")
|
||||
frame.texture.ingroup = "PARTY"
|
||||
elseif not ingroup and frame.texture.ingroup ~= "RAID" then
|
||||
frame.texture:SetTexture(addonpath .. "\\img\\circleraid")
|
||||
frame.texture.ingroup = "RAID"
|
||||
end
|
||||
|
||||
-- detect unit class and set color
|
||||
local _, class = UnitClass(unitstr)
|
||||
local color = RAID_CLASS_COLORS[class]
|
||||
if color then
|
||||
frame.texture:SetVertexColor(color.r, color.g, color.b)
|
||||
else
|
||||
frame.texture:SetVertexColor(.5,1,.5)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mapcolors = CreateFrame("Frame", nil, UIParent)
|
||||
|
||||
module.enable = function(self)
|
||||
mapcolors:SetScript("OnUpdate", UpdateWorldMapColors)
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["WorldMap Coordinates"],
|
||||
description = T["Adds coordinates to the bottom of the World Map."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
local delay = CreateFrame("Frame")
|
||||
delay:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
delay:SetScript("OnEvent", function()
|
||||
-- do not load if other map addon is loaded
|
||||
if Cartographer then return end
|
||||
if METAMAP_TITLE then return end
|
||||
|
||||
-- coordinates
|
||||
if not WorldMapButton.coords then
|
||||
WorldMapButton.coords = CreateFrame("Frame", "pfWorldMapButtonCoords", WorldMapButton)
|
||||
WorldMapButton.coords.text = WorldMapButton.coords:CreateFontString(nil, "OVERLAY")
|
||||
WorldMapButton.coords.text:SetPoint("BOTTOMLEFT", WorldMapButton, "BOTTOMLEFT", 3, -21)
|
||||
WorldMapButton.coords.text:SetFontObject(GameFontWhite)
|
||||
WorldMapButton.coords.text:SetTextColor(1, 1, 1)
|
||||
WorldMapButton.coords.text:SetJustifyH("RIGHT")
|
||||
|
||||
-- move coordinates in case of other addons already taking the space
|
||||
if Gatherer_WorldMapDisplay then
|
||||
WorldMapButton.coords.text:SetPoint("LEFT", Gatherer_WorldMapDisplay, "RIGHT", 3, -21)
|
||||
end
|
||||
|
||||
WorldMapButton.player = CreateFrame("Frame", "pfWorldMapButtonCoords", WorldMapButton)
|
||||
WorldMapButton.player.text = WorldMapButton.player:CreateFontString(nil, "OVERLAY")
|
||||
WorldMapButton.player.text:SetPoint("BOTTOMRIGHT", WorldMapButton, "BOTTOMRIGHT", -3, -21)
|
||||
WorldMapButton.player.text:SetFontObject(GameFontWhite)
|
||||
WorldMapButton.player.text:SetTextColor(1, 1, 1)
|
||||
WorldMapButton.player.text:SetJustifyH("RIGHT")
|
||||
|
||||
WorldMapButton.coords:SetScript("OnUpdate", function()
|
||||
local width = WorldMapButton:GetWidth()
|
||||
local height = WorldMapButton:GetHeight()
|
||||
local mx, my = WorldMapButton:GetCenter()
|
||||
local scale = WorldMapButton:GetEffectiveScale()
|
||||
local x, y = GetCursorPosition()
|
||||
|
||||
if mx and my then
|
||||
mx = (( x / scale ) - ( mx - width / 2)) / width * 100
|
||||
my = (( my + height / 2 ) - ( y / scale )) / height * 100
|
||||
end
|
||||
|
||||
local px, py = GetPlayerMapPosition("player")
|
||||
if px > 0 and py > 0 then
|
||||
WorldMapButton.player.text:SetText(string.format("|cffffcc00" .. T["Player"] .. ": |r%.1f / %.1f", px*100, py*100))
|
||||
else
|
||||
WorldMapButton.player.text:SetText(string.format("|cffffcc00" .. T["Player"] .. ": |r" .. T["N/A"]))
|
||||
end
|
||||
|
||||
if mx and my and MouseIsOver(WorldMapButton) then
|
||||
WorldMapButton.coords.text:SetText(string.format("|cffffcc00" .. T["Cursor"] .. ": |r%.1f / %.1f", mx, my))
|
||||
else
|
||||
WorldMapButton.coords.text:SetText(string.format("|cffffcc00" .. T["Cursor"] .. ": |r" .. T["N/A"]))
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,73 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
local HookScript = ShaguTweaks.HookScript
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["WorldMap Window"],
|
||||
description = T["Turns the world map into a movable window. The map can be scaled with <Ctrl> + Mousewheel."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["World & MiniMap"],
|
||||
enabled = true,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
table.insert(UISpecialFrames, "WorldMapFrame")
|
||||
|
||||
function _G.ToggleWorldMap()
|
||||
if WorldMapFrame:IsShown() then
|
||||
WorldMapFrame:Hide()
|
||||
else
|
||||
WorldMapFrame:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local delay = CreateFrame("Frame")
|
||||
delay:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
delay:SetScript("OnEvent", function()
|
||||
-- do not load if other map addon is loaded
|
||||
if Cartographer then return end
|
||||
if METAMAP_TITLE then return end
|
||||
|
||||
UIPanelWindows["WorldMapFrame"] = { area = "center" }
|
||||
|
||||
-- make sure the hooks get only applied once
|
||||
if not this.hooked then
|
||||
this.hooked = true
|
||||
|
||||
HookScript(WorldMapFrame, "OnShow", function()
|
||||
-- customize
|
||||
this:EnableKeyboard(false)
|
||||
this:EnableMouseWheel(1)
|
||||
|
||||
-- set back to default scale
|
||||
WorldMapFrame:SetScale(.85)
|
||||
end)
|
||||
|
||||
HookScript(WorldMapFrame, "OnMouseWheel", function()
|
||||
if IsShiftKeyDown() then
|
||||
WorldMapFrame:SetAlpha(WorldMapFrame:GetAlpha() + arg1/10)
|
||||
elseif IsControlKeyDown() then
|
||||
WorldMapFrame:SetScale(WorldMapFrame:GetScale() + arg1/10)
|
||||
end
|
||||
end)
|
||||
|
||||
HookScript(WorldMapFrame, "OnMouseDown",function()
|
||||
WorldMapFrame:StartMoving()
|
||||
end)
|
||||
|
||||
HookScript(WorldMapFrame, "OnMouseUp",function()
|
||||
WorldMapFrame:StopMovingOrSizing()
|
||||
end)
|
||||
end
|
||||
|
||||
WorldMapFrame:SetMovable(true)
|
||||
WorldMapFrame:EnableMouse(true)
|
||||
|
||||
WorldMapFrame:SetScale(.85)
|
||||
WorldMapFrame:ClearAllPoints()
|
||||
WorldMapFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 30)
|
||||
WorldMapFrame:SetWidth(WorldMapButton:GetWidth() + 15)
|
||||
WorldMapFrame:SetHeight(WorldMapButton:GetHeight() + 55)
|
||||
BlackoutWorld:Hide()
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,67 @@
|
||||
local _G = ShaguTweaks.GetGlobalEnv()
|
||||
local T = ShaguTweaks.T
|
||||
|
||||
local module = ShaguTweaks:register({
|
||||
title = T["XP Bar Text"],
|
||||
description = T["Always shows current XP and rested bonus percentage directly on the experience bar."],
|
||||
expansions = { ["vanilla"] = true, ["tbc"] = true },
|
||||
category = T["General"],
|
||||
enabled = true,
|
||||
order = 70,
|
||||
})
|
||||
|
||||
module.enable = function(self)
|
||||
-- Create a separate overlay frame anchored to the XP bar,
|
||||
-- same approach as actionbar-improved-expbar to avoid touching bar internals
|
||||
local exp = CreateFrame("Frame", nil, UIParent)
|
||||
exp:SetAllPoints(MainMenuExpBar)
|
||||
exp:SetFrameStrata("HIGH")
|
||||
|
||||
exp.text = exp:CreateFontString(nil, "OVERLAY", "GameFontWhite")
|
||||
exp.text:SetFont("Fonts\\ARIALN.TTF", 14, "OUTLINE")
|
||||
exp.text:SetPoint("CENTER", MainMenuExpBar, "CENTER", 0, 1)
|
||||
exp.text:SetJustifyH("CENTER")
|
||||
exp.text:SetTextColor(1, 1, 1)
|
||||
|
||||
local function UpdateXPText()
|
||||
local curr = UnitXP("player")
|
||||
local max = UnitXPMax("player")
|
||||
if not max or max == 0 then
|
||||
exp.text:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
local rest = GetXPExhaustion() or 0
|
||||
local xpPct = math.floor(curr / max * 100)
|
||||
|
||||
local text
|
||||
if rest > 0 then
|
||||
-- Rested XP pool is 150% of max XP, not 100% (mécanique post-patch)
|
||||
local restPct = math.floor(math.min(rest / (max * 1.5) * 100, 100))
|
||||
text = "|cffffffff" .. xpPct .. "%|r |cffaaaaaa(|cffa78aca" .. restPct .. "%|cffaaaaaa)|r"
|
||||
else
|
||||
text = "|cffffffff" .. xpPct .. "%|r"
|
||||
end
|
||||
|
||||
exp.text:SetText(text)
|
||||
exp.text:Show()
|
||||
end
|
||||
|
||||
local events = CreateFrame("Frame", nil, UIParent)
|
||||
events:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
events:RegisterEvent("PLAYER_XP_UPDATE")
|
||||
events:RegisterEvent("UPDATE_EXHAUSTION")
|
||||
events:RegisterEvent("PLAYER_LEVEL_UP")
|
||||
events:SetScript("OnEvent", function()
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
if not this.loaded then
|
||||
this.loaded = true
|
||||
-- hide blizzard's default overlay that renders the original xp text
|
||||
MainMenuBarOverlayFrame:Hide()
|
||||
UpdateXPText()
|
||||
end
|
||||
else
|
||||
UpdateXPText()
|
||||
end
|
||||
end)
|
||||
end
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 457 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 326 KiB |
Reference in New Issue
Block a user