游戏菜单游戏无法加载插件件

后使用快捷导航没有帐号?
查看: 1276|回复: 6
新人欢迎积分1 阅读权限40积分539精华0UID帖子金钱1297 威望0
Lv.4, 积分 539, 距离下一级还需 461 积分
UID帖子威望0 多玩草10 草
从零开始学插件——牛牛爸的插件学习笔记(1)
作为一个陪伴WOW走过10年的老玩家,一直做着编写代码的工作,却没有写一个像样的插件,实属一大憾事。这一次,牛牛爸将再次走进Lua的知识殿堂,探寻WOW API的秘密花园。以能写一个实用并便于使用的插件作为最终目的。如果你也想写一个自己的插件,不妨跟着牛牛爸一起来学习。
首先要说明下,牛牛爸并不是一个程序员,但做了十几年的网页设计工作,比较熟悉HTML、JavaScript、VBScript,而这次学习Lua的主要参考对象也是JavaScript。如果你熟悉JavaScript或其它编程语言的话,学习Lua会事半功倍,如果你没有编程方面的基础,也不要紧。牛牛爸会给你一些代码实例,并告诉你与之相关的知识点,擅长钻研的你,一定可以顺藤摸瓜、举一反三。
目前WOW插件主要分两大类,一类是以界面定制为主,俗称UI类,另一类则是以实现某种功能为主,俗称功能类。在这里我们的主要研究方向是功能类,所以XML方面的知识基本不会涉及。
从某种角度来讲,功能类的插件比UI类的插件要复杂的多,因为它需要编程语言来支撑,也就是Lua。什么是Lua?相信很多来看此帖朋友都已大体了解。不了解的朋友可以去各大百科网站自行脑补。再次申明,我在这里不会向你复制粘贴一些网上到处都有的定义,我更倾向于告诉你要实现什么功能需要用到什么知识,你上哪里能找到这方面的知识。
先列几个我常去查资料的网站:
以上两个都是英文网站,不要担心,牛牛爸的英语也很烂,只不过牛牛爸还有这个:
Google撤出天朝后,留在天朝的东西已不多,而这个翻译页面无疑是当中最实用的。
当然我们也需要Google搜索,因为在查找编程资料方面,百度是那么的力不从心。对于打不开Google主页的朋友,可以尝试:
上面那个网站有时候会当掉,你也可以在百度中搜索“Google镜像”找寻其它Google镜像网站。
有了以上几个网站,你就相当于有了一块耕地,有了粮食种子,你还怕吃不到粮食吗?我知道你已经迫不及待地想要写一个插件出来。好的,不要着急。我们先来了解下插件是由什么文件组成的。其实这些基础知识在NGA或多玩魔兽论坛都可以很容易找到,但我在这里还是要提一下,不然有人会说我净说些没用的。
一个最简单的插件一般有两个文件组成,分别是toc文件和lua文件。toc文件存储着插件的信息,lua文件存储着插件的脚本代码。它们都是纯文本文件,可以使用Windows自带的记事本来编辑,但要注意它们的编码是UTF-8的。我建议你使用Notepad++这款小软件来编写这些文件。编写好的toc文件和lua文件要放到一个以英文命名的文件夹里,然后把这个文件夹复制到wow文件夹下的\Interface\AddOns文件下,如果你已经在使用大脚或魔盒之类的插件,你会发现这里已经有很多文件夹了,像Omen啦,Recount啦,是不是都很熟悉吧?
好了,不说废话了,现在我们就来做一个插件。什么?还没讲toc文件的构成?那是联盟的讲法,而我们是部落。我们先把插件做出来,然后再来理解它的构成。
做个什么插件呢?Hello World?那是联盟的做法,我们部落才不去搞那些没用的。有部落兄弟说了:“咱们明明是部落,为什么动作条两边是狮鹫却不是双足飞龙?”我觉得这个问题提得好。那边又有部落兄弟说了:“我的动作条两边是两个大球啊。”我用忿恨的目光回应他:“你给我死开,你用暗黑界面了不起啊?”其实我也早觉得那两只狮鹫有些碍眼,对于用小屏幕的朋友来说,屏幕左下角用来放伤害统计窗口最适合不过了,但那狮鹫趴在那里实在有碍瞻观。我们第一个插件就是要拿掉这两条狮鹫。
CapHide.toc文件:
## Interface: 60100
## Version: 0.1
## Title: CapHide
## Notes: Hide Your MainMenuBarEndCap
## Title-zhCN: 隐藏动作条装饰
## Notes-zhCN: 隐藏动作条两边的狮鹫装饰
## Author: Bill
CapHide.lua复制代码
第1行Interface是声明插件适用的WOW客户端版本,目前6.1,被记作60100。假如你把这里写成60000,你的插件就成过期的了。除非你在WOW的插件设置里启用过期的插件,否则你的插件将不被游戏加载。相应的,等到WOW客户端更新到6.2时,你需要将这里更新为60200。
第2行Version是声明插件自己的版本。为什么不写“1.0”?低调,要注意低调!其实你写“10.0”也没人管你,主要是自己用以区分。每当插件改进了,就可以把这里的数往上加加。因为Interface和Version往往是改动最频繁的,所以放在前两行。
第3行Title是插件的名称,会在英文客户端下显示,所以要写上英文。但估计咱们写的插件也不会有老外来用,所以空着这里或去掉这一行也是可以的。
第4行Notes是插件的说明,也是在英文客户端下显示,同上,可以空着或去掉。
第5行Title-zhCN是插件的中文名称,会在简体中文客户端下显示,就是我们自己要看的啦,起个好听点的名字吧。
第6行Notes-zhCN是插件的中文说明,会在简体中文客户端下显示,随便写写就行。
第7行Author是插件的作者,就是你的名字啦,如果你不想让你的名字在英文客户端下成为鬼画符,就署上你的英文大名吧。
最后一行CapHide.lua是告诉客户端你插件都包含哪些代码文件,一行一个。在这里就只有CapHide.lua啦。
再来看CapHide.lua文件:
MainMenuBarLeftEndCap:Hide()
MainMenuBarRightEndCap:Hide()复制代码
没错,只有两行。我们甚至没有用到Lua语句,只调用了WOW API。将你的插件文件夹放到WOW插件文件夹(\wow\Interface\AddOns)下,运行WOW,在插件选择界面(点击角色选择界面左下角按钮)中应该就能找到你的插件了。进到游戏里面,你会发现动作条两边的狮鹫不见了。是不是很酷呢?如果你在插件选择界面里找不到你的插件,请检查你文件的编码是否为UTF-8,文件所在文件夹的位置是否正确。
今天的插件知识就介绍到这里,改天我们再继续深入探讨。最后奉上两条小贴士,供喜欢锦上添花的朋友参考。
问:我在插件选择界面里看到有些插件名称的颜色是彩色的,我也想弄成彩色的,该怎么做?
答:以本文代码为例,可以在“隐藏动作条装饰”前面加上代码“|cff00CCFF”,在后面加上代码“|r”,其中“|cff”表示颜色标记开始,“|r”表示颜色标记结束,“00CCFF”就是颜色代码了,这样的代码对做网页和平面设计的朋友来说应该很熟悉。
问:我想让我的插件在插件选择界面里靠前显示,该怎么做?
答:应该不难发现,插件选择界面里的插件名称都是按字符顺序排列的。在字符排序里面,符号比字母优先,所以你想让你的插件名称靠前显示的话,可以在你的插件名前加上符号前缀,比如大脚和魔盒就是通过中括号“[]”来实现排序靠前的。
本帖最后由 猎人Bill 于
16:43 编辑
史诗弓 0/1
幽灵狼宝宝 0/1
Heartbreaker
Lv.4, 积分 319, 距离下一级还需 681 积分
UID帖子威望0 多玩草0 草
强帖先留个楼再慢慢看
新人欢迎积分1 阅读权限40积分539精华0UID帖子金钱1297 威望0
Lv.4, 积分 539, 距离下一级还需 461 积分
UID帖子威望0 多玩草10 草
从零开始学插件——牛牛爸的插件学习笔记(2)
在上一小节,牛牛爸分享了几个查阅资料的网站,还介绍了toc文件的一些知识。这次,我们把目光主要放到lua文件上来。目前,我们的lua文件只有两行代码,插件基本上没有灵活性可言。这次,我们来看下如何给这个小插件做上一个设置界面,并通过设置界面自由地开启或关闭插件的功能。
早期的插件设置界面都是独立的,即插件自己画一个窗口,在需要的时候显示,在不需要的时候隐藏。而随着暴雪后来推出专门的插件设置界面,现在大多数插件都将自己的设置窗口附着到暴雪的插件设置界面中。那怎么来实现呢?两个方法,一个是通过xml文件,另一个是通过lua文件。我在上一小节说过,我们的研究方向是功能性插件,基本不涉及xml的知识。所以我们通过lua文件来画窗口。
大多数教程都会先教读者掌握xml的方法,再传授lua的方法,最后做个比较,告诉你lua的方法更好。虽然遵循了循序渐进的原则,但未免有些啰嗦。而我们部落向来是选择最直接有效的方法。所以我们在这里不讲怎么用xml文件布局窗体,也不讲怎样画一个独立的窗体,就直接讲怎样用lua在插件设置界面附上我们的窗体。
Config.lua
local f = CreateFrame(&Frame&, nil, InterfaceOptionsFramePanelContainer)
f.name = &CapHide&
InterfaceOptions_AddCategory(f)复制代码
把Config.lua文件列入你的CapHide.toc中,登录游戏看一下“界面”里面的“插件”选项卡,左侧是不是已经有我们的“CapHide”了?只是点击CapHide后,里面什么也没有。当然是没有了,因为我们还没有画上。
在这里要告诉大家一个调试插件的方法。如果你只是改动了插件的lua文件或xml文件,你可以在游戏里使用“/rl”命令来重新载入插件,你最新改动的代码就生效了。如果你改动的是toc文件,则需要退出游戏重新进入,否则容易出错。
现在我来解释下Config.lua文件的三行代码。第1行,新建一个“Frame”类型的窗体,作为“InterfaceOptionsFramePanelContainer”的子窗体,并保存到局部变量“f”中。第2行,给这个新窗体起名字为“CapHide”,不然它没法在设置界面中被列出。第3行,调用API“InterfaceOptions_AddCategory”将这个新窗口添加到插件设置界面中。
因为我们之前没有介绍任何lua语法,所以这三行代码乍看上去也会有些头大,但对于有编程基础的朋友,则会很容易理解。没有编程基础的朋友可以先去了解下lua中的变量知识,然后再来看,就比较容易理解了。
现在我们有了一个设置界面,但里面空空如也,我们要在里面放上两个东西。一个是标题,另一个是一个可以勾选的复选框。
标题的代码如下(追加到Config.lua文件中):
local l = f:CreateFontString(nil, &ARTWORK&, &GameFontNormalLarge&)
l:SetPoint(&TOP&, 0, -15)
l:SetText(&隐藏动作条装饰&)复制代码
我来解释下这三行代码。第1行,在“f”窗体下新建一个字符标签,放到“ARTWORK”层,使用“GameFontNormalLarge”字体,保存到局部变量“l”中。至于还有什么层,还有什么字体,你可以去自行查阅CreateFontString的信息,查阅后,你也不需要问我那个“nil”是干嘛的了。第2行,将新建的字符标签放到指定位置,详查SetPoint字条。第3行,指定字符标签的文字内容,应该没什么好解释的了。
再看复选框的代码(追加到Config.lua文件中):
local c1 = CreateFrame(&CheckButton&, &x&, f, &OptionsCheckButtonTemplate&)
c1:SetPoint(&TOPLEFT&, 10, -45)
getglobal(c1:GetName()..&Text&):SetText(&隐藏动作条两边装饰&)复制代码
我再来解释下这几行代码。第1行,新建一个“CheckButton”类型的窗体,命名为“x”,作为“f”的子窗体,使用“OptionsCheckButtonTemplate”模版,并保存到局部变量“c1”中。信息量有点多,我来解释下可能存在的几个疑点。(1)“CheckButton”为什么不叫“控件”,要叫“窗体”?在WOWUI中,确实是这么称呼的。对于没大接触编程的朋友可能会不大习惯,因为我们传统上理解的窗体是那种可以最小化、最大化和关闭的窗口。而在这里,窗体里的很多元素都叫窗体。(2)刚才都没有给窗体命名,这里为什么要命名?因为我们在下面要用到这个窗体的名字。(3)什么是模版?模版是暴雪预设好的,比较常用的,具有一定格式的窗体,我们使用模版可以减少装饰代码。比如这个“OptionsCheckButtonTemplate”模版自带了字符标签,我们就不需要另建字符标签了。
第2行,跟之前那段的第2行差不多,没什么好说的。你现在需要特别注意第3行。如果你通过查看别人做的插件的源代码来了解插件知识的话,这行代码其实并不常见。因为初学插件知识的人往往不会这么用,而那些做插件的老手往往喜欢借助Ace库,它们也不会写这么浅显的代码。这行代码的意思是将OptionsCheckButtonTemplate模版中的FontString的文字内容设定为“隐藏动作条两边装饰”。这里比较难理解的是为什么不直接用c1:SetText(&隐藏动作条两边装饰&),事实上那行不通,那用c1.FontString:SetText(&隐藏动作条两边装饰&)呢?也不行,因为FontString不是一个窗体。所以我们才会用getglobal()这么奇怪的一个函数。这个函数的大体意思是获取脚本的变量的值,这么说可能有些抽象,说实话我也是稀里糊涂地来理解的,我把它看作是JavaScript的getElementById。你看它括号里的c1:GetName()..&Text&,实际上是一个脚本元素的名称,是先获取c1这个窗体的Name,然后把这个Name跟“Text”字符串连接,也就是“xText”。也就是说这一行也可以这样写:getglobal(&xText&):SetText(&隐藏动作条两边装饰&),前提是你以后不会再去改动c1这个窗体的Name了,否则上面改了,下面没改,就会出错了。最后,我还要告诉你这一行的另一种写法,那就是:_G[c1:GetName()..&Text&]:SetText(&隐藏动作条两边装饰&)。你肯定会问我那个“_G”是个什么玩意儿,事实上我也很难讲清楚,去问Google吧。
下面我们要让插件根据我们对复选框的“选中”或“未选中”做出反应。你可以把这个反应代码直接写到复选框的OnClick事件中,这样每次选中或取消,它都会即时生效。但我们的插件界面给我们预留了一个“确定”键,何不让它点击“确定”再生效呢?
看代码(追加到Config.lua文件中):
f.okay = function()
& && &&&if c1:GetChecked() then
& && && && && & MainMenuBarLeftEndCap:Hide()
& && && && && & MainMenuBarRightEndCap:Hide()
& && &&&else
& && && && && & MainMenuBarLeftEndCap:Show()
& && && && && & MainMenuBarRightEndCap:Show()
& && &&&end
end复制代码
这段代码就不挨行解释了。我们按缩进来看,最外侧的是说点击插件界面中的“确定”键执行一个函数,这个函数是一个判断语句,这个判断语句的内容是:如果复选框被选中,则执行隐藏动作条两边装饰的代码,反之,则执行显示动作条两边装饰的代码。我觉得这几行代码很好理解,如果你觉得不太好理解,可能你需要先去了解下lua的函数和判断语句方面的知识。
现在重新载入插件,来点击复选框和确定按钮试一下吧。是不是那两只狮鹫可以随我们的设置来变化了吧?但是每次进入游戏或重新载入插件的时候,因为CapHide.lua的关系,那两只狮鹫总是会先被隐藏。而且设置界面中的复选框也不能根据狮鹫是否已隐藏来自动选中。不要着急,我们会在下一小节来解决这两个小问题。
这小一节的最后,给大家介绍一本书《魔兽世界编程宝典》,这本书有中文版,也有电子版,对于想认真学习插件的朋友,可以去找一下这本书。这本书的作者还建立了一个网站:,里面有很多插件资料,包括我们这一节提到的窗体模版。
本帖最后由 猎人Bill 于
16:42 编辑
史诗弓 0/1
幽灵狼宝宝 0/1
新人欢迎积分1 阅读权限40积分539精华0UID帖子金钱1297 威望0
Lv.4, 积分 539, 距离下一级还需 461 积分
UID帖子威望0 多玩草10 草
从零开始学插件——牛牛爸的插件学习笔记(3)
在上两节,我们做了一个功能非常简陋的小插件。功能是在登录游戏或重载插件时,隐藏动作条两边的装饰,然后可以通过插件界面进行设定,让动作条两边的装饰再显示出来或再次隐藏。但插件无法记住我们的设定,也无法根据当前的状态来自动勾选复选框,显得有些笨拙。这一节,我们来解决这些问题。
首先,我们要引入“角色信息变量”这个概念,“角色信息变量”保存在toc文件中,它是一个或多个全局变量,它的值在退出游戏时自动保存,在登录游戏时自动读取,插件就是靠这个“角色信息变量”来保存插件设定的。现在我们在CapHide.toc中Author那行下面加一行:
## SavedVariables: Bill_CapHide复制代码
Bill_CapHide就是我们声明的“角色信息变量”了,因为是全局变量,所以命名要复杂些,避免跟其它插件的全局变量冲突。除了用SavedVariables来保存“角色信息变量”外,我们还可以使用SavedVariablesPerCharacter,它们的区别是SavedVariables由一个帐号下所有角色共用,也就是说一个帐号下的所有角色使用相同的设置,而SavedVariablesPerCharacter是每个角色单独保存,也就是说一个帐号下的不同角色使用不同的设置。你可以根据你插件的功能来选择使用SavedVariables或SavedVariablesPerCharacter。
现在我们需要修改lua文件,让插件在适当的时候读取和保存Bill_CapHide变量。我们先来看修改后的CapHide.lua文件:
CapHide.lua
local f = CreateFrame(&Frame&)
f:RegisterEvent(&PLAYER_LOGIN&)
f:SetScript(&OnEvent&, function(self, event, ...)
& & & & if event == &PLAYER_LOGIN& then
& & & & & & & & if Bill_CapHide then
& & & & & & & & & & & & MainMenuBarLeftEndCap:Hide()
& & & & & & & & & & & & MainMenuBarRightEndCap:Hide()
& & & & & & & & else
& & & & & & & & & & & & MainMenuBarLeftEndCap:Show()
& & & & & & & & & & & & MainMenuBarRightEndCap:Show()
& & & & & & & & end
& & & & end
end)复制代码
上面代码的判断语句部分你应该会比较熟悉,我们上一节在Config.lua文件中写过类似的代码,只是判断条件由复选框是否选中改为了Bill_CapHide的值是否为true。我们在这里使用了简略的写法,将Bill_CapHide==ture写为Bill_CapHide,这在lua代码中是习惯用法,一上来可能看起来有些别扭,习惯了就好了。
在这里还要说下变量类型的问题,通过以上代码,我们基本可以确定Bill_CapHide是个布尔值型变量,其值无非为true、false、nil。当一个变量未赋值之前,值都是nil。而且lua规定nil等同于false。现在我们再回头看以上代码的判断语句部分,当这段代码在第一次执行时,Bill_CapHide并没有赋值,所以它的值是nil,所以判断语句判断到了else和end之间的部分,也就是说我们初次使用这个插件的时候,动作条两边的装饰是显示的。
现在我们再来看判断语句以外的部分。跟上一节Config.lua文件中的代码也有一些类似。新建了一个窗体,这个窗体没有名字也没有父窗体,所以它不会显示出来。我们建它的目的不是要作为界面,而是要注册一个事件。在这里我们注册了“PLAYER_LOGIN”事件,即角色登录事件。你也可以用别的事件,比如&ADDON_LOADED&,但要注意不同事件参数的不同。我们这里用“PLAYER_LOGIN”一是因为它用起来简单,二是因为我希望让自己的插件尽量在别的插件加载完成后再加载。这段代码比较难理解的应该是第3行,而这第3行里比较难理解的应该是function小括号里的那些参数,尤其是那个“...”。“...”表示任意数量的参数,即事件有很多参数,在这里我们主要取第2个“event”,后面的我们就不需要了,所以用“...”带过。
有的同学可能会提出一个疑问,为什么要建窗体、注册事件这么复杂,只保留那个判断语句不行吗?答案是不行。因为如果不检测事件,你的代码将在游戏一开始加载时就执行,这时“角色信息变量”的值还未被读出来,也就是说即使你Bill_CapHide的值保存了true,它也读取不出来,仍是nil。所以我们至少要在ADDON_LOADED事件之后再来获取“角色信息变量”的值。而PLAYER_LOGIN事件发生在ADDON_LOADED事件之后,还有些什么事件?你可以自行Google。
我们再来看修改后的Config.lua文件:
Config.lua
local f = CreateFrame(&Frame&, nil, InterfaceOptionsFramePanelContainer)
f.name = &CapHide&
InterfaceOptions_AddCategory(f)
local l = f:CreateFontString(nil, &ARTWORK&, &GameFontNormalLarge&)
l:SetPoint(&TOP&, 0, -15)
l:SetText(&隐藏动作条装饰&)
local c1 = CreateFrame(&CheckButton&, &x&, f, &OptionsCheckButtonTemplate&)
c1:SetPoint(&TOPLEFT&, 10, -45)
c1:SetScript(&OnShow&, function(c)
& & & & c:SetChecked(Bill_CapHide)
end)
getglobal(c1:GetName()..&Text&):SetText(&隐藏动作条两边装饰&)
f.okay = function()
& & & & Bill_CapHide=c1:GetChecked()
& & & & if Bill_CapHide then
& & & & & & & & MainMenuBarLeftEndCap:Hide()
& & & & & & & & MainMenuBarRightEndCap:Hide()
& & & & else
& & & & & & & & MainMenuBarLeftEndCap:Show()
& & & & & & & & MainMenuBarRightEndCap:Show()
& & & & end
end复制代码
前两段没有任何改变。第3段我们加上了三行,即从“c1:SetScript”到“end)”,这三行代码的意思是:当复选框显示的时候,读取Bill_CapHide的值,根据Bill_CapHide的值将复选框勾选或不勾选。这里比较容易产生困扰的是小括号里的那个c,c在这里作为参数的一个变量,实际上是将c1传了过来。也就是说我们可以省掉这个参数,直接在下一行将c写为c1,但是这样写就不严谨了。我们这里在触发事件后只执行了一项操作,如果执行了很多复杂的操作,不用参数传递变量的话,代码就不够灵活了。
再来看最后一段,加上了一行“Bill_CapHide=c1:GetChecked()”,即将复选框的选择状态(true或者false)赋值给了Bill_CapHide。还记得吗?Bill_CapHide是“角色信息变量”,这个变量的值在退出游戏时会自动保存的。假如我们现在选中了复选框,并点了“确定”按钮,Bill_CapHide的值就是true了,当下次登录游戏时,插件会读取Bill_CapHide的值,并根据CapHide.lua里的判断语句将动作条两边的装饰隐藏。既然复选框的选择状态已经赋值给Bill_CapHide了,那下面的判断语句也就不用判断复选框了,直接判断Bill_CapHide就可以了。
看到这里你会发现,CapHide.lua文件和Config.lua文件有7行相同的代码,也就是那个判断语句。在所有的编程语言中都有一个重要的指导思想,那就是避免代码重复。这既能让我们的代码变得简练,又能为以后的改进提供效率。如何在能避免代码重复?我们将在下一节再讨论。现在,你已经有了一个符合标准的插件,虽然它的代码还需要一些优化,但毫无疑问,它可以正常地工作了。它能在你进入游戏时自动加载,你可以通过设置界面改变它的设定,它可以保存你的设定。有句话怎么说的来着?麻雀虽小五脏俱全。是的,它是一只麻雀了。你想让它变成一只金丝雀吗?下一节,我们可以试一下。
史诗弓 0/1
幽灵狼宝宝 0/1
新人欢迎积分1 阅读权限40积分539精华0UID帖子金钱1297 威望0
Lv.4, 积分 539, 距离下一级还需 461 积分
UID帖子威望0 多玩草10 草
从零开始学插件——牛牛爸的插件学习笔记(4)
在上小一节,我们的插件基本上已经达到了可以用的程度,但插件代码还需要一些优化,在使用上也可以更方便一些。这一节,就让我们来做一些锦上添花、画龙点睛的工作。
首先,我们要引入“自定义函数”的概念。所谓自定义函数,就是自己写一组代码来实现某个功能,当我们需要用这个功能的时候,可以直接调用这个函数,而不需要每次都写相同的代码。以我们的代码为例,CapHide.lua文件与Config.lua文件都有7行相同的判断语句,我们可以把这个判断语句写成一个函数,代码如下:
function BillTools_CapHide()
& & & & if Bill_CapHide then
& & & & & & & & MainMenuBarLeftEndCap:Hide()
& & & & & & & & MainMenuBarRightEndCap:Hide()
& & & & else
& & & & & & & & MainMenuBarLeftEndCap:Show()
& & & & & & & & MainMenuBarRightEndCap:Show()
& & & & end
end复制代码
注意,我们function前面没有local,也就是说这是一个全局函数,因为我们CapHide.lua与Config.lua两个文件都将用到这个函数。作为全局函数,我们必须给它一个相对复杂的命名,并注意不要跟我们之前的变量名重名。我们可以把这段代码放到CapHide.lua文件中,原CapHide.lua文件中的判断语句从“if Bill_CapHide then”到“end”,可以改为“BillTools_CapHide()”了,代码如下:
local f = CreateFrame(&Frame&)
f:RegisterEvent(&PLAYER_LOGIN&)
f:SetScript(&OnEvent&, function(self, event, ...)
& & & & if event == &PLAYER_LOGIN& then
& & & & & & & & BillTools_CapHide()
& & & & end
end)复制代码
同样,我们可以替换Config.lua文件中的判断语句,Config.lua文件中最后一段,现在代码如下:
f.okay = function()
& & & & Bill_CapHide=c1:GetChecked()
& & & & BillTools_CapHide()
end复制代码
现在代码是不是简洁多了吧?但我们锦上添花的工作还没有结束。你会不会觉得每次调出游戏菜单,再点击“界面”按钮,再点击“插件”选项卡,再选择“CapHide”来设置我们的插件有些麻烦?可不可以通过一个命令直接调出我们插件的设置界面?答案当然是可以的。请在Config.lua文件加上以下代码:
SLASH_BILLTOOLS1 = &/billtools&
SLASH_BILLTOOLS2 = &/bt&
SlashCmdList[&BILLTOOLS&] = function()
& & & & -- 暴雪bug,首次调用需调用两次才能打开目标界面
& & & & InterfaceOptionsFrame_OpenToCategory(&CapHide&)
& & & & InterfaceOptionsFrame_OpenToCategory(&CapHide&)
end复制代码
我们从上往下看,SLASH_BILLTOOLS1和SLASH_BILLTOOLS2看似两个全局变量,但却不是普通的全局变量,它们在这里注册了两个命令,分别是&/billtools&和&/bt&。SlashCmdList是什么呢?你可以把它理解为一个接受命令的接口,当你在聊天栏输入一条命令时(以“/”开头),它会检索已注册的命令有没有符合条件的,如果有,它便会执行相关命令的代码。那我们这里要执行的是什么代码呢?首先,我们看到的是一行注释。我们的学习笔记进行到了第4节才提到注释,真是太不应该了。不过相信很多同学都已经知道如何在lua文件中使用注释了。注释下面那两行代码才是我们要执行的代码,至于为什么写了两行相同的代码,注释里已经写得很明白了。这也是我们在这里使用注释的原因,如果没有这行注释,日后你看到这两行相同的代码,还会以为你当时不小心多输了一行呢。因为我们经常会在Notepad++里按“Ctrl+S”的时候不小心按到“Ctrl+D”。
InterfaceOptionsFrame_OpenToCategory(&CapHide&)的意思应该比较好理解,就是打开插件界面里名字为“CapHide”的窗体。细心的同学可能会提出一个疑问,既然是打开“CapHide”窗体,注册命令的时候为什么不注册&/caphide&或&/ch&?因为我们的插件做到这里,隐藏动作条两边装饰的功能已经基本完结了,而我们的插件还将继续。换言之,CapHide将作为我们插件的一个功能存在,而我们的插件将换一个新的名字。既然是Bill的插件,里面是一些小工具的集合,就干脆叫“BillTools”吧。
保存你的插件,用“/rl”命令重新载入一遍插件,现在输入&/billtools&或&/bt&命令,是不是可以直接打开我们插件的设置界面了吧?最后,让我们再加上一行代码,让插件在每次在你进入游戏或重载插件时提示你插件加载成功,并告知可以使用&/bt&命令打开设置界面。代码如下:
DEFAULT_CHAT_FRAME:AddMessage(&|cff00CCFFBillTools加载成功!使用/bt命令打开设置界面!|r&)复制代码
这行代码加到哪里合适呢?当然是CapHide.lua文件的“BillTools_CapHide()”下面了。既然我们已经用“BillTools”给插件重新命名了,那就把toc文件和lua文件相关的名称也改一下吧。恰好我在写这篇学习笔记时,WOW已经从6.1升级到6.2,toc文件对应的版本号也得调整一下了。最终,调整后的插件文件代码如下:
BillTools.toc
## Interface: 60200
## Version: 0.2
## Title: BillTools
## Notes: Bill's Interface Package
## Title-zhCN: [|cff00CCFFBillTools|r] Bill的工具箱
## Notes-zhCN: Bill的小插件集合
## Author: Bill
## SavedVariables: Bill_CapHide
CapHide.lua
Config.lua复制代码
CapHide.lua
function BillTools_CapHide()
& & & & if Bill_CapHide then
& & & & & & & & MainMenuBarLeftEndCap:Hide()
& & & & & & & & MainMenuBarRightEndCap:Hide()
& & & & else
& & & & & & & & MainMenuBarLeftEndCap:Show()
& & & & & & & & MainMenuBarRightEndCap:Show()
& & & & end
end
local f = CreateFrame(&Frame&)
f:RegisterEvent(&PLAYER_LOGIN&)
f:SetScript(&OnEvent&, function(self, event, ...)
& & & & if event == &PLAYER_LOGIN& then
& & & & & & & & BillTools_CapHide()
& & & & & & & & DEFAULT_CHAT_FRAME:AddMessage(&|cff00CCFFBillTools加载成功!使用/bt命令打开设置界面!|r&)
& & & & end
end)复制代码
Config.lua
-- 注册、响应命令
SLASH_BILLTOOLS1 = &/billtools&
SLASH_BILLTOOLS2 = &/bt&
SlashCmdList[&BILLTOOLS&] = function()
& & & & -- 暴雪bug,首次调用需调用两次才能打开目标界面
& & & & InterfaceOptionsFrame_OpenToCategory(&BillTools&)
& & & & InterfaceOptionsFrame_OpenToCategory(&BillTools&)
end
-- 主界面
local f = CreateFrame(&Frame&, nil, InterfaceOptionsFramePanelContainer)
f.name = &BillTools&
InterfaceOptions_AddCategory(f)
-- 主标题
local r = f:CreateFontString(nil, &ARTWORK&, &GameFontNormalLarge&)
r:SetPoint(&TOP&, 0, -15)
r:SetText(&Bill的工具箱&)
-- 标题
r = f:CreateFontString(&r1&, &ARTWORK&, &GameFontNormalLarge&)
r:SetPoint(&TOPLEFT&, 10, -45)
r:SetText(&界面&)
-- 横线
r = f:CreateTexture(nil, &BACKGROUND&)
r:SetPoint(&TOPLEFT&, &r1&,&&&TOPLEFT&, 0, -20)
r:SetSize(600,1)
r:SetTexture(1, 1, 1, 0.6)
-- 复选框
local c1 = CreateFrame(&CheckButton&, &x&, f, &OptionsCheckButtonTemplate&)
c1:SetPoint(&TOPLEFT&, &r1&,&&&TOPLEFT&, 0, -25)
c1:SetScript(&OnShow&, function(c)
& & & & c:SetChecked(Bill_CapHide)
end)
getglobal(c1:GetName()..&Text&):SetText(&隐藏动作条两边装饰&)
-- 确定
f.okay = function()
& & & & Bill_CapHide=c1:GetChecked()
& & & & BillTools_CapHide()
end复制代码
改动的地方比较多,但如果你已经熟悉之前代码的话,一定会一眼看出哪些代码改动了,并能够理解这些改动的作用。这里要着重说下的是Config.lua文件,我们首次使用CreateTexture画了一条横线,也首次使用了SetPoint的相对定位。已经理解CreateFontString的你应该不难理解CreateTexture,已经理解绝对定位的你应该也不难理解相对定位,因为它们都是类似的。
现在,我们的插件已经初具雏形,尽管它的功能还很有限,但我们已经走过了编写一个简单插件的基本流程。剩下的工作就是对这个插件的功能进行扩展了。想必已经对Lua知识融会贯通的你已经想到下一步该加上什么功能了。是屏蔽聊天窗口那些烦人的广告?还是对绿色装备自动贪婪?对于那些能够举一反三的朋友,已经可以脱离我的学习笔记,依靠从相关网站查询到的相关知识来扩展自己的插件了。对于那些还想跟着我的学习笔记一路走下去的朋友,我们下小一节见!
史诗弓 0/1
幽灵狼宝宝 0/1
新人欢迎积分1 阅读权限30积分81精华0UID4126271帖子金钱163 威望0
Lv.3, 积分 81, 距离下一级还需 169 积分
UID4126271帖子威望0 多玩草10 草
MARK!教学贴啊~~~学习ing~~~
新人欢迎积分1 阅读权限40积分507精华0UID帖子金钱607 威望0
Lv.4, 积分 507, 距离下一级还需 493 积分
UID帖子威望0 多玩草0 草
謝樓主用心且詳細的教學
需要金钱:1100
Powered by
手机盒子客户端点击或扫描下载}

我要回帖

更多关于 网页游戏无法加载插件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信