这里只介绍和插件编写比较有关的几个函数. 详细的Lua手册请参照Lua Reference Manual 5.1.
assert(value) - 检查一个值是否为非nil, 若不是则(如果在wow.exe打开调试命令)显示对话框以及输出错误调试信息
collectgarbage() - 垃圾收集器. (新增于1.10.1)
date(format, time) - 返回当前用户机器上的时间.
error("error message",level) - 发生错误时,输出一条定义的错误信息.使用pcall() (见下面)捕捉错误.
gcinfo() - 返回使用中插件内存的占用量(kb)以及当前垃圾收集器的使用量(kB).
getfenv(function or integer) - 返回此表已获取函数的堆栈结构或者堆栈等级
getmetatable(obj, mtable) - 获取当前的元表或者用户数据对象.
loadstring("Lua code") - 分析字符串中的lua代码块并且将结果作为一个函数返回
next(table, index) - 返回下一个key,一对表值.允许遍历整个表
pcall(func, arg1, arg2, ...) - 受保护调用. 执行函数内容,同时捕获所有的异常和错误.
select(index, list) - 返回选择此列表中的商品数值.或者是此件物品在列表中的索引值
setfenv(function or integer, table) - 设置此表已获取函数的堆栈结构或者堆栈等级
setmetatable(obj, mtable) - 设置当前表的元表或者用户数据对象
time(table) - 返回从一个unix时间值
type(var) - 判断当前变量的类型, "number", "string", "table", "function" 或者 "userdata".
unpack(table) - 解压一个表.返回当前表中的所有值.
xpcall(func, err) - 返回一个布尔值指示成功执行的函数以及调用失败的错误信息.另外运行函数或者错误的返回值
table函数库
一部分的table函数只对其数组部分产生影响, 而另一部分则对整个table均产生影响. 下面会分开说明.
table.concat(table, sep, start, end)
concat是concatenate(连锁, 连接)的缩写. table.concat()函数列出参数中指定table的数组部分从start位置到end位置的所有元素, 元素间以指定的分隔符(sep)隔开.
除了table外, 其他的参数都不是必须的, 分隔符的默认值是空字符, start的默认值是1, end的默认值是数组部分的总长.
sep, start, end这三个参数是顺序读入的, 所以虽然它们都不是必须参数, 但如果要指定靠后的参数, 必须同时指定前面的参数.
> tbl = {"alpha", "beta", "gamma"}> print(table.concat(tbl, ":"))alpha:beta:gamma> print(table.concat(tbl, nil, 1, 2))alphabeta> print(table.concat(tbl, "\n", 2, 3))betagamma
table.insert(table, pos, value)
table.insert()函数在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾.
> tbl = {"alpha", "beta", "gamma"}> table.insert(tbl, "delta")> table.insert(tbl, "epsilon")> print(table.concat(tbl, ", ")alpha, beta, gamma, delta, epsilon> table.insert(tbl, 3, "zeta")> print(table.concat(tbl, ", ")alpha, beta, zeta, gamma, delta, epsilon
table.maxn(table)
table.maxn()函数返回指定table中所有正数key值中最大的key值. 如果不存在key值为正数的元素, 则返回0. 此函数不限于table的数组部分.
> tbl = {[1] = "a", [2] = "b", [3] = "c", [26] = "z"}> print(#tbl)3 -- 因为26和之前的数字不连续, 所以不算在数组部分内> print(table.maxn(tbl))26> tbl[91.32] = true> print(table.maxn(tbl))91.32
table.remove(table, pos)
table.remove()函数删除并返回table数组部分位于pos位置的元素. 其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元素删起.
table.sort(table, comp)
table.sort()函数对给定的table进行升序排序.
> tbl = {"alpha", "beta", "gamma", "delta"}> table.sort(tbl)> print(table.concat(tbl, ", "))alpha, beta, delta, gamma
comp是一个可选的参数, 此参数是一个外部函数, 可以用来自定义sort函数的排序标准.
此函数应满足以下条件: 接受两个参数(依次为a, b), 并返回一个布尔型的值, 当a应该排在b前面时, 返回true, 反之返回false.
例如, 当我们需要降序排序时, 可以这样写:
> sortFunc = function(a, b) return b < a end> table.sort(tbl, sortFunc)> print(table.concat(tbl, ", "))gamma, delta, beta, alpha
用类似的原理还可以写出更加复杂的排序函数. 例如, 有一个table存有工会三名成员的姓名及等级信息:
guild = {}table.insert(guild, { name = "Cladhaire", class = "Rogue", level = 70,})table.insert(guild, { name = "Sagart", class = "Priest", level = 70,})table.insert(guild, { name = "Mallaithe", class = "Warlock", level = 40,})
对这个table进行排序时, 应用以下的规则: 按等级升序排序, 在等级相同时, 按姓名升序排序.
可以写出这样的排序函数:
function sortLevelNameAsc(a, b) if a.level == b.level then return a.name < b.name else return a.level < b.level endend
测试功能如下:
> table.sort(guild, sortLevelNameAsc)> for idx, value in ipairs(guild) do print(idx, value.name) end1, Mallaithe2, Cladhaire3, Sagart
数学函数库
以下是一些常用的Lua标准库的数学成员, 按字母顺序排列.
函数 功能
math.abs(x) 返回x的绝对值math.ceil(x) 返回不小于x的最小整数math.deg(x) 将弧度制的x转化为角度math.exp(x) 返回e的x次方math.floor(x) 返回不大于x的最大整数math.fmod(x, y) 或x % y, 返回x除以y的余数math.log(x) 返回x的自然对数值math.log10(x) 返回x的常用对数值math.max(x, y, z, ...) 返回参数列表中的最大值math.min(x, y, z, ...) 返回参数列表中的最小值math.modf(x) 返回两个值, 依次为x的整数和小数部分math.pi 圆周率常量math.pow(x, y) 计算并返回x的y次方math.rad(x) 将角度制的x转化为弧度math.random(m, n) 产生随机数, 参数可选并影响范围: 无参数时为[0, 1), 单参数时为[1, m], 双参数时为[m, n]math.randomseed(x) 重设随机种子math.sqrt(x) 开平方根运算
字符串函数库
以下是一些常用的Lua标准库的字符串工具:
函数 功能
string.len(s) 返回s的长度string.lower(s) 返回一个s的副本, 其中的所有大写字母均转换为小写string.rep(s, n) 返回一个字符串, 由n个s头尾相接而成string.reverse(s) 返回一个由s倒转构成的字符串string.sub(s, i, j) 返回s的子字符串, 从i开始, 到j(可缺, 默认为末尾)结束 i, j可以是负值, 此时从字符串结尾开始向前计算 例如: Hello的-3~-1代表llo子字符串string.upper(s) 返回一个s的副本, 其中的所有小写字母均转换为大写
format(formatstring[, value[, ...]]) - 格式化字符串
gsub(string,pattern,replacement[, limitCount]) - 全局替换
strbyte(string[, index]) - 转换字符串为整数值(可以指定某个字符).
strchar(asciiCode[, ...]) - 转换整数为相对应的字符
strfind(string, pattern[, initpos[, plain]]) - 在一个指定的目标字符串中搜索指定的内容(第三个参数为索引),返回其具体位置.
strlen(string) - 返回当前字符串的字符数
strlower(string) - 将字符串的字母转换为小写格式
strmatch(string, pattern[, initpos]) - 与strfind不同的是,macth返回的是具体值,而find返回的是此值的位置
strrep(seed,count) - 返回一个字符串种子副本的个数
strsub(string, index[, endIndex]) - 返回字符串指定位置的值.
strupper(string) - 将字符串的字母转为大写格式
tonumber(arg[, base]) - 若参数能转为数字则返回一个数值.可以指定转换的类型.默认为十进制整数
tostring(arg) - 转换参数为字符串
字符串格式化
Lua提供了string.format()函数来生成具有特定格式的字符串, 函数的第一个参数是格式(formatstring), 之后是对应格式中每个代号的各种数据. 由于格式字符串的存在, 使得产生的长字符串可读性大大提高了. 这个函数的格式很像C语言中的printf().
格式字符串可能包含以下的转义码:
%c - 接受一个数字, 并将其转化为ASCII码表中对应的字符%d, %i - 接受一个数字并将其转化为有符号的整数格式%o - 接受一个数字并将其转化为八进制数格式%u - 接受一个数字并将其转化为无符号整数格式%x - 接受一个数字并将其转化为十六进制数格式, 使用小写字母%X - 接受一个数字并将其转化为十六进制数格式, 使用大写字母%e - 接受一个数字并将其转化为科学记数法格式, 使用小写字母e%E - 接受一个数字并将其转化为科学记数法格式, 使用大写字母E%f - 接受一个数字并将其转化为浮点数格式%g(%G) - 接受一个数字并将其转化为%e(%E, 对应%G)及%f中较短的一种格式%q - 接受一个字符串并将其转化为可安全被Lua编译器读入的格式%s - 接受一个字符串并按照给定的参数格式化该字符串
为进一步细化格式, 可以在%号后添加参数. 参数将以如下的顺序读入:
(1) 符号: 一个+号表示其后的数字转义符将让正数显示正号. 默认情况下只有负数显示符号.(2) 占位符: 一个0, 在后面指定了字串宽度时占位用. 不填时的默认占位符是空格.(3) 对齐标识: 在指定了字串宽度时, 默认为右对齐, 增加-号可以改为左对齐.(4) 宽度数值(5) 小数位数/字串裁切: 在宽度数值后增加的小数部分n, 若后接f(浮点数转义符, 如%6.3f)则设定该浮点数的小数只保留n位, 若后接s(字符串转义符, 如%5.3s)则设定该字符串只显示前n位.
在这些参数的后面则是上述所列的转义码类型(c, d, i, f, ...).
以下是一些例子:
string.format("%%c: %c", 83) 输出Sstring.format("%+d", 17.0) 输出+17string.format("d", 17) 输出00017string.format("%o", 17) 输出21string.format("%u", 3.14) 输出3string.format("%x", 13) 输出dstring.format("%X", 13) 输出Dstring.format("%e", 1000) 输出1.000000e+03string.format("%E", 1000) 输出1.000000E+03string.format("%6.3f", 13) 输出13.000string.format("%q", "One\nTwo") 输出"One\ Two"string.format("%s", "monkey") 输出monkeystring.format("s", "monkey") 输出 monkeystring.format("%5.3s", "monkey") 输出 mon
在魔兽世界中还有另一个string.format()参数, 允许不按后面的列出顺序读取参数. 在这种情况下, 使用参数的排位+$符号来指定特定的参数.(此语句在非WoW的Lua编译器中将不能正确运作. 请使用WoWLua或Lua511WoW)
例如:
> print(string.format("%2$d, %1$d, %d", 13, 17))17, 13, 13
如果设定了$参数, 其必须紧接在%符号之后, 并且所有的后续参数(在这里指13, 17)都必须被访问; 换言之如果有3个参数, 不能只使用1$和3$. 可以混用含有$和不含$的转义符; 不含$的转义符将自动从参数列表的头部开始获取数据.
$参数在实现本地化中非常方便. 在不同的语言中, 特定的名词可能会以不同顺序出现. 使用带有$参数的格式字符串, 可以使不同语言版本的客户端共用相同的参数列表.
例如下面这句游戏提示:
Cladhaire's Shadow Word: Pain is removed.
在德语版客户端中是这样写的:
'Shadow Word: Pain' von Cladhaire wurde entfernt.
在英文版中技能(暗言术·痛)出现在角色名称(Cladhaire)之后, 但在德语版中顺序正相反. 如果参数列表中角色名称是排在技能名称之前, 可以为不同的客户端分别写出如下的格式字符串:
英文版: %s's %s is removed.德文版: '%2$s' von %1$s wurde entfernt.
这样只要向string.format()传入不同的格式字符串即可, 不需重写具有不同参数次序的语句.
字符串配对
书写插件经常会遇到的一个问题是: 如何处理游戏提供的文本并从中配对获取所需的信息. Lua提供了一系列的函数, 这些函数可以根据给定的配对表达式, 和给定的字符串配对, 并处理成功配对的部分.
配对表达式支持以下的字符类:
单个字符(除^$()%.[]*+-?外): 与该字符自身配对.(点): 与任何字符配对%a: 与任何字母配对%c: 与任何控制符配对(例如\n)%d: 与任何数字配对%l: 与任何小写字母配对%p: 与任何标点(punctuation)配对%s: 与空白字符配对%u: 与任何大写字母配对%w: 与任何字母/数字配对%x: 与任何十六进制数配对%z: 与任何代表0的字符配对%x(此处x是非字母非数字字符): 与字符x配对. 主要用来处理表达式中有功能的字符(^$()%.[]*+-?)的配对问题, 例如%%与%配对[数个字符类]: 与任何[]中包含的字符类配对. 例如[%w_]与任何字母/数字, 或下划线符号(_)配对[^数个字符类]: 与任何不包含在[]中的字符类配对. 例如[^%s]与任何非空白字符配对
(还有一个转义码是%f. %f被称作Frontier Pattern, 因为一些原因没有被写入Lua的标准文档中. 有兴趣的朋友可以看lua-users wiki: Frontier Pattern)
当上述的字符类用大写书写时, 表示与非此字符类的任何字符配对. 例如, %S表示与任何非空白字符配对.
配对表达式是由上述字符类代号加上特定选项构成的, 这些特定选项包括:
不加任何选项(例如"%a"): 与单个该类字符配对后接*号(例如"%a*"): 与0个或更多该类字符配对. 只与给定字符串中符合要求的最长子串配对.后接+号(例如"%a+"): 与1个或更多该类字符配对. 只与给定字符串中符合要求的最长子串配对.后接+号(例如"%a-"): 与0个或更多该类字符配对. 只与给定字符串中符合要求的最短子串配对.后接?号(例如"%a?"): 与0个或1个该类字符配对.
配对表达式还可包含以下两个成员:
%bxy: 其中x, y是字符. 与x开始, y结束, 并且x, y在字符串中平衡配对的字符串配对. 平衡配对表示: 设一初始值为零的计数器, 从给定字符串左侧至右侧逐个读取字符, 每读取一个x, 计数器+1, 每读取一个y, 计数器-1, 那么最后一个y恰好是第一个使计数器归零的y. 也可以说, 在%bxy成功配对的字符串中, 找不到更短的子字符串使其满足%bxy配对. %n: 其中n是1~9的数字. 与捕获(见下文)的第n个配对字串配对.
例如: 给定字串"abc ABC 123 !@# \n \000 %"
配对表达式 配对结果
%a a b c A B C%a* abc ABC%a+ abc ABC%a-%s abc ABC%a? a b c A B C