注意: 虽然AI脚本可以使用大部分common.j的库函数, 但有些类型的函数在AI不能正常工作, 如:
a) 返回字符串类型(string)的本地函数, 如I2S(), SubString()等
b) 需要以code, trigger, boolexpr 等类型数据为参数的本地函数, 如触发器函数, 队列函数(ForGroup, 等)
注意: AI中不可以使用Blizzard.j的函数, 触发器中也不可以使用common.ai的函数, AI和触发器都可以使用common.j的函数(当然, 对于AI, 还受上面所说的限制)
common.ai和common.j是写AI时可以调用和参考库文件, 要研究AI, 先去读这2个文件.
3) 跨脚本通讯(Inter-Script Communication)
在游戏中, 可能会有多个独立的Jass脚本文件同时运行. 比如在对战地图中的游戏, 运行触发器脚本文件的同时, 也可能运行了每个电脑玩家的AI脚本文件. 每个脚本文件之间的全局变量不是共享的. 所以, 一个电脑玩家的AI脚本中设置的全局变量不会影响另一个电脑玩家的AI脚本的执行.
触发器脚本也不可以和AI脚本共享全局变量. 但可以用传递命令的方法进行脚本之间的数据交换. 命令由一对数值型数据(integer)组成: 命令值(command value)和数据值(data value).
从触发器脚本向AI脚本发出通讯命令, 可以使用common.j中定义的以下本地函数:
native CommandAI takes player num,
integer command, integer data returns nothing
参数:
player num //玩家
integer command //命令
integer data //命令数据
以下是AI中使用的common.j函数, 注意: 每个电脑玩家都会有独立的AI脚本, 所以, 以下函数都没有要求玩家作为函数参数.
每个电脑玩家都有命令堆来堆放接受到的命令. 想知道有多数个命令堆放在命令堆, 可以用下面的函数:
native CommandsWaiting takes nothing returns integer
参数: 无
返回: 命令堆的命令数(integer)
获得存放在命令堆中最顶端的命令():
//返回命令
native GetLastCommand takes nothing returns integer
//返回命令数据
native GetLastData takes nothing returns integer
上面2个函数都不会移除命令堆中的命令, 要移除堆中的命令, 可以用:
native PopLastCommand takes nothing returns nothing
4) 队列(Enumerations)
虽然JASS不能自定义数据结构(因为JASS缺少指针操作符), 但API库中提供了一些实现队列操作的函数. 如一组单位为单位组(group), 一组玩家为势力(force), 虽然一组可破坏物没有明确定义它的数据类型, 但也可以用API函数来操作.
单位组和势力的操作函数很类似.
单位组处理函数
// 初始化单位组
native CreateGroup takes nothing returns group
// 在指定单位组中增加指定单位
native GroupAddUnit takes group whichGroup, unit whichUnit returns nothing
// 在指定单位组中移除指定单位
native GroupRemoveUnit takes group whichGroup, unit whichUnit returns nothing
势力处理函数
// 初始化势力
native CreateForce takes nothing returns force
// 在指定势力中增加指定玩家
native ForceAddPlayer takes force whichForce, player whichPlayer returns nothing
// 在指定势力中移除指定玩家
native ForceRemovePlayer takes force whichForce, player whichPlayer returns nothing
JASS不能直接操作队列里面的元素, 它是通过callback类型的函数来实现对队列的操作:
// 对指定单位组中的每个单位都运行指定callback函数callback
// (对应GUI语言的For Each Unit in )
native ForGroup takes group whichGroup, code callback returns nothing
// 对指定势力中的每个玩家都运行指定callback函数callback
// (对应GUI语言的For Each Player in )
native ForForce takes force whichForce, code callback returns nothing
输入上面两个函数的callback函数必须是无参数无返回值函数(takes nothing returns nothing)
同样, 操作可破坏物也可以用在区域内的可破坏物作为队列, 可以以用类似的方法:
// 在指定区域r内符合指定过滤器filter的都运行指定callback函数actionFunc
// (过滤器见下节的讲解)
native EnumDestructablesInRect takes rect r,
boolexpr filter, code actionFunc returns nothing
在callback函数, 可以用下面的函数获得队列中的下一个元素:
// 获得单位组中的下一个单位
// (对应GUI语言的Pick Every Unit in )
constant native GetEnumUnit takes nothing returns unit
// 获得势力中的下一个玩家
// (对应GUI语言的Pick Every Player in )
constant native GetEnumPlayer takes nothing returns player
// 获得可破坏物组中的下一个可破坏物
// (对应GUI语言的Pick Every Destructables in )
constant native GetEnumDestructable takes nothing returns destructable
注意: AI中不支持队列函数的使用.
这是杀死单位组中所有单位的实例:
// 这是callback函数, 无参数并无返回值
function KillGroupCallback takes nothing returns nothing
// 获得单位组中的下一个单位
local unit nextUnit = GetEnumUnit()
// 杀死该单位
call KillUnit(nextUnit)
endfunction
// 调用ForGroup
// 对单位组groupToKill中的每个单位都运行函数KillGroupCallback
call ForGroup(groupToKill, function KillGroupCallback)
另一个经常是用的例子是在队列中查找特定条件的元素. 不幸的是, 因为JASS只支持callback函数来处理队列中的元素, 所以只有用全局变量来保存不同单位的属性. 下面是找出单位组里生命最高的单位的例子:
//定义全局变量
globals
//用于储存两单位比较后较高的生命值, 初始化为 0
real mostLifeSoFar
//用于储存两单位比较后有较高生命值的单位, 初始化为 null
unit unitWithMostLifeSoFar
endglobals
//比较单位生命值的callback函数
function MostLifeCallback takes nothing returns nothing
//获得单位组中的下一个单位
local unit nextUnit = GetEnumUnit()
//获得单位属性 - 生命
//UNIT_STATE_LIFE是common.j中定义的常量
local real life = GetUnitState(nextUnit, UNIT_STATE_LIFE)
|