vrtc / chorus (public) (License: CC0) (since 2023-08-12) (hash sha1)
World of Warcraft add-on stub. The overall goal is to create a specialized raid frame.
List of commits:
Subject Hash Author Date (UTC)
feat: simplify group frame selection 54fc78a2911abdefcf46e024cfdb6b5ec6be4a06 Vladyslav Bondarenko 2025-03-06 00:52:30
feat!: add secure raid frame toggle d130e6aeaa257ba6780c0921603967637dbf6f3f Vladyslav Bondarenko 2025-03-04 01:05:13
fix!: setup first configuraiton correctly 3ec860fe8d74ccff36c2eac206de0db98e210885 Vladyslav Bondarenko 2025-03-04 00:56:54
fix: show background correctly for all raid frames 1062919d1fc2420e4030ab6d04d26f845c49c71f Vladyslav Bondarenko 2025-03-03 21:43:59
doc: add link to release page 71cbeae09f116f2ee45fc4a7b5633c5e11a8b977 Vladyslav Bondarenko 2025-03-03 12:38:28
fix: unit class power status bar 22531fe524a0864eee9a2eb81a52e538810acdef Vladyslav Bondarenko 2025-03-02 09:50:43
feat: add instruction to build from any directory 31d7bcc6785190187fef4847586a75a60b8e678a Vladyslav Bondarenko 2025-03-01 23:32:55
feat: update build instructions bed1c76a425768336b76e98bb6ca709d2574021e Vladyslav Bondarenko 2025-03-01 23:09:16
feat!: add working druid power frame a874279e4ac6c92d88650493cdf9bb0c9be37bc8 Vladyslav Bondarenko 2025-03-01 20:54:20
feat!: add mechanism for class specific power bars 7d514689e77c6cc7eaa889d3dda8db2ddd419e0d Vladyslav Bondarenko 2025-03-01 19:08:45
feat: add different unit power type templates for 86979977d4d9946bf6bff3d595640c91ecf7289b Vladyslav Bondarenko 2025-03-01 16:34:23
fix: use builtin status bar color method 0265bfe7c193fc7588146f47529025408873cb4d Vladyslav Bondarenko 2025-03-01 16:33:48
fix: change power bar color correctly d2b3ff5918366228cfc8747074c15d8c6ecc7a96 Vladyslav Bondarenko 2025-03-01 14:38:05
feat: add custom combo points frame d374739a80a7bec053385f01c9be06517a506af6 Vladyslav Bondarenko 2025-03-01 14:25:47
fix: satisfy static analysis cf209fb2c502ef491bec62f331eb2e63d95dd28b Vladyslav Bondarenko 2025-02-26 21:11:19
fix!: tiny health status bar shrinks correctly f1e6ab44663a62b17995eec3feb43709863dd92f Vladyslav Bondarenko 2025-02-26 19:52:43
feat!: replace deprecated unit status bars dd8056c5ba236667f8dd340f8e74e837757bed80 Vladyslav Bondarenko 2025-02-26 19:26:47
feat!: add new unit health display 6b2b9d93bdda1f5f8284b37d2bbe21e35387eedd Vladyslav Bondarenko 2025-02-26 15:17:19
feat: add tiny auras to small unit frame 835541052fb5452ef35573faf39a5faacc243be3 Vladyslav Bondarenko 2025-02-14 18:32:36
feat: add chorus slash command 11427128e833d0f7acaaf720d5fe13746ea95e72 Vladyslav Bondarenko 2025-02-12 20:45:56
Commit 54fc78a2911abdefcf46e024cfdb6b5ec6be4a06 - feat: simplify group frame selection
When player changes group, toggle appropriate raid frames. Remove the
algorithm that selected frames based on group size.

Previous mechanism for selecting the group frame to toggle was buggy.
The new mechanism is much simplier and more reliable.

Currently only small raid frame profile will ever be shown.

The idea is to allow the user to select explicitly from either large,
small or tiny raid frames.

