List of commits:
Subject Hash Author Date (UTC)
feat(choir)!: Range indicator 931a0510b562986ec76dc22f329f4af4ed723cdf Vladyslav Bondarenko 2021-10-29 10:40:46
fix(choir)!: Health bar in combat a6622578dd5a1b4e4babf699a4cf1e4eb6bb70d6 Vladyslav Bondarenko 2021-10-28 07:42:57
feat(choir)!: Decorate unit buttons 4dc5ed44a9519b275f4256cfe4281110b7a94c9a Vladyslav Bondarenko 2021-10-25 21:20:56
feat(choir)!: Copy action bar binding 70ce056ffda7f12d913ce9a42b128ea257bdd0dc Vladyslav Bondarenko 2021-10-23 23:34:56
feat!: Initial commit 45c4e781e5ff0a69f8b0bea3a869e2384c7ca454 Vladyslav Bondarenko 2021-10-23 06:03:14
Commit 931a0510b562986ec76dc22f329f4af4ed723cdf - feat(choir)!: Range indicator
When a unit is out of range of a specific spell that depends on the
player class render the unit health bar partially transparent to
indicate the lack of reach.

The range to a unit is tested by specific spell that the player
character is able to cast. The spell that is used is decided every time
the player character changes their spells set. Therefore it works as new
spells are learned or when talent spec is changed.

