├── .github
└── workflows
│ └── curse.yml
├── .gitignore
├── .gitmodules
├── .images
├── example.jpg
├── screenshot.jpg
├── weixin.jpg
└── zhifubao.jpg
├── .lua-format
├── CHANGELOG.md
├── Core
├── Action.lua
├── Addon.lua
├── Condition.lua
├── Core.xml
├── Director.lua
├── Manager
│ ├── BattleCacheManager.lua
│ ├── PluginManager.lua
│ └── ScriptManager.lua
├── Prototype
│ ├── BattleCache.lua
│ └── Plugin.lua
├── Script.lua
├── Share.lua
├── Stack.lua
└── Util.lua
├── Extension
├── Actions.lua
├── Conditions.lua
├── Extension.xml
├── Played.lua
├── Round.lua
└── Snippets.lua
├── LICENSE.md
├── Libs
├── AceAddon-3.0
│ ├── AceAddon-3.0.lua
│ └── AceAddon-3.0.xml
├── AceConfig-3.0
│ ├── AceConfig-3.0.lua
│ ├── AceConfig-3.0.xml
│ ├── AceConfigCmd-3.0
│ │ ├── AceConfigCmd-3.0.lua
│ │ └── AceConfigCmd-3.0.xml
│ ├── AceConfigDialog-3.0
│ │ ├── AceConfigDialog-3.0.lua
│ │ └── AceConfigDialog-3.0.xml
│ └── AceConfigRegistry-3.0
│ │ ├── AceConfigRegistry-3.0.lua
│ │ └── AceConfigRegistry-3.0.xml
├── AceDB-3.0
│ ├── AceDB-3.0.lua
│ └── AceDB-3.0.xml
├── AceEvent-3.0
│ ├── AceEvent-3.0.lua
│ └── AceEvent-3.0.xml
├── AceGUI-3.0
│ ├── AceGUI-3.0.lua
│ ├── AceGUI-3.0.xml
│ └── widgets
│ │ ├── AceGUIContainer-BlizOptionsGroup.lua
│ │ ├── AceGUIContainer-DropDownGroup.lua
│ │ ├── AceGUIContainer-Frame.lua
│ │ ├── AceGUIContainer-InlineGroup.lua
│ │ ├── AceGUIContainer-ScrollFrame.lua
│ │ ├── AceGUIContainer-SimpleGroup.lua
│ │ ├── AceGUIContainer-TabGroup.lua
│ │ ├── AceGUIContainer-TreeGroup.lua
│ │ ├── AceGUIContainer-Window.lua
│ │ ├── AceGUIWidget-Button.lua
│ │ ├── AceGUIWidget-CheckBox.lua
│ │ ├── AceGUIWidget-ColorPicker.lua
│ │ ├── AceGUIWidget-DropDown-Items.lua
│ │ ├── AceGUIWidget-DropDown.lua
│ │ ├── AceGUIWidget-EditBox.lua
│ │ ├── AceGUIWidget-Heading.lua
│ │ ├── AceGUIWidget-Icon.lua
│ │ ├── AceGUIWidget-InteractiveLabel.lua
│ │ ├── AceGUIWidget-Keybinding.lua
│ │ ├── AceGUIWidget-Label.lua
│ │ ├── AceGUIWidget-MultiLineEditBox.lua
│ │ └── AceGUIWidget-Slider.lua
├── AceHook-3.0
│ ├── AceHook-3.0.lua
│ └── AceHook-3.0.xml
├── AceLocale-3.0
│ ├── AceLocale-3.0.lua
│ └── AceLocale-3.0.xml
├── AceSerializer-3.0
│ ├── AceSerializer-3.0.lua
│ └── AceSerializer-3.0.xml
├── AceTimer-3.0
│ ├── AceTimer-3.0.lua
│ └── AceTimer-3.0.xml
├── CallbackHandler-1.0
│ ├── CallbackHandler-1.0.lua
│ └── CallbackHandler-1.0.xml
├── Embeds.xml
├── LibBase64-1.0
│ ├── LibBase64-1.0.lua
│ ├── LibBase64-1.0.toc
│ └── lib.xml
├── LibDBIcon-1.0
│ └── LibDBIcon-1.0.lua
├── LibDataBroker-1.1
│ └── LibDataBroker-1.1.lua
├── LibStub
│ └── LibStub.lua
└── LibWindow-1.1
│ ├── CHANGES.txt
│ ├── LibStub.lua
│ ├── LibWindow-1.1.toc
│ └── LibWindow-1.1
│ └── LibWindow-1.1.lua
├── Load.xml
├── Localization
├── Localization.xml
├── deDE.lua
├── enUS.lua
├── esES.lua
├── frFR.lua
├── itIT.lua
├── koKR.lua
├── ptBR.lua
├── ruRU.lua
├── zhCN.lua
└── zhTW.lua
├── Plugins
├── AllInOne.lua
├── Base.lua
├── FirstEnemy.lua
└── Plugins.xml
├── README.md
├── Share
├── Share.xml
├── Version0.lua
├── Version1.lua
└── Version2.lua
├── UI
├── Import.lua
├── MainPanel.lua
├── Minimap.lua
├── Option.lua
├── PetBattle.lua
├── UI.lua
├── UI.xml
└── Widgets
│ ├── AutoCompleteBox.lua
│ ├── AutoCompleteItem.lua
│ ├── ScriptEditor.lua
│ └── ScriptItem.lua
├── package.json
└── tdBattlePetScript.toc
/.github/workflows/curse.yml:
--------------------------------------------------------------------------------
1 | name: Curseforge
2 | on:
3 | push:
4 | tags:
5 | - v*
6 |
7 | jobs:
8 | publish:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - uses: actions/checkout@v3
13 | with:
14 | submodules: true
15 |
16 | - uses: actions/setup-node@v3
17 | with:
18 | node-version: '16'
19 |
20 | - run: npm install --location=global wow-curse-tools
21 | - run: wct publish --token ${{ secrets.CURSE_TOKEN }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vscode
2 | /.tags
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Libs/LibCRC32-1.0"]
2 | path = Libs/LibCRC32-1.0
3 | url = https://github.com/DengSir/LibCRC32-1.0.git
4 | [submodule "Libs/tdGUI"]
5 | path = Libs/tdGUI
6 | url = https://github.com/DengSir/tdGUI.git
7 |
--------------------------------------------------------------------------------
/.images/example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DengSir/tdBattlePetScript/58d19ec8c2fc1708fd9af187113f752cb13b27ba/.images/example.jpg
--------------------------------------------------------------------------------
/.images/screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DengSir/tdBattlePetScript/58d19ec8c2fc1708fd9af187113f752cb13b27ba/.images/screenshot.jpg
--------------------------------------------------------------------------------
/.images/weixin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DengSir/tdBattlePetScript/58d19ec8c2fc1708fd9af187113f752cb13b27ba/.images/weixin.jpg
--------------------------------------------------------------------------------
/.images/zhifubao.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DengSir/tdBattlePetScript/58d19ec8c2fc1708fd9af187113f752cb13b27ba/.images/zhifubao.jpg
--------------------------------------------------------------------------------
/.lua-format:
--------------------------------------------------------------------------------
1 | column_limit: 120
2 | keep_simple_control_block_one_line: false
3 | keep_simple_function_one_line: false
4 | extra_sep_at_table_end: true
5 | double_quote_to_single_quote: true
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [10.0.0]
2 |
3 | - Updated for Dragonflight.
4 | - Added `collected` to the Pets API (`true` if the pet is in your collection).
5 | - Added `trap` to the Status API (`true` if the trap is usable (or potentially usable if enemy hp is low enough)).
6 | - Fixed condition behavior when the condition includes a non-existent pet or ability. This allows (among others) using ability `(Ghostly Bite:654) [enemy.ability (Mudslide:572).duration < 5]`, even if the current pet does not have Mudslide, to be used in generic scripts. See the discussion in [this issue](https://github.com/DengSir/tdBattlePetScript/issues/26) for more detail and exact semantics.
7 | - General bug fixes
8 |
--------------------------------------------------------------------------------
/Core/Action.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Action.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Util = ns.Util
9 | local Addon = ns.Addon
10 | local Action = {} ns.Action = Action
11 |
12 | Action.apis = {}
13 |
14 | function Addon:RegisterAction(...)
15 | local last = select('#', ...)
16 | local method = select(last, ...)
17 |
18 | if last < 2 or type(method) ~= 'function' then
19 | error('Usage: :RegisterAction(name, [name2, ...], method)')
20 | end
21 |
22 | for i = 1, last - 1 do
23 | Action.apis[select(i, ...)] = method
24 | end
25 | end
26 |
27 | function Action:Run(action)
28 | local cmd, value = self:ParseAction(action)
29 |
30 | local fn = self.apis[cmd]
31 | return fn and fn(value)
32 | end
33 |
34 | function Action:ParseAction(action)
35 | Util.assert(type(action) == 'string', 'Invalid Action: `%s`', action)
36 |
37 | if action:find('^%-%-') then
38 | return '--', action
39 | end
40 |
41 | local cmd, value = Util.ParseQuote(action)
42 |
43 | Util.assert(cmd, 'Invalid Action: `%s`', action)
44 | Util.assert(self.apis[cmd], 'Invalid Action: `%s` (Not found command)', action)
45 |
46 | return cmd, value ~= '' and value or nil
47 | end
48 |
--------------------------------------------------------------------------------
/Core/Addon.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Addon.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ADDON, ns = ...
8 | local Addon = LibStub('AceAddon-3.0'):NewAddon('tdBattlePetScript', 'AceEvent-3.0', 'LibClass-2.0')
9 | local GUI = LibStub('tdGUI-1.0')
10 |
11 | ns.Addon = Addon
12 | ns.UI = {}
13 | ns.L = LibStub('AceLocale-3.0'):GetLocale('tdBattlePetScript', true)
14 | ns.ICON = [[Interface\Icons\INV_Misc_PenguinPet]]
15 |
16 | _G.tdBattlePetScript = Addon
17 |
18 | function Addon:OnInitialize()
19 | local defaults = {
20 | global = {
21 | scripts = {
22 |
23 | },
24 | notifies = {
25 |
26 | }
27 | },
28 | profile = {
29 | pluginDisabled = {},
30 | pluginOrders = {},
31 | settings = {
32 | autoSelect = true,
33 | hideNoScript = true,
34 | noWaitDeleteScript = false,
35 | editorFontFace = STANDARD_TEXT_FONT,
36 | editorFontSize = 14,
37 | autoButtonHotKey = 'A',
38 | testBreak = true,
39 | lockScriptSelector = false,
40 | },
41 | minimap = {
42 | minimapPos = 50,
43 | },
44 | position = {
45 | point = 'CENTER', x = 0, y = 0, width = 350, height = 450,
46 | },
47 | scriptSelectorPosition = {
48 | point = 'TOP', x = 0, y = -60,
49 | }
50 | }
51 | }
52 |
53 | self.db = LibStub('AceDB-3.0'):New('TD_DB_BATTLEPETSCRIPT_GLOBAL', defaults, true)
54 |
55 | self.db.RegisterCallback(self, 'OnDatabaseShutdown')
56 | end
57 |
58 | function Addon:OnEnable()
59 | self:RegisterMessage('PET_BATTLE_SCRIPT_SCRIPT_ADDED')
60 | self:RegisterMessage('PET_BATTLE_SCRIPT_SCRIPT_REMOVED')
61 | self:InitSettings()
62 | self:UpdateDatabase()
63 | end
64 |
65 | function Addon:InitSettings()
66 | for key, value in pairs(self.db.profile.settings) do
67 | self:SetSetting(key, value)
68 | end
69 | end
70 |
71 | function Addon:UpdateDatabase()
72 | local oldVersion = self.db.global.version or 0
73 | local newVersion = tonumber(GetAddOnMetadata(ADDON, 'Version')) or 99999.99
74 |
75 | if oldVersion ~= newVersion then
76 | self.db.global.version = newVersion
77 |
78 | C_Timer.After(0.9, function()
79 | GUI:Notify{
80 | text = format('%s\n|cff00ffff%s%s|r', ADDON, ns.L['Update to version: '], newVersion),
81 | icon = ns.ICON,
82 | help = ''
83 | }
84 | end)
85 | end
86 | end
87 |
88 | function Addon:OnModuleCreated(module)
89 | local name = module:GetName()
90 | if name:find('^UI%.') then
91 | ns.UI[name:match('^UI%.(.+)$')] = module
92 | else
93 | ns[name] = module
94 | end
95 | end
96 |
97 | function Addon:OnDatabaseShutdown()
98 | self:SendMessage('PET_BATTLE_SCRIPT_DB_SHUTDOWN')
99 | end
100 |
101 | function Addon:PET_BATTLE_SCRIPT_SCRIPT_ADDED(_, plugin, key, script)
102 | self.db.global.scripts[plugin:GetPluginName()][key] = script:GetDB()
103 | end
104 |
105 | function Addon:PET_BATTLE_SCRIPT_SCRIPT_REMOVED(_, plugin, key)
106 | self.db.global.scripts[plugin:GetPluginName()][key] = nil
107 | end
108 |
109 | function Addon:GetSetting(key)
110 | return self.db.profile.settings[key]
111 | end
112 |
113 | function Addon:SetSetting(key, value)
114 | self.db.profile.settings[key] = value
115 | self:SendMessage('PET_BATTLE_SCRIPT_SETTING_CHANGED', key, value)
116 | self:SendMessage('PET_BATTLE_SCRIPT_SETTING_CHANGED_' .. key, value)
117 | end
118 |
119 | function Addon:ResetSetting(key)
120 | if type(self.db.profile[key]) == 'table' then
121 | wipe(self.db.profile[key])
122 |
123 | for k, v in pairs(self.db.defaults.profile[key]) do
124 | if type(v) == 'table' then
125 | self.db.profile[key][k] = CopyTable(v)
126 | else
127 | self.db.profile[key][k] = v
128 | end
129 | end
130 | else
131 | error('not support')
132 | end
133 | end
134 |
135 | function Addon:ResetFrames()
136 | self:ResetSetting('position')
137 | self:ResetSetting('scriptSelectorPosition')
138 | self:SendMessage('PET_BATTLE_SCRIPT_RESET_FRAMES')
139 | end
140 |
--------------------------------------------------------------------------------
/Core/Condition.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Condition.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Util = ns.Util
9 | local Addon = ns.Addon
10 | local Condition = {} ns.Condition = Condition
11 |
12 | Condition.apis = {}
13 | Condition.opts = setmetatable({
14 | __default = {
15 | owner = true,
16 | pet = true,
17 | arg = true,
18 | type = 'compare',
19 | }
20 | }, {
21 | __newindex = function(t, k, v)
22 | rawset(t, k, setmetatable(v, {__index = t.__default}))
23 | end,
24 | __index = function(t)
25 | return t.__default
26 | end,
27 | })
28 |
29 | local opTabler = {
30 | compare = {
31 | ['='] = function(a, b) return a == b end,
32 | ['=='] = function(a, b) return a == b end,
33 | ['!='] = function(a, b) return a ~= b end,
34 | ['>'] = function(a, b) return a > b end,
35 | ['<'] = function(a, b) return a < b end,
36 | ['>='] = function(a, b) return a >= b end,
37 | ['<='] = function(a, b) return a <= b end,
38 | ['~'] = function(a, v) return v[a] end,
39 | ['!~'] = function(a, v) return not v[a] end,
40 | },
41 | boolean = {
42 | ['='] = function(a) return a end,
43 | ['!'] = function(a) return not a end,
44 | },
45 | equality = {
46 | ['='] = function(a, b) return a == b end,
47 | ['=='] = function(a, b) return a == b end,
48 | ['!='] = function(a, b) return a ~= b end,
49 | ['~'] = function(a, v) return v[a] end,
50 | ['!~'] = function(a, v) return not v[a] end,
51 | }
52 | }
53 |
54 | local multiTabler = {
55 | ['~'] = true,
56 | ['!~'] = true,
57 | }
58 |
59 | local parses = {
60 | 'valueParse',
61 | 'argParse',
62 | }
63 |
64 | local function trynumber(value)
65 | return tonumber(value) or value
66 | end
67 |
68 | local function trynil(value)
69 | return value ~= '' and value or nil
70 | end
71 |
72 | function Addon:RegisterCondition(name, opts, api)
73 | if opts then
74 | if opts.type and not opTabler[opts.type] then
75 | error([[Bad argument opts.type (expect compare/boolean/equality)]], 2)
76 | end
77 |
78 | for i, v in ipairs(parses) do
79 | if opts[v] and type(opts[v]) ~= 'function' then
80 | error(format([[Bad argument opts.%s (expect function)]], v), 2)
81 | end
82 | end
83 | end
84 |
85 | Condition.apis[name] = api
86 | Condition.opts[name] = opts
87 | end
88 |
89 | function Condition:Run(condition)
90 | if not condition then
91 | return true
92 | end
93 | if type(condition) == 'string' then
94 | return self:RunCondition(condition)
95 | elseif type(condition) == 'table' then
96 | for _, v in ipairs(condition) do
97 | if not self:Run(v) then
98 | return false
99 | end
100 | end
101 | return true
102 | else
103 | Util.assert(false, 'Invalid Condition: `%s` (type error)', condition)
104 | end
105 | end
106 |
107 | function Condition:RunCondition(condition)
108 | local owner, pet, cmd, arg, op, value = self:ParseCondition(condition)
109 |
110 | local fn = self.apis[cmd]
111 | local opts = self.opts[cmd]
112 | if not fn then
113 | error('Big Bang !!!!!!')
114 | end
115 |
116 | local res = fn(owner, pet, arg)
117 | return opTabler[opts.type][op](res, value)
118 | end
119 |
120 | function Condition:ParsePet(str)
121 | if not str then
122 | return
123 | end
124 |
125 | local owner, pet = Util.ParseQuote(str)
126 | owner = Util.ParsePetOwner(owner)
127 | if not owner then
128 | return
129 | end
130 |
131 | petInputed = not not pet
132 | pet = Util.ParsePetIndex(owner, pet)
133 | return owner, pet, petInputed
134 | end
135 |
136 | function Condition:ParseCmd(major, minor)
137 | if not major then
138 | return
139 | end
140 |
141 | local cmd, arg = Util.ParseQuote(major)
142 | return minor and format('%s.%s', cmd, minor) or cmd, arg, not not arg
143 | end
144 |
145 | function Condition:ParseApi(str)
146 | if not str then
147 | return
148 | end
149 |
150 | local inQuote = false
151 | local args = {''}
152 |
153 | for char in str:gmatch('.') do
154 | if char == '.' and not inQuote then
155 | tinsert(args, '')
156 | else
157 | args[#args] = args[#args] .. char
158 | end
159 |
160 | if char == '(' then
161 | inQuote = true
162 | elseif char == ')' then
163 | inQuote = false
164 | end
165 | end
166 |
167 | local owner, pet, petInputed = self:ParsePet(args[1])
168 | local cmd, arg, argInputed = self:ParseCmd(unpack(args, owner and 2 or 1))
169 |
170 | return owner, pet, cmd, arg, petInputed, argInputed
171 | end
172 |
173 | function Condition:ParseCondition(condition)
174 | local non, args, op, value = condition:match('^(!?)([^!=<>~]+)%s*([!=<>~]*)%s*(.*)$')
175 |
176 | Util.assert(non, 'Invalid Condition: `%s` (Can`t parse)', condition)
177 |
178 | local owner, pet, cmd, arg, petInputed, argInputed = self:ParseApi(args:trim())
179 |
180 | Util.assert(cmd, 'Invalid Condition: `%s` (Can`t parse)', condition)
181 | Util.assert(self.apis[cmd], 'Invalid Condition: `%s` (Not found cmd: `%s`)', condition, cmd)
182 |
183 | op = trynil(op)
184 | value = trynil(value)
185 | non = trynil(non)
186 |
187 | local opts = self.opts[cmd]
188 |
189 | if opts.type == 'compare' or opts.type == 'equality' then
190 | Util.assert(not non, 'Invalid Condition: `%s` (Not need non)', condition)
191 | Util.assert(op, 'Invalid Condition: `%s` (Require op)', condition)
192 | Util.assert(value, 'Invalid Condition: `%s` (Require value)', condition)
193 | elseif opts.type == 'boolean' then
194 | Util.assert(not op, 'Invalid Condition: `%s` (Not need op)', condition)
195 | Util.assert(not value, 'Invalid Condition: `%s` (Not need value)', condition)
196 |
197 | value = nil
198 | op = non or '='
199 | else
200 | Util.assert(true)
201 | end
202 |
203 | Util.assert(opTabler[opts.type][op], 'Invalid Condition: `%s` (Invalid op)', condition)
204 |
205 | if value then
206 | if multiTabler[op] then
207 | local values = {strsplit(',', value)}
208 | value = {}
209 |
210 | for i, v in ipairs(values) do
211 | v = trynumber(v:trim())
212 | if opts.valueParse then
213 | v = Util.assert(opts.valueParse(v), 'Invalid Condition: `%s` (Error value)', condition)
214 | end
215 | value[v] = true
216 | end
217 | else
218 | value = trynumber(value)
219 | if opts.valueParse then
220 | value = Util.assert(opts.valueParse(value), 'Invalid Condition: `%s` (Error value)', condition)
221 | end
222 | end
223 | end
224 |
225 | if not opts.owner then
226 | Util.assert(not owner, 'Invalid Condition: `%s` (Not need owner)', condition)
227 | end
228 |
229 | if not opts.pet then
230 | Util.assert(not petInputed, 'Invalid Condition: `%s` (Not need pet)', condition)
231 | end
232 |
233 | if not opts.arg then
234 | Util.assert(not argInputed, 'Invalid Condition: `%s` (Not need arg)', condition)
235 | else
236 | arg = trynumber(arg)
237 | if opts.argParse then
238 | arg = opts.argParse(owner, pet, arg)
239 | end
240 | end
241 | return owner, pet, cmd, arg, op, value
242 | end
243 |
--------------------------------------------------------------------------------
/Core/Core.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Core/Director.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Director.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Util = ns.Util
9 | local Addon = ns.Addon
10 | local Action = ns.Action
11 | local Condition = ns.Condition
12 | local Director = Addon:NewModule('Director', 'AceEvent-3.0')
13 |
14 | function Director:OnInitialize()
15 | self:RegisterEvent('PET_BATTLE_CLOSE', 'ClearScript')
16 | end
17 |
18 | function Director:Run()
19 | if not self.script then
20 | return
21 | end
22 | self:Action(self.script:GetScript())
23 | end
24 |
25 | function Director:Debug(script)
26 | self:Action(script)
27 | end
28 |
29 | function Director:Action(item)
30 | if type(item) == 'table' then
31 | for i, v in ipairs(item) do
32 | if Condition:Run(v[2]) and self:Action(v[1]) then
33 | return true
34 | end
35 | end
36 | elseif type(item) == 'string' then
37 | if Action:Run(item) then
38 | return true
39 | end
40 | else
41 | error('No item')
42 | end
43 | end
44 |
45 | local function FormatMacro(tab, action, condition)
46 | if not condition then
47 | return tab .. action
48 | elseif type(condition) == 'string' then
49 | return format('%s%s [ %s ]', tab, action, condition)
50 | else
51 | return format('%s%s [ %s ]', tab, action, table.concat(condition, ' & '))
52 | end
53 | end
54 |
55 | local function mergeCondition(dest, ...)
56 | for i = 1, select('#', ...) do
57 | local v = select(i, ...)
58 | if type(v) == 'table' then
59 | mergeCondition(dest, unpack(v))
60 | elseif type(v) == 'string' then
61 | v = v:trim()
62 | if v ~= '' then
63 | tinsert(dest, v)
64 | end
65 | end
66 | end
67 | return dest
68 | end
69 |
70 | local function MergeCondition(...)
71 | local condition = mergeCondition({}, ...)
72 | if #condition > 1 then
73 | return condition
74 | elseif #condition == 1 then
75 | return condition[1]
76 | else
77 | return nil
78 | end
79 | end
80 |
81 | local function CheckCondition(item)
82 | if type(item) == 'string' then
83 | return Condition:ParseCondition(item)
84 | elseif type(item) == 'table' then
85 | for i, v in ipairs(item) do
86 | CheckCondition(v)
87 | end
88 | elseif not item then
89 | return
90 | else
91 | Util.assert(false, 'Invalid Script (Struct Error)')
92 | end
93 | end
94 |
95 | local function CheckAction(item)
96 | if type(item) == 'string' then
97 | return Action:ParseAction(item)
98 | elseif type(item) == 'table' then
99 | for i, v in ipairs(item) do
100 | CheckCondition(v[2])
101 | CheckAction(v[1])
102 | end
103 | else
104 | Util.assert(false, 'Invalid Script (Struct Error)')
105 | end
106 | end
107 |
108 | function Director:Check(item)
109 | return pcall(CheckAction, item)
110 | end
111 |
112 | function Director:BuildScript(code)
113 | if type(code) ~= 'string' then
114 | return nil, 'No code'
115 | end
116 |
117 | local script = {}
118 | local stack = ns.Stack:New()
119 |
120 | stack:Push(script)
121 |
122 | for line in code:gmatch('[^\r\n]+') do
123 | line = line:trim()
124 |
125 | if line ~= '' then
126 | local script = stack:Top()
127 | local action, condition do
128 | if line:find('^%-%-') then
129 | action = line
130 | elseif line:find('[', nil, true) then
131 | action, condition = line:match('^/?(.+)%s+%[(.+)%]$')
132 | else
133 | action = line:match('^/?(.+)$')
134 | end
135 | end
136 |
137 | if not action then
138 | return nil, format('Invalid Line: `%s`', line)
139 | end
140 |
141 | if condition then
142 | condition = MergeCondition({strsplit('&', condition)})
143 | end
144 |
145 | if action == 'if' then
146 | stack:Push({})
147 | tinsert(script, {stack:Top(), condition})
148 | elseif action == 'endif' or action == 'ei' then
149 | stack:Pop()
150 |
151 | local parent = stack:Top()
152 | if not parent then
153 | return nil, 'Invalid Script: if endif unpaired'
154 | end
155 |
156 | if #script == 1 then
157 | local dest = parent[#parent]
158 | local item = script[1]
159 |
160 | dest[1] = item[1]
161 | dest[2] = MergeCondition(dest[2], item[2])
162 | end
163 | else
164 | tinsert(script, {action, condition})
165 | end
166 | end
167 | end
168 |
169 | if stack:Top() ~= script then
170 | return nil, 'Invalid Script: if endif unpaired'
171 | end
172 |
173 | local ok, err = Director:Check(script)
174 | if not ok then
175 | return nil, err
176 | end
177 | return script
178 | end
179 |
180 | function Director:BeautyScript(script, deep)
181 | deep = deep or 0
182 |
183 | local tab = strrep(' ', deep * 4)
184 | local sb = {}
185 |
186 | for i, v in ipairs(script) do
187 | local condition = MergeCondition(v[2])
188 | local action = v[1]
189 |
190 | if type(action) == 'string' then
191 | tinsert(sb, FormatMacro(tab, action, condition))
192 | elseif type(action) == 'table' then
193 | tinsert(sb, FormatMacro(tab, 'if', condition))
194 | tinsert(sb, self:BeautyScript(action, deep + 1))
195 | tinsert(sb, FormatMacro(tab, 'endif'))
196 | end
197 | end
198 | return table.concat(sb, '\n')
199 | end
200 |
201 | local function errorhandler(err)
202 | return geterrorhandler()(err)
203 | end
204 |
205 | function Director:Select()
206 | local list = {}
207 |
208 | for name, plugin in Addon:IterateEnabledPlugins() do
209 | local ok, key = xpcall(function() return plugin:GetCurrentKey() end, errorhandler)
210 | local script = ok and key and plugin:GetScript(key)
211 | if script then
212 | tinsert(list, script)
213 | end
214 | end
215 | return list
216 | end
217 |
218 | function Director:SetScript(script)
219 | self.script = script
220 | self:SendMessage('PET_BATTLE_SCRIPT_SCRIPT_UPDATE')
221 | end
222 |
223 | function Director:GetScript()
224 | return self.script
225 | end
226 |
227 | function Director:ClearScript()
228 | self.script = nil
229 | self:SendMessage('PET_BATTLE_SCRIPT_SCRIPT_UPDATE')
230 | end
231 |
--------------------------------------------------------------------------------
/Core/Manager/BattleCacheManager.lua:
--------------------------------------------------------------------------------
1 | -- BattleCacheManager.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/20/2018, 2:52:21 PM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local BattleCacheManager = Addon:NewModule('BattleCacheManager', 'AceEvent-3.0')
9 | local BattleCachePrototype = {}
10 |
11 | ns.BattleCachePrototype = BattleCachePrototype
12 |
13 | BattleCacheManager:SetDefaultModulePrototype(BattleCachePrototype)
14 |
15 | function BattleCacheManager:OnInitialize()
16 | self.caches = _G.TD_DB_BATTLEPETSCRIPT_BATTLE_CACHE or {}
17 |
18 | self:RegisterMessage('PET_BATTLE_SCRIPT_DB_SHUTDOWN')
19 |
20 | if C_PetBattles.IsInBattle() then
21 | self:RegisterEvent('PET_BATTLE_CLOSE', function()
22 | self:UnregisterEvent('PET_BATTLE_CLOSE')
23 | self:RegisterEvent('PET_BATTLE_OPENING_START')
24 | end)
25 | else
26 | self:RegisterEvent('PET_BATTLE_OPENING_START')
27 | end
28 | end
29 |
30 | function BattleCacheManager:PET_BATTLE_SCRIPT_DB_SHUTDOWN()
31 | if C_PetBattles.IsInBattle() then
32 | _G.TD_DB_BATTLEPETSCRIPT_BATTLE_CACHE = self.caches
33 | else
34 | _G.TD_DB_BATTLEPETSCRIPT_BATTLE_CACHE = nil
35 | end
36 | end
37 |
38 | function BattleCacheManager:PET_BATTLE_OPENING_START()
39 | for _, module in self:IterateModules() do
40 | module:OnBattleStart()
41 | end
42 | end
43 |
44 | function BattleCacheManager:AllocCache(name, default)
45 | if not self.caches[name] then
46 | self.caches[name] = CopyTable(default) or {}
47 | end
48 | return self.caches[name]
49 | end
50 |
--------------------------------------------------------------------------------
/Core/Manager/PluginManager.lua:
--------------------------------------------------------------------------------
1 | -- PluginManager.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/23/2018, 11:16:26 PM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local ScriptManager = ns.ScriptManager
9 | local PluginPrototype = {}
10 | local L = ns.L
11 | local GUI = LibStub('tdGUI-1.0')
12 |
13 | ns.PluginPrototype = PluginPrototype
14 |
15 | local PluginManager = Addon:NewModule('PluginManager', 'AceEvent-3.0')
16 |
17 | function PluginManager:OnInitialize()
18 | self.moduleWatings = {}
19 | self.moduleEnableQueue = {}
20 | self.pluginsOrdered = {}
21 | self.pluginsNotInstalled = {}
22 | self.db = Addon.db
23 | end
24 |
25 | function PluginManager:OnEnable()
26 | self:InitPlugins()
27 | self:InitOrders()
28 | self:UpdatePlugins()
29 | self:RebuildPluginOrders()
30 | self:InitPluginsNotInstalled()
31 |
32 | C_Timer.After(0, function()
33 | self:LoadPlugins()
34 | end)
35 | end
36 |
37 | function PluginManager:GetPluginList()
38 | return self.pluginsOrdered
39 | end
40 |
41 | function PluginManager:IteratePlugins()
42 | return ipairs(self.pluginsOrdered)
43 | end
44 |
45 | function PluginManager:IterateEnabledPlugins()
46 | return coroutine.wrap(function()
47 | for _, plugin in ipairs(self.pluginsOrdered) do
48 | if plugin:IsEnabled() then
49 | coroutine.yield(plugin:GetPluginName(), plugin)
50 | end
51 | end
52 | end)
53 | end
54 |
55 | function PluginManager:InitPlugins()
56 | for name, plugin in self:IterateModules() do
57 | self.db.global.scripts[name] = self.db.global.scripts[name] or {}
58 |
59 | for key, db in pairs(self.db.global.scripts[name]) do
60 | ScriptManager:AddScript(plugin, key, Addon:GetClass('Script'):New(db, plugin, key))
61 | end
62 | end
63 | end
64 |
65 | function PluginManager:InitOrders()
66 | local default = {'Rematch', 'Base', 'FirstEnemy', 'AllInOne'}
67 | local pluginOrdersMap = tInvert(self.db.profile.pluginOrders)
68 | local pluginOrders = {} do
69 | for k in pairs(pluginOrdersMap) do
70 | tinsert(pluginOrders, k)
71 | end
72 | sort(pluginOrders, function(lhs, rhs)
73 | return pluginOrdersMap[lhs] < pluginOrdersMap[rhs]
74 | end)
75 | end
76 |
77 | for i, v in pairs(default) do
78 | if not pluginOrdersMap[v] and self:GetModule(v, true) then
79 | tinsert(pluginOrders, v)
80 | end
81 | end
82 |
83 | self.db.profile.pluginOrders = pluginOrders
84 | end
85 |
86 | function PluginManager:UpdatePlugins()
87 | local base = Addon:GetPlugin('Base')
88 | local firstEnemy = Addon:GetPlugin('FirstEnemy')
89 | if not base or not firstEnemy then
90 | return
91 | end
92 |
93 | local found = false
94 | for key, script in base:IterateScripts() do
95 | if type(key) == 'number' then
96 | found = true
97 |
98 | base:RemoveScript(key)
99 | firstEnemy:AddScript(key, script)
100 | end
101 | end
102 |
103 | if found then
104 | C_Timer.After(1, function()
105 | GUI:Notify{
106 | text = L.PLUGINFIRSTENEMY_NOTIFY,
107 | icon = ns.ICON,
108 | OnAccept = function()
109 | Addon:OpenOptionFrame('plugins')
110 | end
111 | }
112 | end)
113 | end
114 | end
115 |
116 | function PluginManager:InitPluginsNotInstalled()
117 | local thirdPlugins = {
118 | {
119 | addon = 'Rematch',
120 | plugin = 'tdBattlePetScript_Rematch',
121 | url = 'https://www.curseforge.com/wow/addons/tdbattlepetscript-rematch'
122 | }
123 | }
124 |
125 | local addons = {} do
126 | for i = 1, GetNumAddOns() do
127 | addons[GetAddOnInfo(i)] = true
128 | end
129 | end
130 |
131 | for _, v in ipairs(thirdPlugins) do
132 | if addons[v.pluginName or v.addon] and not addons[v.plugin] then
133 | table.insert(self.pluginsNotInstalled, v)
134 | end
135 | end
136 | end
137 |
138 | function PluginManager:GetNotInstalledPlugins()
139 | return self.pluginsNotInstalled
140 | end
141 |
142 | function PluginManager:RebuildPluginOrders()
143 | wipe(self.pluginsOrdered)
144 |
145 | for _, name in ipairs(self.db.profile.pluginOrders) do
146 | local plugin = self:GetModule(name, true)
147 | if plugin then
148 | tinsert(self.pluginsOrdered, plugin)
149 | end
150 | end
151 | end
152 |
153 | function PluginManager:LoadPlugins()
154 | while true do
155 | local module = table.remove(self.moduleEnableQueue, 1)
156 | if not module then
157 | break
158 | end
159 |
160 | if self:IsPluginAllowed(module:GetPluginName()) then
161 | module:Enable()
162 | end
163 | end
164 | end
165 |
166 | function PluginManager:ADDON_LOADED(_, addon)
167 | repeat
168 | local modules = self.moduleWatings[addon]
169 | if modules then
170 | self.moduleWatings[addon] = nil
171 |
172 | for _, module in ipairs(modules) do
173 | if self:IsPluginAllowed(module:GetPluginName()) then
174 | module:Enable()
175 | end
176 | end
177 | end
178 | until not self.moduleWatings[addon]
179 |
180 | if not next(self.moduleWatings) then
181 | self:UnregisterEvent('ADDON_LOADED')
182 | end
183 | end
184 |
185 | function PluginManager:MoveUpPlugin(name)
186 | local pluginOrders = self.db.profile.pluginOrders
187 | local index = tIndexOf(pluginOrders, name)
188 | if not index or index == 1 then
189 | return
190 | end
191 |
192 | tDeleteItem(pluginOrders, name)
193 | tinsert(pluginOrders, index - 1, name)
194 |
195 | self:RebuildPluginOrders()
196 | end
197 |
198 | function PluginManager:MoveDownPlugin(name)
199 | local pluginOrders = self.db.profile.pluginOrders
200 | local index = tIndexOf(pluginOrders, name)
201 | if not index or index == #pluginOrders then
202 | return
203 | end
204 |
205 | tDeleteItem(pluginOrders, name)
206 | tinsert(pluginOrders, index + 1, name)
207 |
208 | self:RebuildPluginOrders()
209 | end
210 |
211 | function PluginManager:EnableModuleWithAddonLoaded(module, addon)
212 | module:Disable()
213 |
214 | if not IsAddOnLoaded(addon) then
215 | self.moduleWatings[addon] = self.moduleWatings[addon] or {}
216 | tinsert(self.moduleWatings[addon], module)
217 |
218 | self:RegisterEvent('ADDON_LOADED')
219 | else
220 | tinsert(self.moduleEnableQueue, module)
221 | end
222 | end
223 |
224 | function PluginManager:IsPluginAllowed(name)
225 | return not self.db.profile.pluginDisabled[name]
226 | end
227 |
228 | function PluginManager:SetPluginAllowed(name, flag)
229 | self.db.profile.pluginDisabled[name] = not flag or nil
230 |
231 | C_Timer.After(0, function()
232 | local module = Addon:GetPlugin(name)
233 | if flag then
234 | module:Enable()
235 | else
236 | module:Disable()
237 | end
238 | end)
239 | end
240 |
241 | ---- Addon
242 |
243 | function Addon:NewPlugin(name, ...)
244 | return PluginManager:NewModule(name, PluginPrototype, ...)
245 | end
246 |
247 | function Addon:GetPlugin(name)
248 | return PluginManager:GetModule(name, true)
249 | end
250 |
251 | function Addon:IteratePlugins()
252 | return PluginManager:IteratePlugins()
253 | end
254 |
255 | function Addon:IterateEnabledPlugins()
256 | return PluginManager:IterateEnabledPlugins()
257 | end
258 |
--------------------------------------------------------------------------------
/Core/Manager/ScriptManager.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | ScriptManager.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local ScriptManager = Addon:NewModule('ScriptManager', 'AceEvent-3.0')
10 |
11 | local db = setmetatable({}, {
12 | __index = function(t, k)
13 | t[k] = {}
14 | return t[k]
15 | end
16 | })
17 |
18 | function ScriptManager:AddScript(plugin, key, script)
19 | db[plugin][key] = script
20 | self:SendMessage('PET_BATTLE_SCRIPT_SCRIPT_ADDED', plugin, key, script)
21 | self:SendMessage('PET_BATTLE_SCRIPT_SCRIPT_LIST_UPDATE')
22 | end
23 |
24 | function ScriptManager:GetScript(plugin, key)
25 | return db[plugin][key]
26 | end
27 |
28 | function ScriptManager:RemoveScript(plugin, key)
29 | db[plugin][key] = nil
30 | self:SendMessage('PET_BATTLE_SCRIPT_SCRIPT_REMOVED', plugin, key)
31 | self:SendMessage('PET_BATTLE_SCRIPT_SCRIPT_LIST_UPDATE')
32 | end
33 |
34 | function ScriptManager:IteratePluginScripts(plugin)
35 | return pairs(db[plugin])
36 | end
37 |
--------------------------------------------------------------------------------
/Core/Prototype/BattleCache.lua:
--------------------------------------------------------------------------------
1 | -- BattleCache.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/24/2018, 12:09:10 AM
5 |
6 | local ns = select(2, ...)
7 | local BattleCacheManager = ns.BattleCacheManager
8 | local BattleCachePrototype = ns.BattleCachePrototype
9 |
10 | function BattleCachePrototype:AllocCache(default)
11 | return BattleCacheManager:AllocCache(self:GetName(), default)
12 | end
13 |
14 | function BattleCachePrototype:OnBattleStart()
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/Core/Prototype/Plugin.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Plugin.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 | local ns = select(2, ...)
7 | local L = ns.L
8 | local UI = ns.UI
9 | local Addon = ns.Addon
10 | local ScriptManager = ns.ScriptManager
11 | local PluginManager = ns.PluginManager
12 | local PluginPrototype = ns.PluginPrototype
13 |
14 | ---- override
15 |
16 | function PluginPrototype:GetCurrentKey()
17 | error(format('`%s`:GetCurrentKey not define', self:GetPluginName()))
18 | end
19 |
20 | function PluginPrototype:GetTitleByKey(key)
21 | return self:AllocName()
22 | end
23 |
24 | function PluginPrototype:OnTooltipFormatting(tip, key)
25 | tip:AddLine(L.SCRIPT_SELECTOR_LOST_TOOLTIP, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, true)
26 | end
27 |
28 | function PluginPrototype:OnExport(key)
29 | return
30 | end
31 |
32 | function PluginPrototype:OnImport(data)
33 | return
34 | end
35 |
36 | ---- method
37 |
38 | function PluginPrototype:GetScript(key)
39 | return ScriptManager:GetScript(self, key)
40 | end
41 |
42 | function PluginPrototype:RemoveScript(key)
43 | return ScriptManager:RemoveScript(self, key)
44 | end
45 |
46 | function PluginPrototype:AddScript(key, script)
47 | return ScriptManager:AddScript(self, key, script)
48 | end
49 |
50 | function PluginPrototype:IterateScripts()
51 | return ScriptManager:IteratePluginScripts(self)
52 | end
53 |
54 | function PluginPrototype:GetPluginName()
55 | return self:GetName()
56 | end
57 |
58 | function PluginPrototype:EnableWithAddon(addon)
59 | return PluginManager:EnableModuleWithAddonLoaded(self, addon)
60 | end
61 |
62 | function PluginPrototype:SetPluginTitle(title)
63 | self._title = title
64 | end
65 |
66 | function PluginPrototype:GetPluginTitle()
67 | return self._title or self:GetPluginName()
68 | end
69 |
70 | function PluginPrototype:SetPluginIcon(icon)
71 | self._icon = icon
72 | end
73 |
74 | function PluginPrototype:GetPluginIcon()
75 | return self._icon or ns.ICON
76 | end
77 |
78 | function PluginPrototype:SetPluginNotes(notes)
79 | self._notes = notes
80 | end
81 |
82 | function PluginPrototype:GetPluginNotes()
83 | return self._notes
84 | end
85 |
86 | function PluginPrototype:OpenScriptEditor(key, name)
87 | return UI.MainPanel:OpenScriptDialog(self, key, name)
88 | end
89 |
90 | function PluginPrototype:AllocName()
91 | local id = 0
92 | for key, script in self:IterateScripts() do
93 | local _id = tonumber(script:GetName():match('^' .. L['New script'] .. ' (%d+)$'))
94 | if _id then
95 | id = max(id, _id)
96 | end
97 | end
98 | return L['New script'] .. ' ' .. (id + 1)
99 | end
100 |
--------------------------------------------------------------------------------
/Core/Script.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Script.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local Director = ns.Director
10 | local Script = Addon:NewClass('Script')
11 |
12 | function Script:Constructor(db, plugin, key)
13 | self.db = db
14 | self.key = key
15 | self.plugin = plugin
16 | end
17 |
18 | function Script:GetDB()
19 | return self.db
20 | end
21 |
22 | function Script:GetName()
23 | return self.db.name
24 | end
25 |
26 | function Script:SetName(name)
27 | self.db.name = name
28 | end
29 |
30 | function Script:GetCode()
31 | return self.db.code
32 | end
33 |
34 | function Script:SetCode(code)
35 | local script, err = Director:BuildScript(code)
36 | if not script then
37 | return false, err
38 | end
39 |
40 | self.db.code = code
41 | self.script = script
42 | return true
43 | end
44 |
45 | function Script:GetKey()
46 | return self.key
47 | end
48 |
49 | function Script:GetPlugin()
50 | return self.plugin
51 | end
52 |
53 | function Script:GetScript()
54 | if not self.script then
55 | self.script = Director:BuildScript(self.db.code)
56 | end
57 | return self.script
58 | end
59 |
--------------------------------------------------------------------------------
/Core/Share.lua:
--------------------------------------------------------------------------------
1 | -- Share.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/21/2018, 9:50:36 AM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local Director = ns.Director
9 |
10 | local SharePrototype = {
11 | Export = nop,
12 | Import = nop,
13 | Is = nop,
14 | }
15 |
16 | local handlers = {}
17 |
18 | function Addon:NewShareHandler(version)
19 | local handler = CopyTable(SharePrototype)
20 | handler.version = version
21 |
22 | tinsert(handlers, handler)
23 | sort(handlers, function(a, b)
24 | return a.version > b.version
25 | end)
26 |
27 | return handler
28 | end
29 |
30 | function Addon:Export(script)
31 | return handlers[1]:Export(script)
32 | end
33 |
34 | function Addon:Import(code)
35 | for _, handler in ipairs(handlers) do
36 | if handler:Is(code) then
37 | local ok, data = handler:Import(code)
38 | if not ok or not data or not data.db or not data.db.code then
39 | return false
40 | end
41 |
42 | if not Director:BuildScript(data.db.code) then
43 | return false
44 | end
45 | return true, data
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/Core/Stack.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Stack.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 |
10 | local Stack = Addon:NewClass('Stack') ns.Stack = Stack
11 |
12 | function Stack:Constructor()
13 | self.stack = {}
14 | end
15 |
16 | function Stack:Push(item)
17 | if item ~= nil then
18 | tinsert(self.stack, 1, item)
19 | end
20 | end
21 |
22 | function Stack:Pop()
23 | return table.remove(self.stack, 1)
24 | end
25 |
26 | function Stack:Top()
27 | return self.stack[1]
28 | end
29 |
--------------------------------------------------------------------------------
/Core/Util.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Api.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Util = {} ns.Util = Util
9 |
10 | function Util.ParseID(value)
11 | return type(value) == 'string' and tonumber(value:match(':(%d+)$')) or nil
12 | end
13 |
14 | function Util.ComparePet(owner, index, pet)
15 | return pet == C_PetBattles.GetName(owner, index) or tonumber(pet) == C_PetBattles.GetPetSpeciesID(owner, index)
16 | end
17 |
18 | function Util.ParseQuote(str)
19 | local major, quote = str:match('^([^()]+)%((.+)%)$')
20 | if major then
21 | return major, Util.ParseID(quote) or quote
22 | end
23 | return str, nil
24 | end
25 |
26 | function Util.ParseIndex(value)
27 | return type(value) == 'string' and tonumber(value:match('^#(%d+)$')) or nil
28 | end
29 |
30 | function Util.ParsePetOwner(owner)
31 | return owner == 'self' and Enum.BattlePetOwner.Ally or
32 | owner == 'ally' and Enum.BattlePetOwner.Ally or
33 | owner == 'enemy' and Enum.BattlePetOwner.Enemy or nil
34 | end
35 |
36 | function Util.ParsePetIndex(owner, pet)
37 | if not owner then
38 | return
39 | end
40 | if not pet then
41 | return C_PetBattles.GetActivePet(owner)
42 | end
43 | local index = Util.ParseIndex(pet)
44 | if index then
45 | if index >= 1 and index <= C_PetBattles.GetNumPets(owner) then
46 | return index
47 | end
48 | else
49 | local active = C_PetBattles.GetActivePet(owner)
50 | if Util.ComparePet(owner, active, pet) then
51 | return active
52 | end
53 | for i = 1, C_PetBattles.GetNumPets(owner) do
54 | if Util.ComparePet(owner, i, pet) then
55 | return i
56 | end
57 | end
58 | end
59 | end
60 |
61 | function Util.ParseAbility(owner, pet, ability)
62 | local index = Util.ParseIndex(ability)
63 | if index then
64 | if index and index >= 1 and index <= NUM_BATTLE_PET_ABILITIES then
65 | return index
66 | end
67 | else
68 | local best, bestDuration
69 | for i = 1, NUM_BATTLE_PET_ABILITIES do
70 | local id, name = C_PetBattles.GetAbilityInfo(owner, pet, i)
71 | if id == tonumber(ability) or name == ability then
72 | local usable, duration = C_PetBattles.GetAbilityState(owner, pet, i)
73 | if usable then
74 | return i
75 | end
76 | if not bestDuration or bestDuration > duration then
77 | bestDuration = duration
78 | best = i
79 | end
80 | end
81 | end
82 | return best
83 | end
84 | end
85 |
86 | local function FindAura(owner, pet, aura)
87 | for i = 1, C_PetBattles.GetNumAuras(owner, pet) do
88 | local id, name = C_PetBattles.GetAbilityInfoByID(C_PetBattles.GetAuraInfo(owner, pet, i))
89 | if id == aura or name == aura then
90 | return owner, pet, i
91 | end
92 | end
93 | end
94 |
95 | function Util.FindAura(owner, pet, aura)
96 | for i, pet in ipairs({pet, PET_BATTLE_PAD_INDEX}) do
97 | local owner, pet, i = FindAura(owner, pet, aura)
98 | if owner then
99 | return owner, pet, i
100 | end
101 | end
102 | end
103 |
104 | function Util.assert(flag, formatter, ...)
105 | if not flag then
106 | error(format(formatter, ...), 0)
107 | end
108 | return flag
109 | end
110 |
111 | local function lower(value)
112 | if type(value) == 'string' then
113 | return value:lower()
114 | end
115 | return value
116 | end
117 |
118 | local PET_TYPES = {} do
119 | for id = 1, C_PetJournal.GetNumPetTypes() do
120 | local name = _G['BATTLE_PET_NAME_' .. id]:lower()
121 | PET_TYPES[name] = id
122 | PET_TYPES[id] = id
123 | end
124 | end
125 |
126 | function Util.ParsePetType(value)
127 | if not value then
128 | return nil
129 | end
130 | return PET_TYPES[lower(value)] or PET_TYPES[Util.ParseID(value)] or nil
131 | end
132 |
133 | local PET_QUALITIES = {} do
134 | for id = 1, 6 do
135 | local name = _G['BATTLE_PET_BREED_QUALITY' .. id]:lower()
136 | PET_QUALITIES[name] = id
137 | PET_QUALITIES[id] = id
138 | end
139 | end
140 |
141 | function Util.ParseQuality(value)
142 | return value and PET_QUALITIES[lower(value)] or nil
143 | end
144 |
--------------------------------------------------------------------------------
/Extension/Actions.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Actions.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local Util = ns.Util
10 |
11 |
12 | Addon:RegisterAction('test', function(arg)
13 | print(arg)
14 | return Addon:GetSetting('testBreak')
15 | end)
16 |
17 |
18 | Addon:RegisterAction('change', function(index)
19 | local active = C_PetBattles.GetActivePet(Enum.BattlePetOwner.Ally)
20 | if index == 'next' then
21 | index = active % C_PetBattles.GetNumPets(Enum.BattlePetOwner.Ally) + 1
22 | else
23 | index = Util.ParsePetIndex(Enum.BattlePetOwner.Ally, index)
24 | end
25 | -- if not index or active == index or C_PetBattles.GetHealth(Enum.BattlePetOwner.Ally, index) == 0 then
26 | -- return false
27 | -- end
28 |
29 | if not index or active == index or not (C_PetBattles.CanActivePetSwapOut() or C_PetBattles.ShouldShowPetSelect()) or not C_PetBattles.CanPetSwapIn(index) then
30 | return false
31 | end
32 |
33 | C_PetBattles.ChangePet(index)
34 | return true
35 | end)
36 |
37 |
38 | Addon:RegisterAction('ability', 'use', function(ability)
39 | local index = C_PetBattles.GetActivePet(Enum.BattlePetOwner.Ally)
40 | local ability= Util.ParseAbility(Enum.BattlePetOwner.Ally, index, ability)
41 | if not ability then
42 | return false
43 | end
44 | if not C_PetBattles.GetAbilityState(Enum.BattlePetOwner.Ally, index, ability) then
45 | return false
46 | end
47 | C_PetBattles.UseAbility(ability)
48 | return true
49 | end)
50 |
51 |
52 | Addon:RegisterAction('quit', function()
53 | C_PetBattles.ForfeitGame()
54 | return true
55 | end)
56 |
57 |
58 | Addon:RegisterAction('standby', function()
59 | if not C_PetBattles.IsSkipAvailable() then
60 | return false
61 | end
62 | C_PetBattles.SkipTurn()
63 | return true
64 | end)
65 |
66 |
67 | Addon:RegisterAction('catch', function()
68 | if not C_PetBattles.IsTrapAvailable() then
69 | return false
70 | end
71 | C_PetBattles.UseTrap()
72 | return true
73 | end)
74 |
75 | Addon:RegisterAction('--', function()
76 | return false
77 | end)
78 |
--------------------------------------------------------------------------------
/Extension/Conditions.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Conditions.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local Util = ns.Util
10 | local Round = ns.BattleCacheManager:GetModule('Round')
11 | local Played = ns.BattleCacheManager:GetModule('Played')
12 |
13 |
14 | local function getOpponent(owner)
15 | return owner == Enum.BattlePetOwner.Ally and Enum.BattlePetOwner.Enemy or Enum.BattlePetOwner.Ally
16 | end
17 |
18 | local function getOpponentActivePet(owner)
19 | local opponent = getOpponent(owner)
20 | return opponent, C_PetBattles.GetActivePet(opponent)
21 | end
22 |
23 | local function GetAbilityAttackModifier(owner, pet, ability)
24 | if not pet or not ability then
25 | return
26 | end
27 | local abilityType, noStrongWeakHints = select(7, C_PetBattles.GetAbilityInfo(owner, pet, ability))
28 | if noStrongWeakHints then
29 | return
30 | end
31 |
32 | local opponentType = C_PetBattles.GetPetType(getOpponentActivePet(owner))
33 |
34 | return C_PetBattles.GetAttackModifier(abilityType, opponentType)
35 | end
36 |
37 | local infinite = tonumber('inf')
38 | local function logical_max_health(owner, pet)
39 | return pet and C_PetBattles.GetMaxHealth(owner, pet) or infinite
40 | end
41 |
42 | Addon:RegisterCondition('dead', { type = 'boolean', arg = false }, function(owner, pet)
43 | return C_PetBattles.GetHealth(owner, pet) == 0
44 | end)
45 |
46 |
47 | Addon:RegisterCondition('hp', { type = 'compare', arg = false }, function(owner, pet)
48 | return C_PetBattles.GetHealth(owner, pet)
49 | end)
50 |
51 |
52 | Addon:RegisterCondition('hp.full', { type = 'boolean', arg = false }, function(owner, pet)
53 | return C_PetBattles.GetHealth(owner, pet) == logical_max_health(owner, pet)
54 | end)
55 |
56 |
57 | Addon:RegisterCondition('hp.can_explode', { type = 'boolean', arg = false }, function(owner, pet)
58 | return pet and C_PetBattles.GetHealth(owner, pet) < floor(logical_max_health(getOpponentActivePet(owner)) * 0.4)
59 | end)
60 |
61 |
62 | Addon:RegisterCondition('hp.low', { type = 'boolean', pet = false, arg = false }, function(owner, pet)
63 | return C_PetBattles.GetHealth(owner, pet) < C_PetBattles.GetHealth(getOpponentActivePet(owner))
64 | end)
65 |
66 |
67 | Addon:RegisterCondition('hp.high', { type = 'boolean', pet = false, arg = false }, function(owner, pet)
68 | return C_PetBattles.GetHealth(owner, pet) > C_PetBattles.GetHealth(getOpponentActivePet(owner))
69 | end)
70 |
71 |
72 | Addon:RegisterCondition('hpp', { type = 'compare', arg = false }, function(owner, pet)
73 | return C_PetBattles.GetHealth(owner, pet) / logical_max_health(owner, pet) * 100
74 | end)
75 |
76 |
77 | Addon:RegisterCondition('aura.exists', { type = 'boolean' }, function(owner, pet, aura)
78 | return aura and Util.FindAura(owner, pet, aura)
79 | end)
80 |
81 |
82 | Addon:RegisterCondition('aura.duration', { type = 'compare' }, function(owner, pet, aura)
83 | local owner, pet, index = Util.FindAura(owner, pet, aura)
84 | if aura and index then
85 | return (select(3, C_PetBattles.GetAuraInfo(owner, pet, index)))
86 | end
87 | return 0
88 | end)
89 |
90 |
91 | Addon:RegisterCondition('weather', { type = 'boolean', owner = false, pet = false }, function(_, _, weather)
92 | local id, name = 0, ''
93 | local aura = C_PetBattles.GetAuraInfo(Enum.BattlePetOwner.Weather, PET_BATTLE_PAD_INDEX, 1)
94 | if aura then
95 | id, name = C_PetBattles.GetAbilityInfoByID(aura)
96 | end
97 | return weather and (id == weather or name == weather)
98 | end)
99 |
100 |
101 | Addon:RegisterCondition('weather.duration', { type = 'compare', owner = false, pet = false }, function(_, _, weather)
102 | local id, _, duration = C_PetBattles.GetAuraInfo(Enum.BattlePetOwner.Weather, PET_BATTLE_PAD_INDEX, 1)
103 | if weather and id and (id == weather or select(2, C_PetBattles.GetAbilityInfoByID(id)) == weather) then
104 | return duration
105 | end
106 | return 0
107 | end)
108 |
109 |
110 | Addon:RegisterCondition('active', { type = 'boolean', arg = false }, function(owner, pet)
111 | return C_PetBattles.GetActivePet(owner) == pet
112 | end)
113 |
114 |
115 | Addon:RegisterCondition('ability.usable', { type = 'boolean', argParse = Util.ParseAbility }, function(owner, pet, ability)
116 | local isUsable, currentCooldown, currentLockdown = C_PetBattles.GetAbilityState(owner, pet, ability)
117 | return ability and isUsable
118 | end)
119 |
120 |
121 | Addon:RegisterCondition('ability.duration', { type = 'compare', argParse = Util.ParseAbility }, function(owner, pet, ability)
122 | local isUsable, currentCooldown, currentLockdown = C_PetBattles.GetAbilityState(owner, pet, ability)
123 | return ability and currentCooldown or infinite
124 | end)
125 |
126 |
127 | Addon:RegisterCondition('ability.strong', { type = 'boolean', argParse = Util.ParseAbility }, function(owner, pet, ability)
128 | local modifier = GetAbilityAttackModifier(owner, pet, ability)
129 | return modifier and modifier > 1
130 | end)
131 |
132 |
133 | Addon:RegisterCondition('ability.weak', { type = 'boolean', argParse = Util.ParseAbility }, function(owner, pet, ability)
134 | local modifier = GetAbilityAttackModifier(owner, pet, ability)
135 | return modifier and modifier < 1
136 | end)
137 |
138 |
139 | Addon:RegisterCondition('ability.type', { type = 'equality', argParse = Util.ParseAbility, valueParse = Util.ParsePetType }, function(owner, pet, ability)
140 | return (select(7, C_PetBattles.GetAbilityInfo(owner, pet, ability)))
141 | end)
142 |
143 |
144 | Addon:RegisterCondition('round', { type = 'compare', pet = false, arg = false }, function(owner)
145 | if owner then
146 | return Round:GetRoundByOwner(owner)
147 | else
148 | return Round:GetRound()
149 | end
150 | end)
151 |
152 | Addon:RegisterCondition('played', { type = 'boolean', arg = false }, function(owner, pet)
153 | return pet and Played:IsPetPlayed(owner, pet)
154 | end)
155 |
156 | Addon:RegisterCondition('speed', { type = 'compare', arg = false }, C_PetBattles.GetSpeed)
157 | Addon:RegisterCondition('power', { type = 'compare', arg = false }, C_PetBattles.GetPower)
158 | Addon:RegisterCondition('level', { type = 'compare', arg = false }, C_PetBattles.GetLevel)
159 |
160 |
161 | Addon:RegisterCondition('level.max', { type = 'boolean', arg = false }, function(owner, pet)
162 | return pet and C_PetBattles.GetLevel(owner, pet) == 25
163 | end)
164 |
165 |
166 | Addon:RegisterCondition('speed.fast', { type = 'boolean', pet = false, arg = false }, function(owner)
167 | return C_PetBattles.GetSpeed(owner, C_PetBattles.GetActivePet(owner)) > C_PetBattles.GetSpeed(getOpponentActivePet(owner))
168 | end)
169 |
170 |
171 | Addon:RegisterCondition('speed.slow', { type = 'boolean', pet = false, arg = false }, function(owner)
172 | return C_PetBattles.GetSpeed(owner, C_PetBattles.GetActivePet(owner)) < C_PetBattles.GetSpeed(getOpponentActivePet(owner))
173 | end)
174 |
175 |
176 | Addon:RegisterCondition('type', { type = 'equality', arg = false, valueParse = Util.ParsePetType }, function(owner, pet)
177 | return C_PetBattles.GetPetType(owner, pet)
178 | end)
179 |
180 |
181 | Addon:RegisterCondition('quality', { type = 'compare', arg = false, valueParse = Util.ParseQuality }, function(owner, pet)
182 | return pet and C_PetBattles.GetBreedQuality(owner, pet)
183 | end)
184 |
185 |
186 | Addon:RegisterCondition('exists', { type = 'boolean', pet = 1, arg = false }, function(owner, pet)
187 | return not not pet
188 | end)
189 |
190 |
191 | Addon:RegisterCondition('is', { type = 'boolean', pet = 1 }, function(owner, pet, other)
192 | return pet and Util.ComparePet(owner, pet, Util.ParseID(other) or other)
193 | end)
194 |
195 |
196 | Addon:RegisterCondition('id', { type = 'equality', pet = 1, arg = false }, function(owner, pet)
197 | return pet and C_PetBattles.GetPetSpeciesID(owner, pet) or 0
198 | end)
199 |
200 | Addon:RegisterCondition('collected', { type = 'boolean', arg = false }, function(owner, pet)
201 | local name = select(2, C_PetBattles.GetName(owner, pet))
202 | return select(2, C_PetJournal.FindPetIDByName(name)) ~= nil
203 | end)
204 |
205 | Addon:RegisterCondition('trap', { type = 'boolean', owner = false , pet = false, arg = false }, function()
206 | local usable, err = C_PetBattles.IsTrapAvailable()
207 | return usable or (not usable and err == 4)
208 | end)
209 |
--------------------------------------------------------------------------------
/Extension/Extension.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Extension/Played.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Played.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 | local ns = select(2, ...)
7 | local Played = ns.BattleCacheManager:NewModule('Played', 'AceEvent-3.0')
8 |
9 | function Played:OnEnable()
10 | self.played = self:AllocCache({})
11 |
12 | self:RegisterEvent('PET_BATTLE_PET_CHANGED')
13 | end
14 |
15 | function Played:OnBattleStart()
16 | wipe(self.played)
17 | end
18 |
19 | function Played:PET_BATTLE_PET_CHANGED(_, owner)
20 | self.played[self:GetPetSlot(owner, C_PetBattles.GetActivePet(owner))] = true
21 | end
22 |
23 | function Played:GetPetSlot(owner, pet)
24 | return (owner - 1) * NUM_BATTLE_PETS_IN_BATTLE + pet
25 | end
26 |
27 | function Played:IsPetPlayed(owner, pet)
28 | return self.played[self:GetPetSlot(owner, pet)]
29 | end
30 |
--------------------------------------------------------------------------------
/Extension/Round.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Round.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 | local ns = select(2, ...)
7 | local Round = ns.BattleCacheManager:NewModule('Round', 'AceEvent-3.0')
8 |
9 | function Round:OnEnable()
10 | self.rounds = self:AllocCache({
11 | [0] = 0,
12 | [Enum.BattlePetOwner.Ally] = 0,
13 | [Enum.BattlePetOwner.Enemy] = 0
14 | })
15 |
16 | self:RegisterEvent('PET_BATTLE_PET_ROUND_RESULTS')
17 | self:RegisterEvent('PET_BATTLE_PET_CHANGED')
18 | end
19 |
20 | function Round:PET_BATTLE_PET_ROUND_RESULTS(_, round)
21 | -- for some reason, the event is fired twice if an enemy(?) pet dies,
22 | -- leading to increasing self.round counter twice. See issue #1.
23 | if round == self.rounds[0] - 1 then
24 | return
25 | end
26 | self.rounds[0] = round + 1
27 | self.rounds[Enum.BattlePetOwner.Ally] = self.rounds[Enum.BattlePetOwner.Ally] + 1
28 | self.rounds[Enum.BattlePetOwner.Enemy] = self.rounds[Enum.BattlePetOwner.Enemy] + 1
29 | end
30 |
31 | function Round:PET_BATTLE_PET_CHANGED(_, owner)
32 | if self.rounds[owner] then
33 | self.rounds[owner] = 1
34 | end
35 | end
36 |
37 | function Round:OnBattleStart()
38 | self.rounds[0] = 0
39 | self.rounds[Enum.BattlePetOwner.Ally] = 0
40 | self.rounds[Enum.BattlePetOwner.Enemy] = 0
41 | end
42 |
43 | function Round:GetRound()
44 | return self.rounds[0]
45 | end
46 |
47 | function Round:GetRoundByOwner(owner)
48 | return self.rounds[owner]
49 | end
50 |
--------------------------------------------------------------------------------
/Extension/Snippets.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Snippets.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 |
8 | local ns = select(2, ...)
9 | local Addon = ns.Addon
10 | local Util = ns.Util
11 | local Condition = ns.Condition
12 |
13 | local Snippets = {} ns.Snippets = Snippets
14 |
15 | do
16 | local function factory(opts)
17 | local words = opts.words or {}
18 | local filter = opts.filter
19 |
20 | if opts.extend then
21 | local set = {}
22 | local function add(k)
23 | if set[k] then return end
24 | set[k] = true
25 | tinsert(words, k)
26 | end
27 |
28 | for k in pairs(opts.extend) do
29 | add(strsplit('.', k))
30 | add(k)
31 | end
32 | end
33 |
34 | sort(words)
35 |
36 | local function callback(item)
37 | return tinsert(words, 1, table.remove(words, item.index))
38 | end
39 |
40 | local function default(list, word, ...)
41 | if not word then
42 | return
43 | end
44 |
45 | local front, tail
46 | local len = #word
47 | for i, v in ipairs(words) do
48 | if v ~= word then
49 | front = v:sub(1, len)
50 |
51 | if front == word and (not filter or filter(v, word, ...)) then
52 | tail = v:sub(len + 1)
53 |
54 | tinsert(list, {
55 | text = format('|cff00ff00%s|r%s', front, tail),
56 | value = tail,
57 | callback = callback,
58 | index = i,
59 | })
60 | end
61 | end
62 | end
63 | return 1
64 | end
65 |
66 | return {
67 | __default = default,
68 | }
69 | end
70 |
71 | Snippets.Condition = factory({
72 | extend = Condition.apis,
73 | filter = function(v, word, owner, pet, arg, non, petInputed, argInputed)
74 | if not Condition.apis[v] then
75 | return true
76 | end
77 |
78 | local opts = Condition.opts[v]
79 | if not opts.owner ~= not owner and v ~= 'round' then
80 | return false
81 | end
82 | if opts.pet and not pet then
83 | return false
84 | end
85 | if not opts.pet and petInputed then
86 | return false
87 | end
88 | if non and opts.type ~= 'boolean' then
89 | return false
90 | end
91 | if not opts.arg and argInputed then
92 | return false
93 | end
94 |
95 | local len = #word
96 | local pos = v:find('.', nil, true)
97 | if opts.arg and not argInputed and pos and len >= pos then
98 | return false
99 | end
100 |
101 | if pos and pos > len then
102 | return false
103 | end
104 | return true
105 | end
106 | })
107 |
108 | Snippets.Action = factory({
109 | words = { 'if', 'endif' },
110 | extend = ns.Action.apis,
111 | })
112 |
113 | Snippets.Target = factory({
114 | words = { 'self', 'enemy', 'ally' }
115 | })
116 | end
117 |
118 | function Snippets:Check(line)
119 | local list, column = {}
120 | local condition = line:match('[[&]%s*([^&[]+)$')
121 |
122 | if condition then
123 | local owner, pet, word, arg, non, petInputed, argInputed = self:ParseCondition(condition)
124 | word = word or line:match('(%w+)$')
125 | if not word then
126 | return
127 | end
128 |
129 | if not owner then
130 | self.Target.__default(list, word)
131 | end
132 |
133 | if arg or not self.Condition[word] then
134 | column = self.Condition.__default(list, word, owner, pet, arg, non, petInputed, argInputed)
135 | else
136 | column = self.Condition[word](list, word, owner, pet)
137 | end
138 | else
139 | word = line:match('^%s*(%w+)$')
140 | if not word then
141 | return
142 | end
143 |
144 | if not self.Action[word] then
145 | column = self.Action.__default(list, word)
146 | else
147 | column = self.Action[word](list, word)
148 | end
149 | end
150 |
151 | if not column or #list == 0 then
152 | return
153 | end
154 | return list, column
155 | end
156 |
157 | function Snippets:ParseCondition(condition)
158 | if not condition then
159 | return
160 | end
161 |
162 | local non do
163 | local _cond
164 | non, _cond = condition:match('^(!?)%s*(.+)$')
165 | non = non == '!'
166 |
167 | if non then
168 | condition = _cond
169 | end
170 | end
171 |
172 | local owner, pet, cmd, arg, petInputed, argInputed = Condition:ParseApi(condition)
173 |
174 | return owner, pet, cmd, arg, non, petInputed, argInputed
175 | end
176 |
177 | local empty = {}
178 | local function tfillrow(t, column)
179 | for i = 1, column - #t % column do
180 | tinsert(t, empty)
181 | end
182 | end
183 |
184 | local function makeNameSnippet(name, id)
185 | return {
186 | text = name,
187 | value = format('(%s:%d)', name, id),
188 | }
189 | end
190 |
191 | local function makeIndexSnippet(index)
192 | return {
193 | text = format('#%d', index),
194 | value = format('(#%d)', index),
195 | }
196 | end
197 |
198 | local function makeIconSnippet(icon)
199 | return {
200 | icon = icon
201 | }
202 | end
203 |
204 | local function fillAbility(list, owner, pet)
205 | for i = 1, NUM_BATTLE_PET_ABILITIES do
206 | local id, name, icon = C_PetBattles.GetAbilityInfo(owner, pet, i)
207 | if id then
208 | tinsert(list, makeIconSnippet(icon))
209 | tinsert(list, makeNameSnippet(name, id))
210 | tinsert(list, makeIndexSnippet(i))
211 | end
212 | end
213 | return 3
214 | end
215 |
216 | local function fillPet(list, owner)
217 | for i = 1, C_PetBattles.GetNumPets(owner) do
218 | local name = C_PetBattles.GetName(owner, i)
219 | local icon = C_PetBattles.GetIcon(owner, i)
220 | local id = C_PetBattles.GetPetSpeciesID(owner, i)
221 |
222 | tinsert(list, makeIconSnippet(icon))
223 | tinsert(list, makeNameSnippet(name, id))
224 | tinsert(list, makeIndexSnippet(i))
225 | end
226 | return 3
227 | end
228 |
229 | Snippets.Action.use = function(list)
230 | return fillAbility(list, Enum.BattlePetOwner.Ally, C_PetBattles.GetActivePet(Enum.BattlePetOwner.Ally))
231 | end
232 |
233 | Snippets.Action.ability = Snippets.Action.use
234 |
235 | local function fillNext(list, column)
236 | tinsert(list, empty)
237 | tinsert(list, {
238 | text = 'next',
239 | value = '(next)',
240 | })
241 | tfillrow(list, column)
242 | return column
243 | end
244 |
245 | Snippets.Action.change = function(list)
246 | return fillNext(list, fillPet(list, Enum.BattlePetOwner.Ally))
247 | end
248 |
249 | Snippets.Condition.enemy = function(list)
250 | return fillPet(list, Enum.BattlePetOwner.Enemy)
251 | end
252 |
253 | Snippets.Condition.ally = function(list)
254 | return fillPet(list, Enum.BattlePetOwner.Ally)
255 | end
256 |
257 | Snippets.Condition.self = Snippets.Condition.ally
258 |
259 | Snippets.Condition.weather = function(list)
260 | local weathers = {
261 | 171, -- Weather_BurntEarth
262 | 590, -- Weather_ArcaneStorm
263 | 596, -- Weather_Moonlight
264 | 257, -- Weather_Darkness
265 | 454, -- Weather_Sandstorm
266 | 205, -- Weather_Blizzard
267 | 718, -- Weather_Mud
268 | 229, -- Weather_Rain
269 | 403, -- Weather_Sunlight
270 | 203, -- Weather_LightningStorm
271 | 2320, -- Weather_LightningStorm
272 | ---, -- Weather_Windy
273 | 2350, -- Weather_Toxic_Gas
274 | }
275 |
276 | for i, id in ipairs(weathers) do
277 | local id, name, icon = C_PetBattles.GetAbilityInfoByID(id)
278 |
279 | tinsert(list, makeIconSnippet(icon))
280 | tinsert(list, makeNameSnippet(name, id))
281 | end
282 | return 2
283 | end
284 |
285 | Snippets.Condition.aura = function(list, word, owner, pet)
286 | if not owner or not pet then
287 | return
288 | end
289 |
290 | for _, pet in ipairs({pet, PET_BATTLE_PAD_INDEX}) do
291 | for i = 1, C_PetBattles.GetNumAuras(owner, pet) do
292 | local id, name, icon = C_PetBattles.GetAbilityInfoByID(C_PetBattles.GetAuraInfo(owner, pet, i))
293 |
294 | tinsert(list, makeIconSnippet(icon))
295 | tinsert(list, makeNameSnippet(name, id))
296 | end
297 | end
298 | return 2
299 | end
300 |
301 | Snippets.Condition.ability = function(list, word, owner, pet)
302 | return fillAbility(list, owner, pet)
303 | end
304 |
305 | Snippets.Condition.is = function(list, word, owner, pet)
306 | return fillPet(list, owner)
307 | end
308 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Dengzhun Lu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Libs/AceAddon-3.0/AceAddon-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceConfig-3.0/AceConfig-3.0.lua:
--------------------------------------------------------------------------------
1 | --- AceConfig-3.0 wrapper library.
2 | -- Provides an API to register an options table with the config registry,
3 | -- as well as associate it with a slash command.
4 | -- @class file
5 | -- @name AceConfig-3.0
6 | -- @release $Id: AceConfig-3.0.lua 1202 2019-05-15 23:11:22Z nevcairiel $
7 |
8 | --[[
9 | AceConfig-3.0
10 |
11 | Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
12 |
13 | ]]
14 |
15 | local cfgreg = LibStub("AceConfigRegistry-3.0")
16 | local cfgcmd = LibStub("AceConfigCmd-3.0")
17 |
18 | local MAJOR, MINOR = "AceConfig-3.0", 3
19 | local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
20 |
21 | if not AceConfig then return end
22 |
23 | --TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true)
24 | --TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true)
25 |
26 | -- Lua APIs
27 | local pcall, error, type, pairs = pcall, error, type, pairs
28 |
29 | -- -------------------------------------------------------------------
30 | -- :RegisterOptionsTable(appName, options, slashcmd, persist)
31 | --
32 | -- - appName - (string) application name
33 | -- - options - table or function ref, see AceConfigRegistry
34 | -- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
35 |
36 | --- Register a option table with the AceConfig registry.
37 | -- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
38 | -- @paramsig appName, options [, slashcmd]
39 | -- @param appName The application name for the config table.
40 | -- @param options The option table (or a function to generate one on demand). http://www.wowace.com/addons/ace3/pages/ace-config-3-0-options-tables/
41 | -- @param slashcmd A slash command to register for the option table, or a table of slash commands.
42 | -- @usage
43 | -- local AceConfig = LibStub("AceConfig-3.0")
44 | -- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
45 | function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
46 | local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
47 | if not ok then error(msg, 2) end
48 |
49 | if slashcmd then
50 | if type(slashcmd) == "table" then
51 | for _,cmd in pairs(slashcmd) do
52 | cfgcmd:CreateChatCommand(cmd, appName)
53 | end
54 | else
55 | cfgcmd:CreateChatCommand(slashcmd, appName)
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/Libs/AceConfig-3.0/AceConfig-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceDB-3.0/AceDB-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceEvent-3.0/AceEvent-3.0.lua:
--------------------------------------------------------------------------------
1 | --- AceEvent-3.0 provides event registration and secure dispatching.
2 | -- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
3 | -- CallbackHandler, and dispatches all game events or addon message to the registrees.
4 | --
5 | -- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
6 | -- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
7 | -- and can be accessed directly, without having to explicitly call AceEvent itself.\\
8 | -- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
9 | -- make into AceEvent.
10 | -- @class file
11 | -- @name AceEvent-3.0
12 | -- @release $Id: AceEvent-3.0.lua 1202 2019-05-15 23:11:22Z nevcairiel $
13 | local CallbackHandler = LibStub("CallbackHandler-1.0")
14 |
15 | local MAJOR, MINOR = "AceEvent-3.0", 4
16 | local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
17 |
18 | if not AceEvent then return end
19 |
20 | -- Lua APIs
21 | local pairs = pairs
22 |
23 | AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
24 | AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
25 |
26 | -- APIs and registry for blizzard events, using CallbackHandler lib
27 | if not AceEvent.events then
28 | AceEvent.events = CallbackHandler:New(AceEvent,
29 | "RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
30 | end
31 |
32 | function AceEvent.events:OnUsed(target, eventname)
33 | AceEvent.frame:RegisterEvent(eventname)
34 | end
35 |
36 | function AceEvent.events:OnUnused(target, eventname)
37 | AceEvent.frame:UnregisterEvent(eventname)
38 | end
39 |
40 |
41 | -- APIs and registry for IPC messages, using CallbackHandler lib
42 | if not AceEvent.messages then
43 | AceEvent.messages = CallbackHandler:New(AceEvent,
44 | "RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
45 | )
46 | AceEvent.SendMessage = AceEvent.messages.Fire
47 | end
48 |
49 | --- embedding and embed handling
50 | local mixins = {
51 | "RegisterEvent", "UnregisterEvent",
52 | "RegisterMessage", "UnregisterMessage",
53 | "SendMessage",
54 | "UnregisterAllEvents", "UnregisterAllMessages",
55 | }
56 |
57 | --- Register for a Blizzard Event.
58 | -- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
59 | -- Any arguments to the event will be passed on after that.
60 | -- @name AceEvent:RegisterEvent
61 | -- @class function
62 | -- @paramsig event[, callback [, arg]]
63 | -- @param event The event to register for
64 | -- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
65 | -- @param arg An optional argument to pass to the callback function
66 |
67 | --- Unregister an event.
68 | -- @name AceEvent:UnregisterEvent
69 | -- @class function
70 | -- @paramsig event
71 | -- @param event The event to unregister
72 |
73 | --- Register for a custom AceEvent-internal message.
74 | -- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
75 | -- Any arguments to the event will be passed on after that.
76 | -- @name AceEvent:RegisterMessage
77 | -- @class function
78 | -- @paramsig message[, callback [, arg]]
79 | -- @param message The message to register for
80 | -- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
81 | -- @param arg An optional argument to pass to the callback function
82 |
83 | --- Unregister a message
84 | -- @name AceEvent:UnregisterMessage
85 | -- @class function
86 | -- @paramsig message
87 | -- @param message The message to unregister
88 |
89 | --- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
90 | -- @name AceEvent:SendMessage
91 | -- @class function
92 | -- @paramsig message, ...
93 | -- @param message The message to send
94 | -- @param ... Any arguments to the message
95 |
96 |
97 | -- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
98 | -- @param target target object to embed AceEvent in
99 | function AceEvent:Embed(target)
100 | for k, v in pairs(mixins) do
101 | target[v] = self[v]
102 | end
103 | self.embeds[target] = true
104 | return target
105 | end
106 |
107 | -- AceEvent:OnEmbedDisable( target )
108 | -- target (object) - target object that is being disabled
109 | --
110 | -- Unregister all events messages etc when the target disables.
111 | -- this method should be called by the target manually or by an addon framework
112 | function AceEvent:OnEmbedDisable(target)
113 | target:UnregisterAllEvents()
114 | target:UnregisterAllMessages()
115 | end
116 |
117 | -- Script to fire blizzard events into the event listeners
118 | local events = AceEvent.events
119 | AceEvent.frame:SetScript("OnEvent", function(this, event, ...)
120 | events:Fire(event, ...)
121 | end)
122 |
123 | --- Finally: upgrade our old embeds
124 | for target, v in pairs(AceEvent.embeds) do
125 | AceEvent:Embed(target)
126 | end
127 |
--------------------------------------------------------------------------------
/Libs/AceEvent-3.0/AceEvent-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/AceGUI-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | BlizOptionsGroup Container
3 | Simple container widget for the integration of AceGUI into the Blizzard Interface Options
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "BlizOptionsGroup", 26
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame = CreateFrame
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Scripts
17 | -------------------------------------------------------------------------------]]
18 |
19 | local function OnShow(frame)
20 | frame.obj:Fire("OnShow")
21 | end
22 |
23 | local function OnHide(frame)
24 | frame.obj:Fire("OnHide")
25 | end
26 |
27 | --[[-----------------------------------------------------------------------------
28 | Support functions
29 | -------------------------------------------------------------------------------]]
30 |
31 | local function okay(frame)
32 | frame.obj:Fire("okay")
33 | end
34 |
35 | local function cancel(frame)
36 | frame.obj:Fire("cancel")
37 | end
38 |
39 | local function default(frame)
40 | frame.obj:Fire("default")
41 | end
42 |
43 | local function refresh(frame)
44 | frame.obj:Fire("refresh")
45 | end
46 |
47 | --[[-----------------------------------------------------------------------------
48 | Methods
49 | -------------------------------------------------------------------------------]]
50 |
51 | local methods = {
52 | ["OnAcquire"] = function(self)
53 | self:SetName()
54 | self:SetTitle()
55 | end,
56 |
57 | -- ["OnRelease"] = nil,
58 |
59 | ["OnWidthSet"] = function(self, width)
60 | local content = self.content
61 | local contentwidth = width - 63
62 | if contentwidth < 0 then
63 | contentwidth = 0
64 | end
65 | content:SetWidth(contentwidth)
66 | content.width = contentwidth
67 | end,
68 |
69 | ["OnHeightSet"] = function(self, height)
70 | local content = self.content
71 | local contentheight = height - 26
72 | if contentheight < 0 then
73 | contentheight = 0
74 | end
75 | content:SetHeight(contentheight)
76 | content.height = contentheight
77 | end,
78 |
79 | ["SetName"] = function(self, name, parent)
80 | self.frame.name = name
81 | self.frame.parent = parent
82 | end,
83 |
84 | ["SetTitle"] = function(self, title)
85 | local content = self.content
86 | content:ClearAllPoints()
87 | if not title or title == "" then
88 | content:SetPoint("TOPLEFT", 10, -10)
89 | self.label:SetText("")
90 | else
91 | content:SetPoint("TOPLEFT", 10, -40)
92 | self.label:SetText(title)
93 | end
94 | content:SetPoint("BOTTOMRIGHT", -10, 10)
95 | end
96 | }
97 |
98 | --[[-----------------------------------------------------------------------------
99 | Constructor
100 | -------------------------------------------------------------------------------]]
101 | local function Constructor()
102 | local frame = CreateFrame("Frame", nil, InterfaceOptionsFramePanelContainer)
103 | frame:Hide()
104 |
105 | -- support functions for the Blizzard Interface Options
106 | frame.okay = okay
107 | frame.cancel = cancel
108 | frame.default = default
109 | frame.refresh = refresh
110 |
111 | -- 10.0 support function aliases (cancel has been removed)
112 | frame.OnCommit = okay
113 | frame.OnDefault = default
114 | frame.OnRefresh = refresh
115 |
116 | frame:SetScript("OnHide", OnHide)
117 | frame:SetScript("OnShow", OnShow)
118 |
119 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
120 | label:SetPoint("TOPLEFT", 10, -15)
121 | label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
122 | label:SetJustifyH("LEFT")
123 | label:SetJustifyV("TOP")
124 |
125 | --Container Support
126 | local content = CreateFrame("Frame", nil, frame)
127 | content:SetPoint("TOPLEFT", 10, -10)
128 | content:SetPoint("BOTTOMRIGHT", -10, 10)
129 |
130 | local widget = {
131 | label = label,
132 | frame = frame,
133 | content = content,
134 | type = Type
135 | }
136 | for method, func in pairs(methods) do
137 | widget[method] = func
138 | end
139 |
140 | return AceGUI:RegisterAsContainer(widget)
141 | end
142 |
143 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
144 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | DropdownGroup Container
3 | Container controlled by a dropdown on the top.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "DropdownGroup", 22
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local assert, pairs, type = assert, pairs, type
11 |
12 | -- WoW APIs
13 | local CreateFrame = CreateFrame
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Scripts
17 | -------------------------------------------------------------------------------]]
18 | local function SelectedGroup(self, event, value)
19 | local group = self.parentgroup
20 | local status = group.status or group.localstatus
21 | status.selected = value
22 | self.parentgroup:Fire("OnGroupSelected", value)
23 | end
24 |
25 | --[[-----------------------------------------------------------------------------
26 | Methods
27 | -------------------------------------------------------------------------------]]
28 | local methods = {
29 | ["OnAcquire"] = function(self)
30 | self.dropdown:SetText("")
31 | self:SetDropdownWidth(200)
32 | self:SetTitle("")
33 | end,
34 |
35 | ["OnRelease"] = function(self)
36 | self.dropdown.list = nil
37 | self.status = nil
38 | for k in pairs(self.localstatus) do
39 | self.localstatus[k] = nil
40 | end
41 | end,
42 |
43 | ["SetTitle"] = function(self, title)
44 | self.titletext:SetText(title)
45 | self.dropdown.frame:ClearAllPoints()
46 | if title and title ~= "" then
47 | self.dropdown.frame:SetPoint("TOPRIGHT", -2, 0)
48 | else
49 | self.dropdown.frame:SetPoint("TOPLEFT", -1, 0)
50 | end
51 | end,
52 |
53 | ["SetGroupList"] = function(self,list,order)
54 | self.dropdown:SetList(list,order)
55 | end,
56 |
57 | ["SetStatusTable"] = function(self, status)
58 | assert(type(status) == "table")
59 | self.status = status
60 | end,
61 |
62 | ["SetGroup"] = function(self,group)
63 | self.dropdown:SetValue(group)
64 | local status = self.status or self.localstatus
65 | status.selected = group
66 | self:Fire("OnGroupSelected", group)
67 | end,
68 |
69 | ["OnWidthSet"] = function(self, width)
70 | local content = self.content
71 | local contentwidth = width - 26
72 | if contentwidth < 0 then
73 | contentwidth = 0
74 | end
75 | content:SetWidth(contentwidth)
76 | content.width = contentwidth
77 | end,
78 |
79 | ["OnHeightSet"] = function(self, height)
80 | local content = self.content
81 | local contentheight = height - 63
82 | if contentheight < 0 then
83 | contentheight = 0
84 | end
85 | content:SetHeight(contentheight)
86 | content.height = contentheight
87 | end,
88 |
89 | ["LayoutFinished"] = function(self, width, height)
90 | self:SetHeight((height or 0) + 63)
91 | end,
92 |
93 | ["SetDropdownWidth"] = function(self, width)
94 | self.dropdown:SetWidth(width)
95 | end
96 | }
97 |
98 | --[[-----------------------------------------------------------------------------
99 | Constructor
100 | -------------------------------------------------------------------------------]]
101 | local PaneBackdrop = {
102 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
103 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
104 | tile = true, tileSize = 16, edgeSize = 16,
105 | insets = { left = 3, right = 3, top = 5, bottom = 3 }
106 | }
107 |
108 | local function Constructor()
109 | local frame = CreateFrame("Frame")
110 | frame:SetHeight(100)
111 | frame:SetWidth(100)
112 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
113 |
114 | local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
115 | titletext:SetPoint("TOPLEFT", 4, -5)
116 | titletext:SetPoint("TOPRIGHT", -4, -5)
117 | titletext:SetJustifyH("LEFT")
118 | titletext:SetHeight(18)
119 |
120 | local dropdown = AceGUI:Create("Dropdown")
121 | dropdown.frame:SetParent(frame)
122 | dropdown.frame:SetFrameLevel(dropdown.frame:GetFrameLevel() + 2)
123 | dropdown:SetCallback("OnValueChanged", SelectedGroup)
124 | dropdown.frame:SetPoint("TOPLEFT", -1, 0)
125 | dropdown.frame:Show()
126 | dropdown:SetLabel("")
127 |
128 | local border = CreateFrame("Frame", nil, frame, "BackdropTemplate")
129 | border:SetPoint("TOPLEFT", 0, -26)
130 | border:SetPoint("BOTTOMRIGHT", 0, 3)
131 | border:SetBackdrop(PaneBackdrop)
132 | border:SetBackdropColor(0.1,0.1,0.1,0.5)
133 | border:SetBackdropBorderColor(0.4,0.4,0.4)
134 |
135 | --Container Support
136 | local content = CreateFrame("Frame", nil, border)
137 | content:SetPoint("TOPLEFT", 10, -10)
138 | content:SetPoint("BOTTOMRIGHT", -10, 10)
139 |
140 | local widget = {
141 | frame = frame,
142 | localstatus = {},
143 | titletext = titletext,
144 | dropdown = dropdown,
145 | border = border,
146 | content = content,
147 | type = Type
148 | }
149 | for method, func in pairs(methods) do
150 | widget[method] = func
151 | end
152 | dropdown.parentgroup = widget
153 |
154 | return AceGUI:RegisterAsContainer(widget)
155 | end
156 |
157 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
158 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | InlineGroup Container
3 | Simple container widget that creates a visible "box" with an optional title.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "InlineGroup", 22
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Methods
17 | -------------------------------------------------------------------------------]]
18 | local methods = {
19 | ["OnAcquire"] = function(self)
20 | self:SetWidth(300)
21 | self:SetHeight(100)
22 | self:SetTitle("")
23 | end,
24 |
25 | -- ["OnRelease"] = nil,
26 |
27 | ["SetTitle"] = function(self,title)
28 | self.titletext:SetText(title)
29 | end,
30 |
31 |
32 | ["LayoutFinished"] = function(self, width, height)
33 | if self.noAutoHeight then return end
34 | self:SetHeight((height or 0) + 40)
35 | end,
36 |
37 | ["OnWidthSet"] = function(self, width)
38 | local content = self.content
39 | local contentwidth = width - 20
40 | if contentwidth < 0 then
41 | contentwidth = 0
42 | end
43 | content:SetWidth(contentwidth)
44 | content.width = contentwidth
45 | end,
46 |
47 | ["OnHeightSet"] = function(self, height)
48 | local content = self.content
49 | local contentheight = height - 20
50 | if contentheight < 0 then
51 | contentheight = 0
52 | end
53 | content:SetHeight(contentheight)
54 | content.height = contentheight
55 | end
56 | }
57 |
58 | --[[-----------------------------------------------------------------------------
59 | Constructor
60 | -------------------------------------------------------------------------------]]
61 | local PaneBackdrop = {
62 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
63 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
64 | tile = true, tileSize = 16, edgeSize = 16,
65 | insets = { left = 3, right = 3, top = 5, bottom = 3 }
66 | }
67 |
68 | local function Constructor()
69 | local frame = CreateFrame("Frame", nil, UIParent)
70 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
71 |
72 | local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
73 | titletext:SetPoint("TOPLEFT", 14, 0)
74 | titletext:SetPoint("TOPRIGHT", -14, 0)
75 | titletext:SetJustifyH("LEFT")
76 | titletext:SetHeight(18)
77 |
78 | local border = CreateFrame("Frame", nil, frame, "BackdropTemplate")
79 | border:SetPoint("TOPLEFT", 0, -17)
80 | border:SetPoint("BOTTOMRIGHT", -1, 3)
81 | border:SetBackdrop(PaneBackdrop)
82 | border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
83 | border:SetBackdropBorderColor(0.4, 0.4, 0.4)
84 |
85 | --Container Support
86 | local content = CreateFrame("Frame", nil, border)
87 | content:SetPoint("TOPLEFT", 10, -10)
88 | content:SetPoint("BOTTOMRIGHT", -10, 10)
89 |
90 | local widget = {
91 | frame = frame,
92 | content = content,
93 | titletext = titletext,
94 | type = Type
95 | }
96 | for method, func in pairs(methods) do
97 | widget[method] = func
98 | end
99 |
100 | return AceGUI:RegisterAsContainer(widget)
101 | end
102 |
103 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
104 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | ScrollFrame Container
3 | Plain container that scrolls its content and doesn't grow in height.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "ScrollFrame", 26
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs, assert, type = pairs, assert, type
11 | local min, max, floor = math.min, math.max, math.floor
12 |
13 | -- WoW APIs
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Support functions
18 | -------------------------------------------------------------------------------]]
19 | local function FixScrollOnUpdate(frame)
20 | frame:SetScript("OnUpdate", nil)
21 | frame.obj:FixScroll()
22 | end
23 |
24 | --[[-----------------------------------------------------------------------------
25 | Scripts
26 | -------------------------------------------------------------------------------]]
27 | local function ScrollFrame_OnMouseWheel(frame, value)
28 | frame.obj:MoveScroll(value)
29 | end
30 |
31 | local function ScrollFrame_OnSizeChanged(frame)
32 | frame:SetScript("OnUpdate", FixScrollOnUpdate)
33 | end
34 |
35 | local function ScrollBar_OnScrollValueChanged(frame, value)
36 | frame.obj:SetScroll(value)
37 | end
38 |
39 | --[[-----------------------------------------------------------------------------
40 | Methods
41 | -------------------------------------------------------------------------------]]
42 | local methods = {
43 | ["OnAcquire"] = function(self)
44 | self:SetScroll(0)
45 | self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
46 | end,
47 |
48 | ["OnRelease"] = function(self)
49 | self.status = nil
50 | for k in pairs(self.localstatus) do
51 | self.localstatus[k] = nil
52 | end
53 | self.scrollframe:SetPoint("BOTTOMRIGHT")
54 | self.scrollbar:Hide()
55 | self.scrollBarShown = nil
56 | self.content.height, self.content.width, self.content.original_width = nil, nil, nil
57 | end,
58 |
59 | ["SetScroll"] = function(self, value)
60 | local status = self.status or self.localstatus
61 | local viewheight = self.scrollframe:GetHeight()
62 | local height = self.content:GetHeight()
63 | local offset
64 |
65 | if viewheight > height then
66 | offset = 0
67 | else
68 | offset = floor((height - viewheight) / 1000.0 * value)
69 | end
70 | self.content:ClearAllPoints()
71 | self.content:SetPoint("TOPLEFT", 0, offset)
72 | self.content:SetPoint("TOPRIGHT", 0, offset)
73 | status.offset = offset
74 | status.scrollvalue = value
75 | end,
76 |
77 | ["MoveScroll"] = function(self, value)
78 | local status = self.status or self.localstatus
79 | local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
80 |
81 | if self.scrollBarShown then
82 | local diff = height - viewheight
83 | local delta = 1
84 | if value < 0 then
85 | delta = -1
86 | end
87 | self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
88 | end
89 | end,
90 |
91 | ["FixScroll"] = function(self)
92 | if self.updateLock then return end
93 | self.updateLock = true
94 | local status = self.status or self.localstatus
95 | local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
96 | local offset = status.offset or 0
97 | -- Give us a margin of error of 2 pixels to stop some conditions that i would blame on floating point inaccuracys
98 | -- No-one is going to miss 2 pixels at the bottom of the frame, anyhow!
99 | if viewheight < height + 2 then
100 | if self.scrollBarShown then
101 | self.scrollBarShown = nil
102 | self.scrollbar:Hide()
103 | self.scrollbar:SetValue(0)
104 | self.scrollframe:SetPoint("BOTTOMRIGHT")
105 | if self.content.original_width then
106 | self.content.width = self.content.original_width
107 | end
108 | self:DoLayout()
109 | end
110 | else
111 | if not self.scrollBarShown then
112 | self.scrollBarShown = true
113 | self.scrollbar:Show()
114 | self.scrollframe:SetPoint("BOTTOMRIGHT", -20, 0)
115 | if self.content.original_width then
116 | self.content.width = self.content.original_width - 20
117 | end
118 | self:DoLayout()
119 | end
120 | local value = (offset / (viewheight - height) * 1000)
121 | if value > 1000 then value = 1000 end
122 | self.scrollbar:SetValue(value)
123 | self:SetScroll(value)
124 | if value < 1000 then
125 | self.content:ClearAllPoints()
126 | self.content:SetPoint("TOPLEFT", 0, offset)
127 | self.content:SetPoint("TOPRIGHT", 0, offset)
128 | status.offset = offset
129 | end
130 | end
131 | self.updateLock = nil
132 | end,
133 |
134 | ["LayoutFinished"] = function(self, width, height)
135 | self.content:SetHeight(height or 0 + 20)
136 |
137 | -- update the scrollframe
138 | self:FixScroll()
139 |
140 | -- schedule another update when everything has "settled"
141 | self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
142 | end,
143 |
144 | ["SetStatusTable"] = function(self, status)
145 | assert(type(status) == "table")
146 | self.status = status
147 | if not status.scrollvalue then
148 | status.scrollvalue = 0
149 | end
150 | end,
151 |
152 | ["OnWidthSet"] = function(self, width)
153 | local content = self.content
154 | content.width = width - (self.scrollBarShown and 20 or 0)
155 | content.original_width = width
156 | end,
157 |
158 | ["OnHeightSet"] = function(self, height)
159 | local content = self.content
160 | content.height = height
161 | end
162 | }
163 | --[[-----------------------------------------------------------------------------
164 | Constructor
165 | -------------------------------------------------------------------------------]]
166 | local function Constructor()
167 | local frame = CreateFrame("Frame", nil, UIParent)
168 | local num = AceGUI:GetNextWidgetNum(Type)
169 |
170 | local scrollframe = CreateFrame("ScrollFrame", nil, frame)
171 | scrollframe:SetPoint("TOPLEFT")
172 | scrollframe:SetPoint("BOTTOMRIGHT")
173 | scrollframe:EnableMouseWheel(true)
174 | scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel)
175 | scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged)
176 |
177 | local scrollbar = CreateFrame("Slider", ("AceConfigDialogScrollFrame%dScrollBar"):format(num), scrollframe, "UIPanelScrollBarTemplate")
178 | scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
179 | scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16)
180 | scrollbar:SetMinMaxValues(0, 1000)
181 | scrollbar:SetValueStep(1)
182 | scrollbar:SetValue(0)
183 | scrollbar:SetWidth(16)
184 | scrollbar:Hide()
185 | -- set the script as the last step, so it doesn't fire yet
186 | scrollbar:SetScript("OnValueChanged", ScrollBar_OnScrollValueChanged)
187 |
188 | local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
189 | scrollbg:SetAllPoints(scrollbar)
190 | scrollbg:SetColorTexture(0, 0, 0, 0.4)
191 |
192 | --Container Support
193 | local content = CreateFrame("Frame", nil, scrollframe)
194 | content:SetPoint("TOPLEFT")
195 | content:SetPoint("TOPRIGHT")
196 | content:SetHeight(400)
197 | scrollframe:SetScrollChild(content)
198 |
199 | local widget = {
200 | localstatus = { scrollvalue = 0 },
201 | scrollframe = scrollframe,
202 | scrollbar = scrollbar,
203 | content = content,
204 | frame = frame,
205 | type = Type
206 | }
207 | for method, func in pairs(methods) do
208 | widget[method] = func
209 | end
210 | scrollframe.obj, scrollbar.obj = widget, widget
211 |
212 | return AceGUI:RegisterAsContainer(widget)
213 | end
214 |
215 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
216 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | SimpleGroup Container
3 | Simple container widget that just groups widgets.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "SimpleGroup", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Methods
18 | -------------------------------------------------------------------------------]]
19 | local methods = {
20 | ["OnAcquire"] = function(self)
21 | self:SetWidth(300)
22 | self:SetHeight(100)
23 | end,
24 |
25 | -- ["OnRelease"] = nil,
26 |
27 | ["LayoutFinished"] = function(self, width, height)
28 | if self.noAutoHeight then return end
29 | self:SetHeight(height or 0)
30 | end,
31 |
32 | ["OnWidthSet"] = function(self, width)
33 | local content = self.content
34 | content:SetWidth(width)
35 | content.width = width
36 | end,
37 |
38 | ["OnHeightSet"] = function(self, height)
39 | local content = self.content
40 | content:SetHeight(height)
41 | content.height = height
42 | end
43 | }
44 |
45 | --[[-----------------------------------------------------------------------------
46 | Constructor
47 | -------------------------------------------------------------------------------]]
48 | local function Constructor()
49 | local frame = CreateFrame("Frame", nil, UIParent)
50 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
51 |
52 | --Container Support
53 | local content = CreateFrame("Frame", nil, frame)
54 | content:SetPoint("TOPLEFT")
55 | content:SetPoint("BOTTOMRIGHT")
56 |
57 | local widget = {
58 | frame = frame,
59 | content = content,
60 | type = Type
61 | }
62 | for method, func in pairs(methods) do
63 | widget[method] = func
64 | end
65 |
66 | return AceGUI:RegisterAsContainer(widget)
67 | end
68 |
69 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
70 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Button Widget
3 | Graphical Button.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Button", 24
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local _G = _G
14 | local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Scripts
18 | -------------------------------------------------------------------------------]]
19 | local function Button_OnClick(frame, ...)
20 | AceGUI:ClearFocus()
21 | PlaySound(852) -- SOUNDKIT.IG_MAINMENU_OPTION
22 | frame.obj:Fire("OnClick", ...)
23 | end
24 |
25 | local function Control_OnEnter(frame)
26 | frame.obj:Fire("OnEnter")
27 | end
28 |
29 | local function Control_OnLeave(frame)
30 | frame.obj:Fire("OnLeave")
31 | end
32 |
33 | --[[-----------------------------------------------------------------------------
34 | Methods
35 | -------------------------------------------------------------------------------]]
36 | local methods = {
37 | ["OnAcquire"] = function(self)
38 | -- restore default values
39 | self:SetHeight(24)
40 | self:SetWidth(200)
41 | self:SetDisabled(false)
42 | self:SetAutoWidth(false)
43 | self:SetText()
44 | end,
45 |
46 | -- ["OnRelease"] = nil,
47 |
48 | ["SetText"] = function(self, text)
49 | self.text:SetText(text)
50 | if self.autoWidth then
51 | self:SetWidth(self.text:GetStringWidth() + 30)
52 | end
53 | end,
54 |
55 | ["SetAutoWidth"] = function(self, autoWidth)
56 | self.autoWidth = autoWidth
57 | if self.autoWidth then
58 | self:SetWidth(self.text:GetStringWidth() + 30)
59 | end
60 | end,
61 |
62 | ["SetDisabled"] = function(self, disabled)
63 | self.disabled = disabled
64 | if disabled then
65 | self.frame:Disable()
66 | else
67 | self.frame:Enable()
68 | end
69 | end
70 | }
71 |
72 | --[[-----------------------------------------------------------------------------
73 | Constructor
74 | -------------------------------------------------------------------------------]]
75 | local function Constructor()
76 | local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
77 | local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate")
78 | frame:Hide()
79 |
80 | frame:EnableMouse(true)
81 | frame:SetScript("OnClick", Button_OnClick)
82 | frame:SetScript("OnEnter", Control_OnEnter)
83 | frame:SetScript("OnLeave", Control_OnLeave)
84 |
85 | local text = frame:GetFontString()
86 | text:ClearAllPoints()
87 | text:SetPoint("TOPLEFT", 15, -1)
88 | text:SetPoint("BOTTOMRIGHT", -15, 1)
89 | text:SetJustifyV("MIDDLE")
90 |
91 | local widget = {
92 | text = text,
93 | frame = frame,
94 | type = Type
95 | }
96 | for method, func in pairs(methods) do
97 | widget[method] = func
98 | end
99 |
100 | return AceGUI:RegisterAsWidget(widget)
101 | end
102 |
103 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
104 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | ColorPicker Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "ColorPicker", 25
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local pairs = pairs
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent = CreateFrame, UIParent
13 |
14 | --[[-----------------------------------------------------------------------------
15 | Support functions
16 | -------------------------------------------------------------------------------]]
17 | local function ColorCallback(self, r, g, b, a, isAlpha)
18 | if not self.HasAlpha then
19 | a = 1
20 | end
21 | self:SetColor(r, g, b, a)
22 | if ColorPickerFrame:IsVisible() then
23 | --colorpicker is still open
24 | self:Fire("OnValueChanged", r, g, b, a)
25 | else
26 | --colorpicker is closed, color callback is first, ignore it,
27 | --alpha callback is the final call after it closes so confirm now
28 | if isAlpha then
29 | self:Fire("OnValueConfirmed", r, g, b, a)
30 | end
31 | end
32 | end
33 |
34 | --[[-----------------------------------------------------------------------------
35 | Scripts
36 | -------------------------------------------------------------------------------]]
37 | local function Control_OnEnter(frame)
38 | frame.obj:Fire("OnEnter")
39 | end
40 |
41 | local function Control_OnLeave(frame)
42 | frame.obj:Fire("OnLeave")
43 | end
44 |
45 | local function ColorSwatch_OnClick(frame)
46 | ColorPickerFrame:Hide()
47 | local self = frame.obj
48 | if not self.disabled then
49 | ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
50 | ColorPickerFrame:SetFrameLevel(frame:GetFrameLevel() + 10)
51 | ColorPickerFrame:SetClampedToScreen(true)
52 |
53 | ColorPickerFrame.func = function()
54 | local r, g, b = ColorPickerFrame:GetColorRGB()
55 | local a = 1 - OpacitySliderFrame:GetValue()
56 | ColorCallback(self, r, g, b, a)
57 | end
58 |
59 | ColorPickerFrame.hasOpacity = self.HasAlpha
60 | ColorPickerFrame.opacityFunc = function()
61 | local r, g, b = ColorPickerFrame:GetColorRGB()
62 | local a = 1 - OpacitySliderFrame:GetValue()
63 | ColorCallback(self, r, g, b, a, true)
64 | end
65 |
66 | local r, g, b, a = self.r, self.g, self.b, self.a
67 | if self.HasAlpha then
68 | ColorPickerFrame.opacity = 1 - (a or 0)
69 | end
70 | ColorPickerFrame:SetColorRGB(r, g, b)
71 |
72 | ColorPickerFrame.cancelFunc = function()
73 | ColorCallback(self, r, g, b, a, true)
74 | end
75 |
76 | ColorPickerFrame:Show()
77 | end
78 | AceGUI:ClearFocus()
79 | end
80 |
81 | --[[-----------------------------------------------------------------------------
82 | Methods
83 | -------------------------------------------------------------------------------]]
84 | local methods = {
85 | ["OnAcquire"] = function(self)
86 | self:SetHeight(24)
87 | self:SetWidth(200)
88 | self:SetHasAlpha(false)
89 | self:SetColor(0, 0, 0, 1)
90 | self:SetDisabled(nil)
91 | self:SetLabel(nil)
92 | end,
93 |
94 | -- ["OnRelease"] = nil,
95 |
96 | ["SetLabel"] = function(self, text)
97 | self.text:SetText(text)
98 | end,
99 |
100 | ["SetColor"] = function(self, r, g, b, a)
101 | self.r = r
102 | self.g = g
103 | self.b = b
104 | self.a = a or 1
105 | self.colorSwatch:SetVertexColor(r, g, b, a)
106 | end,
107 |
108 | ["SetHasAlpha"] = function(self, HasAlpha)
109 | self.HasAlpha = HasAlpha
110 | end,
111 |
112 | ["SetDisabled"] = function(self, disabled)
113 | self.disabled = disabled
114 | if self.disabled then
115 | self.frame:Disable()
116 | self.text:SetTextColor(0.5, 0.5, 0.5)
117 | else
118 | self.frame:Enable()
119 | self.text:SetTextColor(1, 1, 1)
120 | end
121 | end
122 | }
123 |
124 | --[[-----------------------------------------------------------------------------
125 | Constructor
126 | -------------------------------------------------------------------------------]]
127 | local function Constructor()
128 | local frame = CreateFrame("Button", nil, UIParent)
129 | frame:Hide()
130 |
131 | frame:EnableMouse(true)
132 | frame:SetScript("OnEnter", Control_OnEnter)
133 | frame:SetScript("OnLeave", Control_OnLeave)
134 | frame:SetScript("OnClick", ColorSwatch_OnClick)
135 |
136 | local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
137 | colorSwatch:SetWidth(19)
138 | colorSwatch:SetHeight(19)
139 | colorSwatch:SetTexture(130939) -- Interface\\ChatFrame\\ChatFrameColorSwatch
140 | colorSwatch:SetPoint("LEFT")
141 |
142 | local texture = frame:CreateTexture(nil, "BACKGROUND")
143 | colorSwatch.background = texture
144 | texture:SetWidth(16)
145 | texture:SetHeight(16)
146 | texture:SetColorTexture(1, 1, 1)
147 | texture:SetPoint("CENTER", colorSwatch)
148 | texture:Show()
149 |
150 | local checkers = frame:CreateTexture(nil, "BACKGROUND")
151 | colorSwatch.checkers = checkers
152 | checkers:SetWidth(14)
153 | checkers:SetHeight(14)
154 | checkers:SetTexture(188523) -- Tileset\\Generic\\Checkers
155 | checkers:SetTexCoord(.25, 0, 0.5, .25)
156 | checkers:SetDesaturated(true)
157 | checkers:SetVertexColor(1, 1, 1, 0.75)
158 | checkers:SetPoint("CENTER", colorSwatch)
159 | checkers:Show()
160 |
161 | local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
162 | text:SetHeight(24)
163 | text:SetJustifyH("LEFT")
164 | text:SetTextColor(1, 1, 1)
165 | text:SetPoint("LEFT", colorSwatch, "RIGHT", 2, 0)
166 | text:SetPoint("RIGHT")
167 |
168 | --local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
169 | --highlight:SetTexture(136810) -- Interface\\QuestFrame\\UI-QuestTitleHighlight
170 | --highlight:SetBlendMode("ADD")
171 | --highlight:SetAllPoints(frame)
172 |
173 | local widget = {
174 | colorSwatch = colorSwatch,
175 | text = text,
176 | frame = frame,
177 | type = Type
178 | }
179 | for method, func in pairs(methods) do
180 | widget[method] = func
181 | end
182 |
183 | return AceGUI:RegisterAsWidget(widget)
184 | end
185 |
186 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
187 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | EditBox Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "EditBox", 28
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local tostring, pairs = tostring, pairs
10 |
11 | -- WoW APIs
12 | local PlaySound = PlaySound
13 | local GetCursorInfo, ClearCursor, GetSpellInfo = GetCursorInfo, ClearCursor, GetSpellInfo
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 | local _G = _G
16 |
17 | --[[-----------------------------------------------------------------------------
18 | Support functions
19 | -------------------------------------------------------------------------------]]
20 | if not AceGUIEditBoxInsertLink then
21 | -- upgradeable hook
22 | hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end)
23 | end
24 |
25 | function _G.AceGUIEditBoxInsertLink(text)
26 | for i = 1, AceGUI:GetWidgetCount(Type) do
27 | local editbox = _G["AceGUI-3.0EditBox"..i]
28 | if editbox and editbox:IsVisible() and editbox:HasFocus() then
29 | editbox:Insert(text)
30 | return true
31 | end
32 | end
33 | end
34 |
35 | local function ShowButton(self)
36 | if not self.disablebutton then
37 | self.button:Show()
38 | self.editbox:SetTextInsets(0, 20, 3, 3)
39 | end
40 | end
41 |
42 | local function HideButton(self)
43 | self.button:Hide()
44 | self.editbox:SetTextInsets(0, 0, 3, 3)
45 | end
46 |
47 | --[[-----------------------------------------------------------------------------
48 | Scripts
49 | -------------------------------------------------------------------------------]]
50 | local function Control_OnEnter(frame)
51 | frame.obj:Fire("OnEnter")
52 | end
53 |
54 | local function Control_OnLeave(frame)
55 | frame.obj:Fire("OnLeave")
56 | end
57 |
58 | local function Frame_OnShowFocus(frame)
59 | frame.obj.editbox:SetFocus()
60 | frame:SetScript("OnShow", nil)
61 | end
62 |
63 | local function EditBox_OnEscapePressed(frame)
64 | AceGUI:ClearFocus()
65 | end
66 |
67 | local function EditBox_OnEnterPressed(frame)
68 | local self = frame.obj
69 | local value = frame:GetText()
70 | local cancel = self:Fire("OnEnterPressed", value)
71 | if not cancel then
72 | PlaySound(856) -- SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON
73 | HideButton(self)
74 | end
75 | end
76 |
77 | local function EditBox_OnReceiveDrag(frame)
78 | local self = frame.obj
79 | local type, id, info = GetCursorInfo()
80 | local name
81 | if type == "item" then
82 | name = info
83 | elseif type == "spell" then
84 | name = GetSpellInfo(id, info)
85 | elseif type == "macro" then
86 | name = GetMacroInfo(id)
87 | end
88 | if name then
89 | self:SetText(name)
90 | self:Fire("OnEnterPressed", name)
91 | ClearCursor()
92 | HideButton(self)
93 | AceGUI:ClearFocus()
94 | end
95 | end
96 |
97 | local function EditBox_OnTextChanged(frame)
98 | local self = frame.obj
99 | local value = frame:GetText()
100 | if tostring(value) ~= tostring(self.lasttext) then
101 | self:Fire("OnTextChanged", value)
102 | self.lasttext = value
103 | ShowButton(self)
104 | end
105 | end
106 |
107 | local function EditBox_OnFocusGained(frame)
108 | AceGUI:SetFocus(frame.obj)
109 | end
110 |
111 | local function Button_OnClick(frame)
112 | local editbox = frame.obj.editbox
113 | editbox:ClearFocus()
114 | EditBox_OnEnterPressed(editbox)
115 | end
116 |
117 | --[[-----------------------------------------------------------------------------
118 | Methods
119 | -------------------------------------------------------------------------------]]
120 | local methods = {
121 | ["OnAcquire"] = function(self)
122 | -- height is controlled by SetLabel
123 | self:SetWidth(200)
124 | self:SetDisabled(false)
125 | self:SetLabel()
126 | self:SetText()
127 | self:DisableButton(false)
128 | self:SetMaxLetters(0)
129 | end,
130 |
131 | ["OnRelease"] = function(self)
132 | self:ClearFocus()
133 | end,
134 |
135 | ["SetDisabled"] = function(self, disabled)
136 | self.disabled = disabled
137 | if disabled then
138 | self.editbox:EnableMouse(false)
139 | self.editbox:ClearFocus()
140 | self.editbox:SetTextColor(0.5,0.5,0.5)
141 | self.label:SetTextColor(0.5,0.5,0.5)
142 | else
143 | self.editbox:EnableMouse(true)
144 | self.editbox:SetTextColor(1,1,1)
145 | self.label:SetTextColor(1,.82,0)
146 | end
147 | end,
148 |
149 | ["SetText"] = function(self, text)
150 | self.lasttext = text or ""
151 | self.editbox:SetText(text or "")
152 | self.editbox:SetCursorPosition(0)
153 | HideButton(self)
154 | end,
155 |
156 | ["GetText"] = function(self, text)
157 | return self.editbox:GetText()
158 | end,
159 |
160 | ["SetLabel"] = function(self, text)
161 | if text and text ~= "" then
162 | self.label:SetText(text)
163 | self.label:Show()
164 | self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
165 | self:SetHeight(44)
166 | self.alignoffset = 30
167 | else
168 | self.label:SetText("")
169 | self.label:Hide()
170 | self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
171 | self:SetHeight(26)
172 | self.alignoffset = 12
173 | end
174 | end,
175 |
176 | ["DisableButton"] = function(self, disabled)
177 | self.disablebutton = disabled
178 | if disabled then
179 | HideButton(self)
180 | end
181 | end,
182 |
183 | ["SetMaxLetters"] = function (self, num)
184 | self.editbox:SetMaxLetters(num or 0)
185 | end,
186 |
187 | ["ClearFocus"] = function(self)
188 | self.editbox:ClearFocus()
189 | self.frame:SetScript("OnShow", nil)
190 | end,
191 |
192 | ["SetFocus"] = function(self)
193 | self.editbox:SetFocus()
194 | if not self.frame:IsShown() then
195 | self.frame:SetScript("OnShow", Frame_OnShowFocus)
196 | end
197 | end,
198 |
199 | ["HighlightText"] = function(self, from, to)
200 | self.editbox:HighlightText(from, to)
201 | end
202 | }
203 |
204 | --[[-----------------------------------------------------------------------------
205 | Constructor
206 | -------------------------------------------------------------------------------]]
207 | local function Constructor()
208 | local num = AceGUI:GetNextWidgetNum(Type)
209 | local frame = CreateFrame("Frame", nil, UIParent)
210 | frame:Hide()
211 |
212 | local editbox = CreateFrame("EditBox", "AceGUI-3.0EditBox"..num, frame, "InputBoxTemplate")
213 | editbox:SetAutoFocus(false)
214 | editbox:SetFontObject(ChatFontNormal)
215 | editbox:SetScript("OnEnter", Control_OnEnter)
216 | editbox:SetScript("OnLeave", Control_OnLeave)
217 | editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
218 | editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
219 | editbox:SetScript("OnTextChanged", EditBox_OnTextChanged)
220 | editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
221 | editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
222 | editbox:SetScript("OnEditFocusGained", EditBox_OnFocusGained)
223 | editbox:SetTextInsets(0, 0, 3, 3)
224 | editbox:SetMaxLetters(256)
225 | editbox:SetPoint("BOTTOMLEFT", 6, 0)
226 | editbox:SetPoint("BOTTOMRIGHT")
227 | editbox:SetHeight(19)
228 |
229 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
230 | label:SetPoint("TOPLEFT", 0, -2)
231 | label:SetPoint("TOPRIGHT", 0, -2)
232 | label:SetJustifyH("LEFT")
233 | label:SetHeight(18)
234 |
235 | local button = CreateFrame("Button", nil, editbox, "UIPanelButtonTemplate")
236 | button:SetWidth(40)
237 | button:SetHeight(20)
238 | button:SetPoint("RIGHT", -2, 0)
239 | button:SetText(OKAY)
240 | button:SetScript("OnClick", Button_OnClick)
241 | button:Hide()
242 |
243 | local widget = {
244 | alignoffset = 30,
245 | editbox = editbox,
246 | label = label,
247 | button = button,
248 | frame = frame,
249 | type = Type
250 | }
251 | for method, func in pairs(methods) do
252 | widget[method] = func
253 | end
254 | editbox.obj, button.obj = widget, widget
255 |
256 | return AceGUI:RegisterAsWidget(widget)
257 | end
258 |
259 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
260 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Heading Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "Heading", 20
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local pairs = pairs
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent = CreateFrame, UIParent
13 |
14 | --[[-----------------------------------------------------------------------------
15 | Methods
16 | -------------------------------------------------------------------------------]]
17 | local methods = {
18 | ["OnAcquire"] = function(self)
19 | self:SetText()
20 | self:SetFullWidth()
21 | self:SetHeight(18)
22 | end,
23 |
24 | -- ["OnRelease"] = nil,
25 |
26 | ["SetText"] = function(self, text)
27 | self.label:SetText(text or "")
28 | if text and text ~= "" then
29 | self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0)
30 | self.right:Show()
31 | else
32 | self.left:SetPoint("RIGHT", -3, 0)
33 | self.right:Hide()
34 | end
35 | end
36 | }
37 |
38 | --[[-----------------------------------------------------------------------------
39 | Constructor
40 | -------------------------------------------------------------------------------]]
41 | local function Constructor()
42 | local frame = CreateFrame("Frame", nil, UIParent)
43 | frame:Hide()
44 |
45 | local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
46 | label:SetPoint("TOP")
47 | label:SetPoint("BOTTOM")
48 | label:SetJustifyH("CENTER")
49 |
50 | local left = frame:CreateTexture(nil, "BACKGROUND")
51 | left:SetHeight(8)
52 | left:SetPoint("LEFT", 3, 0)
53 | left:SetPoint("RIGHT", label, "LEFT", -5, 0)
54 | left:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
55 | left:SetTexCoord(0.81, 0.94, 0.5, 1)
56 |
57 | local right = frame:CreateTexture(nil, "BACKGROUND")
58 | right:SetHeight(8)
59 | right:SetPoint("RIGHT", -3, 0)
60 | right:SetPoint("LEFT", label, "RIGHT", 5, 0)
61 | right:SetTexture(137057) -- Interface\\Tooltips\\UI-Tooltip-Border
62 | right:SetTexCoord(0.81, 0.94, 0.5, 1)
63 |
64 | local widget = {
65 | label = label,
66 | left = left,
67 | right = right,
68 | frame = frame,
69 | type = Type
70 | }
71 | for method, func in pairs(methods) do
72 | widget[method] = func
73 | end
74 |
75 | return AceGUI:RegisterAsWidget(widget)
76 | end
77 |
78 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
79 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Icon Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "Icon", 21
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local select, pairs, print = select, pairs, print
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent = CreateFrame, UIParent
13 |
14 | --[[-----------------------------------------------------------------------------
15 | Scripts
16 | -------------------------------------------------------------------------------]]
17 | local function Control_OnEnter(frame)
18 | frame.obj:Fire("OnEnter")
19 | end
20 |
21 | local function Control_OnLeave(frame)
22 | frame.obj:Fire("OnLeave")
23 | end
24 |
25 | local function Button_OnClick(frame, button)
26 | frame.obj:Fire("OnClick", button)
27 | AceGUI:ClearFocus()
28 | end
29 |
30 | --[[-----------------------------------------------------------------------------
31 | Methods
32 | -------------------------------------------------------------------------------]]
33 | local methods = {
34 | ["OnAcquire"] = function(self)
35 | self:SetHeight(110)
36 | self:SetWidth(110)
37 | self:SetLabel()
38 | self:SetImage(nil)
39 | self:SetImageSize(64, 64)
40 | self:SetDisabled(false)
41 | end,
42 |
43 | -- ["OnRelease"] = nil,
44 |
45 | ["SetLabel"] = function(self, text)
46 | if text and text ~= "" then
47 | self.label:Show()
48 | self.label:SetText(text)
49 | self:SetHeight(self.image:GetHeight() + 25)
50 | else
51 | self.label:Hide()
52 | self:SetHeight(self.image:GetHeight() + 10)
53 | end
54 | end,
55 |
56 | ["SetImage"] = function(self, path, ...)
57 | local image = self.image
58 | image:SetTexture(path)
59 |
60 | if image:GetTexture() then
61 | local n = select("#", ...)
62 | if n == 4 or n == 8 then
63 | image:SetTexCoord(...)
64 | else
65 | image:SetTexCoord(0, 1, 0, 1)
66 | end
67 | end
68 | end,
69 |
70 | ["SetImageSize"] = function(self, width, height)
71 | self.image:SetWidth(width)
72 | self.image:SetHeight(height)
73 | --self.frame:SetWidth(width + 30)
74 | if self.label:IsShown() then
75 | self:SetHeight(height + 25)
76 | else
77 | self:SetHeight(height + 10)
78 | end
79 | end,
80 |
81 | ["SetDisabled"] = function(self, disabled)
82 | self.disabled = disabled
83 | if disabled then
84 | self.frame:Disable()
85 | self.label:SetTextColor(0.5, 0.5, 0.5)
86 | self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5)
87 | else
88 | self.frame:Enable()
89 | self.label:SetTextColor(1, 1, 1)
90 | self.image:SetVertexColor(1, 1, 1, 1)
91 | end
92 | end
93 | }
94 |
95 | --[[-----------------------------------------------------------------------------
96 | Constructor
97 | -------------------------------------------------------------------------------]]
98 | local function Constructor()
99 | local frame = CreateFrame("Button", nil, UIParent)
100 | frame:Hide()
101 |
102 | frame:EnableMouse(true)
103 | frame:SetScript("OnEnter", Control_OnEnter)
104 | frame:SetScript("OnLeave", Control_OnLeave)
105 | frame:SetScript("OnClick", Button_OnClick)
106 |
107 | local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlight")
108 | label:SetPoint("BOTTOMLEFT")
109 | label:SetPoint("BOTTOMRIGHT")
110 | label:SetJustifyH("CENTER")
111 | label:SetJustifyV("TOP")
112 | label:SetHeight(18)
113 |
114 | local image = frame:CreateTexture(nil, "BACKGROUND")
115 | image:SetWidth(64)
116 | image:SetHeight(64)
117 | image:SetPoint("TOP", 0, -5)
118 |
119 | local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
120 | highlight:SetAllPoints(image)
121 | highlight:SetTexture(136580) -- Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight
122 | highlight:SetTexCoord(0, 1, 0.23, 0.77)
123 | highlight:SetBlendMode("ADD")
124 |
125 | local widget = {
126 | label = label,
127 | image = image,
128 | frame = frame,
129 | type = Type
130 | }
131 | for method, func in pairs(methods) do
132 | widget[method] = func
133 | end
134 |
135 | widget.SetText = function(self, ...) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(...) end
136 |
137 | return AceGUI:RegisterAsWidget(widget)
138 | end
139 |
140 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
141 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | InteractiveLabel Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "InteractiveLabel", 21
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local select, pairs = select, pairs
10 |
11 | --[[-----------------------------------------------------------------------------
12 | Scripts
13 | -------------------------------------------------------------------------------]]
14 | local function Control_OnEnter(frame)
15 | frame.obj:Fire("OnEnter")
16 | end
17 |
18 | local function Control_OnLeave(frame)
19 | frame.obj:Fire("OnLeave")
20 | end
21 |
22 | local function Label_OnClick(frame, button)
23 | frame.obj:Fire("OnClick", button)
24 | AceGUI:ClearFocus()
25 | end
26 |
27 | --[[-----------------------------------------------------------------------------
28 | Methods
29 | -------------------------------------------------------------------------------]]
30 | local methods = {
31 | ["OnAcquire"] = function(self)
32 | self:LabelOnAcquire()
33 | self:SetHighlight()
34 | self:SetHighlightTexCoord()
35 | self:SetDisabled(false)
36 | end,
37 |
38 | -- ["OnRelease"] = nil,
39 |
40 | ["SetHighlight"] = function(self, ...)
41 | self.highlight:SetTexture(...)
42 | end,
43 |
44 | ["SetHighlightTexCoord"] = function(self, ...)
45 | local c = select("#", ...)
46 | if c == 4 or c == 8 then
47 | self.highlight:SetTexCoord(...)
48 | else
49 | self.highlight:SetTexCoord(0, 1, 0, 1)
50 | end
51 | end,
52 |
53 | ["SetDisabled"] = function(self,disabled)
54 | self.disabled = disabled
55 | if disabled then
56 | self.frame:EnableMouse(false)
57 | self.label:SetTextColor(0.5, 0.5, 0.5)
58 | else
59 | self.frame:EnableMouse(true)
60 | self.label:SetTextColor(1, 1, 1)
61 | end
62 | end
63 | }
64 |
65 | --[[-----------------------------------------------------------------------------
66 | Constructor
67 | -------------------------------------------------------------------------------]]
68 | local function Constructor()
69 | -- create a Label type that we will hijack
70 | local label = AceGUI:Create("Label")
71 |
72 | local frame = label.frame
73 | frame:EnableMouse(true)
74 | frame:SetScript("OnEnter", Control_OnEnter)
75 | frame:SetScript("OnLeave", Control_OnLeave)
76 | frame:SetScript("OnMouseDown", Label_OnClick)
77 |
78 | local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
79 | highlight:SetTexture(nil)
80 | highlight:SetAllPoints()
81 | highlight:SetBlendMode("ADD")
82 |
83 | label.highlight = highlight
84 | label.type = Type
85 | label.LabelOnAcquire = label.OnAcquire
86 | for method, func in pairs(methods) do
87 | label[method] = func
88 | end
89 |
90 | return label
91 | end
92 |
93 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
94 |
95 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Keybinding Widget
3 | Set Keybindings in the Config UI.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Keybinding", 26
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Scripts
18 | -------------------------------------------------------------------------------]]
19 |
20 | local function Control_OnEnter(frame)
21 | frame.obj:Fire("OnEnter")
22 | end
23 |
24 | local function Control_OnLeave(frame)
25 | frame.obj:Fire("OnLeave")
26 | end
27 |
28 | local function Keybinding_OnClick(frame, button)
29 | if button == "LeftButton" or button == "RightButton" then
30 | local self = frame.obj
31 | if self.waitingForKey then
32 | frame:EnableKeyboard(false)
33 | frame:EnableMouseWheel(false)
34 | self.msgframe:Hide()
35 | frame:UnlockHighlight()
36 | self.waitingForKey = nil
37 | else
38 | frame:EnableKeyboard(true)
39 | frame:EnableMouseWheel(true)
40 | self.msgframe:Show()
41 | frame:LockHighlight()
42 | self.waitingForKey = true
43 | end
44 | end
45 | AceGUI:ClearFocus()
46 | end
47 |
48 | local ignoreKeys = {
49 | ["BUTTON1"] = true, ["BUTTON2"] = true,
50 | ["UNKNOWN"] = true,
51 | ["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
52 | ["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
53 | }
54 | local function Keybinding_OnKeyDown(frame, key)
55 | local self = frame.obj
56 | if self.waitingForKey then
57 | local keyPressed = key
58 | if keyPressed == "ESCAPE" then
59 | keyPressed = ""
60 | else
61 | if ignoreKeys[keyPressed] then return end
62 | if IsShiftKeyDown() then
63 | keyPressed = "SHIFT-"..keyPressed
64 | end
65 | if IsControlKeyDown() then
66 | keyPressed = "CTRL-"..keyPressed
67 | end
68 | if IsAltKeyDown() then
69 | keyPressed = "ALT-"..keyPressed
70 | end
71 | end
72 |
73 | frame:EnableKeyboard(false)
74 | frame:EnableMouseWheel(false)
75 | self.msgframe:Hide()
76 | frame:UnlockHighlight()
77 | self.waitingForKey = nil
78 |
79 | if not self.disabled then
80 | self:SetKey(keyPressed)
81 | self:Fire("OnKeyChanged", keyPressed)
82 | end
83 | end
84 | end
85 |
86 | local function Keybinding_OnMouseDown(frame, button)
87 | if button == "LeftButton" or button == "RightButton" then
88 | return
89 | elseif button == "MiddleButton" then
90 | button = "BUTTON3"
91 | elseif button == "Button4" then
92 | button = "BUTTON4"
93 | elseif button == "Button5" then
94 | button = "BUTTON5"
95 | end
96 | Keybinding_OnKeyDown(frame, button)
97 | end
98 |
99 | local function Keybinding_OnMouseWheel(frame, direction)
100 | local button
101 | if direction >= 0 then
102 | button = "MOUSEWHEELUP"
103 | else
104 | button = "MOUSEWHEELDOWN"
105 | end
106 | Keybinding_OnKeyDown(frame, button)
107 | end
108 |
109 | --[[-----------------------------------------------------------------------------
110 | Methods
111 | -------------------------------------------------------------------------------]]
112 | local methods = {
113 | ["OnAcquire"] = function(self)
114 | self:SetWidth(200)
115 | self:SetLabel("")
116 | self:SetKey("")
117 | self.waitingForKey = nil
118 | self.msgframe:Hide()
119 | self:SetDisabled(false)
120 | self.button:EnableKeyboard(false)
121 | self.button:EnableMouseWheel(false)
122 | end,
123 |
124 | -- ["OnRelease"] = nil,
125 |
126 | ["SetDisabled"] = function(self, disabled)
127 | self.disabled = disabled
128 | if disabled then
129 | self.button:Disable()
130 | self.label:SetTextColor(0.5,0.5,0.5)
131 | else
132 | self.button:Enable()
133 | self.label:SetTextColor(1,1,1)
134 | end
135 | end,
136 |
137 | ["SetKey"] = function(self, key)
138 | if (key or "") == "" then
139 | self.button:SetText(NOT_BOUND)
140 | self.button:SetNormalFontObject("GameFontNormal")
141 | else
142 | self.button:SetText(key)
143 | self.button:SetNormalFontObject("GameFontHighlight")
144 | end
145 | end,
146 |
147 | ["GetKey"] = function(self)
148 | local key = self.button:GetText()
149 | if key == NOT_BOUND then
150 | key = nil
151 | end
152 | return key
153 | end,
154 |
155 | ["SetLabel"] = function(self, label)
156 | self.label:SetText(label or "")
157 | if (label or "") == "" then
158 | self.alignoffset = nil
159 | self:SetHeight(24)
160 | else
161 | self.alignoffset = 30
162 | self:SetHeight(44)
163 | end
164 | end,
165 | }
166 |
167 | --[[-----------------------------------------------------------------------------
168 | Constructor
169 | -------------------------------------------------------------------------------]]
170 |
171 | local ControlBackdrop = {
172 | bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
173 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
174 | tile = true, tileSize = 16, edgeSize = 16,
175 | insets = { left = 3, right = 3, top = 3, bottom = 3 }
176 | }
177 |
178 | local function keybindingMsgFixWidth(frame)
179 | frame:SetWidth(frame.msg:GetWidth() + 10)
180 | frame:SetScript("OnUpdate", nil)
181 | end
182 |
183 | local function Constructor()
184 | local name = "AceGUI30KeybindingButton" .. AceGUI:GetNextWidgetNum(Type)
185 |
186 | local frame = CreateFrame("Frame", nil, UIParent)
187 | local button = CreateFrame("Button", name, frame, "UIPanelButtonTemplate")
188 |
189 | button:EnableMouse(true)
190 | button:EnableMouseWheel(false)
191 | button:RegisterForClicks("AnyDown")
192 | button:SetScript("OnEnter", Control_OnEnter)
193 | button:SetScript("OnLeave", Control_OnLeave)
194 | button:SetScript("OnClick", Keybinding_OnClick)
195 | button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
196 | button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
197 | button:SetScript("OnMouseWheel", Keybinding_OnMouseWheel)
198 | button:SetPoint("BOTTOMLEFT")
199 | button:SetPoint("BOTTOMRIGHT")
200 | button:SetHeight(24)
201 | button:EnableKeyboard(false)
202 |
203 | local text = button:GetFontString()
204 | text:SetPoint("LEFT", 7, 0)
205 | text:SetPoint("RIGHT", -7, 0)
206 |
207 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
208 | label:SetPoint("TOPLEFT")
209 | label:SetPoint("TOPRIGHT")
210 | label:SetJustifyH("CENTER")
211 | label:SetHeight(18)
212 |
213 | local msgframe = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
214 | msgframe:SetHeight(30)
215 | msgframe:SetBackdrop(ControlBackdrop)
216 | msgframe:SetBackdropColor(0,0,0)
217 | msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
218 | msgframe:SetFrameLevel(1000)
219 | msgframe:SetToplevel(true)
220 |
221 | local msg = msgframe:CreateFontString(nil, "OVERLAY", "GameFontNormal")
222 | msg:SetText("Press a key to bind, ESC to clear the binding or click the button again to cancel.")
223 | msgframe.msg = msg
224 | msg:SetPoint("TOPLEFT", 5, -5)
225 | msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
226 | msgframe:SetPoint("BOTTOM", button, "TOP")
227 | msgframe:Hide()
228 |
229 | local widget = {
230 | button = button,
231 | label = label,
232 | msgframe = msgframe,
233 | frame = frame,
234 | alignoffset = 30,
235 | type = Type
236 | }
237 | for method, func in pairs(methods) do
238 | widget[method] = func
239 | end
240 | button.obj = widget
241 |
242 | return AceGUI:RegisterAsWidget(widget)
243 | end
244 |
245 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
246 |
--------------------------------------------------------------------------------
/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Label Widget
3 | Displays text and optionally an icon.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Label", 28
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local max, select, pairs = math.max, select, pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Support functions
17 | -------------------------------------------------------------------------------]]
18 |
19 | local function UpdateImageAnchor(self)
20 | if self.resizing then return end
21 | local frame = self.frame
22 | local width = frame.width or frame:GetWidth() or 0
23 | local image = self.image
24 | local label = self.label
25 | local height
26 |
27 | label:ClearAllPoints()
28 | image:ClearAllPoints()
29 |
30 | if self.imageshown then
31 | local imagewidth = image:GetWidth()
32 | if (width - imagewidth) < 200 or (label:GetText() or "") == "" then
33 | -- image goes on top centered when less than 200 width for the text, or if there is no text
34 | image:SetPoint("TOP")
35 | label:SetPoint("TOP", image, "BOTTOM")
36 | label:SetPoint("LEFT")
37 | label:SetWidth(width)
38 | height = image:GetHeight() + label:GetStringHeight()
39 | else
40 | -- image on the left
41 | image:SetPoint("TOPLEFT")
42 | if image:GetHeight() > label:GetStringHeight() then
43 | label:SetPoint("LEFT", image, "RIGHT", 4, 0)
44 | else
45 | label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0)
46 | end
47 | label:SetWidth(width - imagewidth - 4)
48 | height = max(image:GetHeight(), label:GetStringHeight())
49 | end
50 | else
51 | -- no image shown
52 | label:SetPoint("TOPLEFT")
53 | label:SetWidth(width)
54 | height = label:GetStringHeight()
55 | end
56 |
57 | -- avoid zero-height labels, since they can used as spacers
58 | if not height or height == 0 then
59 | height = 1
60 | end
61 |
62 | self.resizing = true
63 | frame:SetHeight(height)
64 | frame.height = height
65 | self.resizing = nil
66 | end
67 |
68 | --[[-----------------------------------------------------------------------------
69 | Methods
70 | -------------------------------------------------------------------------------]]
71 | local methods = {
72 | ["OnAcquire"] = function(self)
73 | -- set the flag to stop constant size updates
74 | self.resizing = true
75 | -- height is set dynamically by the text and image size
76 | self:SetWidth(200)
77 | self:SetText()
78 | self:SetImage(nil)
79 | self:SetImageSize(16, 16)
80 | self:SetColor()
81 | self:SetFontObject()
82 | self:SetJustifyH("LEFT")
83 | self:SetJustifyV("TOP")
84 |
85 | -- reset the flag
86 | self.resizing = nil
87 | -- run the update explicitly
88 | UpdateImageAnchor(self)
89 | end,
90 |
91 | -- ["OnRelease"] = nil,
92 |
93 | ["OnWidthSet"] = function(self, width)
94 | UpdateImageAnchor(self)
95 | end,
96 |
97 | ["SetText"] = function(self, text)
98 | self.label:SetText(text)
99 | UpdateImageAnchor(self)
100 | end,
101 |
102 | ["SetColor"] = function(self, r, g, b)
103 | if not (r and g and b) then
104 | r, g, b = 1, 1, 1
105 | end
106 | self.label:SetVertexColor(r, g, b)
107 | end,
108 |
109 | ["SetImage"] = function(self, path, ...)
110 | local image = self.image
111 | image:SetTexture(path)
112 |
113 | if image:GetTexture() then
114 | self.imageshown = true
115 | local n = select("#", ...)
116 | if n == 4 or n == 8 then
117 | image:SetTexCoord(...)
118 | else
119 | image:SetTexCoord(0, 1, 0, 1)
120 | end
121 | else
122 | self.imageshown = nil
123 | end
124 | UpdateImageAnchor(self)
125 | end,
126 |
127 | ["SetFont"] = function(self, font, height, flags)
128 | if not self.fontObject then
129 | self.fontObject = CreateFont("AceGUI30LabelFont" .. AceGUI:GetNextWidgetNum(Type))
130 | end
131 | self.fontObject:SetFont(font, height, flags)
132 | self:SetFontObject(self.fontObject)
133 | end,
134 |
135 | ["SetFontObject"] = function(self, font)
136 | self.label:SetFontObject(font or GameFontHighlightSmall)
137 | UpdateImageAnchor(self)
138 | end,
139 |
140 | ["SetImageSize"] = function(self, width, height)
141 | self.image:SetWidth(width)
142 | self.image:SetHeight(height)
143 | UpdateImageAnchor(self)
144 | end,
145 |
146 | ["SetJustifyH"] = function(self, justifyH)
147 | self.label:SetJustifyH(justifyH)
148 | end,
149 |
150 | ["SetJustifyV"] = function(self, justifyV)
151 | self.label:SetJustifyV(justifyV)
152 | end,
153 | }
154 |
155 | --[[-----------------------------------------------------------------------------
156 | Constructor
157 | -------------------------------------------------------------------------------]]
158 | local function Constructor()
159 | local frame = CreateFrame("Frame", nil, UIParent)
160 | frame:Hide()
161 |
162 | local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
163 | local image = frame:CreateTexture(nil, "BACKGROUND")
164 |
165 | -- create widget
166 | local widget = {
167 | label = label,
168 | image = image,
169 | frame = frame,
170 | type = Type
171 | }
172 | for method, func in pairs(methods) do
173 | widget[method] = func
174 | end
175 |
176 | return AceGUI:RegisterAsWidget(widget)
177 | end
178 |
179 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
180 |
--------------------------------------------------------------------------------
/Libs/AceHook-3.0/AceHook-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceLocale-3.0/AceLocale-3.0.lua:
--------------------------------------------------------------------------------
1 | --- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
2 | -- @class file
3 | -- @name AceLocale-3.0
4 | -- @release $Id: AceLocale-3.0.lua 1284 2022-09-25 09:15:30Z nevcairiel $
5 | local MAJOR,MINOR = "AceLocale-3.0", 6
6 |
7 | local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
8 |
9 | if not AceLocale then return end -- no upgrade needed
10 |
11 | -- Lua APIs
12 | local assert, tostring, error = assert, tostring, error
13 | local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
14 |
15 | local gameLocale = GetLocale()
16 | if gameLocale == "enGB" then
17 | gameLocale = "enUS"
18 | end
19 |
20 | AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
21 | AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
22 |
23 | -- This metatable is used on all tables returned from GetLocale
24 | local readmeta = {
25 | __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
26 | rawset(self, key, key) -- only need to see the warning once, really
27 | geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
28 | return key
29 | end
30 | }
31 |
32 | -- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
33 | local readmetasilent = {
34 | __index = function(self, key) -- requesting totally unknown entries: return key
35 | rawset(self, key, key) -- only need to invoke this function once
36 | return key
37 | end
38 | }
39 |
40 | -- Remember the locale table being registered right now (it gets set by :NewLocale())
41 | -- NOTE: Do never try to register 2 locale tables at once and mix their definition.
42 | local registering
43 |
44 | -- local assert false function
45 | local assertfalse = function() assert(false) end
46 |
47 | -- This metatable proxy is used when registering nondefault locales
48 | local writeproxy = setmetatable({}, {
49 | __newindex = function(self, key, value)
50 | rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
51 | end,
52 | __index = assertfalse
53 | })
54 |
55 | -- This metatable proxy is used when registering the default locale.
56 | -- It refuses to overwrite existing values
57 | -- Reason 1: Allows loading locales in any order
58 | -- Reason 2: If 2 modules have the same string, but only the first one to be
59 | -- loaded has a translation for the current locale, the translation
60 | -- doesn't get overwritten.
61 | --
62 | local writedefaultproxy = setmetatable({}, {
63 | __newindex = function(self, key, value)
64 | if not rawget(registering, key) then
65 | rawset(registering, key, value == true and key or value)
66 | end
67 | end,
68 | __index = assertfalse
69 | })
70 |
71 | --- Register a new locale (or extend an existing one) for the specified application.
72 | -- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
73 | -- game locale.
74 | -- @paramsig application, locale[, isDefault[, silent]]
75 | -- @param application Unique name of addon / module
76 | -- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
77 | -- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
78 | -- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
79 | -- @usage
80 | -- -- enUS.lua
81 | -- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
82 | -- L["string1"] = true
83 | --
84 | -- -- deDE.lua
85 | -- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
86 | -- if not L then return end
87 | -- L["string1"] = "Zeichenkette1"
88 | -- @return Locale Table to add localizations to, or nil if the current locale is not required.
89 | function AceLocale:NewLocale(application, locale, isDefault, silent)
90 |
91 | -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
92 | local activeGameLocale = GAME_LOCALE or gameLocale
93 |
94 | local app = AceLocale.apps[application]
95 |
96 | if silent and app and getmetatable(app) ~= readmetasilent then
97 | geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
98 | end
99 |
100 | if not app then
101 | if silent=="raw" then
102 | app = {}
103 | else
104 | app = setmetatable({}, silent and readmetasilent or readmeta)
105 | end
106 | AceLocale.apps[application] = app
107 | AceLocale.appnames[app] = application
108 | end
109 |
110 | if locale ~= activeGameLocale and not isDefault then
111 | return -- nop, we don't need these translations
112 | end
113 |
114 | registering = app -- remember globally for writeproxy and writedefaultproxy
115 |
116 | if isDefault then
117 | return writedefaultproxy
118 | end
119 |
120 | return writeproxy
121 | end
122 |
123 | --- Returns localizations for the current locale (or default locale if translations are missing).
124 | -- Errors if nothing is registered (spank developer, not just a missing translation)
125 | -- @param application Unique name of addon / module
126 | -- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
127 | -- @return The locale table for the current language.
128 | function AceLocale:GetLocale(application, silent)
129 | if not silent and not AceLocale.apps[application] then
130 | error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
131 | end
132 | return AceLocale.apps[application]
133 | end
134 |
--------------------------------------------------------------------------------
/Libs/AceLocale-3.0/AceLocale-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceSerializer-3.0/AceSerializer-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/AceTimer-3.0/AceTimer-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua:
--------------------------------------------------------------------------------
1 | --[[ $Id: CallbackHandler-1.0.lua 1284 2022-09-25 09:15:30Z nevcairiel $ ]]
2 | local MAJOR, MINOR = "CallbackHandler-1.0", 7
3 | local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
4 |
5 | if not CallbackHandler then return end -- No upgrade needed
6 |
7 | local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
8 |
9 | -- Lua APIs
10 | local error = error
11 | local setmetatable, rawget = setmetatable, rawget
12 | local next, select, pairs, type, tostring = next, select, pairs, type, tostring
13 |
14 | local xpcall = xpcall
15 |
16 | local function errorhandler(err)
17 | return geterrorhandler()(err)
18 | end
19 |
20 | local function Dispatch(handlers, ...)
21 | local index, method = next(handlers)
22 | if not method then return end
23 | repeat
24 | xpcall(method, errorhandler, ...)
25 | index, method = next(handlers, index)
26 | until not method
27 | end
28 |
29 | --------------------------------------------------------------------------
30 | -- CallbackHandler:New
31 | --
32 | -- target - target object to embed public APIs in
33 | -- RegisterName - name of the callback registration API, default "RegisterCallback"
34 | -- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
35 | -- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
36 |
37 | function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName)
38 |
39 | RegisterName = RegisterName or "RegisterCallback"
40 | UnregisterName = UnregisterName or "UnregisterCallback"
41 | if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
42 | UnregisterAllName = "UnregisterAllCallbacks"
43 | end
44 |
45 | -- we declare all objects and exported APIs inside this closure to quickly gain access
46 | -- to e.g. function names, the "target" parameter, etc
47 |
48 |
49 | -- Create the registry object
50 | local events = setmetatable({}, meta)
51 | local registry = { recurse=0, events=events }
52 |
53 | -- registry:Fire() - fires the given event/message into the registry
54 | function registry:Fire(eventname, ...)
55 | if not rawget(events, eventname) or not next(events[eventname]) then return end
56 | local oldrecurse = registry.recurse
57 | registry.recurse = oldrecurse + 1
58 |
59 | Dispatch(events[eventname], eventname, ...)
60 |
61 | registry.recurse = oldrecurse
62 |
63 | if registry.insertQueue and oldrecurse==0 then
64 | -- Something in one of our callbacks wanted to register more callbacks; they got queued
65 | for event,callbacks in pairs(registry.insertQueue) do
66 | local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten.
67 | for object,func in pairs(callbacks) do
68 | events[event][object] = func
69 | -- fire OnUsed callback?
70 | if first and registry.OnUsed then
71 | registry.OnUsed(registry, target, event)
72 | first = nil
73 | end
74 | end
75 | end
76 | registry.insertQueue = nil
77 | end
78 | end
79 |
80 | -- Registration of a callback, handles:
81 | -- self["method"], leads to self["method"](self, ...)
82 | -- self with function ref, leads to functionref(...)
83 | -- "addonId" (instead of self) with function ref, leads to functionref(...)
84 | -- all with an optional arg, which, if present, gets passed as first argument (after self if present)
85 | target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
86 | if type(eventname) ~= "string" then
87 | error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
88 | end
89 |
90 | method = method or eventname
91 |
92 | local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
93 |
94 | if type(method) ~= "string" and type(method) ~= "function" then
95 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
96 | end
97 |
98 | local regfunc
99 |
100 | if type(method) == "string" then
101 | -- self["method"] calling style
102 | if type(self) ~= "table" then
103 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
104 | elseif self==target then
105 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
106 | elseif type(self[method]) ~= "function" then
107 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
108 | end
109 |
110 | if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
111 | local arg=select(1,...)
112 | regfunc = function(...) self[method](self,arg,...) end
113 | else
114 | regfunc = function(...) self[method](self,...) end
115 | end
116 | else
117 | -- function ref with self=object or self="addonId" or self=thread
118 | if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
119 | error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
120 | end
121 |
122 | if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
123 | local arg=select(1,...)
124 | regfunc = function(...) method(arg,...) end
125 | else
126 | regfunc = method
127 | end
128 | end
129 |
130 |
131 | if events[eventname][self] or registry.recurse<1 then
132 | -- if registry.recurse<1 then
133 | -- we're overwriting an existing entry, or not currently recursing. just set it.
134 | events[eventname][self] = regfunc
135 | -- fire OnUsed callback?
136 | if registry.OnUsed and first then
137 | registry.OnUsed(registry, target, eventname)
138 | end
139 | else
140 | -- we're currently processing a callback in this registry, so delay the registration of this new entry!
141 | -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
142 | registry.insertQueue = registry.insertQueue or setmetatable({},meta)
143 | registry.insertQueue[eventname][self] = regfunc
144 | end
145 | end
146 |
147 | -- Unregister a callback
148 | target[UnregisterName] = function(self, eventname)
149 | if not self or self==target then
150 | error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
151 | end
152 | if type(eventname) ~= "string" then
153 | error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
154 | end
155 | if rawget(events, eventname) and events[eventname][self] then
156 | events[eventname][self] = nil
157 | -- Fire OnUnused callback?
158 | if registry.OnUnused and not next(events[eventname]) then
159 | registry.OnUnused(registry, target, eventname)
160 | end
161 | end
162 | if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
163 | registry.insertQueue[eventname][self] = nil
164 | end
165 | end
166 |
167 | -- OPTIONAL: Unregister all callbacks for given selfs/addonIds
168 | if UnregisterAllName then
169 | target[UnregisterAllName] = function(...)
170 | if select("#",...)<1 then
171 | error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
172 | end
173 | if select("#",...)==1 and ...==target then
174 | error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
175 | end
176 |
177 |
178 | for i=1,select("#",...) do
179 | local self = select(i,...)
180 | if registry.insertQueue then
181 | for eventname, callbacks in pairs(registry.insertQueue) do
182 | if callbacks[self] then
183 | callbacks[self] = nil
184 | end
185 | end
186 | end
187 | for eventname, callbacks in pairs(events) do
188 | if callbacks[self] then
189 | callbacks[self] = nil
190 | -- Fire OnUnused callback?
191 | if registry.OnUnused and not next(callbacks) then
192 | registry.OnUnused(registry, target, eventname)
193 | end
194 | end
195 | end
196 | end
197 | end
198 | end
199 |
200 | return registry
201 | end
202 |
203 |
204 | -- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
205 | -- try to upgrade old implicit embeds since the system is selfcontained and
206 | -- relies on closures to work.
207 |
208 |
--------------------------------------------------------------------------------
/Libs/CallbackHandler-1.0/CallbackHandler-1.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Libs/Embeds.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Libs/LibBase64-1.0/LibBase64-1.0.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Name: LibBase64-1.0
3 | Author(s): ckknight (ckknight@gmail.com)
4 | Website: http://www.wowace.com/projects/libbase64-1-0/
5 | Description: A library to encode and decode Base64 strings
6 | License: MIT
7 | ]]
8 |
9 | local LibBase64 = LibStub:NewLibrary("LibBase64-1.0", 1)
10 |
11 | if not LibBase64 then
12 | return
13 | end
14 |
15 | local _chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
16 | local byteToNum = {}
17 | local numToChar = {}
18 | for i = 1, #_chars do
19 | numToChar[i - 1] = _chars:sub(i, i)
20 | byteToNum[_chars:byte(i)] = i - 1
21 | end
22 | _chars = nil
23 | local A_byte = ("A"):byte()
24 | local Z_byte = ("Z"):byte()
25 | local a_byte = ("a"):byte()
26 | local z_byte = ("z"):byte()
27 | local zero_byte = ("0"):byte()
28 | local nine_byte = ("9"):byte()
29 | local plus_byte = ("+"):byte()
30 | local slash_byte = ("/"):byte()
31 | local equals_byte = ("="):byte()
32 | local whitespace = {
33 | [(" "):byte()] = true,
34 | [("\t"):byte()] = true,
35 | [("\n"):byte()] = true,
36 | [("\r"):byte()] = true,
37 | }
38 |
39 | local t = {}
40 |
41 | --- Encode a normal bytestring into a Base64-encoded string
42 | -- @param text a bytestring, can be binary data
43 | -- @param maxLineLength This should be a multiple of 4, greater than 0 or nil. If non-nil, it will break up the output into lines no longer than the given number of characters. 76 is recommended.
44 | -- @param lineEnding a string to end each line with. This is "\r\n" by default.
45 | -- @usage LibBase64.Encode("Hello, how are you doing today?") == "SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw=="
46 | -- @return a Base64-encoded string
47 | function LibBase64.Encode(text, maxLineLength, lineEnding)
48 | if type(text) ~= "string" then
49 | error(("Bad argument #1 to `Encode'. Expected %q, got %q"):format("string", type(text)), 2)
50 | end
51 |
52 | if maxLineLength == nil then
53 | -- do nothing
54 | elseif type(maxLineLength) ~= "number" then
55 | error(("Bad argument #2 to `Encode'. Expected %q or %q, got %q"):format("number", "nil", type(maxLineLength)), 2)
56 | elseif (maxLineLength % 4) ~= 0 then
57 | error(("Bad argument #2 to `Encode'. Expected a multiple of 4, got %s"):format(maxLineLength), 2)
58 | elseif maxLineLength <= 0 then
59 | error(("Bad argument #2 to `Encode'. Expected a number > 0, got %s"):format(maxLineLength), 2)
60 | end
61 |
62 | if lineEnding == nil then
63 | lineEnding = "\r\n"
64 | elseif type(lineEnding) ~= "string" then
65 | error(("Bad argument #3 to `Encode'. Expected %q, got %q"):format("string", type(lineEnding)), 2)
66 | end
67 |
68 | local currentLength = 0
69 |
70 | for i = 1, #text, 3 do
71 | local a, b, c = text:byte(i, i+2)
72 | local nilNum = 0
73 | if not b then
74 | nilNum = 2
75 | b = 0
76 | c = 0
77 | elseif not c then
78 | nilNum = 1
79 | c = 0
80 | end
81 | local num = a * 2^16 + b * 2^8 + c
82 |
83 | local d = num % 2^6
84 | num = (num - d) / 2^6
85 |
86 | local c = num % 2^6
87 | num = (num - c) / 2^6
88 |
89 | local b = num % 2^6
90 | num = (num - b) / 2^6
91 |
92 | local a = num % 2^6
93 |
94 | t[#t+1] = numToChar[a]
95 |
96 | t[#t+1] = numToChar[b]
97 |
98 | t[#t+1] = (nilNum >= 2) and "=" or numToChar[c]
99 |
100 | t[#t+1] = (nilNum >= 1) and "=" or numToChar[d]
101 |
102 | currentLength = currentLength + 4
103 | if maxLineLength and (currentLength % maxLineLength) == 0 then
104 | t[#t+1] = lineEnding
105 | end
106 | end
107 |
108 | local s = table.concat(t)
109 | for i = 1, #t do
110 | t[i] = nil
111 | end
112 | return s
113 | end
114 |
115 | local t2 = {}
116 |
117 | --- Decode a Base64-encoded string into a bytestring
118 | -- this will raise an error if the data passed in is not a Base64-encoded string
119 | -- this will ignore whitespace, but not invalid characters
120 | -- @param text a Base64-encoded string
121 | -- @usage LibBase64.Encode("SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw==") == "Hello, how are you doing today?"
122 | -- @return a bytestring
123 | function LibBase64.Decode(text)
124 | if type(text) ~= "string" then
125 | error(("Bad argument #1 to `Decode'. Expected %q, got %q"):format("string", type(text)), 2)
126 | end
127 |
128 | for i = 1, #text do
129 | local byte = text:byte(i)
130 | if whitespace[byte] or byte == equals_byte then
131 | -- do nothing
132 | else
133 | local num = byteToNum[byte]
134 | if not num then
135 | for i = 1, #t2 do
136 | t2[k] = nil
137 | end
138 |
139 | error(("Bad argument #1 to `Decode'. Received an invalid char: %q"):format(text:sub(i, i)), 2)
140 | end
141 | t2[#t2+1] = num
142 | end
143 | end
144 |
145 | for i = 1, #t2, 4 do
146 | local a, b, c, d = t2[i], t2[i+1], t2[i+2], t2[i+3]
147 |
148 | local nilNum = 0
149 | if not c then
150 | nilNum = 2
151 | c = 0
152 | d = 0
153 | elseif not d then
154 | nilNum = 1
155 | d = 0
156 | end
157 |
158 | local num = a * 2^18 + b * 2^12 + c * 2^6 + d
159 |
160 | local c = num % 2^8
161 | num = (num - c) / 2^8
162 |
163 | local b = num % 2^8
164 | num = (num - b) / 2^8
165 |
166 | local a = num % 2^8
167 |
168 | t[#t+1] = string.char(a)
169 | if nilNum < 2 then
170 | t[#t+1] = string.char(b)
171 | end
172 | if nilNum < 1 then
173 | t[#t+1] = string.char(c)
174 | end
175 | end
176 |
177 | for i = 1, #t2 do
178 | t2[i] = nil
179 | end
180 |
181 | local s = table.concat(t)
182 |
183 | for i = 1, #t do
184 | t[i] = nil
185 | end
186 |
187 | return s
188 | end
189 |
--------------------------------------------------------------------------------
/Libs/LibBase64-1.0/LibBase64-1.0.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 30000
2 | ## Title: Lib: Base64-1.0
3 | ## Notes: A library to encode and decode Base64 strings
4 | ## Author: ckknight
5 | ## X-eMail: ckknight@gmail.com
6 | ## X-Category: Library
7 | ## X-License: MIT
8 | ## X-Curse-Packaged-Version: v1
9 |
10 | LibStub\LibStub.lua
11 | lib.xml
12 |
--------------------------------------------------------------------------------
/Libs/LibBase64-1.0/lib.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/Libs/LibDataBroker-1.1/LibDataBroker-1.1.lua:
--------------------------------------------------------------------------------
1 |
2 | assert(LibStub, "LibDataBroker-1.1 requires LibStub")
3 | assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
4 |
5 | local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
6 | if not lib then return end
7 | oldminor = oldminor or 0
8 |
9 |
10 | lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
11 | lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
12 | local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
13 |
14 | if oldminor < 2 then
15 | lib.domt = {
16 | __metatable = "access denied",
17 | __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
18 | }
19 | end
20 |
21 | if oldminor < 3 then
22 | lib.domt.__newindex = function(self, key, value)
23 | if not attributestorage[self] then attributestorage[self] = {} end
24 | if attributestorage[self][key] == value then return end
25 | attributestorage[self][key] = value
26 | local name = namestorage[self]
27 | if not name then return end
28 | callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
29 | callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
30 | callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
31 | callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
32 | end
33 | end
34 |
35 | if oldminor < 2 then
36 | function lib:NewDataObject(name, dataobj)
37 | if self.proxystorage[name] then return end
38 |
39 | if dataobj then
40 | assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
41 | self.attributestorage[dataobj] = {}
42 | for i,v in pairs(dataobj) do
43 | self.attributestorage[dataobj][i] = v
44 | dataobj[i] = nil
45 | end
46 | end
47 | dataobj = setmetatable(dataobj or {}, self.domt)
48 | self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
49 | self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
50 | return dataobj
51 | end
52 | end
53 |
54 | if oldminor < 1 then
55 | function lib:DataObjectIterator()
56 | return pairs(self.proxystorage)
57 | end
58 |
59 | function lib:GetDataObjectByName(dataobjectname)
60 | return self.proxystorage[dataobjectname]
61 | end
62 |
63 | function lib:GetNameByDataObject(dataobject)
64 | return self.namestorage[dataobject]
65 | end
66 | end
67 |
68 | if oldminor < 4 then
69 | local next = pairs(attributestorage)
70 | function lib:pairs(dataobject_or_name)
71 | local t = type(dataobject_or_name)
72 | assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
73 |
74 | local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
75 | assert(attributestorage[dataobj], "Data object not found")
76 |
77 | return next, attributestorage[dataobj], nil
78 | end
79 |
80 | local ipairs_iter = ipairs(attributestorage)
81 | function lib:ipairs(dataobject_or_name)
82 | local t = type(dataobject_or_name)
83 | assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
84 |
85 | local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
86 | assert(attributestorage[dataobj], "Data object not found")
87 |
88 | return ipairs_iter, attributestorage[dataobj], 0
89 | end
90 | end
91 |
--------------------------------------------------------------------------------
/Libs/LibStub/LibStub.lua:
--------------------------------------------------------------------------------
1 | -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
2 | -- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
3 | local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
4 | local LibStub = _G[LIBSTUB_MAJOR]
5 |
6 | if not LibStub or LibStub.minor < LIBSTUB_MINOR then
7 | LibStub = LibStub or {libs = {}, minors = {} }
8 | _G[LIBSTUB_MAJOR] = LibStub
9 | LibStub.minor = LIBSTUB_MINOR
10 |
11 | function LibStub:NewLibrary(major, minor)
12 | assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
13 | minor = assert(tonumber(string.match(minor, "%d+")), "Minor version must either be a number or contain a number.")
14 |
15 | local oldminor = self.minors[major]
16 | if oldminor and oldminor >= minor then return nil end
17 | self.minors[major], self.libs[major] = minor, self.libs[major] or {}
18 | return self.libs[major], oldminor
19 | end
20 |
21 | function LibStub:GetLibrary(major, silent)
22 | if not self.libs[major] and not silent then
23 | error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
24 | end
25 | return self.libs[major], self.minors[major]
26 | end
27 |
28 | function LibStub:IterateLibraries() return pairs(self.libs) end
29 | setmetatable(LibStub, { __call = LibStub.GetLibrary })
30 | end
31 |
--------------------------------------------------------------------------------
/Libs/LibWindow-1.1/CHANGES.txt:
--------------------------------------------------------------------------------
1 | ------------------------------------------------------------------------
2 | r22 | nevcairiel | 2021-06-29 09:32:58 +0000 (Tue, 29 Jun 2021) | 1 line
3 | Changed paths:
4 | M /trunk/LibWindow-1.1.toc
5 |
6 | Update TOC for 9.1
7 | ------------------------------------------------------------------------
8 | r21 | nevcairiel | 2021-03-15 10:26:43 +0000 (Mon, 15 Mar 2021) | 1 line
9 | Changed paths:
10 | M /trunk/LibWindow-1.1.toc
11 |
12 | Update TOC for 9.0.5
13 | ------------------------------------------------------------------------
14 | r20 | nevcairiel | 2020-12-19 10:45:26 +0000 (Sat, 19 Dec 2020) | 1 line
15 | Changed paths:
16 | M /trunk/LibWindow-1.1.toc
17 |
18 | Update TOC
19 | ------------------------------------------------------------------------
20 | r19 | nevcairiel | 2020-10-13 17:59:08 +0000 (Tue, 13 Oct 2020) | 1 line
21 | Changed paths:
22 | M /trunk/LibWindow-1.1.toc
23 |
24 | Update TOC
25 | ------------------------------------------------------------------------
26 | r18 | nevcairiel | 2019-09-07 08:42:10 +0000 (Sat, 07 Sep 2019) | 1 line
27 | Changed paths:
28 | M /trunk/LibWindow-1.1/LibWindow-1.1.lua
29 |
30 | Verify scale is valid before using, early in the loading process it may not return anything yet
31 | ------------------------------------------------------------------------
32 | r17 | nevcairiel | 2017-08-29 14:31:58 +0000 (Tue, 29 Aug 2017) | 1 line
33 | Changed paths:
34 | M /trunk/LibWindow-1.1.toc
35 |
36 | Update TOC for 7.3
37 | ------------------------------------------------------------------------
38 |
39 |
--------------------------------------------------------------------------------
/Libs/LibWindow-1.1/LibStub.lua:
--------------------------------------------------------------------------------
1 | -- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
2 | -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
3 | -- LibStub is hereby placed in the Public Domain
4 | -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
5 | local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
6 | local LibStub = _G[LIBSTUB_MAJOR]
7 |
8 | -- Check to see is this version of the stub is obsolete
9 | if not LibStub or LibStub.minor < LIBSTUB_MINOR then
10 | LibStub = LibStub or {libs = {}, minors = {} }
11 | _G[LIBSTUB_MAJOR] = LibStub
12 | LibStub.minor = LIBSTUB_MINOR
13 |
14 | -- LibStub:NewLibrary(major, minor)
15 | -- major (string) - the major version of the library
16 | -- minor (string or number ) - the minor version of the library
17 | --
18 | -- returns nil if a newer or same version of the lib is already present
19 | -- returns empty library object or old library object if upgrade is needed
20 | function LibStub:NewLibrary(major, minor)
21 | assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
22 | minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
23 |
24 | local oldminor = self.minors[major]
25 | if oldminor and oldminor >= minor then return nil end
26 | self.minors[major], self.libs[major] = minor, self.libs[major] or {}
27 | return self.libs[major], oldminor
28 | end
29 |
30 | -- LibStub:GetLibrary(major, [silent])
31 | -- major (string) - the major version of the library
32 | -- silent (boolean) - if true, library is optional, silently return nil if its not found
33 | --
34 | -- throws an error if the library can not be found (except silent is set)
35 | -- returns the library object if found
36 | function LibStub:GetLibrary(major, silent)
37 | if not self.libs[major] and not silent then
38 | error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
39 | end
40 | return self.libs[major], self.minors[major]
41 | end
42 |
43 | -- LibStub:IterateLibraries()
44 | --
45 | -- Returns an iterator for the currently registered libraries
46 | function LibStub:IterateLibraries()
47 | return pairs(self.libs)
48 | end
49 |
50 | setmetatable(LibStub, { __call = LibStub.GetLibrary })
51 | end
52 |
--------------------------------------------------------------------------------
/Libs/LibWindow-1.1/LibWindow-1.1.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 90100
2 | ## LoadOnDemand: 1
3 | ## Title: Lib: Window-1.1
4 | ## Version: 1.1.22
5 | ## Notes: A library that handles the basics of "window" style frames
6 | ## Author: Mikk
7 | ## eMail: dpsgnome@mail.com
8 | ## X-Category: Library
9 | ## X-License: Public Domain
10 |
11 | LibStub.lua
12 | LibWindow-1.1\LibWindow-1.1.lua
13 |
--------------------------------------------------------------------------------
/Load.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Localization/Localization.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Localization/deDE.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'deDE')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="deDE", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/enUS.lua:
--------------------------------------------------------------------------------
1 | -- @debug@
2 | local L = LibStub('AceLocale-3.0'):NewLocale(..., 'enUS', true)
3 | -- @end-debug@
4 | --[[@non-debug@
5 | local L = LibStub('AceLocale-3.0'):NewLocale(..., 'enUS', true, true)
6 | --@end-non-debug@]]
7 | if not L then
8 | return
9 | end
10 |
11 | -- @localization(locale=""enUS", format="lua_additive_table", table-name="L", same-key-is-true=true)@
12 |
13 | -- @debug@
14 | -- @import@
15 | L['ADDON_NAME'] = 'Battle pet script'
16 | L['Auto'] = true
17 | L['Beauty script'] = true
18 | L['Create script'] = true
19 | L['Debugging script'] = true
20 | L['DIALOG_COPY_URL_HELP'] = 'Press ctrl-c to copy and open it in the browser'
21 | L['Don\'t ask me'] = true
22 | L['Download'] = true
23 | L['Edit script'] = true
24 | L['Export'] = true
25 | L['Font face'] = true
26 | L['Font size'] = true
27 | L['Found error'] = true
28 | L['Import'] = true
29 | L['IMPORT_CHOOSE_KEY'] = 'Select the key...'
30 | L['IMPORT_CHOOSE_PLUGIN'] = 'Select the script selector...'
31 | L['IMPORT_REINPUT_TEXT'] = 'Re-edit'
32 | L['IMPORT_SCRIPT_EXISTS'] = 'Script exists'
33 | L['IMPORT_SCRIPT_WARNING'] =
34 | 'You have entered the script and are advised to import using the Share string, although you can continue to import as well.'
35 | L['IMPORT_SCRIPT_WELCOME'] = 'Copy Share string or script to edit box.'
36 | L['IMPORT_SHARED_STRING_WARNING'] = 'Share string data incomplete. But you can still import it.'
37 | L['Installed'] = true
38 | L['New script'] = true
39 | L['No script'] = true
40 | L['Not Installed'] = true
41 | L['OPTION_GENERAL_NOTES'] = 'Here are some general Settings.'
42 | L['OPTION_SCRIPTEDITOR_NOTES'] = 'Here is the script editor preferences'
43 | L['OPTION_SCRIPTSELECTOR_NOTES'] = 'Here you can manage the script selector is open, and its priority.'
44 | L['OPTION_SETTINGS_AUTO_SELECT_SCRIPT_BY_ORDER'] = true
45 | L['OPTION_SETTINGS_AUTO_SELECT_SCRIPT_ONLY_ONE'] = 'Automatically select script by script selector priority'
46 | L['OPTION_SETTINGS_AUTOBUTTON_HOTKEY'] = 'Auto button hotkey'
47 | L['OPTION_SETTINGS_HIDE_MINIMAP'] = 'Hide minimap'
48 | L['OPTION_SETTINGS_HIDE_MINIMAP_TOOLTIP'] = 'Changing this setting requires reloading the UI. Do you want to continue?'
49 | L['OPTION_SETTINGS_HIDE_SELECTOR_NO_SCRIPT'] = 'The script selector is not displayed when there is no script'
50 | L['OPTION_SETTINGS_NO_WAIT_DELETE_SCRIPT'] = 'Do not wait for the script to be deleted'
51 | L['OPTION_SETTINGS_TEST_BREAK'] = 'Debug: Action test break script'
52 | L['OPTION_SETTINGS_LOCK_SCRIPT_SELECTOR'] = 'Lock the script selector'
53 | L['OPTION_SETTINGS_RESET_FRAMES'] = 'Reset the panel size and position'
54 | L['Options'] = true
55 | L['PLUGINFIRSTENEMY_NOTIFY'] = 'Discover that you\'ve previously used the modified version of tdBattlePetScript and have migrated some of the scripts for the modified Base Selector to firstEnemy Selector.'
56 | L['PLUGINFIRSTENEMY_NOTES'] = 'This script selector binds the script to the first enemy in the battle.'
57 | L['PLUGINFIRSTENEMY_TITLE'] = 'First enemy'
58 | L['PLUGINALLINONE_NOTES'] = 'This script can be used in all pet battles.'
59 | L['PLUGINALLINONE_TITLE'] = 'All in one'
60 | L['PLUGINBASE_NOTES'] = 'This script selector matches ally and enemy.'
61 | L['PLUGINBASE_TEAM_ALLY'] = 'Ally'
62 | L['PLUGINBASE_TEAM_ENEMY'] = 'Enemy'
63 | L['PLUGINBASE_TITLE'] = 'Base'
64 | L['PLUGINBASE_TOOLTIP_CREATE_SCRIPT'] = 'Base: Create a script for the current match'
65 | L['Run'] = true
66 | L['Save success'] = true
67 | L['Script'] = true
68 | L['Script author'] = true
69 | L['Script editor'] = true
70 | L['Script manager'] = true
71 | L['Script name'] = true
72 | L['Script notes'] = true
73 | L['Script selector'] = true
74 | L['SCRIPT_EDITOR_DELETE_SCRIPT'] = 'Are you sure you want to |cffff0000delete|r the script |cffffd000[%s - %s]|r ?'
75 | L['SCRIPT_EDITOR_LABEL_TOGGLE_EXTRA'] = 'Toggle extension information editor'
76 | L['SCRIPT_IMPORT_LABEL_COVER'] =
77 | 'The matching mode existing script, and continue to import will cover the current script.'
78 | L['SCRIPT_IMPORT_LABEL_EXTRA'] = 'Continue to import the plugin data'
79 | L['SCRIPT_IMPORT_LABEL_GOON'] = 'Cover and continue to import'
80 | L['SCRIPT_SELECTOR_LOST_TOOLTIP'] = 'Script selector developer does not define the function `OnTooltipFormatting`'
81 | L['SCRIPT_SELECTOR_NOT_MATCH'] = 'No script selector matches to the current battle'
82 | L['SCRIPT_SELECTOR_NOTINSTALLED_HELP'] = 'Left click to view, right click to close'
83 | L['SCRIPT_SELECTOR_NOTINSTALLED_TEXT'] = 'A useful script selector is not installed!'
84 | L['Select script'] = true
85 | L['TOGGLE_SCRIPT_MANAGER'] = 'Toggle script manager'
86 | L['TOGGLE_SCRIPT_SELECTOR'] = 'Toggle script selector'
87 | L['TOOLTIP_CREATE_OR_DEBUG_SCRIPT'] = 'Create or debug script'
88 | L['Update to version: '] = true
89 | -- @end-import@
90 | -- @end-debug@
91 |
--------------------------------------------------------------------------------
/Localization/esES.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'esES')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="esES", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/frFR.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'frFR')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="frFR", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/itIT.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'itIT')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="itIT", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/koKR.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'koKR')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="koKR", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/ptBR.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'ptBR')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="ptBR", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/ruRU.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'ruRU')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="ruRU", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Localization/zhCN.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | zhCN.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'zhCN')
8 | if not L then return end
9 |
10 | -- @import@
11 | L.ADDON_NAME = '小宠物战斗脚本'
12 |
13 | L['Auto'] = '自动'
14 | L['Create script'] = '创建脚本'
15 | L['Debugging script'] = '调试脚本'
16 | L['Debugging script'] = '调试脚本'
17 | L['Edit script'] = '修改脚本'
18 | L['Export'] = '导出'
19 | L['Font face'] = '字体'
20 | L['Font size'] = '字体大小'
21 | L['Found error'] = '发现错误'
22 | L['Import'] = '导入'
23 | L['New script'] = '新建脚本'
24 | L['No script'] = '没有脚本'
25 | L['Options'] = '设置'
26 | L['Run'] = '运行'
27 | L['Save success'] = '保存成功'
28 | L['Script author'] = '作者名称'
29 | L['Script editor'] = '脚本编辑器'
30 | L['Script name'] = '脚本名称'
31 | L['Script notes'] = '脚本备注'
32 | L['Script selector'] = '脚本选择器'
33 | L['Script'] = '脚本'
34 | L['Select script'] = '选择脚本'
35 | L['Beauty script'] = '美化脚本'
36 | L['Script manager'] = '脚本管理器'
37 | L['Installed'] = '已安装'
38 | L['Not Installed'] = '未安装'
39 | L['Download'] = '下载'
40 | L['Don\'t ask me'] = '不再提醒'
41 |
42 | L['Update to version: '] = '更新到版本:'
43 |
44 | L.TOGGLE_SCRIPT_MANAGER = '切换脚本管理器'
45 | L.TOGGLE_SCRIPT_SELECTOR = '切换脚本选择器'
46 | L.SCRIPT_SELECTOR_LOST_TOOLTIP = '脚本选择器开发者没有定义 OnTooltipFormatting'
47 | L.SCRIPT_EDITOR_LABEL_TOGGLE_EXTRA = '切换扩展信息编辑器'
48 | L.SCRIPT_EDITOR_DELETE_SCRIPT = '你确定要|cffff0000删除|r脚本 |cffffd000[%s - %s]|r 么?'
49 | L.TOOLTIP_CREATE_OR_DEBUG_SCRIPT = '创建或调试脚本'
50 | L.SCRIPT_SELECTOR_NOT_MATCH = '没有脚本选择器匹配到当前战斗'
51 | L.DIALOG_COPY_URL_HELP = '按Ctrl-C复制到浏览器打开'
52 | L.SCRIPT_SELECTOR_NOTINSTALLED_TEXT = '发现一个有用的脚本选择器未安装!'
53 | L.SCRIPT_SELECTOR_NOTINSTALLED_HELP = '左键查看,右键关闭'
54 |
55 | L.SCRIPT_IMPORT_LABEL_COVER = '这个匹配模式下已存在脚本,继续导入将覆盖当前脚本。'
56 | L.SCRIPT_IMPORT_LABEL_EXTRA = '继续导入扩展信息'
57 | L.SCRIPT_IMPORT_LABEL_GOON = '覆盖并继续导入'
58 |
59 | L.IMPORT_SCRIPT_WELCOME = '复制分享字符串或脚本到输入框。'
60 | L.IMPORT_SCRIPT_WARNING = '你输入了脚本,建议你使用分享码导入,当然你也可以继续导入。'
61 | L.IMPORT_REINPUT_TEXT = '重新编辑'
62 | L.IMPORT_CHOOSE_PLUGIN = '请选择脚本选择器...'
63 | L.IMPORT_CHOOSE_KEY = '请选择关建值...'
64 | L.IMPORT_SCRIPT_EXISTS = '已存在脚本'
65 | L.IMPORT_SHARED_STRING_WARNING = '分享字符串数据不全。但依然可以导入。'
66 |
67 | L.OPTION_GENERAL_NOTES = '这里是一些常规设置。'
68 | L.OPTION_SCRIPTSELECTOR_NOTES = '在这里你可以管理脚本选择器是否开启以及脚本选择器的优先级。'
69 | L.OPTION_SETTINGS_AUTO_SELECT_SCRIPT_ONLY_ONE = '只有一个脚本时自动选择'
70 | L.OPTION_SETTINGS_AUTO_SELECT_SCRIPT_BY_ORDER = '自动根据脚本选择器优先级选择脚本'
71 | L.OPTION_SETTINGS_HIDE_SELECTOR_NO_SCRIPT = '没有脚本时不显示脚本选择器'
72 | L.OPTION_SETTINGS_NO_WAIT_DELETE_SCRIPT = '删除脚本时不等待'
73 | L.OPTION_SETTINGS_AUTOBUTTON_HOTKEY = '自动按钮快捷键'
74 | L.OPTION_SCRIPTEDITOR_NOTES = '这里是脚本编辑器的偏好设置'
75 | L.OPTION_SETTINGS_TEST_BREAK = 'Debug: test 命令中断脚本'
76 | L.OPTION_SETTINGS_HIDE_MINIMAP = '隐藏小地图图标'
77 | L.OPTION_SETTINGS_HIDE_MINIMAP_TOOLTIP = '修改这项设置需要重新载入UI,是否继续?'
78 |
79 | L.OPTION_SETTINGS_LOCK_SCRIPT_SELECTOR = '锁定脚本选择器'
80 | L.OPTION_SETTINGS_RESET_FRAMES = '重置面板大小与位置'
81 |
82 | L.PLUGINBASE_TITLE = '基础'
83 | L.PLUGINBASE_NOTES = '这个脚本选择器将脚本绑定到对阵双方的完整阵容。'
84 | L.PLUGINBASE_TEAM_ALLY = '我方阵容'
85 | L.PLUGINBASE_TEAM_ENEMY = '敌方阵容'
86 | L.PLUGINBASE_TOOLTIP_CREATE_SCRIPT = '基础:为当前对阵创建脚本'
87 |
88 | L.PLUGINALLINONE_TITLE = 'All in one'
89 | L.PLUGINALLINONE_NOTES = '所有小宠物战斗都可以使用这个脚本。'
90 |
91 | L.PLUGINFIRSTENEMY_TITLE = 'First enemy'
92 | L.PLUGINFIRSTENEMY_NOTES = '这个脚本选择器将脚本绑定到战斗的第一个敌人。'
93 |
94 | L.PLUGINFIRSTENEMY_NOTIFY = '发现你之前使用过修改版的tdBattlePetScript,已将修改版的Base选择器的部分脚本迁移到FirstEnemy选择器。'
95 | -- @end-import@
96 |
--------------------------------------------------------------------------------
/Localization/zhTW.lua:
--------------------------------------------------------------------------------
1 |
2 | local L = LibStub('AceLocale-3.0'):NewLocale('tdBattlePetScript', 'zhTW')
3 | if not L then return end
4 |
5 | --@debug@
6 | --[[
7 | --@end-debug@
8 | @localization(locale="zhTW", format="lua_additive_table", table-name="L", same-key-is-true=true)@
9 | --@debug@
10 | --]]
11 | --@end-debug@
12 |
--------------------------------------------------------------------------------
/Plugins/AllInOne.lua:
--------------------------------------------------------------------------------
1 | -- AllInOne.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/20/2018, 4:05:16 PM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local Script = ns.Script
9 | local L = ns.L
10 |
11 | local AllInOne = Addon:NewPlugin('AllInOne')
12 |
13 | function AllInOne:OnInitialize(args)
14 | self:EnableWithAddon('Blizzard_PetBattleUI')
15 | self:SetPluginTitle(L.PLUGINALLINONE_TITLE)
16 | self:SetPluginNotes(L.PLUGINALLINONE_NOTES)
17 | self:SetPluginIcon([[Interface\ICONS\ABILITY_SEAL]])
18 | end
19 |
20 | function AllInOne:GetCurrentKey()
21 | return '-'
22 | end
23 |
24 | function AllInOne:IterateKeys()
25 | return pairs({['-'] = true})
26 | end
27 |
28 | function AllInOne:GetTitleByKey(key)
29 | return L.PLUGINALLINONE_TITLE
30 | end
31 |
32 | function AllInOne:OnTooltipFormatting(tip, key)
33 | end
34 |
--------------------------------------------------------------------------------
/Plugins/Base.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Base.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local Script = ns.Script
10 | local L = ns.L
11 |
12 | local Base = Addon:NewPlugin('Base')
13 |
14 | function Base:OnInitialize()
15 | self:EnableWithAddon('Blizzard_PetBattleUI')
16 | self:SetPluginTitle(L.PLUGINBASE_TITLE)
17 | self:SetPluginNotes(L.PLUGINBASE_NOTES)
18 | self:SetPluginIcon([[Interface\ICONS\Ability_Garrison_OrangeBird]])
19 | end
20 |
21 | function Base:OnEnable()
22 | end
23 |
24 | function Base:OnDisable()
25 | end
26 |
27 | function Base:GetCurrentKey()
28 | return self:GetOwnerKey(Enum.BattlePetOwner.Ally) .. ':' .. self:GetOwnerKey(Enum.BattlePetOwner.Enemy)
29 | end
30 |
31 | function Base:GetOwnerKey(owner)
32 | local sb = {}
33 | for i = 1, C_PetBattles.GetNumPets(owner) do
34 | local id = C_PetBattles.GetPetSpeciesID(owner, i)
35 | if id then
36 | tinsert(sb, id)
37 | end
38 | end
39 | return table.concat(sb, ';')
40 | end
41 |
42 | local function SplitTeams(key)
43 | local allys, enemys = key:match('^(.+):(.+)$')
44 |
45 | allys = { strsplit(';', allys ) }
46 | enemys = { strsplit(';', enemys) }
47 |
48 | return allys, enemys
49 | end
50 |
51 | function Base:GetPetTip(id, iconAtRight)
52 | if not id then
53 | return ' '
54 | end
55 | local name, icon, petType = C_PetJournal.GetPetInfoBySpeciesID(id)
56 | if not name then
57 | return ' '
58 | end
59 | return iconAtRight and format('%s |T%s:20|t', name, icon) or format('|T%s:20|t %s', icon, name)
60 | end
61 |
62 | function Base:OnTooltipFormatting(tip, key)
63 | local allys, enemys = SplitTeams(key)
64 |
65 | tip:AddDoubleLine(L.PLUGINBASE_TEAM_ALLY, L.PLUGINBASE_TEAM_ENEMY, GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b)
66 |
67 | for i = 1, max(#allys, #enemys) do
68 | tip:AddDoubleLine(
69 | self:GetPetTip(tonumber(allys[i])),
70 | self:GetPetTip(tonumber(enemys[i]), true),
71 | 1, 1, 1, 1, 1, 1
72 | )
73 | end
74 | end
75 |
--------------------------------------------------------------------------------
/Plugins/FirstEnemy.lua:
--------------------------------------------------------------------------------
1 | -- FirstEnemy.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 10/30/2018, 10:14:46 AM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local Script = ns.Script
9 | local L = ns.L
10 |
11 | local FirstEnemy = Addon:NewPlugin('FirstEnemy')
12 |
13 | function FirstEnemy:OnInitialize()
14 | self:EnableWithAddon('Blizzard_PetBattleUI')
15 | self:SetPluginTitle(L.PLUGINFIRSTENEMY_TITLE)
16 | self:SetPluginNotes(L.PLUGINFIRSTENEMY_NOTES)
17 | self:SetPluginIcon([[Interface\ICONS\Ability_Hisek_Aim]])
18 | end
19 |
20 | function FirstEnemy:GetCurrentKey()
21 | return C_PetBattles.GetPetSpeciesID(Enum.BattlePetOwner.Enemy, 1)
22 | end
23 |
24 | function FirstEnemy:GetTitleByKey(key)
25 | return C_PetJournal.GetPetInfoBySpeciesID(key)
26 | end
27 |
28 | function FirstEnemy:OnTooltipFormatting(tip, key)
29 | local name, icon, petType = C_PetJournal.GetPetInfoBySpeciesID(key)
30 | if name then
31 | tip:AddLine(format('|T%s:20|t %s', icon, name))
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/Plugins/Plugins.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tdBattlePetScript
2 |
3 | This addon makes battle pet combat support scripting.
4 |
5 | ⚠️ **This addon is unmaintained since Shadowlands. Please use the updated addon here:**
6 |
7 | - [Curse](https://www.curseforge.com/wow/addons/pet-battle-scripts)
8 | - [Wago](https://addons.wago.io/addons/pbs)
9 | - [WoW Interface](https://www.wowinterface.com/downloads/info26435-PetBattleScripts.html)
10 | - [GitHub](https://github.com/axc450/pbs/releases)
11 |
12 | ## Screenshot
13 |
14 | 
15 |
16 | ## Script tutorial (Chinese only)
17 |
18 | [Introduction](https://github.com/DengSir/tdBattlePetScript/wiki/Write-script "Introduction")
19 |
20 | [Introduction English](https://github.com/DengSir/tdBattlePetScript/wiki/Write-script-English "Introduction English")
21 |
22 |
23 | [API](https://github.com/DengSir/tdBattlePetScript/wiki/API "API")
24 |
25 | [Script selector development documentation](https://github.com/DengSir/tdBattlePetScript/wiki/Script-selector "Script selector development documentation")
26 |
27 | ## Script
28 |
29 | Example:
30 |
31 | 
32 |
33 | ## Script selector
34 |
35 | ### Script selector: Base
36 |
37 | This script selector bind the script to both teams of the current pet battle.
38 |
39 | ### Script selector: Rematch
40 |
41 | This script selector ind the script to the Rematch team, please download [tdBattlePetScript Rematch](https://wow.curseforge.com/projects/tdbattlepetscript-rematch "tdBattlePetScript Rematch").
42 |
43 |
44 | ## TODOS
45 |
46 | * Translate script
47 | * Share script to friend
48 |
49 |
50 | ## Support development
51 |
52 | [**Paypal Me**](https://www.paypal.me/dengsir "Paypal Me")
53 |
54 | 
55 | 
56 |
--------------------------------------------------------------------------------
/Share/Share.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Share/Version0.lua:
--------------------------------------------------------------------------------
1 | -- ShareVersion0.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/21/2018, 12:10:03 PM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local Director = ns.Director
9 | local VERSION = 0
10 | local Share = Addon:NewShareHandler(VERSION)
11 |
12 | function Share:Import(code)
13 | if not code then
14 | return
15 | end
16 |
17 | if code:trim() == '' then
18 | return
19 | end
20 |
21 | if not Director:BuildScript(code) then
22 | return
23 | end
24 | return true, {db = {code = code}, warning = ns.L.IMPORT_SCRIPT_WARNING}
25 | end
26 |
27 | function Share:Is()
28 | return true
29 | end
30 |
--------------------------------------------------------------------------------
/Share/Version1.lua:
--------------------------------------------------------------------------------
1 | -- ShareVersion1.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/21/2018, 9:59:09 AM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local AceSerializer = LibStub('AceSerializer-3.0')
9 | local Base64 = LibStub('LibBase64-1.0')
10 | local CRC32 = LibStub('LibCRC32-1.0')
11 | local VERSION = 1
12 | local Share = Addon:NewShareHandler(VERSION)
13 |
14 | local template = [[
15 | # tdBattlePetScript Share String
16 | # Url: https://www.curseforge.com/wow/addons/tdbattlepetscript
17 | # Version: %s
18 | # Name: %s
19 | # (Script) : #
20 | %s
21 | ]]
22 |
23 | function Share:RawExport(script)
24 | local code = AceSerializer:Serialize({
25 | db = script:GetDB(),
26 | plugin = script:GetPlugin():GetPluginName(),
27 | key = script:GetKey(),
28 | extra = script:GetPlugin():OnExport(script:GetKey()),
29 | })
30 | return CRC32:enc(code) .. code
31 | end
32 |
33 | function Share:Export(script)
34 | return template:format(
35 | VERSION,
36 | script:GetName(),
37 | Base64.Encode(self:RawExport(script)):gsub('(..?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?)', function(x)
38 | return '# ' .. x .. '\n'
39 | end)
40 | )
41 | end
42 |
43 | function Share:Import(code)
44 | local code = code:match('%(Script%) : (.+)')
45 | if not code then
46 | return false, 'Decode failed'
47 | end
48 |
49 | code = code:gsub('[# ]', '')
50 | local ok, data = pcall(Base64.Decode, code)
51 | if not ok then
52 | return false, 'Decode failed'
53 | end
54 |
55 | local crc, data = data:match('^(%d+)(^.+)$')
56 | if not crc or not data then
57 | return false, 'Decode failed'
58 | end
59 | if CRC32:enc(data) ~= tonumber(crc) then
60 | return false, 'CRC32 error'
61 | end
62 |
63 | local ok, data = AceSerializer:Deserialize(data)
64 | if not ok or type(data) ~= 'table' then
65 | return false, 'Deserialize failed'
66 | end
67 |
68 | if not data.db or not data.db.code then
69 | return false, 'Data error'
70 | end
71 | return true, data
72 | end
73 |
74 | function Share:Is(code)
75 | if not code:find('(Script)', nil, true) then
76 | return
77 | end
78 | local version = code:match('# Version: (%d+)')
79 | return not version or tonumber(version) == VERSION
80 | end
81 |
--------------------------------------------------------------------------------
/Share/Version2.lua:
--------------------------------------------------------------------------------
1 | -- Version2.lua
2 | -- @Author : DengSir (tdaddon@163.com)
3 | -- @Link : https://dengsir.github.io
4 | -- @Date : 9/21/2018, 12:43:33 PM
5 |
6 | local ns = select(2, ...)
7 | local Addon = ns.Addon
8 | local AceSerializer = LibStub('AceSerializer-3.0')
9 | local Base64 = LibStub('LibBase64-1.0')
10 | local VERSION = 2
11 | local Share = Addon:NewShareHandler(VERSION)
12 |
13 | local template = [[
14 | # tdBattlePetScript Share String
15 | # Url: https://www.curseforge.com/wow/addons/tdbattlepetscript
16 | # Version: %s
17 | # Name: %s
18 | # Data: %s
19 | # Code Start
20 | %s
21 | # Code End
22 | ]]
23 |
24 | function Share:Is(code)
25 | local version = code:match('# Version: (%d+)')
26 | return tonumber(version) == VERSION
27 | end
28 |
29 | function Share:Export(script)
30 | local data = Base64.Encode(AceSerializer:Serialize{
31 | plugin = script:GetPlugin():GetPluginName(),
32 | key = script:GetKey(),
33 | extra = script:GetPlugin():OnExport(script:GetKey())
34 | })
35 |
36 | return template:format(
37 | VERSION,
38 | script:GetName(),
39 | data,
40 | script:GetCode()
41 | )
42 | end
43 |
44 | function Share:DecodeData(data)
45 | local ok, data = pcall(Base64.Decode, data)
46 | if not ok then
47 | return
48 | end
49 |
50 | ok, data = AceSerializer:Deserialize(data)
51 | if not ok then
52 | return
53 | end
54 | return data
55 | end
56 |
57 | function Share:Import(code)
58 | local name = code:match('# Name: (%S+)')
59 | local data = code:match('# Data: (%S+)')
60 | local code = code:match('# Code Start(.+)# Code End')
61 |
62 | if not code then
63 | return false, 'Not found code'
64 | end
65 |
66 | code = code:trim()
67 | if code == '' then
68 | return false, 'Not found code'
69 | end
70 |
71 | if data then
72 | data = self:DecodeData(data)
73 | end
74 | if not data then
75 | data = {}
76 | end
77 |
78 | data.db = {
79 | code = code,
80 | name = name,
81 | }
82 | return true, data
83 | end
84 |
--------------------------------------------------------------------------------
/UI/Minimap.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Minimap.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local UI = ns.UI
10 | local L = ns.L
11 | local GUI = LibStub('tdGUI-1.0')
12 | local LibDBIcon = LibStub('LibDBIcon-1.0')
13 |
14 | local Minimap = Addon:NewModule('UI.Minimap', 'AceEvent-3.0')
15 |
16 | function Minimap:OnInitialize()
17 | if Addon:GetSetting('hideMinimap') then
18 | return
19 | end
20 |
21 | local LDB = LibStub('LibDataBroker-1.1')
22 |
23 | local function HideTooltip()
24 | GameTooltip:Hide()
25 |
26 | if LibDBIcon.tooltip then
27 | LibDBIcon.tooltip:Hide()
28 | end
29 | end
30 |
31 | local BrokerObject = LDB:NewDataObject('tdBattlePetScript', {
32 | type = 'launcher',
33 | icon = ns.ICON,
34 | OnClick = function(button, click)
35 | HideTooltip()
36 |
37 | if click == 'RightButton' then
38 | GUI:ToggleMenu(button, {
39 | {
40 | text = 'tdBattlePetScript',
41 | isTitle = true,
42 | },
43 | {
44 | text = L.TOGGLE_SCRIPT_MANAGER,
45 | func = function()
46 | UI.MainPanel:TogglePanel()
47 | end
48 | },
49 | {
50 | text = L.Import,
51 | func = function()
52 | UI.Import.Frame:Show()
53 | UI.MainPanel:HidePanel()
54 | end
55 | },
56 | {
57 | text = L.Options,
58 | func = function()
59 | Addon:OpenOptionFrame()
60 | end
61 | }
62 | })
63 | else
64 | UI.MainPanel:TogglePanel()
65 | end
66 | end,
67 | OnTooltipShow = function(tooltip)
68 | tooltip:SetText('tdBattlePetScript')
69 | tooltip:AddLine(L.ADDON_NAME, GREEN_FONT_COLOR:GetRGB())
70 | tooltip:AddLine(' ')
71 | tooltip:AddLine(UI.LEFT_MOUSE_BUTTON .. L.TOGGLE_SCRIPT_MANAGER, 1, 1, 1)
72 | tooltip:AddLine(UI.RIGHT_MOUSE_BUTTON .. L.Options, 1, 1, 1)
73 | end,
74 | OnLeave = HideTooltip
75 | })
76 |
77 | LibDBIcon:Register('tdBattlePetScript', BrokerObject, Addon.db.profile.minimap)
78 |
79 | self:RegisterMessage('PET_BATTLE_SCRIPT_SETTING_CHANGED_hideMinimap', 'Refresh')
80 | end
81 |
82 | function Minimap:Refresh()
83 | Addon.db.profile.minimap.hide = Addon:GetSetting('hideMinimap') or nil
84 | LibDBIcon:Refresh('tdBattlePetScript')
85 | end
86 |
--------------------------------------------------------------------------------
/UI/UI.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | UI.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local UI = ns.UI
9 |
10 | UI.LEFT_MOUSE_BUTTON = [[|TInterface\TutorialFrame\UI-Tutorial-Frame:12:12:0:0:512:512:10:65:228:283|t ]]
11 | UI.RIGHT_MOUSE_BUTTON = [[|TInterface\TutorialFrame\UI-Tutorial-Frame:12:12:0:0:512:512:10:65:330:385|t ]]
12 |
13 | function UI.OpenScriptTooltip(script, owner, anchor)
14 | return UI.OpenPluginTooltip(script:GetPlugin(), script:GetKey(), owner, anchor)
15 | end
16 |
17 | function UI.OpenPluginTooltip(plugin, key, owner, anchor)
18 | local title = plugin:GetPluginTitle()
19 | local notes = plugin:GetPluginNotes()
20 | local tipFormatting = plugin.OnTooltipFormatting
21 |
22 | GameTooltip:SetOwner(owner, anchor or 'ANCHOR_TOPRIGHT')
23 | GameTooltip:SetText(title)
24 |
25 | if notes then
26 | GameTooltip:AddLine(notes, GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b, true)
27 | end
28 |
29 | if type(tipFormatting) == 'function' then
30 | GameTooltip:AddLine(' ')
31 | tipFormatting(plugin, GameTooltip, key)
32 | end
33 | GameTooltip:Show()
34 | return GameTooltip
35 | end
36 |
--------------------------------------------------------------------------------
/UI/UI.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/UI/Widgets/AutoCompleteBox.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | AutoCompleteBox.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 |
8 | local ns = select(2, ...)
9 | local Addon = ns.Addon
10 | local GUI = LibStub('tdGUI-1.0')
11 | local AutoCompleteBox = Addon:NewClass('AutoCompleteBox', GUI:GetClass('AutoSizeGridView'))
12 |
13 | function AutoCompleteBox:Constructor()
14 | self:Hide()
15 | self:SetSize(100, 100)
16 | self:SetItemHeight(20)
17 | self:SetItemClass(Addon:GetClass('AutoCompleteItem'))
18 | self:SetSelectMode('RADIO')
19 | self:SetClampedToScreen(true)
20 | self:SetFrameStrata('FULLSCREEN_DIALOG')
21 | self:EnableMouse(true)
22 |
23 | self:SetPadding(13)
24 | self:SetItemSpacing(5)
25 | self:SetBackdrop{
26 | bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
27 | edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]],
28 | edgeSize = 16, tileSize = 16, tile = true,
29 | insets = {left = 4, right = 4, top = 4, bottom = 4},
30 | }
31 | self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
32 | self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
33 |
34 | self:SetCallback('OnItemFormatting', self.OnItemFormatting)
35 | self:SetCallback('OnItemClick', self.OnItemClick)
36 | self:SetCallback('OnSelectChanged', self.OnSelectChanged)
37 | self:SetScript('OnKeyDown', self.OnKeyDown)
38 | self:SetScript('OnHide', self.OnHide)
39 | end
40 |
41 | function AutoCompleteBox:Open(object, list, column)
42 | self:SetOwner(object)
43 | self:SetPoint('CENTER')
44 | self:SetColumnCount(column)
45 | self:SetItemList(list)
46 | self:SetSelected(1)
47 | if not list[1].value then
48 | self:SetSelected(self:Move(1))
49 | end
50 | self:Refresh()
51 | self:Show()
52 | end
53 |
54 | function AutoCompleteBox:Input(item)
55 | self:GetOwner():Insert(item.value)
56 | self:Hide()
57 |
58 | if item.callback then
59 | item.callback(item)
60 | end
61 | end
62 |
63 | function AutoCompleteBox:OnItemFormatting(button, item)
64 | button:SetItem(item)
65 | button.CheckedTexture:SetShown(self:IsSelected(button:GetID()))
66 | end
67 |
68 | function AutoCompleteBox:OnItemClick(button, item)
69 | return self:Input(item)
70 | end
71 |
72 | function AutoCompleteBox:OnHide()
73 | self:GetOwner():SetFocus()
74 | end
75 |
76 | function AutoCompleteBox:OnKeyDown(key)
77 | self:SetPropagateKeyboardInput(false)
78 | if key == 'UP' then
79 | self:OnArrowPresssed(-1*self:GetColumnCount())
80 | elseif key == 'DOWN' then
81 | self:OnArrowPresssed(1*self:GetColumnCount())
82 | elseif key == 'LEFT' then
83 | self:OnArrowPresssed(-1)
84 | elseif key == 'RIGHT' then
85 | self:OnArrowPresssed(1)
86 | elseif key == 'ENTER' or key == 'TAB' then
87 | self:OnEnterPressed()
88 | elseif key == 'ESCAPE' then
89 | self:Hide()
90 | else
91 | self:SetPropagateKeyboardInput(true)
92 | self:Hide()
93 | end
94 | end
95 |
96 | function AutoCompleteBox:OnArrowPresssed(delta)
97 | self:SetSelected(self:Move(delta))
98 | end
99 |
100 | function AutoCompleteBox:Move(delta)
101 | local index = self:GetSelected()
102 | local max = self:GetItemCount()
103 |
104 | repeat
105 | index = (index + delta - 1) % self:GetItemCount() + 1
106 | until self:GetItem(index).value
107 |
108 | return index
109 | end
110 |
111 | function AutoCompleteBox:OnEnterPressed()
112 | return self:Input(self:GetSelectedItem())
113 | end
114 |
--------------------------------------------------------------------------------
/UI/Widgets/AutoCompleteItem.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | AutoCompleteItem.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local GUI = LibStub('tdGUI-1.0')
10 | local AutoCompleteItem = Addon:NewClass('AutoCompleteItem', GUI:GetClass('ViewItem'))
11 |
12 | function AutoCompleteItem:Constructor()
13 | local Text = self:CreateFontString(nil, 'ARTWORK', 'ChatFontNormal') do
14 | Text:SetJustifyH('LEFT')
15 | Text:SetPoint('LEFT')
16 | Text:SetPoint('RIGHT')
17 | Text:SetWordWrap(false)
18 | end
19 |
20 | local ct = self:CreateTexture(nil, 'BACKGROUND') do
21 | ct:SetAllPoints(true)
22 | ct:SetColorTexture(1, 0.82, 0, 0.2)
23 | end
24 |
25 | local ht = self:CreateTexture(nil, 'HIGHLIGHT') do
26 | ht:SetAllPoints(true)
27 | ht:SetColorTexture(1, 0.82, 0, 0.2)
28 | end
29 |
30 | local Icon = self:CreateTexture(nil, 'BORDER') do
31 | Icon:SetMask([[Interface\Minimap\UI-Minimap-Background]])
32 | Icon:SetSize(24, 24)
33 | Icon:SetPoint('CENTER')
34 | end
35 |
36 | local IconBorder = self:CreateTexture(nil, 'ARTWORK') do
37 | IconBorder:SetTexture([[Interface\PetBattles\PetBattleHUD]])
38 | IconBorder:SetPoint('TOPLEFT', Icon, 'TOPLEFT', 0, 1)
39 | IconBorder:SetPoint('BOTTOMRIGHT', Icon, 'BOTTOMRIGHT', 1, 0)
40 | IconBorder:SetTexCoord(0.884765625, 0.943359375, 0.681640625, 0.798828125)
41 | end
42 |
43 | self.CheckedTexture = ct
44 | self.Text = Text
45 | self.Icon = Icon
46 | self.IconBorder = IconBorder
47 | end
48 |
49 | function AutoCompleteItem:SetItem(item)
50 | if item.icon then
51 | self.Icon:SetTexture(item.icon)
52 | self.Icon:Show()
53 | self.IconBorder:Show()
54 | else
55 | self.Icon:Hide()
56 | self.IconBorder:Hide()
57 | end
58 |
59 | if item.text then
60 | self.Text:SetText(item.text)
61 | self.Text:Show()
62 | else
63 | self.Text:SetText('')
64 | self.Text:Hide()
65 | end
66 |
67 | self:SetEnabled(item.value)
68 | end
69 |
70 | function AutoCompleteItem:GetAutoWidth()
71 | if self.Icon:IsShown() then
72 | return 24
73 | else
74 | return self.Text:GetStringWidth() + 3
75 | end
76 | end
77 |
--------------------------------------------------------------------------------
/UI/Widgets/ScriptEditor.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | ScriptEditor.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local UI = ns.UI
10 | local GUI = LibStub('tdGUI-1.0')
11 |
12 | local ScriptEditor = Addon:NewClass('ScriptEditor', GUI:GetClass('EditBox'))
13 |
14 | function ScriptEditor:Constructor()
15 | self:SetCallback('OnCursorChanged', self.OnCursorChanged)
16 |
17 | self.AutoCompleteBox = Addon:GetClass('AutoCompleteBox'):New(UIParent)
18 | end
19 |
20 | function ScriptEditor:OnCursorChanged(x, y, w, h)
21 | self.cursorX = x + 10
22 | self.cursorY = y - 10 + self.ScrollFrame:GetVerticalScroll()
23 | end
24 |
25 | function ScriptEditor:OnTextChanged(userInput)
26 | if not userInput or self:IsInIMECompositionMode() or not C_PetBattles.IsInBattle() then
27 | return
28 | end
29 | local pos = self:GetCursorPosition()
30 | local line = self:GetText():sub(1, pos):match('([^\r\n]+)$')
31 | if not line then
32 | return
33 | end
34 |
35 | local list, column = ns.Snippets:Check(line)
36 | if not list then
37 | self.AutoCompleteBox:Hide()
38 | else
39 | self.AutoCompleteBox:ClearAllPoints()
40 | self.AutoCompleteBox:SetPoint('TOPLEFT', self, 'TOPLEFT', self.cursorX, self.cursorY)
41 | self.AutoCompleteBox:Open(self, list, column)
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/UI/Widgets/ScriptItem.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | ScriptItem.lua
3 | @Author : DengSir (tdaddon@163.com)
4 | @Link : https://dengsir.github.io
5 | ]]
6 |
7 | local ns = select(2, ...)
8 | local Addon = ns.Addon
9 | local GUI = LibStub('tdGUI-1.0')
10 |
11 | local ScriptItem = Addon:NewClass('ScriptItem', GUI:GetClass('ViewItem'))
12 |
13 | function ScriptItem:Constructor()
14 | local Bg = self:CreateTexture(nil, 'BACKGROUND') do
15 | Bg:SetPoint('TOPLEFT')
16 | Bg:SetPoint('BOTTOMRIGHT')
17 | Bg:SetAtlas('groupfinder-button-cover')
18 | end
19 |
20 | local Icon = self:CreateTexture(nil, 'BORDER') do
21 | Icon:SetMask([[Interface\Minimap\UI-Minimap-Background]])
22 | Icon:SetSize(28, 28)
23 | Icon:SetPoint('LEFT', 5, 0)
24 | end
25 |
26 | local IconBorder = self:CreateTexture(nil, 'ARTWORK') do
27 | IconBorder:SetTexture([[Interface\PetBattles\PetBattleHUD]])
28 | IconBorder:SetPoint('TOPLEFT', Icon, 'TOPLEFT', 0, 1)
29 | IconBorder:SetPoint('BOTTOMRIGHT', Icon, 'BOTTOMRIGHT', 1, 0)
30 | IconBorder:SetTexCoord(0.884765625, 0.943359375, 0.681640625, 0.798828125)
31 | end
32 |
33 | local Highlight = self:CreateTexture(nil, 'HIGHLIGHT') do
34 | Highlight:SetTexture([[Interface\PVPFrame\PvPMegaQueue]])
35 | Highlight:SetTexCoord(0.00195313, 0.63867188, 0.76953125, 0.83007813)
36 | Highlight:SetBlendMode('ADD')
37 | Highlight:SetPoint('TOPLEFT', 20, -3)
38 | Highlight:SetPoint('BOTTOMRIGHT', -20, 2)
39 | end
40 |
41 | local Checked = self:CreateTexture(nil, 'OVERLAY') do
42 | Checked:SetTexture([[Interface\BUTTONS\UI-CheckBox-Check]])
43 | Checked:SetSize(20, 20)
44 | Checked:SetPoint('RIGHT', -5, -2)
45 | Checked:Hide()
46 | end
47 |
48 | local Text = self:CreateFontString(nil, 'ARTWORK') do
49 | Text:SetPoint('LEFT', Icon, 'RIGHT')
50 | Text:SetPoint('RIGHT', -5, 0)
51 | Text:SetWordWrap(false)
52 | self:SetFontString(Text)
53 | self:SetNormalFontObject('GameFontNormal')
54 | self:SetHighlightFontObject('GameFontHighlight')
55 | end
56 |
57 | self.Text = Text
58 | self.Bg = Bg
59 | self.Icon = Icon
60 | self.IconBorder = IconBorder
61 | self.Checked = Checked
62 | self.Highlight = Highlight
63 | end
64 |
65 | function ScriptItem:SetTexture(texture)
66 | self.Icon:SetTexture(texture)
67 | end
68 |
69 | function ScriptItem:ShowIcon()
70 | self.Icon:Show()
71 | self.IconBorder:Show()
72 | end
73 |
74 | function ScriptItem:HideIcon()
75 | self.Icon:Hide()
76 | self.IconBorder:Hide()
77 | end
78 |
79 | function ScriptItem:SetType(type)
80 | if type == 'plugin' then
81 | self.Text:SetPoint('LEFT', self.Icon, 'RIGHT')
82 | else
83 | self.Text:SetPoint('LEFT', 5, 0)
84 | end
85 | end
86 |
87 | function ScriptItem:SetDesaturated(flag)
88 | self.Icon:SetDesaturated(flag)
89 | self.IconBorder:SetDesaturated(flag)
90 | self.Highlight:SetDesaturated(flag)
91 | self.Highlight:SetAlpha(flag and 0.5 or 1)
92 | self:SetNormalFontObject(flag and 'GameFontDisable' or 'GameFontNormal')
93 | end
94 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tdbattlepetscript",
3 | "version": "10.0.0",
4 | "description": "This addon makes battle pet combat support scripting.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo not implemented"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/DengSir/tdBattlePetScript.git"
12 | },
13 | "keywords": [
14 | "Battlepet",
15 | "Script"
16 | ],
17 | "author": "Dencer",
18 | "license": "MIT",
19 | "bugs": {
20 | "url": "https://github.com/DengSir/tdBattlePetScript/issues"
21 | },
22 | "homepage": "https://github.com/DengSir/tdBattlePetScript#readme",
23 | "wow": {
24 | "name": "tdBattlePetScript",
25 | "curse_id": 254463,
26 | "changelog": "CHANGELOG.md",
27 | "localizations": {
28 | "enUS": "Localization/enUS.lua",
29 | "zhCN": "Localization/zhCN.lua"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tdBattlePetScript.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 100000
2 | ## Title: tdBattlePetScript
3 | ## X-Wago-ID: WYK9036L
4 | ## Description: Battle pet combat scripting
5 | ## Author: axc450
6 | ## Version: 10.0.0
7 | ## OptionalDeps: tdGUI, Ace3
8 | ## SavedVariables: TD_DB_BATTLEPETSCRIPT_GLOBAL
9 | ## SavedVariablesPerCharacter: TD_DB_BATTLEPETSCRIPT_BATTLE_CACHE
10 | ## LoadManagers: AddonLoader
11 | ## X-LoadOn-Always: delayed
12 |
13 | Load.xml
14 |
--------------------------------------------------------------------------------