http://blog.csdn.net/tcxxs/category/148474.aspx1、這是我分析WOW原始UI代碼后,對一些比較關鍵的部分,記錄下來的
2、文章里面如果有什么紕漏,希望大家毫不客氣的提出來,我一定查究!
3、關于基礎問題可以參考
WOW UI
《UI制作入門》http://www.pcgames.com.cn/netgames/zhuanti/wow/expert/Ui.htm
《WOW UI定制入門》http://202.113.13.169/site/mybbs/read.php?tid=33
《WOW插件制作指南》http://www.cnblogs.com/bluefee/archive/2005/04/14/137217.html
《ADDONS編寫普及》http://wowbbs.game.mop.com/viewthread.php?tid=216755&extra=page%3D1
《動手寫個屬于自己的UI》http://wowbbs.game.mop.com/viewthread.php?tid=149814&fpage=1&highlight=
XML
《XML初學進階》http://www.chinausd.com/code/code.asp?id=173/5058
《XMLSpy 2005 Enterprise Edition》http://www.altova.com/download_spy_enterprise.html
Lua
《Lua5.0參考手冊中文版》http://www.cnblogs.com/bluefee/archive/2005/04/15/138576.html
《Lua 程序設計初步》http://bbs.battlecn.net/read.php?tid=541871&fpage=1
《通過例子學習Lua》http://www.wowtc.com/bbs/read.php?tid=4999&fpage=2
《Programming in LUA中文版》http://www.wowtc.com/bbs/read.php?tid=4998&fpage=2
《LuaEdit v2.5》http://luaforge.net/projects/luaedit/
4、關于如何提取MPQ文件,如何查看BLP圖像,可以參考
《WoW Working Link》http://www.fukt.bth.se/%7Ek/wow/stuff/howto-extract-interface-files.txt
《Win MPQ》http://wow.duowan.com/2005-05-16/007R/26857843.html
《Win BLP Viewer》http://gamedown.yesky.com/game/108/108805.html
5、關于查詢資料可以參考
《WoW Wiki》http://www.wowwiki.com/Interface_Customization/
《WOW APIs》http://www.cnblogs.com/bluefee/archive/2005/04/12/136270.html
《UI&Macro Forum》http://forums.worldofwarcraft.com/board.aspx?fn=wow-interface-customization
6、如果該問題是可以類推,或是從上下文能馬上理解,或是從字面就知道含義的我就不羅嗦了
7、對于相同的問題我一般只分析一次,或是簡要的提示一下,具體內容可以參考我以前的分析
8、如果你對自己查找資料的能力感到抱歉,可以E-mail向我詢問,我會努力幫助你
9、聯系方式E-mail: asdic.xxs@gmail.com Blog: blog.csdn.net/tcxxs QQ: 35548917
10、做人要厚道,轉載請注明出處!
--------------------------------------------------
正式開始:
1、版本:1.7.1 (4659)
2、這次我寫的是ActionbuttonTemplate.xml,ActionBarFrame.xml和ActionButton.lua
他們是動作按鈕的基礎UI,也是大家比較關心的一部分,在Interface/FrameXML里面
3、這次分析用到的名詞解釋:
【模板】學過C++語言的人都知道虛函數,實際上是一個道理,只是作為子代繼承的規范,不可創建實例
【柵格】一個用來放置圖標的格子,默認為無圖標時隱藏,當然你也可以顯示它
【額外柵格】包括了戰士姿態,德魯依外形,盜賊潛行的柵格
【柵格ID】每個柵格都有對應的ID,是該柵格的唯一標示
【圖標】每個技能和物品,包括交易技能,食物,宏等都有一個可以拖動的圖標
【動作鍵】當把圖標放置到柵格上時,這個整體就叫動作鍵
【額外動作鍵】當把圖標放置到額外柵格上時,這個整體就叫額外動作鍵
【動作條】一般12個柵格組成一排或者一列,稱這個為動作條
【額外動作條】由12個額外柵格組成一排或者一列,稱這個為額外動作條
【動作條ID】在默認動作條中每個動作條都有頁碼,是這個動作條的唯一標示
這里解釋一下各個動作條的位置,主動作條包括1,2頁
然后右邊1,右邊2,右下,左下依次為3到6頁,柵格ID排列如圖
61-72(左下)49-60(右下)37 25
(右邊2) I I (右邊1)
1-12(主AB)13-24(2頁) 48 36
這里注意一個問題,為什么有的UI可以實現96個(FB,DUF等)或者更多呢
這是因為額外柵格的存在,這些UI把空閑的額外柵格加以利用罷了
調用這些額外柵格的動作鍵應該用其對應的函數
【閃動】當執行自動攻擊或者自動射擊技能時,改動作鍵就處于閃動狀態
【CD】CoolDown的簡寫
【信息提示】即GameTooltip,當鼠標指向某個東西時顯示的提示信息
【光環】包括buff,debuff,物品附加屬性等
【arg1..N】arg為事件觸發是傳入的參數,可以為0到多個
--------------------------------------------
源代碼及注釋
-----------------------ActionButtonTemplate.xml
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<CheckButton name="ActionButtonTemplate" virtual="true">
【動作鍵】【模板】
<Size>
<AbsDimension x="36" y="36"/>
</Size>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentIcon"/>
背景層放置【圖標】
</Layer>
<Layer level="ARTWORK">
層的從下到上為:BackGround,ArtWork,OverLay
<Texture name="$parentFlash" file="Interface\Buttons\UI-QuickslotRed" hidden="true"/>
【閃動】效果的紋理
<FontString name="$parentHotKey" inherits="NumberFontNormalSmallGray" justifyH="RIGHT">
該【動作鍵】的快捷鍵信息
<Size>
<AbsDimension x="32" y="10"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="2" y="-2"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
該【動作鍵】數量信息
<Anchors>
注意,這里沒有Size標簽,所以它為自動大小
<Anchor point="BOTTOMRIGHT">
<Offset>
<AbsDimension x="-2" y="2"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
<Layer level="OVERLAY">
<FontString name="$parentName" inherits="GameFontHighlightSmallOutline">
該【動作鍵】名字,例如:宏的名字
<Size>
<AbsDimension x="36" y="10"/>
</Size>
<Anchors>
<Anchor point="BOTTOM">
<Offset>
<AbsDimension x="0" y="2"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Model name="$parentCooldown" inherits="CooldownFrameTemplate"/>
直接應用【CD】模板,沒有測試過,還望高人賜教,或者等我以后試
</Frames>
<NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2">
【圖標】邊框紋理,如果該【柵格】已放置【圖標】,則顯示這個紋理
若沒有放置,則顯示UI-Quickslot,它比UI-Quickslot2稍微小點
<Size>
<AbsDimension x="64" y="64"/>
</Size>
<Anchors>
<Anchor point="CENTER">
<Offset>
<AbsDimension x="0" y="-1"/>
立體效果,而且UI-Quickslot的顯示位置也依賴UI-Quickslot2
但是【圖標】的實際放置位置卻并不依賴這個位置,由BackGround層決定
</Offset>
</Anchor>
</Anchors>
</NormalTexture>
<PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
點擊【動作鍵】時的紋理
<HighlightTexture alphaMode="ADD" file="Interface\Buttons\ButtonHilight-Square"/>
鼠標經過【柵格】時的紋理
<CheckedTexture alphaMode="ADD" file="Interface\Buttons\CheckButtonHilight"/>
等待施法時【柵格】的紋理,例如:你點擊加血法術到選擇目標那段時間顯示
</CheckButton>
</Ui>
------------------------ActionBarFrame.xml
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="ActionButton.lua"/>
<CheckButton name="ActionBarButtonTemplate" inherits="ActionButtonTemplate" virtual="true">
<Scripts>
<OnLoad>
ActionButton_OnLoad();
</OnLoad>
<OnEvent>
ActionButton_OnEvent(event);
</OnEvent>
<OnClick>
if ( IsShiftKeyDown() ) then
安住shift再點【動作鍵】,即拖拉【圖標】
PickupAction(ActionButton_GetPagedID(this));
鼠標吸附該【圖標】
else
否則執行該【動作鍵】命令
MacroFrame_EditMacro();
UseAction(ActionButton_GetPagedID(this), 1);
UseAction(slot [,checkCursor] [,onSelf])函數
slot參數為該【動作鍵】ID號
checkCursor參數為是否在其他事件中返回是鼠標點擊,0或者1
onSelf參數為是否對自己施法,0或者1
end
ActionButton_UpdateState();
點擊后應該更新【動作鍵】狀態
</OnClick>
<OnDragStart>
if ( LOCK_ACTIONBAR ~= "1" ) then
如果【動作鍵】并未設定為鎖定
PickupAction(ActionButton_GetPagedID(this));
ActionButton_UpdateState();
end
</OnDragStart>
<OnReceiveDrag>
if ( LOCK_ACTIONBAR ~= "1" ) then
PlaceAction(ActionButton_GetPagedID(this));
PlaceAction,放下鼠標上吸附的【動作鍵】
注意,這里并不要求一定要放在柵格上,因為你可以摧毀一個【動作鍵】
ActionButton_UpdateState();
end
</OnReceiveDrag>
<OnEnter>
ActionButton_SetTooltip();
經過【動作鍵】時,顯示【信息提示】
</OnEnter>
<OnLeave>
this.updateTooltip = nil;
GameTooltip:Hide();
</OnLeave>
<OnUpdate>
ActionButton_OnUpdate(arg1);
更新【閃動】效果
</OnUpdate>
</Scripts>
</CheckButton>
下面定義了主【動作條】
<CheckButton name="ActionButton1" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="1">
MainMenuBarArtFrame,即默認最下面的一條工具欄,包括了主【動作條】,人物工具條,背包
但是注意,并不包括兩旁的2只鷹的紋理
<Anchors>
<Anchor point="BOTTOMLEFT">
<Offset>
<AbsDimension x="8" y="4"/>
左下和右下的【動作條】都依據主【動作條】的位置
【信息提示】和【額外柵格】并不依據這個偏移,但是它會根據左下和右下【動作條】的出現而更改高度
若僅改變該偏移,則如果該人物有【額外柵格】,則人物的主【動作條】將會在原位又出現一個
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton2" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="2">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton1" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton3" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="3">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton2" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton4" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="4">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton3" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton5" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="5">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton4" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton6" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="6">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton5" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton7" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="7">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton6" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton8" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="8">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton7" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton9" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="9">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton8" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton10" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="10">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton9" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton11" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="11">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton10" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<CheckButton name="ActionButton12" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="12">
<Anchors>
<Anchor point="LEFT" relativeTo="ActionButton11" relativePoint="RIGHT">
<Offset>
<AbsDimension x="6" y="0"/>
</Offset>
</Anchor>
</Anchors>
</CheckButton>
<Button name="ActionBarUpButton" parent="MainMenuBarArtFrame">
主【動作條】位置上的上翻頁按鈕
<Size>
<AbsDimension x="32" y="32"/>
</Size>
<Anchors>
<Anchor point="CENTER" relativeTo="MainMenuBarArtFrame" relativePoint="TOPLEFT">
<Offset>
<AbsDimension x="522" y="-22"/>
</Offset>
</Anchor>
</Anchors>
<HitRectInsets>
<AbsInset left="6" right="6" top="7" bottom="7"/>
這個一直沒有測試成功,還望高人指點迷津
</HitRectInsets>
<Scripts>
<OnLoad>
MainMenuBarPageNumber:SetText(CURRENT_ACTIONBAR_PAGE);
CURRENT_ACTIONBAR_PAGE,當前【動作條ID】
當你顯示了其他【動作條】如:左下【動作條】,那么它將不會在翻頁中重復出現
this:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
當主【動作條】的頁碼改變時觸發
</OnLoad>
<OnEvent>
if ( event == "ACTIONBAR_PAGE_CHANGED" ) then
MainMenuBarPageNumber:SetText(CURRENT_ACTIONBAR_PAGE);
end
</OnEvent>
<OnClick>
ActionBar_PageUp();
PlaySound("UChatScrollButton");
PlaySound(SoundName),播放一個WOW內置的聲音
SoundName為內置參數的名字,可以參考下面地址
http://www.wowwiki.com/API_PlaySound
注意,你不要試圖在MPQ文件中找到這個名字
</OnClick>
</Scripts>
<NormalTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Up"/>
<PushedTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Down"/>
<DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Disabled"/>
被鎖定時的紋理,未測試成功,望高人指點一二
<HighlightTexture alphaMode="ADD" file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Highlight"/>
</Button>
<Button name="ActionBarDownButton" parent="MainMenuBarArtFrame">
<Size>
<AbsDimension x="32" y="32"/>
</Size>
<Anchors>
<Anchor point="CENTER" relativeTo="MainMenuBarArtFrame" relativePoint="TOPLEFT">
<Offset>
<AbsDimension x="522" y="-42"/>
</Offset>
</Anchor>
</Anchors>
<HitRectInsets>
<AbsInset left="6" right="6" top="7" bottom="7"/>
</HitRectInsets>
<Scripts>
上翻中已經注冊并處理了事件,這里不重復
<OnClick>
ActionBar_PageDown();
PlaySound("UChatScrollButton");
</OnClick>
</Scripts>
<NormalTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Up"/>
<PushedTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Down"/>
<DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Disabled"/>
<HighlightTexture alphaMode="ADD" file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Highlight"/>
</Button>
</Ui>
------------------------ActionButton.lua
CURRENT_ACTIONBAR_PAGE = 1;
當前【動作條ID】
NUM_ACTIONBAR_PAGES = 6;
【動作條ID】總數
NUM_ACTIONBAR_BUTTONS = 12;
每個【動作條】的【動作鍵】數
ATTACK_BUTTON_FLASH_TIME = 0.4;
【閃動】效果時間間隔,為0.4S
BOTTOMLEFT_ACTIONBAR_PAGE = 6;
初始左下【動作條ID】
BOTTOMRIGHT_ACTIONBAR_PAGE = 5;
初始右下【動作條ID】
LEFT_ACTIONBAR_PAGE = 4;
初始右邊2【動作條ID】
RIGHT_ACTIONBAR_PAGE = 3;
初始右邊1【動作條ID】
-- Table of actionbar pages and whether they're viewable or not
VIEWABLE_ACTION_BAR_PAGES = {1, 1, 1, 1, 1, 1};
初始化為每頁【動作條】都能夠顯示,0為隱藏
function ActionButtonDown(id)
實現按下【動作鍵】
if ( BonusActionBarFrame:IsVisible() ) then
如果是【額外動作鍵】
local button = getglobal("BonusActionButton"..id);
if ( button:GetButtonState() == "NORMAL" ) then
若未按下
button:SetButtonState("PUSHED");
end
return;
該函數用if-else是同樣的
end
local button = getglobal("ActionButton"..id);
if ( button:GetButtonState() == "NORMAL" ) then
button:SetButtonState("PUSHED");
end
end
由上下2個函數可以看出,暴雪對【動作鍵】和【額外動作鍵】同樣對待
這個也是其他UI可以利用【額外柵格】的基礎
function ActionButtonUp(id, onSelf)
if ( BonusActionBarFrame:IsVisible() ) then
local button = getglobal("BonusActionButton"..id);
if ( button:GetButtonState() == "PUSHED" ) then
button:SetButtonState("NORMAL");
-- Used to save a macro
MacroFrame_EditMacro();
UseAction(ActionButton_GetPagedID(button), 0);
if ( IsCurrentAction(ActionButton_GetPagedID(button)) ) then
IsCurrentAction,等待施法,并不是正在吟唱
button:SetChecked(1);
設定該【動作鍵】正處于等待狀態
else
button:SetChecked(0);
end
end
return;
end
local button = getglobal("ActionButton"..id);
if ( button:GetButtonState() == "PUSHED" ) then
button:SetButtonState("NORMAL");
-- Used to save a macro
MacroFrame_EditMacro();
UseAction(ActionButton_GetPagedID(button), 0, onSelf);
if ( IsCurrentAction(ActionButton_GetPagedID(button)) ) then
button:SetChecked(1);
else
button:SetChecked(0);
end
end
end
function ActionBar_PageUp()
CURRENT_ACTIONBAR_PAGE = CURRENT_ACTIONBAR_PAGE + 1;
local nextPage;
for i=CURRENT_ACTIONBAR_PAGE, NUM_ACTIONBAR_PAGES do
if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
如果該頁能顯示
nextPage = i;
break;
end
end
if ( not nextPage ) then
如果沒有找到能夠顯示的下一頁
CURRENT_ACTIONBAR_PAGE = 1;
else
CURRENT_ACTIONBAR_PAGE = nextPage;
end
ChangeActionBarPage();
這個函數變換將當主【動作條】變換到CURRENT_ACTIONBAR_PAGE指向的【動作條】
end
function ActionBar_PageDown()
CURRENT_ACTIONBAR_PAGE = CURRENT_ACTIONBAR_PAGE - 1;
local prevPage;
for i=CURRENT_ACTIONBAR_PAGE, 1, -1 do
if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
prevPage = i;
break;
end
end
if ( not prevPage ) then
for i=NUM_ACTIONBAR_PAGES, 1, -1 do
把“1”換成“CURRENT_ACTIONBAR_PAGE+1”也是可以的
把這個for循環對比ActionBar_PageUp的同一地方
可見,暴雪員工相當的肯定在上翻的時候第1頁是可以顯示的
而在下翻的時候顯得信心不足,還重復檢查了一次NUM_ACTIONBAR_PAGES到CURRENT_ACTIONBAR_PAGE
這是因為左下、右下AB的出現只是修改5,6頁的可見性,并不影響1頁的可見性
所以在下翻的時候需要對1到6頁均做可見性檢查
但是,重復檢查的區間的確是多余的,估計是暴雪員工偷懶
因為“1”比“CURRENT_ACTIONBAR_PAGE+1”要好寫得多
if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
prevPage = i;
break;
end
end
end
CURRENT_ACTIONBAR_PAGE = prevPage;
ChangeActionBarPage();
end
function ActionButton_OnLoad()
this.showgrid = 0;
顯示空【柵格】的標志
this.flashing = 0;
處于【閃動】的標志
this.flashtime = 0;
【閃動】時間間隔計算的中間量
ActionButton_Update();
this:RegisterForDrag("LeftButton", "RightButton");
對this所指向的窗體注冊鼠標拖拉行為,參數至少一個,也可以注冊多個
參數為LeftButton,RightButton,表示使用某個鼠標鍵執行
this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
對this所指向的窗體注冊鼠標點擊行為,參數至少一個,也可以注冊多個
參數為LeftButtonDown,LeftButtonUp,RightButtonDown,RightButtonUp
注意,在OnClick標簽中傳入的arg1參數只返回LeftButton或者RightButton
this:RegisterEvent("PLAYER_ENTERING_WORLD");
this:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
當【額外柵格】更新時觸發
this:RegisterEvent("ACTIONBAR_SHOWGRID");
當拖拉【圖標】時觸發,arg1為LeftButton或者RightButton
this:RegisterEvent("ACTIONBAR_HIDEGRID");
當停止拖拉【圖標】時觸發
this:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
this:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
當【柵格】內容變更時觸發,arg1為變更【柵格ID】
this:RegisterEvent("ACTIONBAR_UPDATE_STATE");
當【柵格】狀態更新時觸發,包括了【CD】和可用性鑒定
但是不包括自動攻擊和自動射擊事件
arg1為鼠標LeftButton,RightButton,也可能為nil
this:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
當更新【圖標】可用性后觸發
this:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
當更新【CD】后觸發
當【CD】開始的時候,arg1返回使用的鼠標按鈕LeftButton或者RightButton
當【CD】結束的時候,arg1返回nil
this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
當變更裝備時或者經過一定時間后觸發
this:RegisterEvent("PLAYER_AURAS_CHANGED");
當玩家【光環】改變時觸發,包括了【光環】的消失和出現
注意,屬性完全相同【光環】重復釋放并不能觸發該事件
this:RegisterEvent("PLAYER_TARGET_CHANGED");
當玩家的目標變更時觸發,包括取消和選定目標
arg1為該目標持續時間,單位分鐘,小數保留3位
this:RegisterEvent("UNIT_AURASTATE");
當某單位短時間【光環】改變時觸發,需進一步測試
this:RegisterEvent("UNIT_INVENTORY_CHANGED");
當玩家裝備變更時或者當觀察玩家裝備并發生裝備變更時觸發
this:RegisterEvent("CRAFT_SHOW");
this:RegisterEvent("CRAFT_CLOSE");
工藝窗口的顯示與關閉,arg1為鼠標點擊鍵
this:RegisterEvent("TRADE_SKILL_SHOW");
this:RegisterEvent("TRADE_SKILL_CLOSE");
交易技能制作物品窗口的顯示與關閉,arg1為鼠標點擊鍵
this:RegisterEvent("UNIT_HEALTH");
當任何一個單位的血量發生變化時觸發,arg1參數為該單位ID
player,pet,target,mouseover,party1..4,partypet1..4,raid1..40,raidpet1..40,npc
注意,該事件擁有很高的優先級,特別當參數為player時
this:RegisterEvent("UNIT_MANA");
當任何一個單位的魔法量發生變化時觸發,arg1參數為該單位ID
this:RegisterEvent("UNIT_RAGE");
當任何一個單位的怒氣值發生變化時觸發,arg1參數為該單位ID
this:RegisterEvent("UNIT_FOCUS");
當任何一個單位的焦距值發生變化時觸發,arg1參數為該單位ID
注意,該事件實際上已經廢除,因為現在獵人使用MANA,而不是FOCUS
this:RegisterEvent("UNIT_ENERGY");
當任何一個單位的能量發生變化時觸發,arg1參數為該單位ID
this:RegisterEvent("PLAYER_ENTER_COMBAT");
當玩家進入自動攻擊狀態時觸發,自動射擊不包括在內
注意,僅當你使用自動攻擊時觸發該事件
使用其他任何技能或者攻擊行為都不可觸發
this:RegisterEvent("PLAYER_LEAVE_COMBAT");
離開自動攻擊狀態或者死亡時觸發
this:RegisterEvent("PLAYER_COMBO_POINTS");
當連擊點變更時觸發,arg1總返回player,而并不時連擊點數
this:RegisterEvent("UPDATE_BINDINGS");
當快捷鍵更改時觸發
this:RegisterEvent("START_AUTOREPEAT_SPELL");
當自動射擊開始時觸發,而不是自動攻擊
this:RegisterEvent("STOP_AUTOREPEAT_SPELL");
離開自動射擊狀態或者死亡時觸發
ActionButton_UpdateHotkeys();
end
function ActionButton_UpdateHotkeys(actionButtonType)
if ( not actionButtonType ) then
actionButtonType = "ACTIONBUTTON";
end
local hotkey = getglobal(this:GetName().."HotKey");
該對象在模板中為Fontstring
local action = actionButtonType..this:GetID();
actionButtonType,為該類命令的名字
this:GetID,得到該命令在該類中的ID號
注意,這2個字符串組成了最終的命令的名字
如NUMPAD2,NUMPAD為類型,2為ID
但是有些類型就一個命令無ID,如LEFT
hotkey:SetText(KeyBindingFrame_GetLocalizedName(GetBindingKey(action), "KEY_"));
GetBindingKey得到命令的快捷鍵名字,后面加上KEY_是為了顯示命令的字串
例如:KEY_NUMPAD2就顯示為“數字鍵盤2”
KeyBindingFrame_GetLocalizedName,由這個函數在快捷鍵窗口中顯示該命令的快捷鍵
end
function ActionButton_Update()
-- Special case code for bonus bar buttons
-- Prevents the button from updating if the bonusbar is still in an animation transition
if ( this.isBonus and this.inTransition ) then
ActionButton_UpdateUsable();
ActionButton_UpdateCooldown();
return;
end
local icon = getglobal(this:GetName().."Icon");
local buttonCooldown = getglobal(this:GetName().."Cooldown");
local texture = GetActionTexture(ActionButton_GetPagedID(this));
if ( texture ) then
icon:SetTexture(texture);
icon:Show();
如果該【柵格】有【圖標】,即若為【動作鍵】則顯示
this.rangeTimer = TOOLTIP_UPDATE_TIME;
每隔TOOLTIP_UPDATE_TIME事件間隔更新一次距離信息
TOOLTIP_UPDATE_TIME為0.2S
this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
-- Save texture if the button is a bonus button, will be needed later
if ( this.isBonus ) then
判斷自己是否為【額外柵格】
this.texture = texture;
end
else
icon:Hide();
buttonCooldown:Hide();
this.rangeTimer = nil;
this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
getglobal(this:GetName().."HotKey"):SetVertexColor(0.6, 0.6, 0.6);
end
ActionButton_UpdateCount();
if ( HasAction(ActionButton_GetPagedID(this)) ) then
判斷該【柵格】是否有【圖標】,即是否為【動作鍵】
this:Show();
ActionButton_UpdateState();
ActionButton_UpdateUsable();
ActionButton_UpdateCooldown();
ActionButton_UpdateFlash();
elseif ( this.showgrid == 0 ) then
this:Hide();
else
這里表示,當該【柵格】沒有【圖標】
但是顯示空【柵格】選項開啟時,不顯示公共CD效果
buttonCooldown:Hide();
end
if ( GameTooltip:IsOwned(this) ) then
判斷該【動作鍵】是否擁有【信息提示】
ActionButton_SetTooltip();
else
this.updateTooltip = nil;
end
-- Update Macro Text
local macroName = getglobal(this:GetName().."Name");
macroName:SetText(GetActionText(ActionButton_GetPagedID(this)));
GetActionText返回宏的名字
end
function ActionButton_ShowGrid(button)
if ( not button ) then
button = this;
end
button.showgrid = button.showgrid+1;
getglobal(button:GetName().."NormalTexture"):SetVertexColor(1.0, 1.0, 1.0, 0.5);
SetVertexColor(R,G,B)這個函數需要注意,可能學過3D的都知道,這個是頂點著色,取值0到1小數
頂點著色并不是直接設置RGB的數值,而是在原有的RGB數值上乘以頂點著色指定的RGB百分比修正值
例如:一個色塊RGB為50,100,30,如果你寫入SetVertexColor(0.5,0,1),結果RGB為25,0,30
button:Show();
end
function ActionButton_HideGrid(button)
if ( not button ) then
button = this;
end
button.showgrid = button.showgrid-1;
if ( button.showgrid == 0 and not HasAction(ActionButton_GetPagedID(button)) ) then
把這里判斷showgrid變量為0和這一對函數對showgrid的操作聯系起來看
就像是用堆棧實現括號配對一樣保證了顯示和隱藏的規范
button:Hide();
end
end
function ActionButton_UpdateState()
if ( IsCurrentAction(ActionButton_GetPagedID(this)) or IsAutoRepeatAction(ActionButton_GetPagedID(this)) ) then
IsAutoRepeatAction,自動射擊
IsAttackAction,自動攻擊
this:SetChecked(1);
else
this:SetChecked(0);
end
end
function ActionButton_UpdateUsable()
注意,這個函數的主體是個技能按鈕模板,所以針對的是一個【動作鍵】
所以,當你拖動某個【圖標】時,其他【圖標】并不會跟著更新
local icon = getglobal(this:GetName().."Icon");
模板中定義
local normalTexture = getglobal(this:GetName().."NormalTexture");
local isUsable, notEnoughMana = IsUsableAction(ActionButton_GetPagedID(this));
得到當前技能柵格的ID,這個是所有柵格ID號,包括73~96的
if ( isUsable ) then
是否在射程,當前在其他游戲規則中是否可用,是否在CD等
icon:SetVertexColor(1.0, 1.0, 1.0);
normalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif ( notEnoughMana ) then
是否足夠魔法、怒氣、能量
icon:SetVertexColor(0.5, 0.5, 1.0);
normalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
icon:SetVertexColor(0.4, 0.4, 0.4);
這個是灰色效果,當你拖拉【圖標】時,原【柵格】則為這個效果
normalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function ActionButton_UpdateCount()
local text = getglobal(this:GetName().."Count");
在模板中數量為Fontstring
if ( IsConsumableAction(ActionButton_GetPagedID(this)) ) then
判斷是否改【柵格】的物品為消費品
text:SetText(GetActionCount(ActionButton_GetPagedID(this)));
else
text:SetText("");
end
end
function ActionButton_UpdateCooldown()
local cooldown = getglobal(this:GetName().."Cooldown");
在模板中該【CD】定義為一個Model
local start, duration, enable = GetActionCooldown(ActionButton_GetPagedID(this));
CooldownFrame_SetTimer(cooldown, start, duration, enable);
end
function ActionButton_OnEvent(event)
if ( event == "ACTIONBAR_SLOT_CHANGED" ) then
if ( arg1 == -1 or arg1 == ActionButton_GetPagedID(this) ) then
如果變更的【柵格】不明或者變更的【柵格】為自己則更新
ActionButton_Update();
end
return;
end
if ( event == "PLAYER_ENTERING_WORLD" or event == "ACTIONBAR_PAGE_CHANGED" ) then
總結起來是,當游戲環境有大的變化時,更新自己
ActionButton_Update();
return;
end
if ( event == "UPDATE_BONUS_ACTIONBAR" ) then
if ( this.isBonus ) then
ActionButton_Update();
end
return;
end
if ( event == "ACTIONBAR_SHOWGRID" ) then
ActionButton_ShowGrid();
return;
end
if ( event == "ACTIONBAR_HIDEGRID" ) then
ActionButton_HideGrid();
return;
end
if ( event == "UPDATE_BINDINGS" ) then
ActionButton_UpdateHotkeys();
return;
end
-- All event handlers below this line MUST only be valid when the button is visible
if ( not this:IsVisible() ) then
如果該【圖標】不可見,那么直接返回,即下面的所有事件均要求該【圖標】可見,即應該為一個【動作鍵】
return;
end
if ( event == "UNIT_HEALTH" or event == "UNIT_MANA" or event == "UNIT_RAGE" or event == "UNIT_FOCUS" or event == "UNIT_ENERGY" ) then
if ( arg1 == "player" ) then
如果發生在玩家身上,應該判斷所有技能的可用性
ActionButton_UpdateUsable();
end
elseif ( event == "PLAYER_TARGET_CHANGED" or event == "PLAYER_AURAS_CHANGED" ) then
ActionButton_UpdateUsable();
elseif ( event == "UNIT_AURASTATE" ) then
if ( arg1 == "player" or arg1 == "target" ) then
ActionButton_UpdateUsable();
end
elseif ( event == "UNIT_INVENTORY_CHANGED" ) then
if ( arg1 == "player" ) then
ActionButton_Update();
end
elseif ( event == "ACTIONBAR_UPDATE_STATE" ) then
ActionButton_UpdateState();
elseif ( event == "ACTIONBAR_UPDATE_USABLE" or event == "UPDATE_INVENTORY_ALERTS" or event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
ActionButton_UpdateUsable();
ActionButton_UpdateCooldown();
elseif ( event == "CRAFT_SHOW" or event == "CRAFT_CLOSE" or event == "TRADE_SKILL_SHOW" or event == "TRADE_SKILL_CLOSE" ) then
ActionButton_UpdateState();
elseif ( event == "PLAYER_ENTER_COMBAT" ) then
if ( IsAttackAction(ActionButton_GetPagedID(this)) ) then
ActionButton_StartFlash();
end
elseif ( event == "PLAYER_LEAVE_COMBAT" ) then
if ( IsAttackAction(ActionButton_GetPagedID(this)) ) then
ActionButton_StopFlash();
end
elseif ( event == "PLAYER_COMBO_POINTS" ) then
ActionButton_UpdateUsable();
elseif ( event == "START_AUTOREPEAT_SPELL" ) then
if ( IsAutoRepeatAction(ActionButton_GetPagedID(this)) ) then
ActionButton_StartFlash();
end
elseif ( event == "STOP_AUTOREPEAT_SPELL" ) then
if ( ActionButton_IsFlashing() and not IsAttackAction(ActionButton_GetPagedID(this)) ) then
如果該技能在【閃動】,并且不是自動攻擊
ActionButton_StopFlash();
end
end
end
function ActionButton_SetTooltip()
if ( GetCVar("UberTooltips") == "1" ) then
Uber,乳房。。。。。
這句應該是判斷是否屬于一般類型,母類型
UberTooltips詳細信息提示
GameTooltip_SetDefaultAnchor(GameTooltip, this);
一般位于屏幕右下角,會根據【動作條】的多少自動改變位置
else
如果這個【柵格】的【信息提示】不屬于默認的形式則
if ( this:GetParent() == MultiBarBottomRight or this:GetParent() == MultiBarRight or this:GetParent() == MultiBarLeft ) then
【動作條】MultiBarBottomRight右下,MultiBarRight右方,MultiBarLeft左邊下
GameTooltip:SetOwner(this, "ANCHOR_LEFT");
這里解釋下SetOwner函數,GameTooltip:SetOwner(owner, anchor);
其中owner是參照物,anchor是對齊方式,取值如下:
ANCHOR_TOPRIGHT 相當于 SetPoint("BOTTOMRIGHT",object,"TOPRIGHT")
ANCHOR_RIGHT 相當于 SetPoint("BOTTOMLEFT",object,"TOPRIGHT")
ANCHOR_BOTTOMRIGHT 相當于 SetPoint("TOPLEFT",object,"BOTTOMRIGHT")
ANCHOR_TOPLEFT 相當于 SetPoint("BOTTOMLEFT",object,"TOPLEFT")
ANCHOR_LEFT 相當于 SetPoint("BOTTOMRIGHT",object,"TOPLEFT")
ANCHOR_BOTTOMLEFT 相當于 SetPoint("TOPRIGHT",object,"BOTTOMLEFT")
else
GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
end
end
if ( GameTooltip:SetAction(ActionButton_GetPagedID(this)) ) then
SetAction,返回值為該【信息提示】是否需要實時更新
this.updateTooltip = TOOLTIP_UPDATE_TIME;
else
this.updateTooltip = nil;
end
end
function ActionButton_OnUpdate(elapsed)
if ( ActionButton_IsFlashing() ) then
this.flashtime = this.flashtime - elapsed;
if ( this.flashtime <= 0 ) then
flashtime初始為0,即第一次flash的時間并不為0.4,而是第一個elapsed決定
local overtime = -this.flashtime;
overtime,該函數的一個中間量,用語變化符號
if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
這個if為了下面給flashtime更新是不出現負數考慮
注意,ERROR文本框的文本并不和這里的時間掛鉤
overtime = 0;
end
this.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime;
更新flashtime,使得從第二次開始間隔一個ATTACK_BUTTON_FLASH_TIME
local flashTexture = getglobal(this:GetName().."Flash");
if ( flashTexture:IsVisible() ) then
效果的實現即為反復顯示這個flash紋理
flashTexture:Hide();
else
flashTexture:Show();
end
end
end
-- Handle range indicator
if ( this.rangeTimer ) then
if ( this.rangeTimer < 0 ) then
local count = getglobal(this:GetName().."HotKey");
if ( IsActionInRange( ActionButton_GetPagedID(this)) == 0 ) then
IsActionInRange,返回指定【動作鍵】是否在距離之內
返回nil表示該【柵格】無【圖標】,或者沒有選定目標
返回0表示不在距離之內,返回1表示在距離之內
注意,如果你沒有試圖釋放這個【動作鍵】在目標身上,它可能總返回1
count:SetVertexColor(1.0, 0.1, 0.1);
else
count:SetVertexColor(0.6, 0.6, 0.6);
end
this.rangeTimer = TOOLTIP_UPDATE_TIME;
else
this.rangeTimer = this.rangeTimer - elapsed;
end
end
if ( not this.updateTooltip ) then
return;
end
this.updateTooltip = this.updateTooltip - elapsed;
if ( this.updateTooltip > 0 ) then
return;
end
if ( GameTooltip:IsOwned(this) ) then
ActionButton_SetTooltip();
else
this.updateTooltip = nil;
end
end
function ActionButton_GetPagedID(button)
if( button == nil ) then
message("nil button passed into ActionButton_GetPagedID(), contact Jeff");
嚴重錯誤需要彈出消息框
return 0;
end
if ( button.isBonus and CURRENT_ACTIONBAR_PAGE == 1 ) then
如果是【額外動作條】并且當前【動作條ID】為1
local offset = GetBonusBarOffset();
GetBonusBarOffset,得到【額外動作條】的偏移量
返回1到3,分別對應1到3號戰士姿態,或者德魯依外形,或者是盜賊狀態
if ( offset == 0 and BonusActionBarFrame and BonusActionBarFrame.lastBonusBar ) then
應該是判斷當意外失去【額外動作條】定位時,定位于最近一次改變的
注意,如果該職業無【額外動作條】時,偏移量也為0
offset = BonusActionBarFrame.lastBonusBar;
end
return (button:GetID() + ((NUM_ACTIONBAR_PAGES + offset - 1) * NUM_ACTIONBAR_BUTTONS));
注意NUM_ACTIONBAR_PAGES + offset用的是加法,所以我們肯定暴雪偷偷藏了24個【額外柵格】
elseif ( button:GetParent():GetName() == "MultiBarBottomLeft" ) then
return (button:GetID() + ((BOTTOMLEFT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
elseif ( button:GetParent():GetName() == "MultiBarBottomRight" ) then
return (button:GetID() + ((BOTTOMRIGHT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
elseif ( button:GetParent():GetName() == "MultiBarLeft" ) then
return (button:GetID() + ((LEFT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
elseif ( button:GetParent():GetName() == "MultiBarRight" ) then
return (button:GetID() + ((RIGHT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
else
return (button:GetID() + ((CURRENT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS))
end
end
function ActionButton_UpdateFlash()
local pagedID = ActionButton_GetPagedID(this);
if ( (IsAttackAction(pagedID) and IsCurrentAction(pagedID)) or IsAutoRepeatAction(pagedID) ) then
ActionButton_StartFlash();
else
ActionButton_StopFlash();
end
end
function ActionButton_StartFlash()
this.flashing = 1;
this.flashtime = 0;
ActionButton_UpdateState();
end
function ActionButton_StopFlash()
this.flashing = 0;
getglobal(this:GetName().."Flash"):Hide();
ActionButton_UpdateState();
end
function ActionButton_IsFlashing()
if ( this.flashing == 1 ) then
return 1;
else
return nil;
end
end
---------------------總結一下
常量
TOOLTIP_UPDATE_TIME 【信息提示】更新間隔
CURRENT_ACTIONBAR_PAGE 當前【動作條ID】
NUM_ACTIONBAR_PAGES 總頁碼
NUM_ACTIONBAR_BUTTONS 一個【動作條】的【柵格】數
ATTACK_BUTTON_FLASH_TIME 【閃動】間隔
BOTTOMLEFT_ACTIONBAR_PAGE 左下【動作條ID】
BOTTOMRIGHT_ACTIONBAR_PAGE 右下【動作條ID】
LEFT_ACTIONBAR_PAGE 右邊2【動作條ID】
RIGHT_ACTIONBAR_PAGE 右邊1【動作條ID】
事件
ACTIONBAR_PAGE_CHANGED 【動作條】翻頁
UPDATE_BONUS_ACTIONBAR 【額外動作條】更新
ACTIONBAR_SHOWGRID 顯示【柵格】
ACTIONBAR_HIDEGRID 隱藏【柵格】
ACTIONBAR_SLOT_CHANGED 【柵格】內容變更
ACTIONBAR_UPDATE_STATE 【動作鍵】更新狀態
ACTIONBAR_UPDATE_USABLE 【動作鍵】更新可用性
ACTIONBAR_UPDATE_COOLDOWN 【動作鍵】更新【CD】
UPDATE_INVENTORY_ALERTS 裝備警告
PLAYER_AURAS_CHANGED 【光環】改變
PLAYER_TARGET_CHANGED 目標改變
UNIT_AURASTATE 單位【光環】改變
UNIT_INVENTORY_CHANGED 單位裝備改變
CRAFT_SHOW 工藝窗口顯示
CRAFT_CLOSE 工藝窗口隱藏
TRADE_SKILL_SHOW 交易技能窗口顯示
TRADE_SKILL_CLOSE 交易技能窗口隱藏
UNIT_HEALTH 單位血量改變(優先級極高)
UNIT_MANA 單位魔法改變
UNIT_RAGE 單位怒氣改變
UNIT_FOCUS 單位焦距改變(已廢除)
UNIT_ENERGY 單位能量改變
PLAYER_ENTER_COMBAT 開始自動攻擊
PLAYER_LEAVE_COMBAT 結束自動攻擊
PLAYER_COMBO_POINTS 連擊點改變
UPDATE_BINDINGS 快捷鍵更新
START_AUTOREPEAT_SPELL 開始自動射擊
STOP_AUTOREPEAT_SPELL 結束自動射擊
函數
IsShiftKeyDown Shift鍵是否按下
PickupAction 吸附【圖標】
PlaceAction 放置【圖標】
UseAction 使用【動作鍵】
GetButtonState 得到【動作鍵】狀態
SetButtonState 設置【動作鍵】狀態
Frame:RegisterForDrag 注冊拖拉行為
Frame:RegisterForClicks 注冊點擊行為
GetBindingKey 得到快捷鍵
HasAction 【柵格】是否放置了【圖標】
Frame:SetVertexColor 頂點色彩修正
IsAutoRepeatAction 是否正在自動射擊
IsAttackAction 是否正在自動攻擊
IsUsableAction 【動作鍵】是否可用
IsConsumableAction 是否為消費品
GetActionCooldown 得到【CD】
GetCVar 有待測試
GameTooltip:SetAction 設置【信息提示】
Frame:IsVisible 是否可見
IsActionInRange 是否在距離之內
GetBonusBarOffset 得到【額外動作條】偏移量
累死了。。。。。。明天再貼圖片和排版彩色
http://wowbbs.game.mop.com/forumdisplay.php?fid=138
這個帖子我已經貼了圖片
posted on 2007-06-25 02:11
七星重劍 閱讀(3391)
評論(2) 編輯 收藏 引用 所屬分類:
亂七八糟