相关连接
http://war3.uuu9.com/war3rpg/List_477.shtml
一:介绍
- jass脚本定义为一系列 *.ai 和*.j文件, 这些文件允许触发器脚本或AI脚本
- 地图脚本:common.j, Blizzard.j, war3map.j (按顺序加载)
- AI脚本: common.j, common.ai, 用户自定义AI脚本(human.ia等)
- common.j, Blizzard.j, common.ai 在MPQ中 (Scripts目录中)
- war3map.j 放在*.w3m地图文件中
二: 语法
2.1 类型定义
type new_type extends parent_type
2.1.1 基础类型
Type | 类型 | |
---|---|---|
integer | 整数 | 32 位, -2147483647 到 2147483647 |
real | 实数(即浮点数或小数) | 32 位,并符合 IEEE 标准 754 浮点标准 |
boolean | 布尔 | true, false |
string | 字符串 | 空值可以用 null |
handle | 句柄,结构体引用 | 基本上是一个”指针”。 指一些数据结构 从句柄继承的所有用户定义的类型。 例如,是指向游戏中某些单位数据结构的子类型。可以为任何句柄变量分配值,这意味着它引用任何。 |
code | 函数引用 | 函数引用作为参数,似于 C 或 C++ 中的函数指针 function RunFunctionForAllPlayers takes code theFunction returns nothing |
array | 数组 |
2.1.2 在Jass中Integer的几中特殊形式:
- 十进制: 任意数字, 负数、0、正数, 如: 12, -1999, 9999
- 八进制: 首位为0表示8进制数字, 如012等于10
- 十六进制: 以 0x 开头, 例如:0x2=2,0xA= 10,0x10 = 16,0xFF =255 。
- 字符: ‘xxxx’ 单引号加字符形式,该形式为256进制整数,每个字符代表其AscII码值,区分大小写,一般用来表示单位、物品、技能等代码。比如对战单位里剑圣的代码是 ‘Obla’
- 4 个字符. -整数使用的 4 个字节的 ASCII 中的表示形式,此表示形式主要用于单位/技能/地形片tile/科技/等id。示例:”Aloc”,”B000”
2.1.3 string
string是字符串变量, 可以是null(空值). 注意Jass的字符串是大小写区分的, 赋值时用双引号 “” 引用
- 空值表示方式 null 和 “”
转义
- \n\r 回车符
- \“ 引号
- \\ 转义斜杠
格式
-
** cAARRGGBB** 文本颜色, AA是alpha, RR是红色,GG是绿色,BB是蓝色, 用十六进制值。如 ffCC1100 -
** r** 将文本颜色重置为正常 -
** n** 新行,相当于回车符 如:
|cffff0000技能名称|r (|cffffcc00二级|r) |n 技能描述
技能描述
2.1.4 array
-
指一组同类型的有序列的变量. 数组中包含的元素可以用[n]来指明(n 表示第n + 1个元素, 从 0 算起).
-
以上所说的变量类型中除了code类型, 其他类型的变量都可以定义数组变量
-
数组所有元素初始值是”空”, 比如integer类型的数组初始值为0, handle类型初始值的为null
-
数组不能直接再次初始化, 只能数组按元素赋值
-
数组在函数间不能互相传递. 即是不能把数组作为函数参数, 而且函数也不能返回数组类型的变量.
-
数组元素域在 0 和JASS_MAX_ARRAY_SIZE = 8192 之间, 即是最多有JASS_MAX_ARRAY_SIZE + 1 个元素. JASS_MAX_ARRAY_SIZE是在common.j中定义的常数
locate integer array dropitems set dropitems[0] = 'Xxxx' ...... set dropitems[18] = 'Xbbb' // dropitems[18]指dropitems中第19个变量.
数组不能直接再次初始化, 只能数组按元素赋值, 如:
locate string array playername = "Greedwind" //数组非法赋值 locate string array playername //数组元素只能逐个赋值 set playername[1] = "Greedwind" set playername[2] = "Greedwind's girlfriend" unit array myUnits unit array yourUnits
set myUnits = yourUnits // 非法 set myUnits[0] = yourUnits[10] // 合法
2.1.5 WORLD EDITOR和JASS变量类型对照表:
World Editor 变量名 | Jass变量类型 |
---|---|
Boolean | boolean 布尔型(用于真/假判断) |
Destructible | destructable 可破坏物 |
Dialog | dialog 对话 |
Dialog Button | button 按钮 |
Floating Text | texttag 漂浮文字 |
Integer | integer 数值 |
Item | item 物品 |
Leaderboard | leaderboard 排行榜 |
Player | player 玩家 |
Player Group | force 玩家组 |
Point | location 位置(点) |
Real | real 真值型数字 |
Region | rect 地区 |
Special Effect | effect 特效 |
String | string 字符串 |
Terrain Deformation | terraindeformation 地形 |
Timer | timer 计时器 |
Timer Window | timerdialog 计时器窗口 |
Unit | unit 单位 |
Unit Group | group 单位组 |
Player Score | playerscore 积分(1.13版新类型) |
2.2 变量
2.2.1 全局变量
- 声明都在封闭的globals … endglobals块中
- 每个文件只能有一个全局块
- 每个声明都单独一行
- 变量类型:可以是基本类型,也可以是基本类型的数组
- 变量声明的时候值可选
- 常量声明前面加constant,不能用于数组
globals
type name = expression
type name = expression
type name = expression
...
endglobals
例如,下面是一个整数变量,初始化为值 10:
integer num = 10
初始化为另外两个变量的量值的常数整数变量:
constant integer howManyUnits = numberOfGrunts * numberOfAttacks
未初始化的字符串变量:
string someMessage
单位数组。无法初始化数组。
unit array listOfUnits
2.2.2 局部变量
- 局部变量只能声明在函数里
- 必须声明在函数开头,函数中间逻辑声明会报错
声明格式
local type name = expression
实例
function IntAdd takes integer a, integer b returns integer
local integer result = a + b
return result
endfunction
function Trig_ZFLearn02TrigerActions takes nothing returns nothing
// 必须声明在开头
local integer aa = 10
local integer bb = 20
local integer r
call YDWEDisplayChat( Player(0), 0, udg_zfChatMsg )
call YDWEDisplayChat( Player(0), 0, zfName )
call YDWEDisplayChat( Player(0), 0, "add before: aa=" + I2S(aa) + ", bb=" + I2S(bb))
set r = ZF_TestFunBase(aa, bb)
//local integer rr = r // 这里声明会报错
call YDWEDisplayChat( Player(0), 0, "add after: aa=" + I2S(aa) + ", bb=" + I2S(bb) + ", result=" + I2S(r))
endfunction
2.2.3 set: 给变量赋值,必须加set
function IntAdd takes integer a, integer b returns integer
local integer result = a + b
set a = a + a // 可以
b = b + b // 错误
set a += a // 错误
return result
endfunction
2.2.4 数组
local integer array numArr
set numArr[0] = 1
set numArr[1] = 2
set numArr[3] = 3
call YDWEDisplayChat( Player(0), 0, I2S(numArr[3]) )
2.3 内置函数 native function
-
魔兽 III 引擎中实现的功能, 导出给 JASS 程序员的 API
-
除非您有权访问魔兽III的源代码,否则您可能不会定义新的内置函数,但可能会调用它们
-
他们声明在 common.j, common.ai, Blizzard.j
声明格式:
native func_name takes param_list returns return_type
实例:
native MakeUnitTalk takes string whatToSay, unit targetUnit returns nothing
2.4 自定义函数
- 函数也可以声明为前缀。
constant
- 定义函数的关键字有:
function
…endfunction
,takes
,returns
-
函数名的首个字母不能是数字, 函数名中不能有操作符, 特殊字符和多数非字母符号(如: 空格[~`!@#$%^&*()-+= {}];:’”<>?,./), 也不能使用中文. 函数命名要尽量简明易懂, 突出函数功能. - 参数表是规定传递入函数的数据类型和参数数量, 作用是函数间的数据交换(输入), 参数之间用逗号( , )分开. 不能定义数组作为参数
- 调没有返回值的函数前面一定要加
call
funanme(arg)
声明格式:
function func_name takes param_list returns return_type
variable_declaration
variable_declaration
...
statement
statement
statement
...
endfunction
声明 无参数
和无返回值
的函数, 如
// 声明函数
function myfunction1 takes nothing returns nothing
endfunction
// 调用函数
call myfunction1() // myfunction1为无参数的函数, 调用时不需要传递参数, 即是用
声明 多个参数用逗号分隔
// 声明函数
function myfunction2 takes integer creatnum, unit myunit returns boolean
call CreateNUnitsAtLoc(creatnum, GetUnitTypeId(myunit), Player(1),
GetUnitLoc(GetTriggeringUnit()), bj_UNIT_FACING )
return true
endfunction
// 调用
local boolean isOk = myfunction2(1, myUnit)
set isOk = myfunction2(2, myUnit)
如果函数声明的前缀为 ,如下所示:constant
请注意,您仍然可以使用正文中的语句来更改函数参数,因此在典型意义上,它不是真正的”常数”;它更像是对程序员的暗示
constant function const_func takes integer a returns nothing
...
endfunction
2.4.1 回调函数 用法
- 声明参数类型用
code
- 传递参数时需要加
function
globals
integer zfTimeIndex = 0
timer zfTimer
endglobals
function ZF_TimeOnTick takes nothing returns nothing
set zfTimeIndex = zfTimeIndex + 1
call YDWEDisplayChat( Player(0), 0, "zfTimeIndex=" + I2S(zfTimeIndex) )
if zfTimeIndex >= 5 then
call DestroyTimer(zfTimer)
set zfTimer = null
endif
endfunction
function ZF_TimeStart takes code tickHandlerFun returns nothing // 声明参数类型 code
set zfTimer = CreateTimer()
set zfTimeIndex = 0
call TimerStart(zfTimer, 2.0, true, tickHandlerFun)
endfunction
function Trig_ZFLearn02TrigerActions takes nothing returns nothing
call ZF_TimeStart(function ZF_TimeOnTick) // 传递参数时需要加 `function`
endfunction
2.5 程序执行入口函数
- 每个Jass脚本文件都需要定义执行程序的入口函数
- 在触发器脚本文件war3map.j中,
config()
和main()
是入口函数. config()
函数作用是在开始游戏之前初始化地图, 如按设计时指定点放置单位/可破坏物,初始化单位状态等.main()
函数在游戏开始才执行- 在AI脚本文件中, 用户需自定义
main()
函数作为该脚本文件的程序入口. - 注意: 一张地图中只能有1个触发器脚本文件war3map.j, 此文件包含在w3m或w3x中
- 注意: 一张地图中可以包含多个AI脚本文件, 输入AI脚本文件的目录为: \scripts\
脚本文件执行入口函数的固定格式:
function main takes nothing returns nothing //触发器和AI脚本均使用
function config takes nothing returns nothing //触发器脚本使用
2.6 条件判断 if… elseif…else…endif
语法
if predicate then
statement
statement
...
elseif predicate then
statement
statement
...
elseif predicate then
...
else
statement
statement
...
endif
实例
function ZF_Compare takes integer a, integer b returns integer
local string strA = I2S(a)
local string strB = I2S(b)
if a == b then
call YDWEDisplayChat( Player(0), 0, strA + " == " + strB )
return 0
elseif a > b then
call YDWEDisplayChat( Player(0), 0, strA + " > " + strB )
return -1
else
call YDWEDisplayChat( Player(0), 0, strA + " < " + strB )
return 1
endif
endfunction
2.7 循环 loop … endloop
语法
loop
...
exitwhen expression
...
endloop
实例
local integer iterations = 10
loop
if DidTheThingEnoughTimes() then
call DisplayText("Exiting Early")
exitwhen true
endif
call DoSomething()
set iterations = iterations - 1
exitwhen iterations == 0
endloop
function ZF_TestLoop takes nothing returns nothing
local integer i = 0
call YDWEDisplayChat( Player(0), 0, "循环开始 i=" + I2S(i) )
loop
call YDWEDisplayChat( Player(0), 0, "i=" + I2S(i) )
set i = i + 1
exitwhen i >= 10
endloop
call YDWEDisplayChat( Player(0), 0, "循环结束 i=" + I2S(i) )
endfunction
2.8 运算符
数学计算:
+ | 加 |
---|---|
- | 减 |
* | 乘 |
/ | 除 |
比较符号:
> | 大于 |
---|---|
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
布尔条件
and | 条件 且 |
---|---|
or | 条件 或 |
not | 条件 否 |
字符串拼接
+ | 连接字符串, 比如: local string a = “ZF” + “_” + “大海明月” |
---|---|
2.9 注释用双斜杠
// 注释
local string name = "zf" //声明本地变量
三:问答
3.1 什么是common.j, Blizzard.j, common.ai
- common.j 是最基础的API库文件, 在Trigger Jass和AI Jass中都可以调用.
- Blizzard.j 包含使用Trigger Editor时生成的Trigger Jass中经常调用的库函数/全局变量, 实际上是基于common.j写的子函数. Blizzard.j只能在Trigger Jass中调用.
- common.ai 只能在AI Jass中调用, 它有AI中需要使用的函数和全局变量.
3.2 如何获得最新的common.j, Blizzard.j, common.ai?
在war3.mpq/war3x.mpq/war3patch.mpq都有common.j/Blizzard.j/common.ai, 要获得最新版本的文件, 可以用WINMPQ打开war3patch.mpq, 在WINMPQ右上方的输入框中输入: scripts* ,如果你的war3patch.mpq没有”加密”过, 那么可以找到这3个文件. 如果是”加密”过的, 则需要把war3patch.mpq的文件全部解压到临时目录, 然后用Ultra-Edit中的在文件中搜索字符的功能寻找这3个文件.
3.3 可以在自己的地图中使用自定义的common.j, Blizzard.j, common.ai吗?
可以. 用输入管理器输入自定义的common.j, Blizzard.j, common.ai, 输入目录应为\scripts. 这样, 运行地图中的脚本时, War3就不会到war3patch.mpq寻找这3个文件了而直接从地图中的\scripts\目录调用. 这样做的好处就是可以使库文件的同步一致. 通常, 版本相同的WAR3, 其库文件也相同, 所以多数时候不需要在地图中输入这3个文件. 但如果你更改了这3个基本文件来支持你的Jass, 或者确保为了库文件的一致性, 便可以在地图中输入基础库文件.
3.4 实用问题: 如何创建外观随机可变的地图?
上面说过, main()是地图入口函数, 在main()调用了一些再现地图设计时原貌的子函数如CreateAllUnits(). 因此, 我们可以在CreateAllUnits()中加入随机函数GetRandomInt()来控制单位/物品/可破坏物等初始化过程.
我们可以用WINMPQ打开要修改的地图, 提取war3map.j来修改main()函数及其相关函数. 修改完war3map.j后, 再用WINMPQ导入修改后的war3map.j.
3.5 总结下Blizzard函数名/全局变量名的规律:
前坠/相关词 | 介绍 |
---|---|
前坠 Get | 取得某属性, 此类函数一般有返回值 |
前坠 Set | 设置某属性 |
前缀 Create | 创建 |
前缀 Remove | 移除 |
前坠 Is | 是否判断, 此类函数返回类型都是boolean, 返回true或false |
前缀 bj_ | 在Blizzard.j中定义声明的全局常量(常量是指定义并赋值后不能再改变的值) |
后缀 BJ | 此函数肯定是在Blizzard.j中定义的, 不能在AI中使用. |
中间有 2 数据类型转化函数 | 如S2I(), I2R, I2S()等 |
有 Item/Unit/… | 肯定是与物品/单位/…相关的函数 |
全部大写 | 在common.j中定义声明的全局常量 |