魔兽插件程序员指南

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

程序员快速入手指南
作者:炽火Zero ℃
原文发表于:猫扑魔兽板块实用资料区
引言
本文将以一般的软件编程的眼光审视魔兽插件。

剥去其难解的外皮,让你有个清晰的大致了解。

“一针见血”是技术性教学文章的最高境界——炽火
魔兽插件的架构
插件工程——每个插件就是一个项目(或称为工程)。

目录位置:魔兽目录\Interface\Addons\项目名\
工程描述——即后缀名为Toc的文件。

描述工程的必要信息,也是项目载入时的总入口。

屏幕布局——布局描述使用XML文件。

使用各种标签代表特定对象(控件),并描述相互位置及各种特征属性。

功能脚本——脚本文件使用LUA语言。

使用WoW提供的API函数编写代码实现各种具体操作。

TOC ——工程描述文件
后缀名为toc的文件就是工程文件,包含工程的基本信息。

主要包含以下内容:
1 ##Interface:适用的魔兽版本号
2 ##Title:显示的标题(默认语言)
3 ##Notes:显示的说明(默认语言)
4 ##Title-zhCN:特定语言的标题(简体中文)
5 ##Notes-zhCN:特定语言的说明(简体中文)
6 ##Author: 作者
7 ##Version: 版本
8 ##Dependencies:依赖的插件
9 ##RequiredDeps:必须依赖的其他插件, 与上项作用相同
10 ##OptionalDeps:可选倚赖, 一般为库.
11 ##SavedVariables:统一存放的变量
12 ##SavedVariablesPerCharacter:按角色存放的变量
13 ##LoadOnDemand:1 插件在启用状态下不被加载, 必须在游戏内由另一个插件LoadAddOn()调用加载, 通常为存放数据用.
14 ##LoadWith:当指定插件加载时才加载,前提是LoadOnDemand
15 ##DefaultState:disabled 默认状态
16 ##Secure:安全, 只有暴雪插件才能被标记为安全
17 ##LoadManagers: 加载管理器, 通常是另一个插件(例子: AddonLoader, DBM)
18 ##X-Email: 如题
19 ##X-*: 以X-开头的标记通常为自定义标记, 请遵守这个准则.
20 # 注释1 dklasjfkasdj
21 Script.lua -- 脚本文件
22 % 注释2 dskajfklasdjfklsdaj
23 Layout.xml -- 布局文件
‘#’和‘%’为行注释符号。

而以##开头的注释行可就不光是好看的了,这些都是插件的工程描述标记,要是不注意插件根本就不会载入。

示例中彩色的标记表示标准标记,每个标准标记都有特定功能。

其它eMail, Author等为扩展标记,只有注释功能。

工程标记之后的部分为包含文件列表,脚本文件和布局文件,数量随意,但每种至少要有一个:一个lua或一个xml。

包含文件列表中的顺序对应着载入顺序,非常要紧!!!!
请将所有文件保存为UTF-8 NOBOM, 否则有可能会导致读取错误. 可以用专业文本编辑器修改编码及换行符, 如果你不知道什么是文本编辑器, 可以使用开源的Notepad++.
建议你多下几个插件,打开看看,参考一下。

XML ——屏幕布局描述文件
在魔兽插件中使用XML来描述UI的屏幕布局。

注释符号:<!-- 注释内容--> 。

如果要写中文注释,必须在XML文件开头添加一行:<?xml version="1.0" encoding="UTF-8"?>
XML文件主要内容
一个XML文件往往包含以下内容:
<!-- Ui标签是包含所有其它标签的根标签 -->
<Ui xmlns=""
xmlns:xsi=""
xsi:schemaLocation="
C:\Projects\WoW\Bin\Interface\FrameXML\UI.xsd">
<Script file="localization.lua"/> <!-- 在此载入用于汉化的lua文件 -->
<Frame name="zBar" parent="UIParent"> <!-- 一个Frame框架 -->
<Scripts> <!-- 脚本部分,用于处理事件 -->
<OnLoad>
zBar_OnLoad();
</OnLoad>
<OnEvent>
zBar_OnEvent(event);
</OnEvent>
</Scripts>
</Frame>
</Ui>
Ui标签
<Ui>是最上级标签。

其中的schema用来语法检查,如果你的XML编辑器支持还可以用来代码提示。

否则对我们来说用处不大。

可以简化为:
<Ui xmlns=""
xmlns:xsi="" >
</Ui>
或者更加简化,不太规范但是可用:<Ui>布局内容</Ui>
Script标签
在Ui标签中最先包含的往往是<Script file="lua 文件名"/>表示在此处载入某lua文件。

注意这里也有顺序哦,如果发现变量、函数不存在,检查一下看是不是顺序问题。

这样一来我们有了两种方法载入lua文件。

在xml中载入lua实际上不是非如此不可的,有时候没必要用xml的就直接在toc中放个lua,把xml省掉。

这样做你必须在lua中有个入口,也就是有个裸语句(不在任何function中的)进行事件注册或者调用函数。

Frame标签
XML中最主要的一个标签是<Frame></Frame>。

所谓Frame意指框架,就是用来包含其他东西的。

UIParent是最上层的框架,所有的UI都包含在其中。

与之并列的是一个特殊框架World Frame,包括FPS、截图。

其它控件一般都是Frame的子类,都包含类似的属性和子标签:背景、贴图、边框、事件处理。

如:<button> <slider> <statusbar> 等等。

Frame标签就像一个透明的玻璃容器。

你可以仅用它来装载其它部件,当然也可以给他添加贴图显示出来。

记得游戏中按下“Alt+z”的效果了么,被隐藏的就是UIParent。