When no spell is assigned to check range then the whole feature is
disabled. Then the unit health bars always remain opaque. This is for
the offchance that either the range finding spell is invalid or
not prepared for the given character class.
Author: Vladyslav Bondarenko
Author date (UTC): 2021-10-29 10:40
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2021-10-29 10:40
Parent(s): b10a7e8d73a89881688557497db3e8ce1a47ecb6
Signer:
Signing key:
Signing status: N
Tree: 4f25456337604c17e475d757941cbd646505ce8a
File Lines added Lines deleted
.luacheckrc 5 0
choir.lua 101 15
choir.toc 1 0
File .luacheckrc changed (mode: 100644) (index 700131a..fd1ecd1)
... ... stds.wow = {
5 5 'CreateFrame', 'CreateFrame',
6 6 'GetBindingKey', 'GetBindingKey',
7 7 'GetClassColor', 'GetClassColor',
8 'GetLocale',
9 'GetSpellInfo',
8 10 'GetUnitClass', 'GetUnitClass',
11 'IsSpellInRange',
9 12 'NumberFont_OutlineThick_Mono_Small', 'NumberFont_OutlineThick_Mono_Small',
10 13 'RAID_CLASS_COLORS', 'RAID_CLASS_COLORS',
11 14 'SetOverrideBinding', 'SetOverrideBinding',
 
... ... stds.wow = {
18 21 'UnitIsGhost', 'UnitIsGhost',
19 22 'UnitName', 'UnitName',
20 23 'strtrim', 'strtrim',
24 'date',
21 25 } --[[ these globals can only be accessed ]]-- } --[[ these globals can only be accessed ]]--
22 26 } }
23 27
24 28 stds.choir = { stds.choir = {
25 29 globals = { globals = {
26 30 'BINDING_HEADER_CHOIR', 'BINDING_HEADER_CHOIR',
31 'ChoirRangeSpellName',
27 32 }, },
28 33 read_globals = { read_globals = {
29 34 'ChoirSpoiler1', 'ChoirSpoiler1',
File choir.lua changed (mode: 100644) (index 3571a23..a42686c)
1 local function trace(...)
2 print(date('%X'), '[Choir]:', ...)
3 end
4
1 5 local function getDefaultUnitButtonBarColor() local function getDefaultUnitButtonBarColor()
2 6 return 0, 1, 0 return 0, 1, 0
3 7 end end
 
... ... local function updateUnitButtonBarOverlay(bar, unitDesignation)
110 114
111 115 --[[ Apply bar color update ]]-- --[[ Apply bar color update ]]--
112 116 local r, g, b = getDefaultUnitButtonBarColor() local r, g, b = getDefaultUnitButtonBarColor()
113 --[[ TODO Range indicator ]]--
114 local a = 1
117
115 118 local _, classDesignation = UnitClass(unitDesignation) local _, classDesignation = UnitClass(unitDesignation)
116 119 if classDesignation then if classDesignation then
117 120 r, g, b = getClassColor(classDesignation) r, g, b = getClassColor(classDesignation)
118 121 end end
119 122
123 --[[ TODO Add line of sight indicator ]]--
124 local a = 1
125 local rangeSpell = ChoirRangeSpellName
126 --[[ NOTE IsSpellInRange returns either 0, 1 or nil ]]--
127 if rangeSpell and 1 ~= IsSpellInRange(rangeSpell, unitDesignation) then
128 a = 1 / 2
129 end
130
120 131 local overlay = bar.overlay local overlay = bar.overlay
121 132 assert (overlay ~= nil) assert (overlay ~= nil)
122 133 overlay:SetTexture(r, g, b, a) overlay:SetTexture(r, g, b, a)
 
... ... local function createUnitButtonBar(unitButton)
149 160
150 161 bar.unitButton = unitButton bar.unitButton = unitButton
151 162
152 bar:SetScript('OnEvent', function(healthBarFrame, eventCategory, targetUnit)
163 --[[ Update health indicator ]]--
164 bar:SetScript('OnEvent', function(healthBarFrame)
153 165 assert (healthBarFrame ~= nil) assert (healthBarFrame ~= nil)
154 assert ('UNIT_HEALTH' == eventCategory)
155 assert (targetUnit ~= nil)
156 166 assert (unitButton ~= nil) assert (unitButton ~= nil)
157 167
158 168 local u = unitButton:GetAttribute('unit') local u = unitButton:GetAttribute('unit')
159 169 assert (u ~= nil) assert (u ~= nil)
160 if targetUnit == u then
161 updateUnitButtonBarOverlay(healthBarFrame, targetUnit)
162 updateUnitButtonBarText(healthBarFrame, targetUnit)
163 end
170 updateUnitButtonBarOverlay(healthBarFrame, u)
171 updateUnitButtonBarText(healthBarFrame, u)
164 172 end) end)
173 bar:RegisterEvent('PLAYER_FOCUS_CHANGED')
174 bar:RegisterEvent('PLAYER_TARGET_CHANGED')
165 175 bar:RegisterEvent('UNIT_HEALTH') bar:RegisterEvent('UNIT_HEALTH')
176 bar:RegisterEvent('UNIT_SPELLCAST_FAILED')
177 bar:RegisterEvent('UNIT_SPELLCAST_FAILED_QUIET')
178 bar:RegisterEvent('UNIT_SPELLCAST_SENT')
179 bar:RegisterEvent('UNIT_SPELLCAST_START')
166 180
167 181 return bar return bar
168 182 end end
 
... ... local function createGroup(rootFrame, groupNumber, unitTable)
346 360 return spoiler return spoiler
347 361 end end
348 362
349 local function init(rootFrame)
350 assert (rootFrame ~= nil)
363 local function getRangeSpellNameSuggestion()
364 local _, classDesignation = UnitClass('player')
365 assert (classDesignation ~= nil)
366 assert ('string' == type(classDesignation))
367 classDesignation = strtrim(classDesignation)
368 assert (string.len(classDesignation) >= 2)
369 assert (string.len(classDesignation) <= 64)
351 370
352 rootFrame:UnregisterAllEvents()
371 local map = {
372 ['DRUID'] = {'Cure Poison', 'Healing Touch'},
373 ['PALADIN'] = {'Cleanse', 'Purify', 'Holy Light'},
374 ['PRIEST'] = {'Dispel Magic', 'Cure Disease', 'Lesser Heal'},
375 ['SHAMAN'] = {'Healing Wave'},
376 }
353 377
354 rootFrame:SetSize(1024, 768)
355 rootFrame:SetPoint('CENTER', 0, 0)
378 local t = map[classDesignation]
379 if not t then
380 return
381 end
382 assert (t ~= nil)
383 assert ('table' == type(t))
384 assert (#t >= 1)
385
386 local s = nil
387 local i = 0
388 while (i < #t) do
389 i = i + 1
390 local candidate = t[i]
391 assert (candidate ~= nil)
392 local spellName = GetSpellInfo(candidate)
393 if spellName then
394 s = spellName
395 break
396 end
397 end
398
399 return s
400 end
401
402 local function initRangeSpellName(rootFrame)
403 local f = CreateFrame('FRAME', rootFrame:GetName() .. 'RangeSpellFrame')
404 f:SetScript('OnEvent', function()
405 ChoirRangeSpellName = getRangeSpellNameSuggestion()
406 end)
407 f:RegisterEvent('SPELLS_CHANGED')
408
409 local s = ChoirRangeSpellName
410 if s then
411 assert (s ~= nil)
412 assert ('string' == type(s))
413 s = strtrim(s)
414 assert (string.len(s) >= 2)
415 assert (string.len(s) <= 256)
416 else
417 s = getRangeSpellNameSuggestion()
418 end
419
420 ChoirRangeSpellName = s
421
422 return s
423 end
424
425 local function initSpoiler(rootFrame)
426 assert (rootFrame ~= nil)
356 427
357 428 createGroup(rootFrame, 1) createGroup(rootFrame, 1)
358 429 createGroup(rootFrame, 2) createGroup(rootFrame, 2)
 
... ... local function init(rootFrame)
375 446 _G['BINDING_NAME_CLICK ' .. spoilerParty:GetName() .. ':LeftButton'] = 'Player party' _G['BINDING_NAME_CLICK ' .. spoilerParty:GetName() .. ':LeftButton'] = 'Player party'
376 447
377 448 BINDING_HEADER_CHOIR = 'Choir' BINDING_HEADER_CHOIR = 'Choir'
449 end
450
451 local function init(rootFrame)
452 assert (rootFrame ~= nil)
453
454 local locale = GetLocale()
455 assert (locale == 'enGB' or locale == 'enUS', 'requires English localization')
456
457 rootFrame:UnregisterAllEvents()
458
459 rootFrame:SetSize(1024, 768)
460 rootFrame:SetPoint('CENTER', 0, 0)
461
462 initRangeSpellName(rootFrame)
463 initSpoiler(rootFrame)
378 464
379 print('[Choir]: init')
465 trace('init')
380 466 end end
381 467
382 468 local function main() local function main()
File choir.toc changed (mode: 100644) (index db7ba66..5719708)
2 2 ##Notes: Raid targeting aid for healers ##Notes: Raid targeting aid for healers
3 3 ##Title: Choir ##Title: Choir
4 4 ##Version: 0 ##Version: 0
5 ##SavedVariablesPerCharacter: ChoirRangeSpellName
5 6 bindings.xml bindings.xml
6 7 choir.lua choir.lua
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/vrtc/choir

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/vrtc/choir

Clone this repository using git:
git clone git://git.rocketgit.com/user/vrtc/choir

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main