주의 :: 상당히 심화 사용자용입니다. 전체 내용은 필요한 분만 읽어보시고 가져오기 코드가 한 페이지쯤 내려가면 있습니다.

2.1.0에서 액션 타입으로 "On Init"이 추가되었습니다.
이 기능과 디스플레이 탭에서 설정해야할 색상 등을 커스텀 코드로 유동적으로 바꾸는 방법을 포함한 예제를 만들어 보겠습니다.

전통의 시간차 타이머입니다.


바, 아이콘, 세 개의 텍스트를 표시합니다.
- 위쪽은 전체 생명력 대비 시간차 총량의 비율입니다. 바의 길이 역시 이 비율로 채웁니다.
(3번 예제의 시간차 총량 표시기는 바 전체 길이가 60%였는데 블리자드 기본 유닛프레임에서 100% 기준으로 잡길래 이번에는 100% 기준으로 만들었습니다)
- 바 아래쪽 텍스트는 시간차의 틱당 데미지
- 아이콘 숫자는 남은 틱수입니다
(허수아비에서 큰 시간차 나올 때까지 못하겠어서 중간 시간차까지만 테스트 해봤습니다. 문제 생기면 알려주세요)


가져오기 문자열(문자열에 빠르게 세 번 클릭하시면 전체 선택 됩니다) :
d4uYpaGiQQUKeQgLu0PKcRIsj0ROuImlQYTOQq7cb)IsPQHrrogLQLjPQNPuvMgvfDneI2gcHVPuLghLsX5KuuRtcH5Puf5EuuhKc1cLq6HkLjsvbxKcYgvQ4JkvrnskLGtkPYkvYlPuIAMsj1nPukTtkKFkHYsLu4Ps1uLGRkLyRukP(QKsRfH0BPanxkLK7sb1EPYFvLgm5WcTyPK8yumzk5YI2SK8zjA0sPoTGxtvPzJOBRk2nQ(nsdhHA5kEoknDvUUQA7uaFNsPY4PuCELkTELQQ3lHO5RufUVKISFyNDxbx)X1TCDlxbxN9Im(Y2d7pDgz32462uSQk28Cg5J2nzY1zViJVS7qglzD9I1sHwxNrgY1RO8BhYyjRRxSwk066mYqUojnA5k46xKm5NRGR)8jVGRG7CNRZqgzzDfCD2aVKmDDBBXmYw2DUUvOQkW8jVDDfC9Np5fCfCN7C9jYKUcU(ZN8cUcUZDU(NnFzjozCf11zjozCfCD2aVKmDgz3DU(NnFziJSSUI66dLmDfC9Np5fCfCN7CNRpzzGYlSlXPRh)tSvXX1d8W9YqFiMmV0YzKDx)sBU)KUErjd7F)XXcQgXGfurJJRBfyjMmUBDmuURxh)YPkYK2Q6yOCwBvSvbYWT77dL777K802f4Lpb2J11z(Sh9PqAZ56vFoZfO8MnWccccIKYejH2OtczgQwJF7xSSmNxIodwqqqqHkio9G2OtcDTto0K3F4qj3cliiiOqf0gDsch9GmBgYe01o5ybbbbbbbbn59hoKFtf3pwqqqqjjBIfeeeeeeeejLjscrComqMHQiP0P5gDsch9GS9qB0jj8eTbYweYUjtq2sqMiqKnWccccccccAY7pCOM(lUL)gfrfDEIxtIZHPbbc(lEX9JfeeeuYTWk5wUUvGLyY4UfsBUwNvNRxCgx)MqzzoUcUoZN9Op1Xq5UE1NZCbkVzdSGGGGiPmrsOn6KqMHQ143(fllZ5LOZGfeeeuOcItpOn6Kqx7Kdn59houYTWcccckubTrNKq8priShMHmbDTtowqqqqqqqqtE)HdTrNKqGHYzn4gDscX)enmwqqqqj3cRKB563UeNUoZN9OpUEAGKFSUElgvxHxJBPgg76mF2J(0ViJVSUE1NZCbkVzdSGGGGiPmrsOn6KqMHQ143(fllZ5LOZGfeeeuOcItpOn6Kqx7Kdn59hoKDOKBHfeee0K3F4qB0jjCbgFzXk5wUoZN9Op(WFIxGYD9QpN5cuEZgybbbbrszIKqB0jHmdvRXV9lwwMZlrNbliiiOqfeNEqB0jHU2jhAY7pCitEq29GU5Nqj3cliiiOn6KeEI2azgQfE4SfYi5122gTPPFIjJ7MJ)gybbbbn59ho0gDsch98G2Ots4jAJh0n)eRKB56mF2J(yu8jD9QpN5cuEZgybbbbrszIKqB0jHmdvRXV9lwwMZlrNbliiiOqfeNEqB0jHU2jhAY7pCi)(HsUfwqqqqHkOn6KeSEkH2tq2nzYe01o5ybbbbbbbbn59ho0gDscwpLybbbbLKSjwqqqqqqqqtE)Hd10FXjyVYx)nkIk68eVMB0jjy9uA7TBYKPgybbbbLClSsULRZ8zp6JRx95mxGYB2aliiiisktKeAJojKzOAn(TFXYYCEj6mybbbbfQG40dAJoj01o5qtE)HdvfjztOKBHfeeeuOcAJojH4FIqypmdzc6ANCSGGGGGGGGM8(dh6MFIfeeeuYTWk5wUot7KXxx)tSv8sxN5ZE0N3BxItxN9I3N11z(Sh95TDWkDDMp7rFCNR3odLTpNr1BYKRFHNC2HmwY66fRLcTUoJmKR)53eklZXvW1z(Sh9X1R(CMlq5nBGfeee0K3F4q38tSsUL7C9iZfOCwxbxpWdNRGRBrFz(Sh9XvuxN5ZE0hxpubvRXV9lwwMZlrNb6ANCOjV)WHsUfwyrszIKqbliZq(7xSSmNIghIoJFSiPmrsO4FISqMHks717Z63lr6bzVEFw)E9PhK969z97DF1ewKuMijul8W5dzR(vvEqvKu6azgQfE48HSv)QkpOkskDWclsktKeAJojKzOTjJxUZeFYM(3zIpPFpi)1A8B)ILL58s0z83aRn6KeI)j6bTrNKG1tPh0gDsch98G2Ots4cm(Y6bTrNKWt0giZqM8Gm5bzYdYKhKDtMmzYewyTrNKap(KSEqB0jjeyOCwiZqfzn5bvK1ewv0bk4bzaOahkqCmmSnJ)jY2aYIIfeeeejLjscXJpPh0RhuGHYHmdTNZRtCsswhVI20anWccccAJojbE8jznyWWEqB0jjeyOCwdgmmKziE8j9Gcmuowj3clSiPmrsOjlduUhedLKo785myfQGQnJ(A8FISyf5wq1MrFn(prwctwgOCwSIClOAZOVg)NilHjlduoRbdwggRi3cQ2m6RX)jYsyYYaLZAWGLHnO)jlduUFddDTtowqqqqtwgOCiZq1MrFn(prwctwgOCwdgSmSb9pzzGY9BySGGGGyOK0zNpNbYm0KLbkNWgLKoyLKSjwqqqqtE)HJvYTWclsktKeQ6ZzUaLd9j2kE5gLKondnWcccckubfGmBgYo01o5ybbbbbbbbXqjPZoFotZjlduUhKjpi7EqM8GS3aliiiOKKndvqbiZMHQh6ANCSGGGGGGGGyOK0zNpNP5KLbk3dYUhKDpitEq2BGfeeeusYMHkOaKzZq7d6ANCSGGGGGGGGyOK0zNpNP5KLbk3dYUhKjpitEq2BGfeeeuYTWk5wyH1gDYIOgzzG9YPfE4mKbs(10FlgvxHxJBPgg73dYpXKXDZXFdS2Otwe986mtG4RP)IXnKbs(53dQ6ZzUaL3SbwqqqqqqqqKuMij0RhK1F8GmqK0d6OhwqqqqqqqqKuMijuWYgiZqMWccccccccQIoqbiZq29G2hKffliiiiiiiiiiiOxVxVxVxVxpR)49696969696969696zGiP3rpiZqTWdNpKT6xv10pXKXDZXVh0gDsc84tYAWGHBGfeeeeeeeeeeeuOcY6pqx7KJfeeeeeeeeeeeeeeeuWYgiZqbSGGGGGGGGGGGGGGGGA1KrFXcccccccccccck5wybbbbbbbbLClSGGGGGGGGcvqblBGWEygAJojH4FIqx7KJfeeeeeeeeeee0NyR4LBus60myztdSGGGGGGGGsUfwqqqqqqqqB0jje)teYmuWYgSGGGGGGGGcvqw)b6ANCSGGGGGGGGGGGG2OtsW6P0dAJojHJEEqB0jjCbgFzHmdzGiPh0rppOkskDAA9NgybbbbbbbbLClSsUvd35ox)sBUDiJLSUEXAPqRRZid56xAZ1d7pDgz3246x4jNEy)PZi7eHRBfyjMmUBH0MRgHY2NRxCURhSC9(fllZPOXHOZ462UG112Tdrse1xZePjFUpIGimrK23x91SRYh95EDD()PWeklZH1zKDxNoHKFXlq5UUT2q1OqDBg3636mYwBOA0nK7CDwxVEc2jyIGDF0UpwwX4Z6jIAEVUUbCgz3N1B3Doha



소개할 기능 1. Actions - On Init


진행바를 하나 만듭니다.
이름을 주의해서 만들어야 하며 잠시 후 설명할 것인데 이름을 바꾸시면 코드 중 한 가지를 저 이름대로 수정한 뒤 리로드해야합니다.
다른 것과 겹칠 일 없는 이름, 저는 ' StaggerBarZrr '로 정했습니다.

Actions 탭엘 먼저 갑니다.



WA 2.1.0 버전에서 On Init 액션이 추가되었습니다.

설명하자면
- 독립 애드온의 OnInitialize() 펑션에 해당하는 기능입니다.
- 원하는 코드를 function() - end wrapper 없이 그냥 써 넣습니다(액션쪽 코드는 원래 그러했지요). 전체 코드는 필요할 때 한 번 함수 형태로 실행되긴 합니다.
- 해당 표시기안에 트리거든 디스플레이 텍스트든 커스텀 코드가 하나 이상 있어야 합니다. 이 코드가 수행될 때 앞서서 On Init 액션코드가 실행됩니다.
- On Init은 한 번 실행된 다음에는 표시기가 숨겨졌다 나오든, 불러오기에서 없어졌다 나오든 실행되지 않습니다.
- 그러나 해당 표시기의 커스텀 코드 중 일부를(On Init 코드 자체를 포함해서) 수정하면 On Init이 다시 실행됩니다.

2.1.0 이전에 저는 PLAYER_ENTERING_WORLD로 동작하는 이벤트 트리거를 하나 만들고 여기에 트리거 코드로 OnInit 코드를 썼는데 이걸 편하게 해 줄 기능입니다.


그래서, 제가 구상하는 동작 방식은
1. On Init에서 UNIT_AURA를 등록한 프레임을 만들고 이걸로 시간차 디법을 추적해서 시간차 종류, 틱뎀, 총 데미지, 틱수 등을 전역변수에 저장
2. 트리거는 OnUpdate로 동작하며 저장된 데이터를 가지고 표시 여부, 수치 등을 표시
이러합니다.

이런 방식을 선택한 이유는 디버프를 추적할 때 RegisterUnitEvent로 UNIT_AURA를 플레이어에게만 등록하는 것이 가장 효율적이라 보았기 때문입니다.
불행히도 WA는 이벤트 트리거에 유닛이벤트 등록을 허용하지 않기 때문에 UNIT_AURA를 그냥 등록하고 player 것만 필터링해야합니다.
그래서 이벤트 핸들링은 On Init에 만든 다음 트리거는 OnUpdate로 변수값만 읽어옵시다.


아무튼, On Init 개인추가 코드에 씁시다.


하나하나 봅시다.


if WA_Stagger_Zrr then return end
본래 OnInitialize() 함수는 한 번만 수행되어야 하는데 앞서 말씀드린대로 WA의 On Init 액션은 표시기 일부를 수정하면 다시 실행됩니다.
프레임에 이벤트 등록할 것인데 자꾸 수행되면 좋지 않으니 이미 생성했다면 그냥 종료합니다.
대신 On Init 코드를 수정해도 수정값이 적용되지 않으니 이쪽 코드는 수정한 뒤에 재시작해야하는 불편함이 있습니다.
(if문 안이라서 return이 가능합니다. chunk 밖에서 종료하고 싶으시면 do return end 하셔야 합니다)



local id = "StaggerBarZrr"
진행바의 이름과 정확히 같아야 합니다.
이후에 설명할 것인데 약간 꼼수로 이 진행바를 찾아가서 바 색을 바꾸기 위해 필요합니다.


local auras = {124275, 124274, 124273}
local UnitDebuff, floor = UnitDebuff, floor

local Core = CreateFrame("Frame", "WA_Stagger_Zrr")
Core.aura, Core.dmg, Core.tot, Core.ticks, Core.max = 0, 0, 0, 0, 100000

Core.names, Core.icons = {}, {}
for i, v in ipairs(auras) do
local name, _, icon = GetSpellInfo(v)
Core.names[i], Core.icons[i] = name, icon
end
맨 위 테이블은 시간차 주문 id
다음 줄은 애드온에서 흔히 하는 짓

WA_Stagger_Zrr이라는 프레임을 만듭니다.
여기에 테이블로 데이터도 저장하고 이벤트 핸들러 역할도 합니다.
데이터 변수들 지정하고 작은 시간차, 중간 시간차, 큰 시간차에 해당하는 주문명과 아이콘 주소를 WA_Stagger_Zrr.names, WA_Stagger_Zrr.icons에 저장해둡니다.
이름은 물론 나중에 UnitDebuff에 쓸 것이고 아이콘은 트리거쪽 아이콘 정보 생성에 씁니다.
인덱스 1, 2, 3이 각각 작은, 중간, 큰 시간차입니다.


소개할 기능 2. Display 조작 snippet


원래 디스플레이 쪽에서 설정해야 할 바 색상, 크기, 텍스쳐의 텍스쳐 파일 등등을 직접 수정하는 방법이 여기에 소개할 두 번째 내용입니다.

WA의 디스플레이들은 WeakAuras.regions["이름"]["region"] 이라는 정보 테이블에 정리됩니다.
여기에는 각종 설정값들과 상황마다 적용할 함수들이 포함되어 있습니다.

이번에 사용할 것은 색상값을 지정하는 함수입니다.
region 테이블에 "Color"라는 키 값으로 접근할 수 있습니다.

진행바의 색상은 region.Color(self, r, g, b, a)
그 외에는 region.Color(r, g, b, a)
와 같이 사용됩니다.

#3번 글의 시간차 예제에도 애니매이션 코드를 이용해 색을 바꾸긴 하지만 이 방법은 색상 외에 다른 조작도 가능하니 위의 링크를 참조하세요.
(여담인데 기존 예제에서 메모리 누수가 발생한 이유는 애니메이션 코드 안에서 로컬로 테이블을 생성해서 그렇습니다. OnUpdate 핸들러 안에서는 이런 짓을 하면 안됩니다.)

아무튼, 계속 합시다.
local region, colorFunc
if WeakAuras
and WeakAuras.regions
and WeakAuras.regions[id]
and WeakAuras.regions[id]["region"] then
region = WeakAuras.regions[id]["region"]
colorFunc = region.Color
else
return
end

local function updateColor(i)
if i == 1 then
colorFunc(region, 0, 1, 0, 1)
elseif i == 2 then
colorFunc(region, 1, 1, 0, 1)
elseif i == 3 then
colorFunc(region, 1, 0, 0, 1)
end
end
위쪽 부분은 이 표시기의 region 테이블을 찾아서 region과 Color 함수를 잡아오는 부분입니다.

아래쪽은 나중에 이벤트 핸들러에서 시간차 종류가 바뀌면 바의 색을 바꾸는 부분입니다. 시간차 종류별로 1, 2, 3이 arguement로 들어가고 각각 해당하는 녹색, 노란색, 빨간색으로 바의 색을 바꿉니다.


Core:RegisterUnitEvent("UNIT_AURA", "player")
Core:SetScript("OnEvent", function()
local _, dur, val, tot
local idx = 0
for i = 1, 3 do
_,_,_,_,_,dur,_,_,_,_,_,_,_,_,val,tot = UnitDebuff("player", Core.names[i])
if dur then
idx = i
break
end
end
if idx ~= Core.aura then
updateColor(idx)
end
Core.aura = idx
if dur then
Core.dmg, Core.tot, Core.ticks = val, tot, floor(dur)
end
end)
UNIT_AURA를 플레이어에만 등록하고 이벤트 발생하면 시간차 세 종류 각각 디법이 있나 스캔합니다.
dur, val, tot로 각각 6, 15, 16번 리턴 값을 씁니다

보통 오라는 지속시간이 오라 적용시에 고정값으로 정해지지만 시간차는 틱뎀이 들어가면 지속 시간이 바뀝니다.
처음에는 10초, 이후로 전체 지속시간 자체가 8.99, 7.99 등으로 변하며 1.99초로 바뀌면 1.0초가 되는 순간 막틱이 들어가며 사라집니다.
이걸 이용하면 남은 틱수를 간단히 잡아낼 수 있습니다. floor(dur)

15번 리턴 val은 틱당 데미지

16번 리턴 tot는 남은 데미지 총량입니다

세 가지 오라가 다 없으면 WA_Stagger_Zrr.aura = 0입니다.




조건 탭으로 갑니다.
개인 추가 - 상태 - 매 프레임으로 설정하고 다음 코드들을 넣습니다.

개인추가 조건
Custom Untrigger
지속시간 정보
이름 정보
아이콘 정보
중첩 정보




개인추가 조건
function()
local Core = WA_Stagger_Zrr
if not Core then return false end
if Core.aura ~= 0 then
return true
end
end
앞서 저장한 오라 넘버가 0이 아니면(즉, 오라가 있으면) 표시

Custom Untrigger
function()
return true
end
붙여넣기가 이상하게 됐네요.
언트리거는 원래 트리거가 false일 때만 체크합니다. 우리는 상태 체크하니 트리거 false면 당연히 언트리거 true

지속시간 정보
function()
local Core = WA_Stagger_Zrr
if not Core then return 0, 1, true end
Core.max = UnitHealthMax("player")
return Core.tot, Core.max, true
end
return 현재값, 최대값, static
세 번째 값이 true면 현재값 / 최대값으로 동작합니다.(#2번 글 dynamic info 참조)
시간차 총량이 현재값, 현재 체력이 최대값.
현재 체력은 이따 또 쓰니까 전역변수 저장

#3의 예제에서는 전체값을 총 체력의 60%로 썼습니다(큰 시간차 조건이 틱뎀이 체력의 6% 이상이라서 큰 시간차면 꽉 차게 표시했습니다)
그렇게 하시려면 Core.max*0.6 뭐 이렇게 하고 현재 값도 min(Core.tot, Core.max*0.6) 사용해서 전체량 넘지 않게 하시면 되겠지요.

이름 정보
function()
local Core = WA_Stagger_Zrr
if not Core then return "" end
if Core.dmg < 1000 then
return Core.dmg
else
return ("%.1fk"):format(Core.dmg/1000)
end
end
시간차 틱뎀을 여기에 쓰겠습니다(다이나믹 인포 중에 스트링 받아주는 데가 여기밖에 없습니다)
1000 미만이면 그냥, 이상이면 1000으로 나누고 소수점 1자리 형식 스트링으로.

아이콘 정보
function()
local Core = WA_Stagger_Zrr
if not Core then return end
if Core.aura ~= 0 then
return Core.icons[Core.aura]
end
end
WA_Stagger_Zrr.aura에 현재 시간차 종류가, WA_Stagger_Zrr.icons 테이블에 각각의 아이콘 주소가 들어있습니다.
종류에 맞는 아이콘을 반환


중첩 정보
function()
local Core = WA_Stagger_Zrr
if not Core then return 1 end
return Core.ticks
end
남은 틱수를 여기에 씁니다. 중첩 정보는 숫자 타입만 받아줍니다.


디스플레이 탭으로 갑니다.
- 아이콘 자동으로 체크
- 방향은 위에서 아래로
- 텍스트 회전 없음
- 윗부분 텍스트는 %c (체력대비 총량 비율을 쓸겁니다)
- 아랫부분 텍스트는 %n (이름 정보에 틱뎀 들어있습니다)

개인추가 텍스트 편집창에는

총량이 0이면(이런 일은 없네요 생각해보니) 0%
존재하면 최대 생명력으로 나누고 *100한 다음 반올림
정수 형식 표시하고 뒤에 "%" 붙입니다.
애드온 코드는 "%%" 하셔야 %가 나옵니다.


여기까지요. 바빠서 이전 예제 링크는 생략.