The next step in implementing this feature will probably be changing the
configuration frame and group frame toggle buttons. This will also
require changes to options persisted in `ChorusConf` table.
Author: Vladyslav Bondarenko
Author date (UTC): 2025-03-06 00:52
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2025-03-06 00:52
Parent(s): d130e6aeaa257ba6780c0921603967637dbf6f3f
Signer:
Signing key: EFF9624877D25D02
Signing status: E
Tree: f272b6b591a7420c99968ab1aa3bcf0ab080ac03
File Lines added Lines deleted
src/ChorusGroupFrame.lua 47 179
src/ChorusGroupFrame.xml 1 1
File src/ChorusGroupFrame.lua changed (mode: 100644) (index 848646b..34e21c8)
2 2 @submodule chorus @submodule chorus
3 3 ]] ]]
4 4
5 local GetNumPartyMembers = Chorus.test.GetNumPartyMembers or GetNumPartyMembers
6 local GetNumRaidMembers = Chorus.test.GetNumRaidMembers or GetNumRaidMembers
7 local InCombatLockdown = Chorus.test.InCombatLockdown or InCombatLockdown
8
9 local MAX_RAID_MEMBERS = MAX_RAID_MEMBERS or 40
10
11 5 local Chorus = Chorus local Chorus = Chorus
12 6 local ChorusLargeRaidFrame = ChorusLargeRaidFrame local ChorusLargeRaidFrame = ChorusLargeRaidFrame
13 7 local ChorusPartyFrame = ChorusPartyFrame local ChorusPartyFrame = ChorusPartyFrame
14 8 local ChorusSmallRaidFrame = ChorusSmallRaidFrame local ChorusSmallRaidFrame = ChorusSmallRaidFrame
15 9 local ChorusTinyRaidFrame = ChorusTinyRaidFrame local ChorusTinyRaidFrame = ChorusTinyRaidFrame
16 10
17 Chorus.groupProfileSet = {
18 ChorusPartyFrame,
19 ChorusLargeRaidFrame,
20 ChorusSmallRaidFrame,
21 ChorusTinyRaidFrame
22 }
23
24 local function produceSecureCommand()
25 local t = {
26 {'arena', 5, ChorusPartyFrame},
27 {'party', 4, ChorusPartyFrame},
28 {'raid', 5, ChorusLargeRaidFrame},
29 {'raid', 25, ChorusSmallRaidFrame},
30 {'raid', 40, ChorusTinyRaidFrame},
31 }
32
33 local secureCmd = ''
34 local i = 0
35 while (i < #t) do
36 i = i + 1
37
38 local r = t[i]
39
40 assert(r ~= nil)
41 assert('table' == type(r))
42 assert(3 == #r)
43
44 local j = 0
45
46 local u = r[1]
47 assert(u ~= nil)
48 assert('string' == type(u))
49 --[[ select(2, GetInstanceInfo()) == u ]]--
50 assert('arena' == u or 'party' == u or 'raid' == u)
51
52 local n = r[2]
53 assert(n ~= nil)
54 assert('number' == type(n))
55 n = math.abs(math.ceil(n))
56 assert(n >= 1)
57 assert(n <= MAX_RAID_MEMBERS)
58
59 local statement = ''
60 while (j < n) do
61 j = j + 1
62 local predicate = string.format("[@%s%d,exists]", u, j)
63 statement = statement .. predicate
64 end
65
66 local f = r[3]
67 assert(f ~= nil)
68 assert('table' == type(f) and 'userdata' == type(f[0]))
69
70 local m = f:GetName()
71 assert(m ~= nil)
72 assert('string' == type(m))
73 m = strtrim(m)
74 assert(string.len(m) >= 1)
75
76 statement = string.format("%s %s;\n", statement, m)
77
78 secureCmd = secureCmd .. statement
79 end
80
81 return secureCmd
82 end
83
84
85 --[[--
86 Toggle the visibility raid group profile frame.
87
88 Evaluate a list of all possible raid frame profiles. Consider current player's
89 raid size and current zone. Then, show the most appropriate profile and hide
90 all others.
91
92 Each raid frame profile exists in memory from initialization.
93
94 This may only be run effectively in unrestricted execution environment, that is
95 out of combat.
96
97 The group frame secure handler implements the same feature. However, it uses
98 state drivers and secure frames, that may be executed in restricted environment
99 and during combat.
100
101 @function groupFrameToggleInsecure
102 @return nothing
103 ]]
104 function Chorus.groupFrameToggleInsecure()
105 --[[ @fixme ]]--
106 if InCombatLockdown() then
107 return
108 end
109
110 local n = GetNumRaidMembers() or 0
111
112 if n > 25 then
113 ChorusLargeRaidFrame:Hide()
114 ChorusPartyFrame:Hide()
115 ChorusSmallRaidFrame:Hide()
116 ChorusTinyRaidFrame:Show()
117 elseif n > 5 then
118 ChorusLargeRaidFrame:Hide()
119 ChorusPartyFrame:Hide()
120 ChorusSmallRaidFrame:Show()
121 ChorusTinyRaidFrame:Hide()
122 elseif n >= 1 then
123 ChorusLargeRaidFrame:Show()
124 ChorusPartyFrame:Hide()
125 ChorusSmallRaidFrame:Hide()
126 ChorusTinyRaidFrame:Hide()
127 elseif UnitPlayerOrPetInParty('party1') or (GetNumPartyMembers() or 0) > 0 then
128 ChorusLargeRaidFrame:Hide()
129 ChorusPartyFrame:Show()
130 ChorusSmallRaidFrame:Hide()
131 ChorusTinyRaidFrame:Hide()
132 elseif n <= 0 then
133 ChorusLargeRaidFrame:Hide()
134 ChorusPartyFrame:Hide()
135 ChorusSmallRaidFrame:Hide()
136 ChorusTinyRaidFrame:Hide()
137 end
138 end
139
140 11 --[[-- --[[--
141 12 `ChorusGroupFrame` toggles party, raid or solo frames where appropriate `ChorusGroupFrame` toggles party, raid or solo frames where appropriate
142 13 automatically. automatically.
 
... ... demand, instead of the usual event processors, that are then handled by
152 23 ]] ]]
153 24 function Chorus.groupFrameMain(self) function Chorus.groupFrameMain(self)
154 25 assert(self ~= nil) assert(self ~= nil)
26 assert(self:IsProtected())
155 27
156 28 local secureHandler = ChorusGroupSecureHandler local secureHandler = ChorusGroupSecureHandler
157 29 assert(secureHandler ~= nil) assert(secureHandler ~= nil)
158 30
159 assert(ChorusLargeRaidFrame ~= nil)
160 assert(ChorusPartyFrame ~= nil)
161 assert(ChorusSmallRaidFrame ~= nil)
162 assert(ChorusTinyRaidFrame ~= nil)
31 local t = {
32 ChorusLargeRaidFrame,
33 ChorusPartyFrame,
34 ChorusSmallRaidFrame,
35 ChorusTinyRaidFrame,
36 }
37
38 local i = 0
39 while(i < #t) do
40 i = i + 1
41 local f = t[i]
42 assert(f ~= nil)
43 assert(f:IsProtected())
44 assert(f:GetName() ~= nil)
45 secureHandler:SetFrameRef(f:GetName(), f)
46 end
163 47
164 48 --[[ NOTE: There is a naming convention quirk. The words "Tiny", --[[ NOTE: There is a naming convention quirk. The words "Tiny",
165 49 "Small", "Large" and "Huge" in raid frame designations, refer to the "Small", "Large" and "Huge" in raid frame designations, refer to the
 
... ... function Chorus.groupFrameMain(self)
167 51 intended for raids with __fewer__ members and more details reported per intended for raids with __fewer__ members and more details reported per
168 52 unit. ]]-- unit. ]]--
169 53
170 secureHandler:SetFrameRef('ChorusPartyFrame', ChorusPartyFrame)
171 secureHandler:SetFrameRef('ChorusTinyRaidFrame', ChorusTinyRaidFrame)
172 secureHandler:SetFrameRef('ChorusSmallRaidFrame', ChorusSmallRaidFrame)
173 secureHandler:SetFrameRef('ChorusLargeRaidFrame', ChorusLargeRaidFrame)
174
175 54 --[[ When any of the mentioned units exist, set `group` attribute of --[[ When any of the mentioned units exist, set `group` attribute of
176 55 the `secureHandler` protected frame to the name of a raid frame that is the `secureHandler` protected frame to the name of a raid frame that is
177 56 responsible for reporting that unit to the user. ]]-- responsible for reporting that unit to the user. ]]--
 
... ... function Chorus.groupFrameMain(self)
179 58 --[[ NOTE: The order of switch cases in the macro is significant. The --[[ NOTE: The order of switch cases in the macro is significant. The
180 59 first match takes precedence. ]]-- first match takes precedence. ]]--
181 60
182 local secureCmd = produceSecureCommand()
183 RegisterStateDriver(secureHandler, 'group', secureCmd)
61 --local secureCmd = produceSecureCommand()
62 --RegisterStateDriver(secureHandler, 'group', secureCmd)
63 RegisterStateDriver(self, 'chorus-playeringroup',
64 '[@arena1,exists][@arena2,exists][@arena3,exists][@arena4,exists][@arena5,exists] arena; ' ..
65 '[group:raid] raid; [group:party] party; solo;')
184 66
185 67 --[[ When the property `group` of the given protected frame --[[ When the property `group` of the given protected frame
186 68 `secureHandler` changes value, toggle all of the known raid frame `secureHandler` changes value, toggle all of the known raid frame
 
... ... function Chorus.groupFrameMain(self)
189 71 --[[-- @todo Implement separate or additional arena unit group frame. --[[-- @todo Implement separate or additional arena unit group frame.
190 72 ]] ]]
191 73
192 secureHandler:WrapScript(secureHandler, 'OnAttributeChanged', [[
193 local ChorusLargeRaidFrame = self:GetFrameRef('ChorusLargeRaidFrame')
194 local ChorusPartyFrame = self:GetFrameRef('ChorusPartyFrame')
195 local ChorusSmallRaidFrame = self:GetFrameRef('ChorusSmallRaidFrame')
196 local ChorusTinyRaidFrame = self:GetFrameRef('ChorusTinyRaidFrame')
197
198 local i = 0
199 local n = 0
200 while (i < 40) do
201 i = i + 1
202 if UnitPlayerOrPetInRaid('raid' .. tostring(i)) then
203 n = n + 1
204 end
205 end
74 local body = [[
75 -- Do not rely on arguments. The script must run invariably
76 -- under different contexts.
206 77
207 if n > 25 then
208 ChorusLargeRaidFrame:Hide()
209 ChorusPartyFrame:Hide()
210 ChorusSmallRaidFrame:Hide()
211 ChorusTinyRaidFrame:Show()
212 elseif n > 5 then
213 ChorusLargeRaidFrame:Hide()
214 ChorusPartyFrame:Hide()
78 local ChorusLargeRaidFrame = owner:GetFrameRef('ChorusLargeRaidFrame')
79 local ChorusPartyFrame = owner:GetFrameRef('ChorusPartyFrame')
80 local ChorusSmallRaidFrame = owner:GetFrameRef('ChorusSmallRaidFrame')
81 local ChorusTinyRaidFrame = owner:GetFrameRef('ChorusTinyRaidFrame')
82
83 ChorusLargeRaidFrame:Hide()
84 ChorusPartyFrame:Hide()
85 ChorusSmallRaidFrame:Hide()
86 ChorusTinyRaidFrame:Hide()
87
88 --print(owner:GetName(), self:GetName(), name, value)
89 --print('PlayerInGroup', PlayerInGroup())
90 local groupType = PlayerInGroup()
91 if groupType and 'raid' == groupType then
215 92 ChorusSmallRaidFrame:Show() ChorusSmallRaidFrame:Show()
216 ChorusTinyRaidFrame:Hide()
217 elseif n >= 1 then
218 ChorusLargeRaidFrame:Show()
219 ChorusPartyFrame:Hide()
220 ChorusSmallRaidFrame:Hide()
221 ChorusTinyRaidFrame:Hide()
222 elseif UnitPlayerOrPetInParty('party1') then
223 ChorusLargeRaidFrame:Hide()
93 elseif UnitExists('arena1') or UnitExists('arena2') or UnitExists('arena3') then
94 ChorusPartyFrame:Show()
95 elseif groupType and 'party' == groupType then
224 96 ChorusPartyFrame:Show() ChorusPartyFrame:Show()
225 ChorusSmallRaidFrame:Hide()
226 ChorusTinyRaidFrame:Hide()
227 elseif n <= 0 then
228 ChorusLargeRaidFrame:Hide()
229 ChorusPartyFrame:Hide()
230 ChorusSmallRaidFrame:Hide()
231 ChorusTinyRaidFrame:Hide()
232 97 end end
233 ]])
98 ]]
99 secureHandler:WrapScript(self, 'OnAttributeChanged', body)
234 100
235 101 self:RegisterEvent('PARTY_CONVERTED_TO_RAID') self:RegisterEvent('PARTY_CONVERTED_TO_RAID')
236 102 self:RegisterEvent('PLAYER_ENTERING_WORLD') self:RegisterEvent('PLAYER_ENTERING_WORLD')
 
... ... function Chorus.groupFrameMain(self)
240 106 self:RegisterEvent('RAID_ROSTER_UPDATE') self:RegisterEvent('RAID_ROSTER_UPDATE')
241 107 self:RegisterEvent('PARTY_MEMBERS_CHANGED') self:RegisterEvent('PARTY_MEMBERS_CHANGED')
242 108
243 self:SetScript('OnEvent', Chorus.groupFrameToggleInsecure)
109 self:SetScript('OnEvent', function()
110 secureHandler:Execute(body)
111 end)
244 112 end end
File src/ChorusGroupFrame.xml changed (mode: 100644) (index 3791e1b..f69f470)
1 1 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
2 2 <Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/">
3 3 <Script file="ChorusGroupFrame.lua"/> <Script file="ChorusGroupFrame.lua"/>
4 <Frame name="ChorusGroupFrame" hidden="true" parent="UIParent">
4 <Frame name="ChorusGroupFrame" hidden="true" parent="UIParent" protected="true">
5 5 <Size> <Size>
6 6 <AbsDimension x="800" y="600"/> <AbsDimension x="800" y="600"/>
7 7 </Size> </Size>
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/chorus

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

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

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