|
2016-08-05 06:24
조회: 4,953
추천: 11
[강좌] 버프 프레임 만들기목차 1. 개요 2. 애드온 구조 2-1. 와우의 애드온 시스템 2-2. 사용할 이벤트 2-3. 애드온의 프레임구조 2-4. 애드온 파일 구조 및 파일 만들기 3. 애드온 코드 3-1. MyAuraFrame.toc 파일 3-2. MyAuraFrame.lua 3-2-1. 애드온을 총괄하는 AuraFrame 생성하기 3-2-2. 아이콘 Frame 생성하기 3-2-3. 버프 정보를 아이콘에 업데이트하기 3-2-4. 이벤트를 연결하고 처리하기 4. 마무리 1. 개요 ![]() 예전에 공부할겸 만들어둔 작성했던 글을 좀 더 알기쉽게 풀어서 리뉴얼한 글입니다. 애드온에 대해서 공부하고자 하는 사람 있으면 도움 되기를 바라는 마음에서 인벤에 올리는 것이며, 프로그래밍 지식이 조금이라도 있다는 전제하에 작성한 글이라 아예 모르시면 이해는 어려울 수 있지만 차근차근 따라하기만 해도 애드온은 만드실 수는 있습니다. 참고로 저는 코딩 툴로 무료 에디터인 notepad++ 를 사용했습니다. 필요하신분들은 https://notepad-plus-plus.org/download/v6.9.2.html 로 가셔서 다운 받으시면 됩니다. 2. 구조 2-1. 와우의 애드온 시스템 와우의 애드온 시스템은 이벤트 메시지 기반으로 이뤄어져 있습니다. 체력이 변경되었다, 전투가 발생했다, 아이템을 먹었다, 스킬을 사용했다, 버프를 받았다 등의 상황이 발생하면, 와우 클라이언트는 이벤트라는 것으로 발생시켜 와우 내의 모든 애드온들에게 알려줍니다. 따라서, 애드온 입장에서는 발생된 이벤트 중에서 자신이 원하는 이벤트만 선별하여 처리하면 되겠습니다. 그렇기 때문에 만들고자 하는 애드온의 기능과 관련된 이벤트들이 무엇이 있는지 알아보는 것이 매우 중요합니다. http://wowprogramming.com/docs/events 에 들어가시면 그외 무수히 많은 이벤트들을 보실수 있습니다 2-2. 사용할 이벤트 이번에 만들 버프 애드온에서는 2가지의 이벤트를 사용할 것인데, 첫번째로는 당연히 버프/디버프의 변경 사항을 알려주는 이벤트를 사용할 것이고, 두번째로는 캐릭터가 게임에 접속했을때 발생하는 이벤트를 사용할 것입니다. 접속하자마자 버프 확인하기 위한 목적의 이벤트라고 할수 있습니다. 이 2개의 이벤트는 와우에 다음과 같은 코드로 정의 되어있습니다. UNIT_AURA : 유닛(플레이어, 타겟, 파티 등)의 버프/디버프 변화를 알려주는 이벤트 PLAYER_ENTERING_WORLD : 로딩 화면(캐릭터 접속, 지역 이동) 이 끝나고 플레이할 준비가 시작 되면 발생하는 이벤트. 일단 이러한 이벤트들을 사용한다는 정도만 알고 넘어갑시다. 2-3. 애드온의 프레임구조 프레임이란? 애드온에서 사용자와 상호작용을 하는 UI 를 의미합니다. 예를 들자면, 버튼, 체크버튼, 드롭다운박스, 입력창 등을 의미합니다. 또한 하나의 프레임은 여러개의 프레임으로 이뤄어 질수도 있습니다. 프레임의 종류는 http://wowprogramming.com/docs/widgets_hierarchy 에서 확인 가능합니다. 이번엔 버프 애드온의 프레임 구조를 알아봅시다. 애드온이 구현된 모습 입니다. ![]() 다수 버프 아이콘이 배열되어 있는 형태고, 아이콘에는 [버프이미지], [쿨다운시간과 검은색 반투명 애니메이션] 그리고 아이콘하단에 [중첩 숫자] 가 표시 됩니다. 이를 구조적으로 정리하자면, 아래의 그림과 같습니다. ![]() 애드온을 총괄하는 하나의 프레임(AuraFrame) 있고, 그 안에 여러개의 아이콘 프레임들이 나열 되어있습니다. 그리고 하나의 아이콘 프레임은 또 다시 여러개의 프레임으로 이뤄져 있는데, 아이콘 프레임을 이루는 요소는 다음 3가지와 같습니다. Texture : 아이콘 이미지 레이어 FontString : 중첩을 표시하는 글자 레이어 Cooldown : 버프시간과 검은색 반투명 원형 애니메이션을 표시하는 프레임 레이어는 프레임보다 더 작은 개념의 UI 라고 생각하시면 되며, 레이어는 프레임에 안에서만 생성할 수 있습니다. 2-4. 애드온의 파일 구조 및 파일 만들기 애드온을 구성하는 파일의 종류는 4가지 입니다. Toc 파일 : 애드온의 기본 설정을 명시하는 파일. 애드온의 버전, 이름, 애드온의 파일들, 작성자 등을 명시. Lua 파일 : 소스 파일. 애드온의 기능에 대한 프로그래밍 코드를 작성. Xml 파일 : 화면에 보여지는 프레임의 구조를 담당하는 파일. 이미지파일 : blp, tga 확장자의 이미지 파일. xml 와 lua 에 대해서 좀 더 자세히 설명을 하자면, xml 은 화면에 보여지는 UI 부분을 담당하는 파일이고, lua 는 화면에서 보이지 않지만 애드온 내부에서 동작하는 기능적인 부분을 담당하는 파일입니다. 계산기를 예로 들어 설명하자면, 계산기 버튼의 모습은 xml 파일에 작성되고, 버튼을 눌렀을때 작동되는 덧셈/뺄셈의 기능은 lua에서 작성됩니다. 물론 xml 파일이 없어도, lua 에서 화면에 보여지는 UI 도 만들수 있고, 반대로 xml 에서도 애드온의 기능을 만들수도 있습니다. 단지 이렇게 구분해둔건 애드온을 유지보수하는데 있어서 편하다는 장점이 있기 때문입니다만... 요즘은 Ace 라이브러리처럼 개발의 편의상이 강조된 라이브러리들을 통해 xml 을 사용하지 않고 lua 로만 개발하는 것이 대세입니다. 이번 애드온에서는 대세를 따르는 것은 아니지만 개발을 시작하는 입장에서는 xml 과 lua 동시에 사용하기에는 복잡할 수 있으니, lua 파일과 toc 파일만 생성해서 진행하도록 하겠습니다. - 그럼 애드온 개발의 기반인 폴더와 파일은 생성하도록 합시다. 애드온 이름은 MyAuraFrame 입니다. 와우폴더/interface/addons 아래 MyAuraFrame 폴더를 만들고, MyAuraFrame.lua 파일 MyAuraFrame.toc 파일 을 만들어줍시다. 애드온의 이름과 폴더명, toc 파일 이름은 반드시 동일해야 합니다! 3. 코드 3-1. MyAuraFrame.toc 파일 앞서 설명한대로, 애드온의 각종 정보를 명시하는 파일입니다. - MyAuraFrame.toc 파일을 열고 아래 내용을 넣어 줍시다. ## Interface: 70000 ## Title: MyAuraFrame ## Author: 인벤유저 ## Notes: 나만의 버프 프레임 ## Version: 1.0 MyAuraFrame.lua ※ 코드 설명 - ## Interface : 애드온을 사용할 와우 클라이언트의 버전을 입력합니다. 애드온이 구버전인지 아닌지를 체크하는 부분으로, 현재는 7.0 버전이니 70000 을 입력합니다. 만약 7.1 버전이면, 70100 이 됩니다. - ## Title : 애드온의 이름, "애드온의 폴더명/toc 파일 이름"과 반드시 동일해야합니다. - ## Author : 애드온 작성자 - ## Notes : 애드온 설명 - ## Version : 애드온의 버전입니다. 와우 클라이언트 버전과 완전 별개로, Version 애드온의 고유 버전입니다. 아무렇게나 입력해도 상관 없습니다. 우리는 첫버전이니 1.0 으로 입력해줍시다. - MyAuraFrame.lua : toc 파일에는 애드온을 구성하는 파일들의 목록을 명시해줘야 합니다. 따라서 우리는 MyAuraFrame.lua 파일 하나만 넣어주면 됩니다. 참고로 이미지 파일은 쓰지 않아도 됩니다 작성된 것 외에도, 애드온의 데이터를 저장 여부, 애드온 플러인 설정의 사용 여부도 있으니, 자세한건 http://wowwiki.wikia.com/wiki/The_TOC_Format 을 참고 바랍니다. MyAuraFrame.toc 파일의 작성이 끝났습니다. 다음은 본격적으로 코딩을 시작해 봅시다. 3-2. MyAuraFrame.lua MyAuraFrame.lua는 애드온의 기능을 담당하는 파일입니다만, 이번 애드온에서는 기능 뿐만 아니라 UI와 관련 부분도 같이 작성하겠습니다. 챕터2에서 보았던 내용을 다시 하번 상기해 봅시다. UI 구조는 총괄프레임하나와 여러개의 아이콘 프레임으로 이뤄져있으며, 이벤트는 UNIT_AURA, PLAYER_ENTERING_WORLD 이벤트를 사용할 것 입니다. 이제 그 부분들을 코드로 작성해 보겠습니다. 코드 작성은 크게 4가지로 파트로 나눠서 진행됩니다. 3-2-1. 애드온을 총괄하는 AuraFrame 생성하기 3-2-2. 아이콘 Frame 생성하기 3-2-3. 버프 정보를 아이콘에 업데이트하기 3-2-4. 이벤트를 연결하고 처리하기 3-2-1. 애드온을 총괄하는 AuraFrame 생성하기 자 이제 MyAuraFrame.lua 파일 열고 아래 코드를 넣어 줍시다. local ICON_WIDTH = 40 local ICON_HEIGHT = 40 -- 애드온을 총괄하는 AuraFrame 생성하기 local AuraFrame = CreateFrame("Frame", nil, UIParent); AuraFrame:SetSize(ICON_WIDTH, ICON_HEIGHT); AuraFrame:SetPoint("CENTER",200,50); AuraFrame.icon = {}; -- 버프 아이콘들의 관리하기 위해서 배열 선언 AuraFrame.unit = "player"; -- 플레이어의 버프를 체크하기 위해서 미리 명시함 AuraFrame.isBuff = true; -- 버프만 체크 할거다! 명시함 ※ 코드 설명 - local AuraFrame = CreateFrame("Frame", nil, UIParent); CreateFrame() 는 블리자드에서 제공하는 함수로, 프레임을 만드는 역할을 수행합니다. 프레임을 만들어서 AuraFrame 라는 변수에 넣어주었습니다. local 은 지역변수를 만드는 lua 언어의 예약어입니다.(c언어와 다르게 변수 타입이 없습니다.) 함수의 원형 frame = CreateFrame("frameType" [, "name" [, parent [, "template"]]]) - frameType : 프레임의 종류를 입력합니다. (Frame 외에도 Button, CheckButton 등이 있습니다.) 프레임의 종류 : http://wowprogramming.com/docs/widgets_hierarchy - name : 프레임의 이름인데, 필요없으면 nil 로 넣어줘도 됩니다. (nil 은 null 과 같은 뜻으로 "없음" 을 나타내는 지시어입니다.) - parent : 프레임의 부모프레임을 지정하는 것인데, UIParent 은 와우 모든 프레임의 시조격 부모라고 생각하면 됩니다. 딱히 부모 프레임이 없으면 UIParent 를 넣어주면 됩니다. 부모 프레임이 존재하면 부모 프레임의 관리를 받습니다. 예를 들자면 부모프레임이 화면에서 보이지말라는 Hide 명령을 받게 되면 자식 프레임들도 부모프레임을 따라 화면에 안보이게 됩니다. - template : 템플릿은 미리 만들어둔 세팅값을 불러와서 적용시키는 기능입니다. 예를 들자면, 버튼의 크기, 모양, 이름들을 미리 정의해 템플릿으로 만들어놓고, 필요할때마다 불러오는 겁니다. 블리자드의 기본 프레임들은 다 템플릿으로 만들어 놓고 제공하고 있으니 필요할때마다 불러오면 됩니다. - AuraFrame:SetSize(40, 40); AuraFrame(너비, 높이)의 크기를 지정하는것이지만, 실제로 AuraFrame은 화면에 실제로 보이지 않고 기능적인 역할을 수행하기 위해 만든것이기 때문에 크기는 중요하지 않습니다. - AuraFrame:SetPoint("CENTER",200,50); 버프가 표시될 위치를 지정합니다. 화면 한가운데에서 x 좌표(오른쪽으로)로 200 만큼, y 좌표(위로)로 50 만큼 이동한 자리에서 표시합니다. 3-2-2. 아이콘 Frame 생성하기 - 아래 코드를 이어서 넣어줍시다 -- 오라 아이콘들 생성하고 가져오는 역할을 수행하는 함수 local function GetIcon(self , index) local icon = self.icon[index]; -- 처음에 만들었던 배열에서 아이콘을 가져온다. -- 만약 배열에 아이콘이 없으면 아이콘 프레임을 생성한다. if icon == nil then -- 아이콘 기본틀을 담당할 Frame 을 생성하고, icon = CreateFrame("Frame", nil, self); icon:SetSize(ICON_WIDTH, ICON_HEIGHT); -- 아이콘 크기 지정 if index == 1 then -- 첫번째 아이콘이면, 가장 처음 위치에 지정 icon:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, 0); else -- 2번째 부터는 아이콘 오른쪽으로 한칸씩 정렬한다. icon:SetPoint("LEFT", self.icon[index-1], "RIGHT", 2, 0); end -- 아이콘 이미지 텍스쳐 생성 icon.texture = icon:CreateTexture(nil, "Background"); icon.texture:SetTexture("interface\\icons\\TEMP"); icon.texture:SetAllPoints(); -- 쿨다운 프레임 생성 icon.cooldown = CreateFrame("Cooldown", nil, icon, "CooldownFrameTemplate"); icon.cooldown:SetDrawEdge(false); icon.cooldown:SetDrawSwipe(true); icon.cooldown:SetAllPoints(); -- 중첩 숫자 Text UI 생성 icon.countText = icon:CreateFontString(nil, "OVERLAY"); -- OUTLINE 은 폰트를 굵고 테두리가 표시 되도록하는 옵션이다. icon.countText:SetFont("Fonts\\2002.TTF", 12, "OUTLINE"); icon.countText:SetSize(ICON_WIDTH, 15); icon.countText:SetPoint("TOPRIGHT", icon, "BOTTOMRIGHT"); icon.countText:SetTextColor(1,1,0); icon.countText:SetText("중첩"); -- 테스트용 icon.countText:SetJustifyV("TOP"); icon.countText:SetJustifyH("CENTER"); self.icon[index] = icon; -- 만든 아이콘을 배열에 저장 end return icon; -- 아이콘 반환 end ※ 코드 설명 - local function GetIcon(self , index) GetIcon() 함수는 아이콘 프레임을 생성하고 반환해주는 역할을 수행 합니다. 아이콘프레임의 순서는 곧 버프가 발생한 순서와 동일하며, 그 순서에 맞추어서 아이콘 프레임을 생성하는데, 만약 생성된 아이콘이 있으면, 만들지 않고 이미 만든 프레임을 반환하게 됩니다. 이는 버프가 수시로 생기고 없어지고 하기 때문에, 버프가 생성될때마다 프레임을 만드는게 아니라 안쓰는건 감춰 두었다가 필요할때 재사용하는 방식을 취합니다. 인자 값으로 self 는 AuraFrame 을 넘겨 받게 될것이며, index는 버프의 순서값을 받게 됩니다. - icon:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", 0, 0); 위치를 지정하는 함수입니다. 다른 프레임을 기준으로 위치를 지정하고 있습니다. 내 BOTTOMLEFT(왼쪽하단점) 를 self 프레임의 BOTTOMLEFT(왼쪽하단점) 기준으로 (0,0) 만큼 이동해서 위치시켜라라는 의미입니다. - icon:SetPoint("LEFT", self.icon[index-1], "RIGHT", 2, 0); 내 LEFT(왼쪽끝) 를 self.icon[index-1] 프레임의 RIGHT(오른쪽끝) 기준으로 (2,0) 만큼 이동해서 위치시켜라라는 의미입니다. - icon.texture = icon:CreateTexture(nil, "Background"); 프레임을 만드는 함수에서 보았듯이 이번엔, Texture(이미지) 이라는 layer 요소를 만드는 함수로 Background 로 사용하겠다고 선언하였습니다. layer 요소는 프레임 안에서 속하기 때문에, layer에 속하는 텍스쳐는 반드시 프레임의 도움을 받아 생성해야 합니다. 여기서는 icon 프레임 도움을 받았네요. 자동으로 텍스쳐의 부모프레임은 icon 이 되겠습니다. - icon.texture:SetTexture("interface\\icons\\TEMP"); 위에서 만든 텍스처에 이미지 파일을 넣어주는 함수 입니다. 이미지는 와우 클라이언트에 있는 와우 기본이미지를 넣었습니다. 와우 폴더에 들어가서 보면 해당 경로를 찾아 볼 수 없을텐데요. 위 경로는 클라이언트 안에 있는 경로라고 보시면 되겠습니다. 참고로 경로를 나타내는 문자 는 \ 처럼 두번 사용해야 합니다. 이는 문자열안에서 를 표시하기위한 규칙이라고 보시면 되겠습니다. - icon.texture:SetAllPoints(); SetPoint() 함수 처럼 위치를 직접 지정할수도 있지만, 부모프레임의 위치를 가져다가 물려받을수도 있습니다. SetAllPoints() 가 그러한 기능을 하는 함수 입니다. 여기서는 icon 의 위치를 그대로 받았습니다. - icon.cooldown = CreateFrame("Cooldown", nil, icon, "CooldownFrameTemplate"); 쿨다운 프레임을 생성하고 있습니다. 이름은 없고, 부모 프레임은 icon 입니다. 전에는 없던 템플릿까지 사용하고 있습니다. CooldownFrameTemplate 은 블리자드에서 제공하고 있는 쿨다운용 템플릿으로, 스킬창에서 기본적으로 볼수 있는 검은색 반투명 원형 애니메이션과 시간이 가운데 표시 되는 설정을 미리 정의해둔 템플릿입니다. - icon.cooldown:SetDrawEdge(false); 원형 애니메이션에 맞춰 돌아가는 노란색의 막대기의 표시 여부를 지정합니다. 우리는 필요없기에 false 줍시다. 뭔지 궁금하면 true 로 하셔도 됩니다. - icon.cooldown:SetDrawSwipe(true); 검은색 반투명의 원형 애니메이션을 표시 여부를 지정합니다. true 지정하였습니다. - icon.countText = icon:CreateFontString(nil, "OVERLAY"); 텍스트를 생성하는 함수 입니다. 텍스쳐 생성하는 것과 유사합니다. 텍스쳐와 다르게 OVERLAY 로 지정했는데, 다른 이미지, 텍스트들보다 위에 표시하겠다는 의미로 보시면 됩니다. - icon.countText:SetFont("Fonts\\2002.TTF", 12, "OUTLINE"); 텍스트의 폰트와 크기, 스타일을 지정하는 함수입니다. 폰트의 위치도 이미지처럼 클라이언트 안에 있는 경로라고 생각하시면 됩니다. 검은색 테두리가 있는 "OUTLINE" 스타일로 지정했습니다. - 중간 테스트 여기까지 진행 했으면, 현재까지 문제 없이 잘 되었는지 테스트 해봅시다. - 와우를 실행하고 캐릭터에 접속 합니다. (만약 처음부터 와우를 켜고 애드온을 만들었다면 반드시 와우를 재시작해줍시다.) - 채팅창에 /console scriptErrors 1 을 입력합니다 애드온 에러창을 표시할 수 있도록, 와우의 디버그 모드를 켜는것입니다. (만약 에러창이 나오지 않게 다시 끄려면, /console scriptErrors 0 을 입력하면 됩니다.) - MyAuraFrame.lua 의 가장 마지막줄에 아래 테스트 코드 2줄을 추가하고 저장합니다. GetIcon(AuraFrame, 1); GetIcon(AuraFrame, 2); - 채팅창에 인터페이스를 초기화하는 /reload 를 입력합니다. - 2개의 아이콘이 뜨면 성공 ![]() 만약 에러창이 뜬다면 무슨 에러가 몇번째 줄에 발생했는지 알수 있으니, 에러가 발생한 줄을 확인하고 그 근처를 잘 확인해봅시다. 만약 에러도 안뜨고 아이콘도 안뜬다면, 애드온 폴더, 파일의 이름 toc 의 내용을 확인해봅시다. 확인 후 와우 재접. 테스트가 끝났으면, 테스트 코드로 넣었던 GetIcon(AuraFrame, 1); GetIcon(AuraFrame, 2); 두줄을 삭제 해줍시다. 3-2-3. 버프 정보를 아이콘에 업데이트하기 - MyAuraFrame.lua 에 이어서 작성해줍시다~ -- 오라의 변경 상태를 업데이트 하는 함수 ( self == AuraFrame ) local function AuraFrame_UNIT_AURA(self) local filter = self.isBuff and "HELPFUL" or "HARMFUL"; local max = self.isBuff and BUFF_MAX_DISPLAY or DEBUFF_MAX_DISPLAY; local name, texture, count, duration, expires; local icon; local auraIndex = 1; -- 반복문을 돌면서 오라를 가져온다 for i = 1, max do -- 오라를 가져와서 name, _, texture, count, _, duration, expires = UnitAura(self.unit, i, filter); -- 오라가 있으면, if name then -- 아이콘을 가져와서 icon = GetIcon(self, i); icon.texture:SetTexture(texture); -- 이미지를 넣어주고 icon.cooldown:SetCooldown(expires-duration, duration); -- 중첩이 1 이하는 표현할 필요 없으니, 2이상만 표시 if count > 2 then icon.countText:SetText(count); else icon.countText:SetText(nil); end icon:Show(); -- 아이콘에 정보를 담았으니 출력 else -- 오라는 1부터 차례대로 저장되어 있기 때문에 값이 없다면, 그 이후 값은 안봐도 된다. auraIndex = i; break; end end -- 오라가 계속 생겼다가 사라졌다가 하니, 안쓰는 아이콘은 삭제하는것보다 -- hide 로 안보이게 해두는게 효율적이다. for i = auraIndex, #self.icon do self.icon[i]:Hide(); end end ※ 코드 설명 이번 강좌의 핵심 함수부터 설명하겠습니다. - UnitAura() 함수 버프 또는 디버프의 정보를 가져오는 함수 입니다. 함수의 원형을 살펴봅시다. 함수의 원형 name, rank, icon, count, dispelType, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, _, nameplateShowAll, timeMod, value1, value2, value3 = UnitAura("unit", index [, "filter"]) 인자 값을 보면, - unit : 어떤 대상의 버프/디버프를 가져올것인가? (player, target, focus, pet, party1...) - index : 버프/디버프가 대상이 시전된 시간적 순서를 기준으로 1 부터 인덱스가 정해지며, 버프와 디버프의 인덱스는 별도로 지정됩니다. - fillter : 버프 또는 디버프를 지정하는 인자입니다. 버프면 "HELPFUL", 디버프면 "HARMFUL" 값을 넣어주면 되며, 자신이 시전한 주문만 보고 싶다면, "MINE" 값을 넣어주면 됩니다. 만약 디버프중에 자신이 주문만 보고 싶다면 "HARMFUL | MINE" 이라고 입력합니다. lua는 c언와 다르게 함수의 리턴값으로 여러개의 값을 넘겨줄 수 있습니다. UnitAura 함수를 사용하면 버프 하나에 대한 18개 의 정보를 얻을수 있으며, 만약 해당 정보가 없으면 nil 이 반환 됩니다. 다 알필요는 없고, 중요한 몇가지만 보도록 합시다. - name : 주문의 이름 - icon : 주문의 이미지 (texture) - count : 주문의 중첩 - dispelType : 오라의 종류 (마법, 저주, 독, 일반) - duration : 지속 시간(현재 남은 시간이 아니라, 주문의 지속시간이 원래 몇 초 인지를 말합니다) - expires : 주문이 종료되는 시간입니다. (초단위로 표시합니다) - caster : 주문을 시전한 사람 - spellID : 주문의 숫자 ID 값 보시면 아시겠지만, UnitAura() 함수 한번의 호출로 전체 버프와 디버프의 정보를 가져오는게 아니라, 한번에 호출시 딱 하나의 버프 정보만 가져 올수 있습니다. 그렇기 때문에 모든 버프 또는 디버프의 정보를 가져 오기 위해서는 반복문을 통해서 버프/디버프 개수만큼 호출하는 구조가 필요합니다. 하지만 실제 구현에서는 버프의 개수를 알려주는 함수는 없으니, 반복문을 통해 UnitAura() 함수가 nil 일때까지 호출하면 되겠습니다. - local filter = self.isBuff and "HELPFUL" or "HARMFUL"; UnitAura() 에서 설명한대로 버프 또는 디버프중 어떤 정보를 얻을 것인가하는 필터 값을 지정합니다. 굉장히 중요한 부분으로, 버프는 "HELPFUL", 디버프면 "HARMFUL" 으로 지정합니다. 우리는 가장 처음에 isBuff 값으로 true 를 주었으므로, "HELPFUL" 값이 지정될 것입니다. - local max = self.isBuff and BUFF_MAX_DISPLAY or DEBUFF_MAX_DISPLAY; 반복문을 돌때 최대 얼마만큼 돌아야 하는가 에 대한 최대값으로 사용할 변수 입니다. 그 값으로는 블리자드에서 미리 정의해분 값을 사용하게 되는데, 7.0.3 기준 BUFF_MAX_DISPLAY(32개), DEBUFF_MAX_DISPLAY(16개) 입니다. 애드온에서는 버프이기 때문에 32가 지정됩니다. - for i = 1, max do 루아의 for문(반복문) 구조 입니다. c언어 스타일로 바꾸면 아래와 같습니다. for( i =1 ; i<=max ; i++ ) - name, _, texture, count, _, duration, expires = UnitAura(self.unit, i, filter); 여러개의 정보 중에서 필요한 5가지 정보만 받도록 합니다. "_" 표시는 해당정보는 안받겠다는 의미와 동일합니다. - icon = GetIcon(self, i); 아이콘 프레임을 가져 옵니다. - icon.cooldown:SetCooldown(expires-duration, duration); 쿨다운 프레임을 동작하는 함수 입니다. 첫번째 인자로는 시작 시간, 두번째 인자로는 지속 시간을 지정합니다. UnitAura() 함수에서는 시작시간이 없으므로, 끝나는 시간에서 지속시간을 빼서 시간시간을 계산했습니다. 함수가 실행되면 반투명 원형 애니메이션과 남은시간의 아이콘에 표시되며, 쿨다운이 시작됩니다. - for i = auraIndex, #self.icon do self.icon[i]:Hide(); end 버프가 화면에서 사라지면 아이콘도 화면에서 사라져야 합니다. 따라서 버프의 개수와 아이콘 프레임의 개수를 비교해서 필요없는 아이콘은 화면에서 보이지 않도록 설정합니다. (#self.icon 에서 "#"은 배열의 길이를 알려주는 지시어입니다.) 3-2-4. 이벤트를 연결하고 처리하기 - 이어서 작성합니다 -- 이벤트 핸들러 (self 값으로 이벤트 핸들러를 소유한 AuraFrame 객체가 넘어온다) local function AuraFrame_OnEvent(self, event) if event == "UNIT_AURA" then -- 오라에 변경 사항이 발생했다면, AuraFrame_UNIT_AURA(self); elseif event == "PLAYER_ENTERING_WORLD" then AuraFrame_UNIT_AURA(self); end end AuraFrame:RegisterEvent("PLAYER_ENTERING_WORLD"); AuraFrame:RegisterUnitEvent("UNIT_AURA", AuraFrame.unit); AuraFrame:SetScript("OnEvent",AuraFrame_OnEvent); ※ 코드 설명 - local function AuraFrame_OnEvent(self, event) 이벤트를 받는 용도로 사용할 함수 입니다. self 값은 이벤트를 등록한 프레임이며, event 는 발생한 이벤트 명이 넘어옵니다. 앞서 이벤트 설명에서 말했듯이 UNIT_AURA, PLAYER_ENTERING_WORLD 의 처리 과정을 넣었습니다. 둘다 AuraFrame_UNIT_AURA() 함수를 실행해서 버프 프레임을 업데이트하게 됩니다. - AuraFrame:RegisterEvent("PLAYER_ENTERING_WORLD"); 무수히 많은 이벤트 중에서 원하는 이벤트만 골라 받을수 있도록 등록하는 함수 입니다. PLAYER_ENTERING_WORLD 이벤트가 발생 했을때, 즉 캐릭터가 게임에 접속했거나 지역이동을 마쳤을때, AuraFrame에게 알려주겠다는 의미입니다. - AuraFrame:RegisterUnitEvent("UNIT_AURA", AuraFrame.unit); 이벤트를 받을 조건으로 유닛을 추가하는 함수 입니다. 다시 말하자면 UNIT_AURA의 이벤트 중에서도 AuraFrame.unit 의 값인 player 에 해당되는 이벤트만 받겠다는 것입니다. 만약 RegisterUnitEvent 대신 RegisterEvent 으로 유닛 없이등록한다면, player 뿐안 아니라 타겟, 주시, 파티, 공격대, 팻 등에서 발생한 모든 버프/디버프 변경사항에 대한 이벤트를 받게 되고 이를 선별해서 처리하는 로직까지 필요하게 됩니다. - AuraFrame:SetScript("OnEvent", AuraFrame_OnEvent); 앞서 등록한 이벤트들이 발생했을때, 실행될 함수를 지정하는 부분입니다. 여기서 AuraFrame_OnEvent 함수를 지정했기 때문에 AuraFrame_OnEvent 함수가 실행되게 됩니다. AuraFrame_OnEvent 함수를 등록한 프레임이 AuraFrame 이기 때문에, AuraFrame_OnEvent 함수의 self 값으로 AuraFrame이 넘어가게 됩니다. 4. 마무리 애드온 코드 작성이 모두 끝났습니다! 채팅창에 /reload 를 입력해서 애드온을 작동 시켜봅시다. 문제 없이 잘 작동 되길바랍니다~ 이것저것 확인이 끝났으면, 애드온의 값을 변경시켜서 제대로 동작하는지도 확인해봅시다. AuraFrame.isBuff 의 값을 false 변경하여, 디버프도 잘 동작하는지 확인해 보고, AuraFrame.unit 의 값을 "target" 이나 "focus" 로 바꿔보고 테스트 해봅시다. 혹시 target, focus 로 변경한 후에 뭔가 문제가 있다는 것을 발견 하셨나요? 유닛이 변경되어도 그 즉시 버프/디버프가 업데이트 되지 않는 문제를 발견하실수 있을겁니다. 그 원인은 유닛이 변경되어도 오라가 변경되었다는 이벤트가 발생하지 않기 때문입니다. 따라서 이를 해결하려면 target 과 focus 가 변경될때 발생하는 이벤트를 받아서, 버프를 업데이트하는 로직을 추가 구현해야합니다. 하지만 해당 문제의 해결보다 구조를 이해하는 것이 테스트의 목적이니 무엇때문에 그런 문제가 발생했다는 것만 이해만 하시면 되겠습니다. 만약 여기서 조금더 발전 시키고 싶으신분들은 주문 이름이나 ID 를 체크하여 원하는 것만 출력하는 필터링 기능에 도전 해보시길 추천드립니다. 마지막으로 다시 한번 애드온을 공부하는 사람들에게 많은 도움이 되었으면 좋겠고, 부족한 지식과 필력으로 인해서 잘못된 점이나 이해가 안되는 부분이 있다면, 언제든지 리플, 쪽지 주시면 성실하게 답변, 반영하겠다고 약속 하겠습니다. 그럼 즐거운 와우 되시길!
EXP
189,434
(17%)
/ 210,001
|



ivPia