一、准备工作
(1)查阅
WowWiki: 提供了大量有用的WOW API,其中最重要的有
- World_of_Warcraft_API 列举了所有可用的API
- Event_API 列举了所有事件
- Widget_API 列举了操作GUI的相关API
(2)工具
WowLua: 游戏内Lua编辑器
SciTE: Lua编辑器
二、Lua语法
(1)数据类型
- nil 空
- boolean 布尔值, 0为true
- number 数字
- string 字符串
- userdata 没看懂
- function 函数
- thread 线程,wow插件开发用不到
- table lua最强大数据类型,lua无array和map之分,统一使用table,index从1开始,不是0开始
(2)运算符
- +(加)
- -(减)
- *(乘)
- /(除)
- ^(幂)
- %(取模)
- and(与)
- or(或)
- not(非)
(3)关系运算符
- ==(等于)
- ~=(不等于)
- >(大于)
- >=(大于等于)
- <(小于)
- <=(小于等于)
(4)局部变量和全局变量
do a=1 --全局变量 local b=2 --local 代表局部变量,仅限在此do-end代码块内可见 end print(a)-->1 print(b)-->nil,这里无法使用上面的"local b"
(5)控制语句
if-else
if( a == 10 ) then print("a 的值为 10" ) elseif( a == 20 ) then print("a 的值为 20" ) elseif( a == 30 ) then print("a 的值为 30" ) else print("没有匹配 a 的值" ) end
while
local i = 1 while a[i] do print(a[i]) i = i + 1 end
for
for i = 1, 3 do print(i) end for k, v in pairs(t) do print(k, v) end
repeat...until
a = 10 repeat print("a的值为:", a) a = a + 1 until( a > 15 )
goto
goto quit print('come on') ::quit:: print('quit') --这里只输出quit
(6)函数
定义函数
function GetPlayerPosition(unit) if unit=="player" then return 1,2,3 end end local x,y,z = GetPlayerPosition("player") --lua可以有多个返回值
匿名函数
local x,y,z = function(unit) --不定义函数,直接使用函数体赋值 if unit=="player" then return 1,2,3 end end print(x,y,z)
可变参数函数
--使用...关键字 function variable(...) local a={...}--接收可变参数 print(#a)--获取a的个数 end variable(1,2)-->2 variable(4,3,2,4,5)-->5 variable()-->0
(7)数据库
math
math.abs(x) --绝对值 math.ceil(x) -- 向上取整 math.max(x1,x2,...) --最大值 math.min(x1,x2,...) --最小值 math.random(x, y) --x y之间随机值 math.pi --3.1415926...
string
string.byte(str, start, end) --获取start到end 字节流 string.find(str, pattern, start, plain) --查找,plain表示是否识别为正则表达式 string.format(str, ...) --格式化 string.len(str) --获取长度 string.match(str, pattern, start) --正则查找
table
table.concat(tb1, sep, i, j) --sep是元素分割符,默认"";i起始坐标,默认1;j结束坐标,默认#tb1 table.insert(tb1, position, value) --向tb1插入元素value到position table.sort(tb1, func) --排序,且只作用于array部分,对hash table部分无效,func是比较函数,默认是< table.remove(tb1, position) --删除position位置元素 table.maxn(tb1) --返回最大指针,同时作用于hash table部分(key 为number?)
debug
debug.traceback() --打印堆栈
os
os.date(format, time) --日期,默认格式mm/dd/yy hh:mm:ss os.difftime(time1, time2) --time2 - time1 os.time() --Unix 时间
(8)正则表达式
符号 | 匹配 |
---|---|
^ | 行首 |
$ | 行尾 |
. | 所有字符 |
%a | 字母 |
%c | 控制字符( , ...) |
%d | 数字 |
%l | 小写字母 |
%p | 标点符号(, .) |
%s | 空格(空格,制表符) |
%u | 大写字母 |
%w | 字母和数字(0,1,a,A...) |
%x | 十六进制(0,1,a,A,f,F...) |
local str = "Hello, World! 123" print(str:match("%w*")) --> Hello
三、一个例子
(1)文件结构
一个Wow插件实际上就是一个包含若干文件的文件夹,只需要将文件夹拷贝到World of Warcraft/_classic_/Interface/AddOns目录下,游戏启动时就会自动加载该插件。
一个Wow插件至少包含一个toc文件和若干lua文件,其中
- toc是配置文件,与文件夹同名
- lua是插件代码文件,包含插件业务逻
以HelloWorld插件为例
HelloWorld.toc为配置文件,toc文件格式分两部分:以##开头的是配置项;其他是需要加载的程序文件
##Interface: 10200 (适用于Wow1.2.x版本) ##Title: Hello,World! (插件名) ##Title-zhCN: 一个插件 (插件中文名) ##Notes: a simple debug addon! (简介) ##X-Category: Pet (自定义配置项) HelloWorld.lua (lua文件)
toc完整的配置项如下,也可以自定义配置项(如上,以"X-"开头)
## Interface: 适用的魔兽版本号 ## Title: 显示的标题(默认语言) ## Notes: 显示的说明(默认语言) ## Title-zhCN: 特定语言的标题(简体中文) ## Notes-zhCN: 特定语言的说明(简体中文) ## Author: 作者 ## Version: 版本 ## eMail: 邮箱 ## UIType: 插件类型 ## Dependencies: 依赖的插件 ## RequiredDeps: 必须依赖的其他插件 ## OptionalDeps: 可选倚赖 ## SavedVariables: 统一存放的变量,用于数据持久化 ## SavedVariablesPerCharacter: 按角色存放的变量 ## LoadOnDemand: 0 启动时加载;1 调用时加载 ## LoadWith: 当指定插件加载时才加载,前提是调用时加载 ## DefaultState: 默认是否可用 ## Secure: Blizzard签名插件 Script.lua -- 脚本文件 Layout.xml -- 布局文件
(2)编写Lua代码
lua是代码文件,通过调用Wow API来完成我们想要的功能。
以HelloWorld插件为例,我们希望在适当的时候存入一些key-value数值对,并且随时可以通过key提取对应的value值:
HelloWorld_Text = {} --定义一个table,用于存储数值对 local channel = "SAY" --定义一个本地变量,代表数据将要发送的聊天频道 SLASH_HELLO_WORLD_ADD1 = "/hwadd" --定义一个Slash命令 SLASH_HELLO_WORLD_ADD2 = "/helloworldadd" --别名 SlashCmdList["HELLO_WORLD_ADD"] = function(msg) --指定Slash命令处理器 local id, text = msg:match("(%S+)%s+(.+)") --提取key, value if id and text then --key和value不为nil HelloWorld_Text[id:lower()] = text --存入table end end SLASH_HELLO_WORLD_SHOW1 = "/hwshow" --定义另一个Slash命令 SLASH_HELLO_WORLD_SHOW2 = "/helloworldshow" --别名 SlashCmdList["HELLO_WORLD_SHOW"] = function(msg) --指定Slash命令处理器 local text = HelloWorld_Text[msg:lower()] --按key提取value if text then --value不为nil SendChatMessage(text, channel) --将Value发送到指定聊天频道 end end
(3)调用插件
将HelloWorld文件夹放入Interface/AddOns目录,启动游戏就可以在插件列表看到我们的插件了。
通过/hwadd命令插入一些数据
/hwadd 1 猎人 /hwadd 2 德鲁伊 /hwadd 3 战士
通过/hwshow命令提取数据
/hwshow 3
(4)持久化
到目前为止,我们的数据只是存储在HelloWorld_Text变量中,并没有持久化到本地数据库,一旦游戏退出,数据也消失了。Wow插件的数据持久化非常简单,无需操作数据库,只需要在toc配置文件中配置即可
## SavedVariables: HelloWorld_Text
只需要这一行,系统会自动将HelloWorld_Text变量中的数据存储到数据库,并且在下次加载插件后将这些数据再次赋值到HelloWorld_Text。
至此,一个简单的插件完成!