Add files via upload

This commit is contained in:
2026-07-28 14:26:42 +02:00
committed by GitHub
commit d2ae117132
87 changed files with 36309 additions and 0 deletions
+21
View File
@@ -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.
+145
View File
@@ -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
![preview](screenshots/settings.jpg)
- **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
![preview](screenshots/dark.jpg)
*All options enabled, except for squared minimap.*
![preview](screenshots/castbars.jpg)
*Target Frame Castbars*
![preview](screenshots/bighealthclass.jpg)
*Big Healthbar, Class Portraits, Darkened UI*
![preview](screenshots/debufftimers.jpg)
*Debuff Timers & Mob Health*
+77
View File
@@ -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
+90
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+409
View File
@@ -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
+279
View File
@@ -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
+108
View File
@@ -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
+75
View File
@@ -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)
+469
View File
@@ -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
+129
View File
@@ -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
+169
View File
@@ -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
+144
View File
@@ -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
+86
View File
@@ -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,
}
+86
View File
@@ -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,
}
+86
View File
@@ -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,
}
+86
View File
@@ -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,
}
+86
View File
@@ -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,
}
+86
View File
@@ -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"] = "Ваш хлам продан, и вы заработали",
}
+86
View File
@@ -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"] = "你的垃圾物品已出售,你获得了:",
}
+86
View File
@@ -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,
}
+150
View File
@@ -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
+86
View File
@@ -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
+23
View File
@@ -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
+30
View File
@@ -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
+45
View File
@@ -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
+517
View File
@@ -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
+125
View File
@@ -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
+32
View File
@@ -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
+287
View File
@@ -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
+218
View File
@@ -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
+107
View File
@@ -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
+47
View File
@@ -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
+87
View File
@@ -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
+14
View File
@@ -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
+14
View File
@@ -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
+222
View File
@@ -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
+38
View File
@@ -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
+144
View File
@@ -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
+57
View File
@@ -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
+48
View File
@@ -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
+30
View File
@@ -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
+103
View File
@@ -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
+92
View File
@@ -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
+118
View File
@@ -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
+24
View File
@@ -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
+53
View File
@@ -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
+62
View File
@@ -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
+172
View File
@@ -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
+175
View File
@@ -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
+228
View File
@@ -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
+71
View File
@@ -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
+144
View File
@@ -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
+96
View File
@@ -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
+199
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+113
View File
@@ -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
+78
View File
@@ -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
+80
View File
@@ -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
+85
View File
@@ -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
+107
View File
@@ -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
+68
View File
@@ -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
+73
View File
@@ -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
+67
View File
@@ -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