容器被隐藏了,里面装的东西也就透明了。

子标签和属性
<Frame name="名称,唯一" inherits="myFather继承" toplevel="true等级" parent="UIParent父标签" id="编号" movable="true可移动" enableMouse="true允许鼠标事件" frameStrata="HIGH层级"
hidden="false隐藏">
<Size> <!--大小 -->
<AbsDimension x="" y=""/> <!--绝对尺寸 -->
</Size>
<!-- 简化写法 -->
<Size x="" y=""/>
<Anchors> <!--锚点,用来标记相对位置 -->
<Anchor Point="本控件的参考点" relativeTo="参考控件" relativePoint="参考控件的参考点">
<Offset> <!-- 偏移值 -->
<AbsDimension x="" y=""/>
</Offset>
<!-- 简化写法 -->
<Offset x="" y="" />
</Anchor>
</Anchors>
<!-- 背景和边框 -->
<Backdrop name="$parentBackdrop" bgFile="背景贴图" edgeFile="边框贴图" tile="不知道">
<EdgeSize>
<AbsValue val="18"/> <!-- 边框缩放大小 -->
</EdgeSize>
UI对象的继承关系
UIObject
始祖,所有其他UI对象都由它继承。

LayoutFrame
布局框架,继承UIObject,主要有一些布局函数,(这是一个虚类不可创建实例)。

LUA ——脚本代码文件
更深入的学习请阅读本站的其它文章:ProgrammingInLua,魔兽Api索引
如果你有一门以上的语言基础,那么学习lua语言不是什么难事。

lua是一种灵活的语言,关于他的来源我并不知道多少,只谈一下自己的感受。

基本语法和Basic类似,或者说更像是Asp 的脚本语言吧。

但同时他又借鉴了Java的长处,更加的智能化、灵活。

写法多样又方便不同习惯的人上手。

lua语法很简单,相关资料也很多,我只列出需要注意的部分。

基本语法摘要
行注释符号:“--”
段注释符号:“--[[]]”;实际上还是行注释,而“[[]]”包围的部分编译器会认为是一行。

行结束符号:用“;”或者不写都行,看你的习惯了,只要没有歧义就好
NULL空值:在这里是nil
没有指针:大多数变量类型都是值类型, 表是引用类型.
变量作用域:默认是global(全局作用域),加上local前缀就是局部的了(文件内部作用域)。

函数作用域:和变量一样默认是全局作用域。

lua的函数为first class object, 与变量一样操作.
数组,集合:只有一种,类似于。

我也不知道类似什么。

写法也很随意,举例:
Config = {
attribute1 = "apple",
attribute2 = false,
["attribute3"] = "animal",
[1] = "Button1",
["2"] = "Cool",
}
•关于数组的就看上面的“Lua脚本语言入门”,讲的很清楚。

关于布尔变量:要注意的是只有nil和false表示false,其他一律为true(包括0),而false是要占用引用内存的,建议把false一律换成nil。

关于布尔运算:lua里的布尔运算是很有趣的,也相当合理。

注意运算的值并不是布尔值,而是其中一个操作数的值。

x = a and b; -- 与运算,a为false则x等于a,a为true则x=b。

x = a or b; -- 或运算,a为true则x等于a,a为false则x = b。

•是不是有点晕?其实很合理。

如果你一时绕不清楚,就只要记住结果好了。

布尔运算的妙用:我坚定地认为lua中的布尔运算实际上不是布尔运算,而是简化了的条件语句。

比如:
x = a and b; --相当于:
if (not a) then
x = a;
else
x = b;
end
x = a or b; -- 相当于:
if (a) then
x = a;
else
对象
函数
函数实际上是一种特殊变量
它指向一段代码,更一般的调用符号和一般的对象属性相同,为“.”。

而特殊符号“:”实际上是在调用的时候多加了一个参数“self”,指代调用者本身。

例如:
Frame1:SetAlpha(0.5)
-- 相当于
Frame1.SetAlpha( Frame1, 0.5)
函数的默认参数
有一些函数参数比较特殊:对象事件处理函数,有一些有默认参数,例如(!)已经在4.0被移除
OnClick OnMouseDown OnMouseUp;默认参数 arg1
OnEvent;默认参数event
所以在定义这些函数的时候可以不写参数:
function zOnClick()
if ( arg1 == "LeftButton" ) then
doSomething()
end
end
但是要注意:如果函数定义里写了参数,那么调用函数的时候一定要写参数!!!!否则认为参数为nil。

例如:
<OnClick>if ( not this.lock ) then zOnClick(arg1) end</OnClick>
之所以有默认参数存在是因为在动态改变事件处理函数的时候不能写参数,例如
button:SetScript("OnClick", zOnClick)
默认参数的原理
经过多方考证,这些默认参数均为全局变量。

实现默认参数得流程为:对象触发事件时会调用对应函数,在其中将全局变量即默认参数赋值。

例如xml中有如下描述:
<OnClick>zOnClick()</OnClick>
虽然不知道WoW虚拟机确切的处理方式,但我们可虚拟如下:
-- 事件触发时调用对象的事件处理函数
Object:OnClick("LeftButton")
-- 该处理函数定义模拟如下
function Object:OnClick(arg1)
zOnClick()
end
-- [[
由于arg1 为全局变量,对象被调用时 arg1 被赋值为"LeftButton"
其后Object:OnClick()中又马上调用了zOnClick()插件处理函数,
其中并无被改变的机会,因此 arg1 被成功传递,看起来就像是默认参数了。

-- ]]
默认参数还包括this,但是self 不是全局变量。

其他资料网站
WoW FrameXML源码:
API/Event资料:。

相关文档
最新文档