《闪电战1》地图编辑及脚本教程 小欧欧

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 129

《闪电战 1》

地图编辑及脚本教程

作者:小欧欧

1
目 录
第一章:地图编辑器初级教程

第一节:打开地图和添加单位…………………………………………..4

第二节:添加建筑、战壕及道路……………………………………….16

第三节:空中支援的设置……………………………………………….30

第二章:地图编辑器进阶教程

第一节:新建地图并在游戏中运行…………………………………….33

第二节:给新地图添加脚本…………………………………………….51

第三节:添加援军及援军脚本………………………………………….61

第四节:设置小地图上的紫色箭头…………………………………….68

第五节:单位的初始命令及敌方进攻脚本范例……………………….71

第三章:地图编辑器的常用功能和使用技巧示例

第一节:随机地形和物体的设置………………………………….……76

第二节:各种道路和桥梁的连接和美化…………………….…………80

第三节:设置高地及防御据点示例……………………………….……89

第四节:地图编辑器的常用功能介绍………………………………….95

附录 1:脚本 script 函数说明(汉化作者:Liukun1982) ………98

附录 2:老论坛的脚本编辑入门教程…………………..………...105

附录 A:脚本 script 函数列表(与脚本编辑入门教程配套)…..127

2
前 言
《闪电战 1》是一款经典的以第二次世界大战为背景的即时战略游戏,从发布至今,
已经过去许多年。因为当年国内无良盗版商的虚假广告,这款游戏被误认为是《突袭 2》
的续作,所谓的“突袭 3”,因此遭到不少突袭玩家的抵制,当年我也是抵制的其中之
一。但是瑕不掩瑜,这款游戏的优秀还是打动了我。

最初我没有任何教程,仅仅凭借《突袭 2》的一些修改和地图编辑经验就开始摸索
这个游戏的修改及地图编辑,虽然略知一二,但还是没有摸透,直到后来到闪电战论坛
和各位前辈交流,看了论坛的教程后,才知道如何去制作一张完整的地图。

非常可惜的是,老闪电战论坛因为各种原因最终关闭,导致大量优秀资源流失,其
中各类教程的丢失是最让人心痛的!虽然新论坛已经建立,但是丢失的教程无法找回。
本人作为老论坛的后辈,作为《闪电战》的忠实玩家,有义务把这些教程重新编写。但
是本人水平有限,而且本人并非计算机专业,只能把一些基础的技巧和流程展示给大家。
希望有更高水平的玩家指点。

对于新上手的玩家来说,地图编辑器其实并不难,那么为什么作图的人这么少呢?
原因就在于作图的步骤非常繁琐,而且每一步都需要有人手把手去教。以前的教程图片
较少,新人很难上手,我如果不是之前熟悉了这个编辑器,光看教程也很难学会。所以,
这次我编写的教程就是图文并茂的,手把手教你如何使用地图编辑器和写地图脚本。希
望有兴趣的玩家能耐心看完这个教程。

小欧欧
2014 年 1 月

3
第一章:地图编辑器初级教程

第一节:打开地图和添加单位

首先用地图编辑器前,我们要知道地图文件在哪里。打开闪电战 1 的安装目录,然后打开 data


文件夹。你可以看到很多 pak 结尾的文件。这是闪电战 1 的所有数据文件的压缩包,可以用压缩软
件 WinRAR 打开。(你可以把所有 pak 文件都当做普通的文件夹)找到 data.pak 文件,用 WinRAR
打开。

打开后可以看到下图,里面有很多文件夹,所有的地图文件都在 Maps 文件夹里。

打开 Maps 文件夹,可以看到下图:以 bzm 后缀的就是地图文件。而相同文件名以 lua 后缀的文


件是相应的地图脚本文件,我们会在以后的教程里用到。其他的文件夹里的文件是战役的地图文件
和教程地图,联机地图,不推荐初学者修改。 (Allies.German,USSR 分别对应盟军,德军,苏军的战
役地图,Multiplayer 里的是联机地图)

4
我把 kursk.bzm 文件解压到 F 盘的 Maps 文件夹。(事先在 F 盘建一个 Maps 空文件夹)

然后在游戏安装目录里打开地图编辑器 mapditor.exe

5
打开后可以看到下图,在任务栏左上角点 File——Open 打开地图。

会弹出一个对话框,见下图

Name 就是地图名称和路径,我们可以点后面的 Browse...找到解压的地图文件。

而下面的 MOD 是指用什么组模打开,如果我们是修改原版地图,就选择“no any MOD”

这里强烈不推荐新手使用各种组模打开原版地图,弄不好这会导致无法进入游戏!切记!

6
在 F 盘的 maps 文件夹里找到解压的地图文件,见下图

好了,选择成功后可以看到下图,点“OK”

7
看,成功打开地图了。地图的左边是任务栏,是我们修改地图的主要操作界面,如果不慎关闭,
可以点任务栏右上角左边第 3 个按钮(见红圈)
左边的任务栏第一行“Terrain”是编辑地形的工具,我们先跳过。

点击第二行的“Object,Fences,Bridge”(看不懂英文的,本人建议自己用翻译软件,我这里不一
一解释了)可以看到下图:

8
点击那个小三角,会弹出一排选项,例如我要添加苏军火炮,就选择“Soviet Artillery”

然后在前面的小方框点一下(打钩)
接着在下面的“Thumbnails”前的小圆圈里点一下,就可以看到单位的图标。见下图。

9
然后我们找到 152mm_ML-20,选择它,然后在地图上点一下左键就添加一个文件。
我们可以通过左下角的小地图来调整地图界面的方位。

10
我们添加 2 门炮,但是火炮朝向明显不合适。可以通过“Angle”里的那个指针调整方向,见下
图。

光有炮不行,我们再添加 2 辆重型运输车。选择“Soviet Transp”见下图。

11
和添加火炮一样,添加运输车。

好了,初步编辑到此,我们点左上角的保存图标保存地图。

好了,修改完的地图如何才能在游戏里读取呢?
我们就要把修改好的地图文件制作成新的 Pak 文件。
这里说明一下,data 文件夹里所有的 pak 文件都是同级平行的,如果两个 pak 文件里有同一文
件名的文件,系统会默认读取最新的文件。(这也是各种绿色补丁的工作原理)
利用这一特点,新建一个 pak 文件可以不改动原版的 pak 文件,如果出错,可以直接删掉我们
做的文件,而不影响游戏运行。

12
好了,开始新 pak 文件的制作:首先复制一个最小的 pak 文件“updata-1.pak”

然后重命名为“My-maps”(方便记忆,可以随意命名)

用压缩软件打开 My-maps.pak

13
打开 F 盘,找到我们新建的 Maps 文件夹

如下图,把 Maps 文件夹直接拖到压缩文件里。

然后删掉压缩文件里其他的文件夹,只保留 Maps 文件夹(不删也可以,不过可能会影响游戏


的运行)

14
最后进入游戏看看修改的效果吧,选择自定义任务,选择“Not One Step Back”这个任务(就
是我们修改的任务)

进入游戏后可以看到新添加的单位。

好第一章第一节到此结束!

15
第二节:添加建筑、战壕及道路

我们接着上一讲继续编辑地图。
同样打开地图编辑器,读取上次编辑的地图 kursk.bzm

打开地图后,点左边任务栏的第三行“Entrenchment,Roads,Rivers”进入编辑战壕的界面。
这个地图的苏军战壕过于靠前,所以我们来编辑一下,把鼠标放到战壕上,如图。

16
然后点击键盘的“delete”键,就可以删掉战壕了。如图。

我们看到战壕里的两队步兵还在地图上,如果不删除会导致地图无法读取。
我们回到编辑物体的界面,即任务栏第二行“Objects,Fences,Bridges”
记住,所有物体(包括单位,建筑,植物,其他物件)的添加、移动、删除都在这样界面。

17
选定地图上的步兵,同样按“delete”键删除,如图。

好了,删除了两队步兵。

然后我们点任务栏第一行的地表编辑来美化一下地图,如图。
看见 2X2 的那个选项了吗?那是调整编辑地形的刷子尺寸的,可以选择试试。

18
然后我们继续删除过于靠前的战壕和步兵,如图。多操作几次就会熟练。

删除完战壕,我们在合适的地方重新添加战壕。
还是在编辑战壕的界面,直接在地图上想要添加战壕的地方点一下左键,然后移动鼠标,可以看到
下图的红色线段。有小短线突出的方向就是战壕的朝向,这里补充说明一下,三小段的战壕长度刚
好容纳一队步兵。

好,我们再点一下左键,再次移动鼠标,就可以让战壕拐弯。

19
我们再点一下左键,变换一下方向,如图。
(如果不合适,可以点右键取消)

最后双击一下左键,战壕就添加到地图上了,如图。

20
好了,添加好战壕后我们继续添加步兵,同样在物体编辑的界面,点“Squads”,进行步兵的编辑。
我们找到苏军的 1941 年步兵班。

和添加其他单位一样,在地图上添加步兵。

21
我们点一下任务栏左上角的那个红色框框。

可以看到下图的效果,这样单位和战壕的尺寸就很直观了吧。

22
然后我们把步兵拖到战壕上,此时鼠标会变成向上的箭头,然后放开就成功把步兵放到战壕里了。

23
然后我们继续添加碉堡,回到物体编辑界面,选择“Pillboxes”,如图。

同样的添加方法,把选定的碉堡添加到地图上,如图。

24
然后再添加一队步兵,如图。

和把步兵拖到战壕一样,把步兵拖到建筑里(一样会有向上的箭头)

25
为了美化地图,我们添加一点道路。点击任务栏第三行“Entrenchment,Roads,Rivers”,然后点
“Roads”

选择“road_path”,把“Width”的数据改成 1,这是道路的宽度,数据越大道路越宽。
下面的“Opacity”是道路的透明度,100 是不透明,0 是完全透明。

26
添加的方法和战壕一样,点左键开始,每点一次可以改变方向。

最后双击确定添加。

27
继续添加道路。

好了,添加完成,保存地图。

28
打开上次我们新建的 pak 文件:My-maps.pak

在里面找到 kursk.bzm

然后把我们改好的地图拖进去,点确定就行了。好了,我们进入游戏看看吧。

好第一章第二节到此结束!

29
第三节:空中支援的设置

我们继续之前的教程,同样是拿原版的 kursk 这张地图来举例说明。


打开地图编辑器,读取 kursk 这张地图。
然后看编辑器上面的任务栏中间那个倒过来的飞机图标(鼠标指针处),这就是设定空中支援和交战
方阵营的按钮。见下图。

好了,点击后可以看见弹出一个对话框:
Player[0]即玩家,Player[1]是电脑。
点一下 Player[0]前的小加号。

30
好,继续点 Aviation 前的小加号,可以看见下图。

这里开始详细说明:
1. Paratroop squad name 是空降兵类型,本地图里设定的是 USSR_rilfe_43 即苏军 1943 年步兵班。
如果想修改,点步兵班的名字就可以选择你想要的步兵类型。
2.Paratroop squad count 是每架运输机运载的步兵班数量,本地图里是 2,即每架运输机会投下 2 队
步兵。
3.Relax time 即空中支援的间隔时间,单位是秒。本图里 240 即 240 秒,也就是 4 分钟,你可以点击
数字,然后改动。不建议改得太小,不然地图就很没意思了。
4.Appear points 这是飞机从地图边缘出发的地点,本图里苏军有 3 个出发点。 (注意,如果没有出发
点将不能使用空中支援)
5.Party name 这个就是阵营设定,本图里玩家 0 是苏军。
好我们继续点 Aircrafts 前的小加号。可以看到下图

31
Fighters 即战斗机
Paradropers 即运输机
Bombers 即轰炸机
Attckers 即对地攻击机
我们点对地攻击机前的小加号,可以看到
Name 即飞机类型,这里是伊尔 2,你可以点击飞机名称改变飞机类型。
Formation sive 是每次出动的飞机数量
Count 是你拥有的这个类型飞机的总数量。这里建议把数值设为 Formation sive 的整数倍。
好了,修改好了以后你可以保存,放到游戏里看看修改效果了。

好第一章第三节到此结束!
下一章我们将学习如何新建一张地图,并添加脚本在游戏里运行。

32
第二章:地图编辑器进阶教程

第一节:新建地图并在游戏中运行
在熟悉了前面的【地图编辑教程 1-3】后,就可以进一步学习新地图的制作过程。
新手请按照我的步骤一步步弄,包括地图名和设置,熟悉以后可以参照此教程自由发挥。
此教程比较长,请慢慢看,不要心急!

首先我们打开地图编辑器,点击新建地图(如图)

然后会弹出一个对话框,我们选择 8X8 的小地图,夏季,不使用组模,命名为 text-map1。如图

33
然后就进入编辑器了,我们开始编辑。如图

我们现在左下角设置玩家 0(即玩家)的资源仓库(我方单位和建筑在小地图里是绿色),如图

34
然后在右上角设置玩家 1(即电脑)的资源仓库,
(电脑的单位和建筑在小地图里是红色)如图
这里之所以先设置资源仓库是为了强调这一建筑的重要性,地图上必须要有资源仓库补给车才会自
动补充资源(单纯野外仓库不行)

然后我们回到玩家 0 的设置,添加我方单位,这里设为德军。如图

35
添加完毕(先添加少量单位测试),如图

然后调到玩家 1 设置电脑单位,如图

36
然后回到玩家 0 的基地,选择玩家 0,点击编辑器上方中间的摄像机,这样认为开始的画面就是我
方基地了,如图
(成功添加后编辑器里可以看到一个绿色的摄像机)

接下来我们设置阵营和空中支援,点击摄像机旁边的倒置小飞机,如图。

看到弹出的对话框

37
调节对话框大小,并且点击“+”号展开选项,在玩家 0 的“Party name ”里设置为德国“German”,
空中支援按我的设置弄(这是一个熟悉过程,以后你可以自己发挥),如图

但是单单这样设置是不能调用空军的,因为没有设置起飞点,因此我们点击“Apper points”,如图

38
又弹出一对话框,点击“Add...”添加起飞点,如图

再弹出一对话框,可以看到两个坐标值可以设置,我们取 X=0,Y=0。
(即左下角,左下角数值永远
是 0,0),点 OK。如图

好了,设置好的话“Apper points”选项里可以看到有 1 个起飞点,如图

39
同样设置玩家 1(电脑)的空军和阵营,如图

同样玩家 1 是没有起飞点的,我们要添加,例如我想其在最右侧起飞,把鼠标移到最右边,记住地
图编辑器下方的坐标值(VIS 后面的两个数值)128 ,128. 如图

40
然后和上面一样添加起飞点,坐标:128,128,如图

设置好了,如图

41
点击保存,如图

地图制作完成了,按照建图的路径找到地图文件,如图

然后我再教一次大家制作 PAK 文件,进入闪电战的 data 文件夹,复制最后那个 PAK 文件,如图

42
重命名为我们的地图名 test-map1 (方便你以后查找修改),如图

用 WinRAR 打开新建的 PAK 文件,把放我们新地图的 maps 文件夹拖动添加到 PAK 文件里,如图

添加好了,如图

43
删去多余的文件,这样新图的 pak 文件就出步建好了,如图

但是单单这样我们是无法在游戏里找到地图的,我们还有制作一些文件。
打开 data.pak 文件,按照 Scenarios\Custom\Missions\路径找到 dessau 文件夹,将其解压出来。如图
(注意解压出来后的路径,要和截图的一样)

44
找到我们解压的 dessau 文件夹,(注意看路径,必须一致)如图

同样重命名为 test-map1,如图

45
进入文件夹,可以看到很多文件,其中那个“header.txt”文件即游戏里地图的名字。
双击打开它,重新编辑为“test map 1”记住这个名字,这就是我们的新地图在游戏里的名字。如图

然后双击打开"1.xml"文件,这是游戏读取地图的配置文件,非常重要,里面数据的设置失误会导致
游戏无法读取地图。
打开后我们可以看到里面的数据都是文件的路径指向,如图(记住那个“dessau”,我们接下来要把它
改为“test-map1”,即我们新图的路径)

46
退出 1.xml 文件,点右键选择用写字板打开,如图

打开后我们选择编辑-替换:把“dessau 全部替换为“test-map1”,如图
替换完后保存。

47
保存后退出,再双击打开 1.xml 文件,我们可以看到改动后的效果,如图

然后退出,把整个 Scenarios 文件夹拖拽到新建的 test-map1.pak 文件里,如图

48
添加成功。

这样就大功告成了,进入游戏看看效果吧!

49
第二章第一节到此结束!

50
第二节:给新地图添加脚本

我们接着进阶教程 1,继续给之前新建的地图“test-map1”添加脚本。
首先,我们先解压一个已有的 lua 脚本文件。和之前一样打开 data 文件夹里的 data.pak 文件。
再打开 Maps 文件夹,解压 dessau.lua 文件(最好和之前解压地图文件的路径一样)。
我这里是解压到 D 盘,和之前的地图文件路径一样。

然后找到解压的脚本文件,重命名为 test-map1.lua
(可以看见和之前的地图文件一起在 D 盘的 maps 文件夹里。)

51
然后用记事本打开脚本文件开始编辑。

我们全选内容,然后全部删除。
(我们开始从零开始写脚本)

52
将我下面的脚本命令复制到文件里。
DisplayTrace("test-map1");

function Init()
RunScript("Objective0", 2000);
end;

---------------------------------------

function Objective0()
ObjectiveChanged(0,0);
RunScript("Objective0OK", 10000);
DisplayTrace("消灭敌人!");
Suicide();
end;

function Objective0OK()
if GetNUnitsInArea(1, "AA1") < 1 then
ObjectiveChanged(0,1);
RunScript("MissionWin", 3000);
Suicide();
end;
end;

----------------------------------------

function MissionWin()
if GetNUnitsInArea(1, "AA1") < 1 then
Win(0);
DisplayTrace("恭喜!你赢了!")
Suicide();
end;
end;

53
如下图

复制好后保存。
这就是一个最简单的完整脚本样本,这个脚本的思路是:
1. 游戏开始后 2 秒执行任务 0;
2. 10 秒钟后运行任务 0 完成的脚本。如果达到脚本设置目标,则任务 0 完成。
3. 胜利!

好了,我这里开始解释这段脚本的意义。

DisplayTrace("test-map1"); --------开始任务是,出现的提示,用来验证脚本文件是
否出错。
(如果任务开始时没有这个提示,证明脚本有误)

function Init() -------“Init”命令是所有命令的起点命令,永远要记住!


RunScript("Objective0", 2000); -------2 秒钟后运行“Objective0”命令
end; -------“Init”命令结束!

---------------------------------------(分割线无意义,只是为了以后查找命令方便)

function Objective0() -----------“Objective0”命令


ObjectiveChanged(0,0); -----------任务 0 开始
54
RunScript("Objective0OK", 10000); -----------10 秒钟后运行“Objective0OK”命令
DisplayTrace("消灭敌人!"); -----------“Objective0”命令运行时屏幕出现的提示
Suicide(); -----------命令执行后自毁。(注意,这个千万不要漏了)
end; -----------“Objective0”命令结束

function Objective0OK() -----------“Objective0OK”命令


if GetNUnitsInArea(1, "AA1") < 1 then -----------插入“if”条件命令:当敌人在区域“AA1”的
数量
少于 1 时,执行下面的命令!
ObjectiveChanged(0,1); -----------任务 0 完成
RunScript("MissionWin", 3000); ----------3 秒钟后运行"MissionWin"命令
Suicide(); -----------命令执行后自毁。
end; ------------插入的“if”命令结束
end; ------------“Objective0OK”命令结束(注意,当有 if 命令
时,会有 2 个 end,一个是 if 的结束,另一个是这段命令的结束,
不要漏了)
----------------------------------------(分割线无意义)
function MissionWin() -------------“MissionWin”命令
if GetNUnitsInArea(1, "AA1") < 1 then -----------插入“if”条件命令:当敌人在区域“AA1”
的数量
少于 1 时,执行下面的命令!
Win(0); ------------玩家胜利!
DisplayTrace("恭喜!你赢了!") -----------“MissionWin”命令运行时屏幕出现的提示
Suicide(); -----------命令执行后自毁。
end; ------------插入的“if”命令结束
end; ------------“MissionWin”命令结束

好,解释完了,具体脚本的格式和意义可以看看《闪电战 1 脚本编写基础教程-[闪电战论坛]》,我随
后会提供这个文件的下载。
上面的脚本涉及的“AA1”区域,我们还要在地图编辑器里设置。
打开地图编辑器,读取 test-map1.bzm,把屏幕移动到下图的位置。

55
点左边的任务栏“Map Tools”
还有点下面的“Rectangle”,这是选择方形脚本区域。
(当然那个“Circle”自然就是圆形脚本区域。)
这里说明一下,方形脚本区域用于特定区域的单位计数,圆形脚本区域用于特定地点的视野和单位
命令坐标中心设置。

然后在地图上点击左键拖动,拉出一个绿色的方框。

56
放开左键就设置好了,然后输入区域名词“AA1”

设置成功

57
好了,我们还要告诉地图应该执行那个脚本文件。也就是设置地图文件和脚本文件的关联。
点左上角的任务栏“Map”,弹出菜单后点“Script”

可以看到弹出一个对话框

点“Browse….”
找到脚本文件“test-map1.lua”,点打开,再点“OK” 即可。最后记得保存后退出。这样就设置完
成了。

58
再次打开我们前面制作的 test-map1.pak 文件,打开 maps 文件夹。

把新脚本文件 test-map1.lua 和改动后的 test-map1.bzm 文件添加进去。


(和之前一样,拖进去就行了)

别急,这还没完。我们还有一个工作,就是编辑任务的名称和说明。
按你之前解压的路径打开 test-map1 文件夹
我这里是 D:\Scenarios\Custom\Missions\test-map1

59
“0.txt”即任务 0 的说明,
“0h.txt”即任务 0 的名称。
我们把打开 0h.txt,删掉原来的内容,输入“消灭敌军”,即任务 0 的名称。
打开“0.txt”,删去原来内容,输入“消灭地图上的敌军”即任务 0 的说明。
这里的内容可以随意发挥。
然后把这两个编辑好的文件添加到 test-map1.pak 里,代替原来文件即可。
进入游戏看看效果吧。

第二章第二节到此结束!

60
第三节:添加援军及援军脚本

大家好,我们继续前面的地图编辑教程。
同样打开我们的教学测试地图 test-map1.bzm
在我方地图边缘添加 2 辆虎王坦克做为援军,如图:

然后按 Ctrl 点击选定两辆虎王,再双击左键(在单位身上双击),弹出对话框。

61
可以看到单位的 ID 是默认值“-1”。(就是 Script ID 那行)
我们双击“-1”,就可以改动单位 ID 值,我这里改成 100。如图
(注意,单位的 ID 是对应脚本里的单位 ID 设置,和援军代码是两个概念,但是为了方便记忆,单
位 ID 和援军代码往往设置同样的数值。)

然后关闭对话框,点击左边工具栏的第 5 行“Reinforcement Groups”进行援军设置。

62
我们点击“New Group”新建援军代码,如图

然后会弹出一个对话框,要你输入援军的代码,我们这里设置为 100。
记住,这个“100”是援军代码而不是单位 ID,只是为了方便记忆,所以设置成同样数值。
(避免援军多批次造成的混乱)

63
好了,点击 OK 完成添加,我们可以看见左边的援军列表里已经添加了代码为“100”的援军。
如图

但是这个援军代码没有和单位 ID 形成关联时,是没有任何意义的。我们还要设置援军代码和单位 ID
的关联。(其实就是把特定 ID 的单位加入该代码的援军组,一个援军代码可以和几个单位 ID 关联,
即一个代码的援军可以调用几个 ID 的单位,但是为了方便记忆,我还是建议大家设置一对一的关
联。)点击援军代码列表下方的“add group with script”选项进行关联设置。
(图中的“add”只能看
见一个“d”)。然后可以看见弹出一个对话框,要你输入关联的单位 ID,我们输入两辆虎王的 ID:
100。如图

64
点击 OK,可以看到援军代码列表下方的单位 ID 列表上多了一行“Script Id:100”,证明关联成功!
如图

好了,地图编辑器部分的设置完成,保存后退出,我们进行脚本部分的援军设置。
同前用记事本打开脚本文件 test-map1.lua

在里面添加这段代码:

function GReinforcement100()
LandReinforcement(100);
Suicide();
end;

65
如图

单单这段命令,游戏是不会执行这条命令的,我们还需要把这条命令和其他已经可以运行的命令关
联。我们假设在任务开始后 5 分钟援军增援,那么就在“Objective0”命令里添加相关的指令。
把原脚本:

function Objective0()
ObjectiveChanged(0,0);
RunScript("Objective0OK", 10000);
DisplayTrace("消灭敌人!");
Suicide();
end;

66
改为:
function Objective0()
ObjectiveChanged(0,0);
RunScript("Objective0OK", 10000);
RunScript("GReinforcement100", 300000);
DisplayTrace("消灭敌人!");
Suicide();
end;
如图:

好了,这样就完成了。其中的脚本命令逻辑我在这里简单说一下。
function Init() 开始执行脚本,2 秒钟后执行脚本命令 Objective0
function Objective0() 任务 0 开始,10 秒钟后执行脚本命令 Objective0OK,300 秒钟后执行脚本命
令 GReinforcement100
function Objective0OK 如果区域“AA1”的敌军数量少于 1,则任务 0 完成,3 秒钟后执行脚本命
令 MissionWin
function MissionWin() 如果区域“AA1”的敌军数量少于 1,则玩家胜利!
好了,把修改好的地图和脚本更新到我们之前制作的 pak 文件里,然后到游戏里看看效果吧。
第二章第三节到此结束!
67
第四节:设置小地图上的紫色箭头

设置小地图上的任务指示箭头是做图的最后步骤,在此之前,要确定你的地图编辑完成。
第一步:点击地图编辑器左下角的“Create”按钮——见图一

点击后可以看见,小地图变成游戏里的模式了。——见图 2

68
第二步:完成第一步操作后,会在地图文件所在的文件夹里生成一系列图片文件(包括 tga 和 dds
两个格式的图片),而你所需要的只是那个 XXX_large.tga 图片文件——见图 3

XXX_large.tga 文件是一个 512X512 的图片文件,里面的像素坐标即游戏里的紫色小箭头坐标。


所以,你需要一款可以查看像素坐标的软件,这里推荐使用 HyperSnap-DX 4 绿色版
(网上很容易搜索到,因为版权的问题,我不能提供这个软件!)
第三步:用 HyperSnap-DX 4 绿色版 打开 XXX_large.tga ,然后把鼠标放到你要设置紫色小箭头的位
置,然后看右下角的鼠标坐标值,记下这个数值。例如 x:240 y:350

第四步:用记事本打开地图的 1.xml 文件,看见里面任务的坐标值数据了吧?把里面的坐标值换成


你上面记录的数值即可。——如图 4

69
编辑完毕后,把修改完成的 1.xml 文件覆盖原来的即可。

第二章第四节到此结束!

70
第五节:单位的初始命令及敌方进攻脚本范例

我们在作图时往往需要设置敌方单位进攻、包埋、补给等命令,这就涉及到了赋予单位初始命令的
设置。下面我就来示范如何设置:
打开地图,选定你要设置的单位例如图中的 T-34

然后点击任务栏的“Unit”,选择弹出的第一个选项“Add Star Command” 如图

71
然后就会弹出一个对话框,这个就是设置单位初始命令的地方。

双击第一行的那个“Stop”,然后就弹出命令选项,例如,我要选择“移动-进攻”命令,就选择
“SWARM_TO”

然后再把鼠标移动到你要该单位进攻的地方,点左键(建议点空地),这样就完成一个命令设置了。

72
同理,如果要设定单位包埋,步骤相同,选择“ENTRENCH_SELF”,然后点击到单位身上即可。

常用的命令还有原地待命,选择“STAND_GROUD”,然后点到单位身上。

73
补给车的补给命令“RESUPPLY”,可以选择补给的地点(火炮或坦克旁边)或者点击在补给车身上
(原地补给)

某些补给车可以补充步兵,相应的命令是“RESUPPLY_HUMANS”,设置方法同上。

74
最后示范设置敌方援军进攻的脚本设置方法。

首先在地图编辑器里设置敌方援军,例如“ID 1000”
然后为 ID 1000 的敌方单位设定初始命令“SWARM_TO”,设定你要进攻的区域。
然后设置条件触发调用 ID 1000 的脚本,这样在游戏里就会按照你设定的条件调用 ID 1000 的援军,
并按照你设置的初始命令向预定区域进攻。
例如:
function EattackA()
if GetNUnitsInArea(1, "V1A") < 30 then
RunScript("RReinforcement1000", 1000);
Suicide();
end;
end;

function RReinforcement1000()
LandReinforcement(1000);
DisplayTrace("注 意 ! 敌 人 前 来 增 援 !");
Suicide();
end;

该脚本的意义为:
当区域“V1A”的敌军数量少于 30 时,调用命令“RReinforcement1000()”
命令“RReinforcement1000()”的意义即调用 ID 为 1000 的援军。

第二章第五节到此结束!
第三章将会介绍地图编辑器的其他常用技巧。

75
第三章:地图编辑器的常用功能和使用技巧示例

第一节:随机地形和物体的设置
为了使得地图里的场景更加丰富,我们常常需要添加各种地表装饰物体和树木以及各种地形。
为了提高作图效率,地图编辑器提供了一个设置随机地形和物体的快速方法。
用地图编辑器打开你要编辑的地图,点击左侧任务栏第一行第三个“Fields”,如图:

可以看到有几行可以选择(打勾)的项目,将其设定改如上图。不要选择“Update Map”这个
选项,因为如果选择这个选项会让速度变得很慢。
点击上方的下拉菜单,可以看见弹出很多选项,如下图:

我们可以看到里面有对应的季节,如果我们打开的是夏季地图,那么就选择相应的“summer”
系列,我们先看看那个“summer\field00”的效果吧。
76
选择“summer\field00”后,把鼠标移到地图编辑区域,如图:

然后点击左键,就如图设置道路一样,每点击一次,就会留下一个标记,如图:

77
继续点击左键,将标记点围成一个圈或者区域,标记最后一个点后,双击左键结束。
(只要是三
点以上的标记即可,形状可以不规则,记住最后一点要和初始点重合),如下图:

然后把鼠标放到中间,再双击一次就完成了,我们可以看见随机地形就出现了,如下图:

78
我们可以继续尝试其他的随机地形,选择“summer\field01”,步骤同上,将坐标点连成一个正
方形,双击左键结束,再将鼠标放到正方形中间双击左键,又一个新的随机地形生成了。如下图:

多使用几次就会熟练,大家可以新建空白地图练习。
小提示:在设置坐标点的过程中,如果点击的位置不理想,可以点击右键取消。

好了,第三章第一节到此结束!

79
第二节:各种道路和桥梁的连接和美化

在编辑地图时,常常要设置各种道路和桥梁,在此分享一下相关技巧和经验。
首先是常用的两种类型的道路连接和美化:水泥路与黄泥路的连接。
一般来说,道路的宽度设置为 4 时,可以满足两辆坦克的宽度,我们就以这个宽度为例。
先设置好水泥路,如图至少要 3 个坐标点,我们取 4 个坐标点的为例。

然后把鼠标放到你要连接一端的边缘上的黄色圈圈上,点击右键不放,往下方拖动,然后就可以看
见路的一端变成渐进透明的了。如图

80
然后再选择黄泥路,然后记得把“Opacity”的值改回 100(每次调整透明度后,其都会保持上次的
数值)

然后设置黄泥路,如下图

第一个点点在外面,因为直接点在之前设置好的道路上会选定之前的水泥路,不能添加新路。

81
双击左键完成黄泥路的设置。

然后左键拖动我们要调整那一端的红色小圈圈,拖动到与水泥路重合的位置即可。最后双击左键完
成。如下图:

82
然后是交叉路的转角美化。
如下图十字交叉路口,我们需要美化一下转角。

设置方法:选择同样类型的道路,然后按下图方法设置坐标。

83
生成新道路后再用左键拖动要调整一端的红色小圈圈到合适的位置,最后双击左键完成。

84
接下来是桥梁的设置。和设置道路不同,桥梁只能一次生成,不能改动。如果要改动,只能删掉重
新设置。
(删掉已有桥梁的方法是:点击到设置桥梁的任务栏,然后用鼠标放到要取消的桥梁上,点
击键盘的“Delete”键)
我们先选定需要的桥梁类型,如图:

然后把鼠标移动到河岸一端(即你设想的桥梁起始部)

85
再点击左键,沿桥的延伸方向拖动,直到你需要的长度为止,松开左键,设置便完成了。

然后设置与桥连接的道路。图中这个类型的桥对应的是宽度为 3 的道路。我们就按这个宽度设置道
路。

86
然后在地图上添加道路,坐标点按图中设置,生成道路。

然后用右键分别拖动图中用红圈标记的黄色圈圈,向下拖动,使“Opacity”值变成“0”。
即让桥上的那一段路变成透明。(如果不这么设定,桥被打断时,会显示之前被桥面覆盖的道路),
同样,完成设置后,双击左键完成。

87
最后我们讲一下铁轨和铁路桥的连接。
和水泥桥与水泥路不同,铁路桥对应的铁路宽度为 6。所以在设置铁路前要调整好数值。
然后借用当年老论坛政委的相关教程:
1.铁路桥的中心线其实不是两条铁轨的中间, 而是外侧的那条铁轨(靠近你的那一条)

2. 如图,A 点放在桥头的外侧铁轨, C 点放在桥尾的外侧铁轨, 就可以保证火车可以通行。


3. 如图,B 点用于调节视觉上使铁路与铁路桥的铁轨重合。但这只是为了视觉上的真实,其实即使
铁轨不重合, 也不影响火车通行(事实上, 为了能顺利通行, 你不得不让铁轨保持不重合)

第三章第二节到此结束。

88
第三节:设置高地及防御据点示例

在游戏里,设置高地的防御据点是非常常用的技巧,这里就完整的做一遍给大家示例。
首先我们设置地形起伏。刷子的大小是可以调节的,即“Brush”右侧的滑块。如图

点击左键是抬高地形,右键则是降低地形。
我们轻轻点击左键几下,使得地形高地达到 0.5~0.6。
(地形高度值即下方“VIS”的第三数值)如图:

89
然后添加地形相关的地表装饰

90
然后设定地表类型,用各种地形变换配合,美化。

91
再次添加地形相关的地表装饰

92
再添加战壕,碉堡

继续添加步兵,火炮等单位,必要时设定单位的初始命令。
(如火炮包埋,补给车补给弹药/人员,坦克原地待命等等)

93
最后添加树木美化及掩护

必要时还可以设定脚本区域等等。

第三章第三节到此结束。

94
第四节:地图编辑器的常用功能介绍

地图编辑器里有许多功能可以让我们作图时非常方便,下面我就来一一介绍。

一,首先是在地图编辑器里显示单位的射程,这个功能的按钮在上方工具栏的左侧,图标是一个红
圈加一个向左的箭头,点击后就会显示单位的射程。其旁边还有一个下拉菜单,可以选择相应的单
位类型来分别查看射程。如图:

上图的红圈部分是单位的直射射程,绿色区域是火炮特有的,即不重新部署时,其左右射界。
另外,注意小地图,可以看到绿色的大圈和一个扇形区域。大圈是火炮的曲射射程范围,扇形区域
是火炮不重新部署情况下的曲射射界。
利用这个功能,我们可以十分方便的调整单位的放置位置,不同单位的射程一目了然。

95
二,单位显示过滤功能,这个功能可以让你看到被单位遮挡的部分地图细节。该功能的按键在工具
栏右侧,其图标是一辆坦克,点击后,地图上的单位就只留下黑影,如图:

96
三,建筑物和物体显示过滤功能,前面的单位显示过滤功能相似,该功能能隐藏建筑物和物体,在
设置和调整道路以及添加单位时,非常方便。该功能按键就在单位显示过滤功能按键的右侧,如图:

第三章第四节到此结束。
97
附录 1:脚本 script 函数说明(汉化作者:Liukun1982)

这里我们用 LUA 脚本语言编写脚本。以下内容参考了坛上一位朋友的文章,在此表示感谢。


自定义函数:
RunScript
Suicide
KillScript
GetNUnitsInCircle
GetNUnitsInArea
GetNScriptUnitsInArea
GetNUnitsInScriptGroup
LandReinforcement
Win
Draw
Loose
GiveCommand, Cmd
GiveQCommand, QCmd
ShowActiveScripts
ChangeWarFog
EnableAviation
DisableAviation
ChangePlayer
God
SetIGlobalVar, SetFGlobalVar, SetSGlobalVar
GetIGlobalVar, GetFGlobalVar, GetSGlobalVar
GetObjectHPs
GetNUnitsInParty
GetNUnitsInPartyUF
GetNUnitsInPlayerUF
ChangeFormation
Trace
DisplayTrace
ObjectiveChanged
GetNAmmo
GetPartyOfUnits
DamageObject
GetUnitState
GetSquadInfo
IsFollowing
GetFrontDir
GetActiveShellType
RandomFloat
RandomInt
GetMapSize
98
IsPlayerPresent
GetObjCoord
GetScriptAreaParams
SwitchWeather
SwitchWeatherAutomatic
GetNUnitsInSide
AddIronMan
DeleteReinforcement
ViewZone
IsStandGround
IsEntrenched
GetAviationState

单位指令动作代码: (联系下文 Cmd 与 QCmd)


0 – 强制移动(Q)
1 – 攻击单位
2 – 攻击非单位物体
3 – 移动攻击(A)
4 – 装载单位
5 – 卸下单位
6 – 进入建筑/堑壕
7 – 离开建筑/堑壕
8 – 旋转
9 – 停止所有动作
13 – 停止并进入戒备状态
50 – 站岗
14 – 埋伏
15 – 校准射击(X)
16 – 火力压制(Z)
19 – 召唤轰炸机
20 – 召唤战斗机
21 – 召唤侦察机
22 – 召唤伞兵机
36 – 召唤攻击机
23 – 补给单位
24 – 修理单位
29 – 使用双筒望远镜
31 – 挂载火炮
32 – 部署火炮
34 – 解散步兵班
35 – 形成编队
39 – 跟随
43 – 补给士兵
45 – 筑垒防护
46 – 切换弹药种类

99
脚本文件举例: (我们必须用“Base”给敌军单位定义脚本区域,我们用脚本代码 100 来消灭所有单
位。)
function ToWin()
if ( GetNUnitsInScriptGroup(100) <= 0) then
Win(0);
Suicide();
end;
end;
function TobeDefeated()
if ( GetNUnitsInArea(1, "Base") > 1) then
Loose();
Suicide();
end;
end;
function Init()
RunScript( "ToWin", 3000);
RunScript( "TobeDefeated", 3000);
end;
自定义函数详细讲解:
RunScript
RunScript (脚本函数名称(字串),运行周期(单位毫秒), [,重复执行次数(可以不定义,即默认为
无限循环)];
举例: RunScript ("Objective12", 3000, 3);
Suicide
Suicide ();
如果在通过 RunScript 执行的函数主体调用 Suicide,此函数在完成后将不再重复运行。
KillScript
KillScript (脚本函数名称);
消除已激活(至少执行一次)的特定脚本函数名称的脚本语句。
GetNUnitsInCircle
GetNUnitsInCircle (iPlayer, X, Y, Radius)
iPlayer:玩家代码,X、Y 为坐标上的圆心值,Radius 是半径大小。
返回以坐标 X,Y 的点为圆心,Radius 为半径的圆形区域内特定玩家的单位数量。
GetNUnitsInArea
GetNUnitsInArea (iPlayer, strScriptAreaName)
strScriptAreaName 脚本区域名称(字串——在地图编辑器中设置) ,iPlayer:玩家代码。

GetNScriptUnitsInArea
GetNScriptUnitsInArea (iScriptID, strScriptAreaName)
iScriptID:脚本代码,strScriptAreaName 字符串形式的脚本区域名称。返回特定脚本区域内具有特
定脚本代码的部队(组)单位数量。
GetNUnitsInScriptGroup
GetNUnitsInScriptGroup (iScriptID [, iPlayer])
iScriptID:脚本代码,iPlayer:玩家代码。
返回特定脚本代码部队(组)的单位数量。玩家代码为备选项, (可以不设定)但比如部队组中包含
100
炮兵单位,设置玩家代码参数就有用途。 (如果炮手全部阵亡,火炮变为中立单位——玩家代码 2)。
例: a = GetNUnitsInScriptGroup(102, 1);a=玩家 1 脚本代码为 102 的部队组单位数量。
LandReinforcement
LandReinforcement (iReinfID);
iReinfID:增援组代码放出特定增援组代码的援军。 (事先于地图编辑器设定)。
Win
Win (iParty);
iParty:玩家方代码单人游戏中特定玩家方代码的玩家胜利。多人游戏中特定玩家方代码的玩家胜利,
另一方自动得到已战败通知。
Draw
Draw ();
多人游戏中,所有玩家获得平局。
Loose
Loose ();
单人游戏中人类玩家失败。
GiveCommand, Cmd
GiveCommand (iAction, iScriptID [, params, …];
iAction:动作代码, iScriptID:脚本代码;params:参数。向特定脚本代码的部队发出特定动作代码
(见上文)的指令。如有 params 参数,必须用逗号分隔。Cmd 等同于 GiveCommand。指令将立刻
向单位发出。
Example: GiveCommand (9, 1002);Cmd (3, 1001, 2756, 9678);[本例小括号中后两项为参数]。
GiveQCommand, QCmd
GiveQCommand (iAction, iScriptID [, params, …);
向特定脚本代码的部队添加特定动作代码的指令行。如有 params 参数,必须用逗号分隔。QCmd 等
同于 GiveQCommand。此函数可批量运行,但批量指令的第一个动作必须用 Cmd 函数添加以便立刻
执行。
Example: QCmd (3, 200, 1700, 2530); QCmd (3, 200, 1900, 2530);
ShowActiveScripts
ShowActiveScripts ();
用于 DEBUG 的函数,调用可激活脚本列表。
ChangeWarFog
ChangeWarFog (iParty);
IParty:玩家代码;
用于 DEBUG 的函数,调用特定玩家方的战雾。
EnableAviation
EnableAviation (iParty, iAviationType);
IParty:玩家代码;iAviationType:航空兵类别代码。允许特定玩家方使用特定类别代码的空中支援。
航空兵类别代码包括:0 侦察机 1 战斗机 2 伞兵机 3 轰炸机 4 攻击机-1 全部机种如果玩家方代码
=-1,此函数对所有玩家生效。
DisableAviation
DisableAviation (iParty, iAviationType);
IParty:玩家代码;iAviationType:航空兵类别代码。禁止特定玩家方使用特定类别代码的空中支援。
航空兵类别代码包括:0 侦察机 1 战斗机 2 伞兵机 3 轰炸机 4 攻击机-1 全部机种如果玩家方代码
=-1,此函数对所有玩家生效。(如果看了上面的函数,这个就不用看了,这两个函数功能正相反,
记一个就成了。)
ChangePlayer
101
ChangePlayer (iScriptID, iParty);
IScriptID:脚本代码;iParty:玩家代码。
将特定脚本代码部队的所有权转换给特定玩家方。
举例: ChangePlayer (1000, 2); - 把脚本代码为 100 的单位给玩家 2。
God 大家不会陌生吧:)
God (iParty, iMode);
iMode:模式代码用于调试,模式包含:
0 – 彻底关闭上帝模式
1 – 无敌状态
2 – 无敌状态+一击必杀
3 – 一击必杀
4 – 关闭无敌状态
5 – 关闭一击必杀

SetIGlobalVar, SetFGlobalVar, SetSGlobalVar


SetIGlobalVar (strGlobalVarName, iVar);
SetFGlobalVar (strGlobalVarName, fVar);
SetSGlobalVar (strGlobalVarName, strVar);
设定全局变量值。
StrGlobalVarName 全局变量名。Ivar:整数参数;fvar:浮点整数参数;strVar:字符串参数。
SetIGlobalVar 使用整数参数。
SetFGlobalVar 使用浮点数参数。
SetSGlobalVar 使用字符串参数。

GetIGlobalVar, GetFGlobalVar, GetSGlobalVar


GetIGlobalVar (strGlobalVarName, 0)
GetFGlobalVar (strGlobalVarName, 0)
GetSGlobalVar (strGlobalVarName, 0)
返回全局变量值。
参数特征同上。不同的是,参数为 0。
GetObjectHPs
GetObjectHPs (iScriptID)
IScriptID:脚本代码。
回特定脚本代码物体的生命值。 (不适用于单位! )
GetNUnitsInParty
GetNUnitsInParty (iPlayer)
返回特定玩家代码玩家的单位数量,步兵数量单独计算(一个步兵班=步兵班内士兵数量) 。

GetNUnitsInPartyUF
GetNUnitsInPartyUF (iParty)
多人游戏:返回特定玩家方的单位数量。步兵按班数计算。(一个步兵班=一个单位)。
GetNUnitsInPlayerUF
GetNUnitsInPlayerUF (iPlayer)
多人游戏:返回特定玩家代码玩家的单位数量。步兵按班数计算。 (一个步兵班=一个单位)

ChangeFormation
102
ChangeFormation (iScriptID, iFormation);
iFormation:队形代码; iScriptID:脚本代码。
转换特定脚本代码步兵班的队形。
Trace
Trace (strText [, params, …];
用于调试。
StrText:文本字符串;Params:参数。
可在控制台中调用具有格式的文本字符串。浮点变量可用于参数。
举例: Trace ("I have %g apples of total %g", 2, 3);
DisplayTrace
DisplayTrace (strText [, params, …];
用于调试以及在屏幕上显示说明文本。参数同上。
举例: DisplayTrace ("I have %g apples of total %g", 2, 3);
ObjectiveChanged
ObjectiveChanged (iObjNum, iState);
iObjNum:目标代码
iState:目标状态代码将特定代码的目标转换到特定代码的状态。状态代码包括:
0 – 收到目标
1 – 完成目标
2 – 目标失败
GetNAmmo
GetNAmmo (iScriptID)
IScriptID:脚本代码。
通过列表返回特定脚本代码单位的弹药量。
举例:primary_ammo, secondary_ammo = GetNAmmo (1000)。
GetPartyOfUnits
GetPartyOfUnits (iScriptID)
返回特定脚本代码单位拥有者的代码数字。
DamageObject
DamageObject (iScriptID, fDamage);
对特定脚本代码的物体或单位造成损伤参数的损伤。如果损伤参数=0,物体(单位)被彻底摧毁,
如果损伤参数为负数,则物体(单位不可)会被修复。
GetUnitState
GetUnitState (iScriptID)
返回特定脚本代码单位的当前状态。(当前指令)如果返回值=-1,表明单位不存在或者它是非单位
物体。如果返回 0,状态为未知。
GetSquadInfo
GetSquadInfo (iScriptID)
返回特定脚本代码步兵班的当前队形。如果返回-3,表明步兵班不存在。如果返回-2,表明它不是步
兵班。如果返回-1,表明步兵班已被解散。

IsFollowing
如果返回 1,表明单位正在跟随另一单位。如果返回 0,表明单位不在跟随任何单位。如果返回-1,
表明单位不存在,或为非单位物体。
GetFrontDir
GetFrontDir (iScriptID)
103
返回单位的当前方向。 (范围 0-65535,可通过换算得到 0-360 度)如果返回-1,表明单位不存在或
者为非单位物体。
举例: angle = GetFrontDir (1100) / 65536 * 360;
GetActiveShellType
GetActiveShellType (iScriptID)
返回当前火炮弹药类型。
RandomFloat
RandomFloat ()
随机返回 0 到 1.00 范围内的浮点数值。
RandomInt
RandomInt (n)
随机返回 0 到 n-1 的范围之间整数值。
GetMapSize
GetMapSize ()
返回地图尺寸,单位为 SCRIPT POINT
举例: sizex, sizey = GetMapSize();
IsPlayerPresent
IsPlayerPresent (iPlayer)
多人游戏:返回 1 则玩家存在,返回 0 玩家不存在。
GetObjCoord
GetObjCoord (iScriptID)
返回特定脚本代码物体或单位的坐标。 (单位 SCRIPT POINT)如果返回(-1,-1)表明物体不存在。
举例: x, y = GetObjCoord (2002);
GetScriptAreaParams
GetScriptAreaParams (strScriptAreaName)
StrScriptAreaName:字符串格式的脚本区域名称。
返回脚本区域参数。矩形区域返回中心点坐标与尺寸(长与宽的一半)。圆形区域返回圆心坐标(x,y)
与半径。
举例: x, y, half-length, half-width = GetScriptAreaParams ("Zone1"); x, y, radius = GetScriptAreaParams
("Zone2");
SwitchWeather
SwitchWeather (iState)
IState:状态值,只有 0 和 1 两值。
切换天气状态,0 代表晴朗,1 代表恶劣。
SwitchWeatherAutomatic
SwitchWeatherAutomatic (iState)
是否允许随机自动切换天气状态,0 代表不允许,1 代表允许。
GetNUnitsInSide
GetNUnitsInSide (iParty)
IParty:某一方的代码值。
返回特定玩家方拥有的单位数量,步兵班按人数计算。
AddIronMan
AddIronMan (iScriptID)
禁止 AI 给特定脚本代码的部队进行人员或弹药的补给。
DeleteReinforcement
DeleteReinforcement (iScriptID)
104
从地图上移除特定脚本编码部队组中所有单位。
ViewZone
ViewZone (strScriptAreaName, iParam)
StrScriptAreaName:字符串形式的脚本区域名称;iParam:参数值 0 或 1。
如果参数代码为 1,打开特定脚本区域的战雾,如果代码=0,则关闭战雾。
IsStandGround
IsStandGround (iScriptID)
检查单位是否保持站岗状态。站岗状态则返回 1,否则返回 0。
IsEntrenched
IsEntrenched (iScriptID)
检查单位是否筑垒状态。筑垒状态则返回 1,否则返回 0。
例如,坦克是否筑起掩体。
GetAviationState
GetAviationState (iPlayer)
返回特定代码玩家最后调用的空中支援类型。返回值为 0 到 4(0 侦察机;1 战斗机;2 伞兵机;3 轰
炸机;4 攻击机)。

附录 2:老论坛的脚本编辑入门教程

序 言
《闪电战 1》发行之时,地图编辑器与资源编辑器作为“赠品”与游戏一同打包。然而编辑器
的帮助文件内容有限,而且完全没有介绍如何通过编码(脚本)控制自定义任务内的事件。全靠累
积玩家们在各个论坛上分享的发现,我们才能找出如何发挥编辑器的最大效能。单从脚本语言 LUA
方面来看,同样是依靠准确解码、反复试错以及广泛开放的发现共享才得以完善。数量众多的个人
玩家以“破解”Lua 为己任来制作自定义地图,为跟随者开创了一条更为平坦的道路。直到这些先
驱人物在“闪”界隐退,每一位玩过或尝试过制作自定义地图的玩家都应该感谢那些慷慨分享心得
的编码破译者大量的辛勤劳作。
破译编码过程中产生的重要贡献之一是 Calvin 的 Blitzkrieg Guideto Programming Lua Functions。
它提供了一份闪电战 1 中使用脚本函数的列表以及如何运用这些函数的指导。它对于编写闪电战脚
本的人是十分必要的。这个指南像是一本 LUA 词典,但它没有提供如何将这些术语组合成可用脚本
的浅易说明。 (Calvin 提供了一个例子,但是这个例子不能被称为“简介”所以脚本编写的新手最好
忽略它。)Calvin 的 Blitzkrieg Guideto Programming Lua Functions 可以在 Blitzkrieg Portal 下载。
Wespex 是第一位制作完整编辑地图指南的人,为此他编辑了地图,编写了脚本,并且打包了可
以与其他玩家分享的自定义游戏。这个指南(再版很多次并最终与 Calvin 的指南合并)是任何希望
制作自定义地图玩家的入门教程。在发布这个指南之后,Wespex 在 BKP 论坛就脚本编写提供了非
常广泛的问题答疑。这些指南和答疑最有价值的特征是在脚本范例中提供了全面的注释,不仅提供
了制成的脚本,还解释了脚本运作的原理。如果说现在绝大多数脚本编写者是靠这个指南启蒙应该
是不失公允的。
这个基础教程的编写是为了响应 BKP 论坛上的一些评论以及解决很多地图编辑者在开始尝试
脚本编写时所面临的困难。本教程阐述 Lua 的基本原理并展示如何为自定义游戏的某个基本要点编
写脚本。我将尝试揭开某些技术术语的神秘面纱。

考虑要点
像每一个刚开始编写 Lua 的人那样,我非常熟悉入门的巨大障碍以及脚本无效时的那份挫败感。
105
无论如何,有些事情应该记在我们的脑子里:
Lua 是一种语言,你必须学会单个词句的意思以及如何运用他们来“涂鸦”。即使你聪明绝顶, 这
也并不意味你可以不用认真学习词汇和语法就来编写 Lua 脚本。和人类语言不同,即使你在 Lua 语
句中犯了一个微不足道的错误,它也将彻底无法被程序理解。开始编写 Lua 时的大多数挫败感是来
源于那些“一点不起作用”的脚本, “这几乎不可避免的是你的错误!”自然的反应一般是说: “程序
不在运转”或者“我的电脑出毛病了”。但有 99.9%的可能是你犯下了一个拼写或语法错误。制作自
己的地图并看到自编脚本运转是非常有趣的;但让脚本运转起来并不总是有趣的。即使 BKP 论坛上
最优秀的脚本编写者也承认在调试自己的作品时仍然遇到大量挫折。并非每个人都有足够耐心只为
了一个错位的字母、一个遗漏的括号或一个多余的分号来逐行检查脚本。如果想要编写脚本你必须
接受这个事实,没有任何人能替你简化它。一旦你已经了解 Lua 的基础,最佳学习方法是打开一张
你喜欢的地图并且逐行研究它的脚本(在手边准备一份 Calvin 的指南。译者注:或 liukun1982 翻译
的 script 帮助文档)以弄清具体的原理。
如果你想测试一些新脚本或从其他编写者那里“借”来的脚本,不要在你乐于为傲的 26X26 地
图上进行测试。制作一张 4X4 的测试地图,放上最少的单位,仅测试脚本中对你来说是新鲜内容的
代码块。如果脚本不运行,你可以很快发现问题而不需要检查一大堆其他不相干的东西来判断是否
存在冲突。这是本教程所采用的方针。如果你确实遇到了困难,你可以在论坛中进行搜索,大多数
问题已被讨论过了。如果你仍然无法找到答案,你可以在地图编辑问答专栏发布求助贴。如果你的
问题明确具体(最好复制粘贴一些你的脚本),那些脚本编写的大侠们将会给我们这些小菜鸟提供迅
速而有益的答复。

基础教程使用

以下每一节教程都配套一份与教程同名的地图(.bzm)与脚本(.lua)文件。所有.bzm 文件和.lua 文
件应被复制粘贴到闪电战的 Data\Maps 文件夹。这也是你用来保存自定义地图与脚本的路径。为了
学习每一节教程,你可以用地图编辑器打开地图,用 SciTE 编辑器打开脚本。当你阅读完教程并看
完地图和脚本内容以后,你可以按下地图编辑器工具栏右上角的 RunBlitzkrieg 按钮看看脚本在游戏
中是如何执行的。
前五节课程的每张地图都是建立在前一张地图的基础之上,地图和脚本一步步升级。最后两节
课程是独立的,涵盖了 BKP 论坛中经常提到的问题。本教程推荐你下载 BlitzkriegSciTEEditor。它
非常有效,是免费软件,体积不大,没什么理由不用。它不能替你编写脚本,当脚本无法运行时它
也不能替你找出错误。但在编写与检查脚本时它对你很有帮助,所以还是下载吧!Blitzkrieg SciTE
Editor
(译者注:由于这个编辑器在处理中文时默认以半角格式处理,所以退格删除中文时只删除半个,
从而出现乱码。建议中文的地图编写者最好加装汉化补丁,从而能完美支持在脚本中输入中文。)
注:使用 SciTEEditor 给文件命名时你必须使用一个.lua 后缀否则它会被保存为.xml 格式。

基本原理
脚本是一个 lua 文件。在地图编辑器上有一个“扳手加字母 A”的按键,点击这个按键(译者
注:设置脚本文件名)输入脚本名称,来把地图和相应的 lua 脚本文件联系起来。
脚本包含一系列的指令,叫做 functions(函数),当地图运行时,这些函数使事件发生。函数可
以很简单,可以只是(指令电脑)在特定时间完成一个事件, 或是更复杂的,测试某个条件,并根
据结果做出不同的事情。
注意: 附录 A 给出了一个闪电战脚本特有函数列表
为了使函数和地图配合,地图上的单位,步兵班,建筑等必须指定一个脚本代码(ScriptID),
在地图编辑器中,在左边选择 Objects 界面,双击单位调出“单位属性窗口”,然后双击“ScriptID”
106
文本框并输入一个代码(ID),然后关闭属性窗口。
提示:做一个笔记记录哪个代码是哪个单位。有的地图制作者常常在脚本的开头写下他们的编
码方式。
提示:一个很有用的方法,是给予玩家单位和敌方单位以不同字头的代码(如 100s 和 200s)
很多函数要用到脚本区域(ScriptAreas 也译作脚本范围)。用地图编辑器左边的 MapTools 按键
来定义这些脚本区域:
选择“脚本范围工具”,并且拖动鼠标在在地图上定义一个(方形或圆形)区域,然后输入这个
区域的名称。编写脚本时必须准确的使用这个“脚本区域名称”, 包括大小写和空格等都要一样。
提示:给你的脚本区域一个独特而有明确含义的名字,这样你不会在脚本中混淆。(Farm 和
Town, 而不要用 Area1,Area2)

Lua 语言
Lua 的语法是简单而固定的,必须严格遵守。任何拼写,间隔(空格),或标点的错误,都会导
致脚本不运行或不能正确执行函数的功能。多数的脚本问题都是拼写或语法错误。
下面的词语在 Lua 中有特殊的含义,被认为是保留字(keywords):

and break do else elseif

if end false for function

in local nil not or

repeat return then true until while

无论你认为这些词语在现实中是什么意思,在 Lua 语言中,他们有固定的用法,并且只能那样


用。其中一些词语的用法在下面的教程中会详细解说。按照规则, 这些保留字要用小写。
这里也有一些闪电战的特定保留字,象“RunScript”,“LandReinforcement”,“Win” and“Loose”
等。这些必须正确书写----首字母大写和其它字母小写。Calvin 的指南就像一部字典,可用来指导我
们怎样正确书写这些词语。
提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor),那么所有的保留字,如果你的
拼写正确,会变成蓝色并且以浅蓝背景高亮显示。
脚本编写者所定义的事件(函数)的名称叫“names”。它们可以是任意数字和字母,但不能以
数字开头。按照规则,我以大写字母开头为(函数)名称。举例来说, 在第一课我写的:
function MoveCar()
在这里“function”是保留字,而“MoveCar”是名称
提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor),那么(保留字是蓝色而)名称是
黑色的。
当一个函数的名称确定以后,它就可以在后面被脚本调用。当它被再次使用时,必须放在双引
号内作为字符串被调用。如我在第一课中写的:RunScript(“MoveCar”, 3000)
这里“RunScript”是闪电战专用保留字,
“MoveCar”是字符串,代表我在脚本中定义的一个函
数。一个绝对的要点是这个字符串要被正确的键入, 和之前的函数名完全一样,否则不会被脚本认
可。由于这个原因,用复制粘贴函数名和字符串是最好的办法,可以防止键入错误。在使用双引号
时,在引号和字符串的头以及引号和字符串的尾之间不许有任何空格。
提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor),那么当引号的位置正确时,字符
串显示为紫色文字。如果你看到紫色背景的高亮显示,说明双引号输入有错(少了一半)。注意,这
个脚本编辑器不会检查你键入的字符串正确与否函数和保留字是要用参数来限定的。要明白这个参
107
数的作用,想象函数和保留字就像有人大声对你喊“做”,但这没有任何意义,直到你被告知做什么,
什么时候做,做的频率多少,这些就是限定函数去做的参数。
在 Lua 中参数总是被放在一对括号内,如 RunScript(“MoveCar”, 3000) 保留字“RunScript”
需要知道运行哪个函数,什么时候运行。这两个在括号内的参数, 被定义为运行字符串“MoveCar”
以及值(value )为 3000 (这个在后面的教程中解释).
提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor),这个数值会显示为淡蓝色。当
有超过一个的以逗号隔开的参数,来赋予这个字符串或值,很重要的一点, 如果这个逗号漏写了,
脚本将不能运行。有些保留字或函数不用任何的参数定义,那就是说它们对于脚本是不解自明的,
不需要用例如什么,哪里,何时,频率如何等来定义。没有参数的保留字或函数的括号是空的,但
这对括号仍然必须保留。比如 Suicide() 以及函数名后的括号。漏掉一个空括号是脚本不运行的一个
常见原因。缩排是脚本编写者经常用到的(在编辑器中按 Tab 键),但这不是必须的也不会对脚本
有影响。当然它们非常有助于使语句有条理。我会在举例中用我自己的方法, 而脚本编写者有它们
自己的方法。按照规则,脚本的每一行结尾要有一个分号“;”, (除了某些情形下如一个保留字将直
接对下一行执行操作--这在下面的第三课会解说)
备注:有时候也会包括在脚本中,用于帮助脚本编写者明白或提示某些事情或者告诉其他人写的
是什么。一条备注开始和结束于至少两条短横,如“--NOTE--”(译者注:只需要开头的两条短横;
备注可以是中文但短横等标点必须是英文标点)。备注不会被脚本读取,所以在行首和行尾(译者注:
只需要在行首)键入两个短横可以使这一命令行丧失功能。这一点在测试脚本过程中非常有用。
提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor),这个备注会显示为绿色。

第一节 –– 编写一个函数并使它运行

这一课介绍怎样使一个单位从它的初始位置移动到定义的新位置

第一节的地图
打开地图,这里有一辆小轿车(ScriptID 为 100)(双击单位可查看 ID 号) 和轿车将要到达的一栋建

Lesson1.luaScript 脚本

function MoveCar()
Cmd(0, 100, 916, 1516);
Suicide();
end;
function Init()
RunScript("MoveCar", 3000);
end;

注意: 这个脚本以后缀为 lua 的文件保存,你可以复制粘贴这个脚本的语句到你自己写的脚本中。一


定不要用微软的 Word 软件来编写脚本,因为 Word 允许插入不同内码的文字,而这会导致游戏运行
过程中止(即忽然退出)。

解说
function MoveCar()
建立一个名叫“MoveCar”的函数,这个函数能被脚本调用。
108
Cmd(0, 100, 916, 1516);
命令单位(ID100)“移动(0)”到坐标为 x,y(东 916,北 1516)的新位置。
Suicide();
(自毁)告诉脚本不要继续运行这个函数。(没有这一句,表示函数将无限次反复运行)
end;
(结束)关闭这个正在运行的函数(这是一个函数语句的结尾, 没有这个表示语句不完整,也会导
致脚本中止(即游戏退出))
function Init()
这是一个初始化函数,每个脚本必须有一个 function Init ,否则脚本不会运行!
RunScript("MoveCar", 3000);
就像这句话说的一样! 运行这个叫 “MoveCar”的函数(不要忘记双引号) 和何时运行(游戏开始后
3000 毫秒也就是 3 秒)
end;
结束语句。

注意:可以在 Calvin 的指南或 liukun1982 翻译的 script 中找到 Cmd 命令列表

第二节–– 添加第二个有多项命令的函数

这一节 介绍使第二个单位在与第一个单位不同的时间点,做一系列移动。

第二节地图
这里有一辆小轿车(ScriptID100), 一辆卡车(ScriptID101), 一棵树和一个纪念碑。卡车将绕过纪
念碑驶向建筑。

Lesson1.luaScript 脚本

function MoveCar()
Cmd(0, 100, 916, 1516);
Suicide();
end;
function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
end;

function Init()
RunScript("MoveCar", 3000);
RunScript("MoveTruck", 7000);
end;
解说
function MoveCar()
Cmd(0, 100, 916, 1516);
109
Suicide();
end;

function MoveTruck()
一个新函数,起名 MoveTruck
Cmd(0, 101, 1583, 223);
跟第一个函数一样的移动命令
QCmd(0, 101, 1890, 1570);
QCmd 和 Cmd 一样,只是它产生于前一个命令之后。这个语句命令同一辆卡车在到达第一个点后
继续驶向第二个设定的地点。
QCmd(0, 101, 1100, 1890);
Suicide();
end;

function Init()
RunScript("MoveCar", 3000);
RunScript("MoveTruck", 7000);
这个指示运行第二个函数,但时间是游戏开始七秒后
end;
注意:第二个函数也可以象下面的脚本一样由第一个函数来调用。这是经常被用到的手法,适用
于第二个函数肯定在第一个函数被执行之后被调用。这样做的好处是不用同一时间调用很多函数,
而是只在需要时才调用特定的函数,从而可以减少 CPU 资源的占用。.

脚本

function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
end;

function Init()
RunScript("MoveCar", 3000);
end;

解说
function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
110
第二个函数现在从这里被调用。为使卡车在游戏开始后 7 秒开始移动,我们要把时间改为 4 秒,因
为在游戏开始后第一个函数“MoveCar”已经运行了 3 秒
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
end;

function Init()
RunScript("MoveCar", 3000);

现在这个运行“MoveTruck”的命令可以从 Initfunction 中去掉了。


end;

第三节–– 测试一个条件(是否具备)

这一节将介绍测试一个条件是否达到特定值从而触发一个新的应激行动。这是在闪电战地图中
非常有用并且常用的程序设计。

第三节地图

这个地图上,在房子周围,有一个名为“Farm”的脚本区域,和两个脚本代码(ScriptID)为“103”,
“104”的步兵班. 这两个步兵班隶属于援军组“103” ( reinforcement group >103<). 在地图编辑
器中点击 ReinforcementGroups(援军)键可以看到>103< 包含两个脚本代码 ScriptID(103 和 104).
这是必要的,如果我们要命令这两个步兵班做不同的事情,就需要两个不同的 ID。这栋建筑的

脚本代码(ScriptID)是“10”。

Lesson3.luaScript 脚本

function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
111
end;

function FarmCheck()
if GetNUnitsInArea(0, "Farm") == 2 then
RunScript("SquadArrive", 1000);
Suicide();
end;
end;

function SquadArrive()
LandReinforcement(103);
RunScript("SquadMove", 2000);
Suicide();
end;

function SquadMove()
Cmd(0, 103, 1530, 1320);
Cmd(6, 104, 10);
Suicide();
end;

function Init()

RunScript("MoveCar", 3000);
RunScript("FarmCheck", 2000);
end;

解说 :从现在起只列出新的语句。

function FarmCheck()
if GetNUnitsInArea(0, "Farm") == 2 then

“if”是保留字,用于测试某个条件,以返回两个可能的答案:真或假. 在这里测试的条件是在某个
地域范围内的单位数量:“GetNUnitInrea”表示某一方的单位(“0”,表示玩家单位,“1”表示
敌方单位) 在某地(”Farm”, 不要忘记双引号). 条件是“х==2”表示单位数量是否等于 2?(本课
结尾列出了比较符号的意义).“then” 是另一个保留字,用于定义当这个测试的答案为“真”, 将
发生什么。由于“then”将执行下面一行的命令,所以“then”后面没有“;”(分号)
测试的逻辑答案为真,那么运行另一个函数“SquadArrive”。如果答案为假,那么没事发生但函数继
续运行(继续测试这个条件) Suicide();
end;
这个是“if”语句的结束。作为一个规则,你需要为每个“if”语句加上一个“end;”作为结束
end;
这是整个函数的结束

function SquadArrive()
LandReinforcement(103);
112
RunScript("SquadMove", 2000);
这一句调用援军组 103 到地图上
Suicide();
end;

function SquadMove()
Cmd(0, 103, 1530, 1320);
这一句命令代码为(103)的单位移动(0)到坐标(1530,1320)
Cmd(6, 104, 10);
这一句命令代码为(104) 的单位进入 (6) 代码为(10)的建筑
Suicide();
end;

function Init()
RunScript("MoveCar", 3000);
RunScript("FarmCheck", 2000);
这个语句表示在游戏开始后 2 秒运行函数“FarmCheck”。因为这个是条件函数, 所以什么也不会发
生,直到条件符合
end;
提示:如果你用 BlitzkriegSciTEeditor(闪电战脚本编辑器)
,每一行左边会有一个减号,对应地
需要一个“end” (译者注:点击减号,这个减号和对应的“end”之间的语句可以折叠起来,减号变
为加号。)。我把所有的 end 放在左边,以便检查有相同数量的“end”对应上面的减号。

注意:在条件语句中下列符号的含义:

a==b a 等于 b

a>b a 大于 b

a<b a 小于 b

a>=b a 大于或等于 b

a<=b a 小于或等于 b

a~=b a 不等于 b

注意: 一个有用的模块
下面这个脚本模块能在我写的每个脚本中找到, 因为它有助于(地图和脚本)测试:

function DebugView
Password ("Panzerklein");
DisplayTrace("any text you like");
ShowActiveScripts();
-- God(0, 2);
Suicide();
113
end;

function Init()
Runscript(“DebugView”, 1000);
end;

解说
function DebugView
Password ("Panzerklein");
这一句使其它测试功能发挥作用(译者注:我们叫秘籍开启语句)
注意:如果你在《闪电战 1》中用了《斯大林格勒》中的 ailogic.dll(修正单位开火穿墙补丁), 那
你必须用下面的命令语句:
Password( “www.dtf.ru” )
DisplayTrace("any text you like");
显示游戏讯息,你可以在引号中填入任何东西(译者注:如那个有名的“1024 随风飘 kv”)。为什么
要写这一句?因为这个函数会在游戏开始时运行, 如果这条信息没有显示出来,你就可以知道你的
脚本没有运行 ShowActiveScripts(); 在游戏中的控制模式下,你可以看到哪个函数在运行,在闪电战
游戏中按“Tab”键可以激活控制模式。 God(0, 2); 这是一个欺骗密码。. 参数“0”表示玩家, “2”
表示无敌和一枪毙敌 Password ("Panzerklein"); 这个需要密码才能发生作用(译者注,也就是前面必
须运行了) 这两个短横表示这一语句是注释语句不会被脚本理睬(运行),要使它发生作用(测试
用)只要删除这两个破折号(译者注:在写脚本时,两个破折号加后面的语句可以提示自己,也可
以作为脚本语句的解说提供给其他学习的玩家)
Suicide();
end;

function Init()
Runscript(“DebugView”, 1000);
end;

函数 DebugView 一定要在函数 Init 中调用,就像其他函数一样


注意: 使用 DisplayTrace 命令时,要显示的信息必须在双引号(“”)内,所以你的信息中不能含有双
引号,但你可以使用单引号。

第四节–– 使用目标

这一节包含目标设定和使用变量。

目标被脚本触发从而在游戏中显示有目标信息的面板以及在小地图上的目标箭头。不过目标文
本和目标箭头要用 ResourceEditor 来编辑,需要另作讨论。这里我们只讨论如何触发目标开始和目
标完成。变量是游戏保存的可以再利用的数据,这一课我们会用到全局变量。其它信息请参考 Calvin
的指南。

Lesson4Map 第四节地图
这是在第三课地图的基础上,添加了一些守在战壕中的敌军部队(AI, Player1)和一个新的脚本区
域“Trench”(译者注:意为战壕)
114
Lesson4.luaScript 脚本
在这个脚本中,我把新添加的函数或命令行用(--NEW--) 标了出来

function DebugView() -- NEW -


Password ("Panzerklein");
DisplayTrace("Amazing! This really works");
ShowActiveScripts();
--God(0, 2);
Suicide();
end;

function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
RunScript("ReavealObjective0", 10000); -- NEW -
Suicide();
end;
ObjectiveChanged(0, 0);
DisplayTrace("Off we go");
RunScript("Objective0Check", 2000); -- NEW –
RunScript("Objective0Complete", 3000); -- NEW -
Suicide()
end;

function FarmCheck()
if GetNUnitsInArea(0, "Farm") == 2 then
RunScript("SquadArrive", 1000);
Suicide();
end;
end;

function SquadArrive()
LandReinforcement(103);
RunScript("SquadMove", 2000);
Suicide();
end;

function SquadMove()
115
Cmd(3, 103, 2530, 2850);
Cmd(6, 104, 10);
Suicide();
end;

function Objective0Check() -- NEW -


if GetNScriptUnitsInArea(130, "Trench") >=1 then
SetIGlobalVar("Mission0", 1);
Suicide();
end;
end;

function Objective0Complete() -- NEW -


if GetIGlobalVar("Mission0", 0) == 1 then
ObjectiveChanged(0, 1);
Suicide()
end;
end;

function Init()

RunScript("DebugView", 1000);
RunScript("MoveCar", 3000);
RunScript("FarmCheck", 2000);
end;

解说
function ReavealObjective0() -- NEW -
ObjectiveChanged(0, 0);
这个参数表示哪一个目标(0)改变了,变成了什么,在这里显示(0)
DisplayTrace("Off we go");
只是一个信息,可以忽略
RunScript("Objective0Check", 2000); -- NEW –
运行条件测试函数:达到什么条件才算目标完成
RunScript("Objective0Complete", 3000); -- NEW –
开始运行函数 Objective0Complete,这个函数会显示目标完成的信息
Suicide()
end;

function Objective0Check() -- NEW -


if (130, "Trench") >=1 then
和 GetNUnitsInArea 语句不同,GetNScriptUnitsInArea 计算的是代码为 130 的成员在脚本区域
“Trench”
内的数量
SetIGlobalVar("Mission0", 1);
当条件符合,以指定的参数保存一个变量的名称和值。这里名称是“Mission0”,值是“1” ,这个值
可以是任意整数。(译者注:名称也可以是任意的,只要作者自己明白指的是什么)
116
Suicide();
end;
end;

两个 end: 一个对应 if,一个对应函数主体。

function Objective0Complete() -- NEW -


if GetIGlobalVar("Mission0", 0) == 1 then
这个保留字“if”调用前面由 SetIGlobalVar 保存的参数。第一个参数是保存的全局变量的名称,第
二个参数一直都是“0”。总而言之,这个命令行调用了变量“Mission0”的值并且测试这个值是否
等于“1”。如果答案为“真”, 那么执行下一行命令,如果是“假”, 那么什么也不做,函数继续
运行。
ObjectiveChanged(0, 1);
参数(0,1)表示目标 0 是完成了(1)
Suicide()
end;
end;

两个 end: 一个对应 if,一个对应函数主体。

注意:这里不是必须用全局变量去触发目标完成的信息,但这个变量经常被用来在脚本后部检查是否
全部目标已经完成了。这是我们必须知道的。另一个完成目标的方法是象下面的函数:

function Objective0Check() -- NEW -


if GetNScriptUnitsInArea(130, "Trench") >=1 then
ObjectiveChanged(0, 1);
Suicide();
end;
end;

第五节— 归纳

这一节我们将综合前面的教程内容:目标条件、不同种类的条件测试以及多样的援军呼叫。教
程中将示范 if~ else 以及 if~ elseif 语句的用法,加入胜利和失败条件并且调用全局变量来测试这些
条件是否已经符合。下面的例子换上不同的脚本区域和脚本代码以及不同的条件测试可以作为很多
单人地图的基础。
第五节地图,基于第四节地图
Lesson5.lua 脚本

function DebugView()
Password ("Panzerklein");
DisplayTrace("Lua really isn't scary any more!");
ShowActiveScripts();
--God(0, 2);
Suicide();
117
end;

function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
RunScript("ReavealObjective0", 10000);
Suicide();
end;

function ReavealObjective0()
ObjectiveChanged(0, 0);
DisplayTrace("Off we go");
RunScript("Objective0Check", 2000);
RunScript("Objective0Complete", 3000);
Suicide()
end;

function FarmCheck()

if GetNUnitsInArea(0, "Farm") == 2 then


RunScript("SquadArrive", 1000);
Suicide();
end;
end;

function SquadArrive()
LandReinforcement(103);
RunScript("SquadMove", 2000);
Suicide();
end;

function SquadMove()
Cmd(3, 103, 2530, 2850);
Cmd(6, 104, 10);
Suicide();
end;

function Objective0Check()
if GetNScriptUnitsInArea(103, "Trench") >= 1 then
118
SetIGlobalVar("Mission0", 1);
Suicide();
end;
end;

function Objective0Complete()
if GetIGlobalVar("Mission0", 0) == 1 then
ObjectiveChanged(0, 1);
RunScript("Objective1", 2000); -- NEW --
Suicide();
end;
end;

function Objective1() -- NEW -


ObjectiveChanged(1, 0);
RunScript("Objective1Complete", 3000);
DisplayTrace("Clear out all the Americans from this area");
LandReinforcement(105);
Cmd(3, 105,2335, 3015);
RunScript("HeavyArmourDeploy", 30000);
Suicide();
end;

function Objective1Complete() -- NEW -


if GetNUnitsInParty(1) <= 3 then
ObjectiveChanged(1, 1);
SetIGlobalVar("Mission1", 1);
Suicide();
end;
end;

function HeavyArmourDeploy() -- NEW -


LandReinforcement(106);
RunScript("HeavyArmourMove", 2000);
Suicide();
end;

function HeavyArmourMove() -- NEW -


if GetNUnitsInArea(1, "Trench") > 0 then
Cmd(3, 106, GetScriptreaParam s(“Trench”);
else Cmd(3, 106, 393, 3777);
Suicide();
end;
end;

119
function USCounterattack() -- NEW -
if GetNUnitsInArea(1, "Trench") <= 20 then
RunScript("USTanks", 3000);
Suicide();
end;
end;

function USTanks() -- NEW --Land


Rei nforcement(200);
Suicide();
end;

function WinLoose() -- NEW -


if GetIGlobalVar("Mission0", 0) * GetIGlobalVar("Mission1", 0) == 1 then

Win(0);
elseif
GetNUnitsInScriptGroup(103) + GetNUnitsInScriptGroup(105)
+GetNUnitsInScriptGroup(106) == 0 and
GetIGlobalVar("Mission0", 0) == 1 then
Loose(0);
Suicide();
end;
end;
function Init()
RunScript("DebugView", 1000);
RunScript("MoveCar", 3000);
RunScript("FarmCheck", 2000);
RunScript("USCounterattack", 2000); --NEW--
RunScript("WinLoose", 3000); --NEW--end;

诠释:
function Objective1() -- NEW -
ObjectiveChanged(1, 0);
正 如 第 四 节 中 Objective0 的 诠 释 , 此 函 数 触 发 目 标 1 的 目 标 信 息 与 箭 头
RunScript("Objective1Complete", 3000); 运 行 测 试 目 标 是 否 完 成 的 函 数 ( 三 秒 后 ) 。
DisplayTrace("Clear out all the Americans from this area"); 仅仅显示一条信息,在制作好的任务里它可
以被忽略,因为目标信息会被显示出来

LandReinforcement(105);
triggersthearrivaloflightAFVs(ScriptGroup>105<)
触发轻型装甲战斗车辆的到达(援军组 105)
Cmd(3, 105, 2335, 3015);
将援军组(105)移动到坐标 x,y 的地方
RunScript("HeavyArmourDeploy", 30000);
在 30 秒(30000 豪秒)后运行 HeavyArmourDeploy 函数
120
Suicide();
end;

function Objective1Complete() -- NEW -


if GetNUnitsInParty(1) <= 3 then
测试敌方(1)单位的数量是否小于等于 3
ObjectiveChanged(1, 1);
如果返回结果真则目标 1 完成(1)
SetIGlobalVar("Mission1", 1);
条件符合时这个函数会按照参数中指定的名称和值创造并保存一个变量(——译者注:全局变量)。
在这个例子中名称是 Mission1,值是 1。
Suicide();
end;
end;
因为函数包含一个 if 所以我们要用两个 end

function HeavyArmourDeploy() -- NEW -


LandReinforcement(106);
触发坦克部队的到达(援军组 106)
RunScript("HeavyArmourMove", 2000);
运行选择坦克部队将要去向何方的函数(两秒后)
Suicide();
end;

function HeavyArmourMove() -- NEW -


if GetNUnitsInArea(1, "Trench") > 0 then
测试敌方(1)在区域 Trench 中的单位数量是否大于 0
Cmd(3, 106, GetScriptreaParam s(“Trench”));
如果返回结果真则坦克部队(106)移动攻击(3)到区域 Trench 中心点的坐标
else Cmd(3, 106, 393, 3777);
else-如果结果返回假则(通常这个条件不会给出,也就是说测试返回假则没有任何影响)坦克部队
(106)移动攻击(3)到新的坐标(393,3777)
Suicide();
end;
end;
因为函数包含一个 if 所以我们要用两个 end

function USCounterattack() -- NEW -


if GetNUnitsInArea(1, "Trench") <= 20 then
RunScript("USTanks", 3000);
Suicide();
end;
end;
因为函数包含一个 if 所以我们要用两个 end

function USTanks() -- NEW --Land


121
Rei nforcement(200);
Suicide();
end;

function WinLoose() -- NEW –


if GetIGlobalVar("Mission0", 0) * GetIGlobalVar("Mission1", 0) == 1 then
调用全局变量 Mission0 和 Mission1(当每个目标完成以后都被赋值为 1)并且测试它们的值是否都
是 1(1 乘以 1 等于 1)
Win(0);
如果第一测试返回真则玩家(0)胜利并且显示“你胜利了”信息
elseif
GetNUnitsInScriptGroup(103) + GetNUnitsInScriptGroup(105)
+GetNUnitsInScriptGroup(106) == 0 and

如果第一测试返回假则执行第二测试,在此情况下测试玩家的特定单位是否已经阵亡。And 逻辑符
将这 个测试与另一测试相连,两个测试必须同时返回真,脚本的结果部分才能运行。

GetIGlobalVar("Mission0", 0) == 1 then

测试第一个目标是否已经完成。因为函数 WinLoose 在游戏过程中一直运行(由函数 Init 开启)而玩


家的援军在第一个目标完成之前不会到达。因此,如果我们不使用这个附加条件测试,函数将会在
游戏开始以后 3 秒运行,发现玩家的援军数量等于 0,然后执行下一行语句(——译者注:直接失
败)
Loose(0);
如果第二测试返回真则玩家方失败并显示“你失败了”信息
Suicide();
end;
end;
因为函数包含一个 if 所以我们要用两个 end,只用两个是因为 elseif 不算另一逻辑函数,它只是 if
测试返回假时的输出结果。

function Init()
RunScript("DebugView", 1000);
RunScript("MoveCar", 3000);
RunScript("FarmCheck", 2000);
RunScript("USCounterattack", 2000); --NEW--
RunScript("WinLoose", 3000); --NEW--
end;

注:WInLoose 函数也可以如下编写:

function WinLoose() -- NEW -


if GetIGlobalVar("Mission0", 0) * GetIGlobalVar("Mission1", 0) == 1 then
Win(0);
if GetNUnitsInScriptGroup(103) + GetNUnitsInScriptGroup(105)
+GetNUnitsInScriptGroup(106) == 0 and
122
GetIGlobalVar("Mission0", 0) == 1 then
Loose(0);
Suicide();
end;
end;
end;
三个 end:每个 if 对应一个 end,函数主体需要一个 end

飞机教程

这节教程将示范如何利用脚本根据地图事件来召唤飞机

飞机教程地图
地图上有一个被脚本区域 Bunker 包围着的防御阵地。航空兵在地图编辑器里用 EditUnitsCreation 。
Information 按钮指派给玩家。(它看起来像,这个,我不确定,一个颠倒的蘑菇。——译者注:FT,
明明就是一架飞机,教程作者的想象力过头了哈)点击按钮弹出菜单,然后点击 Player0 旁边的+号,
再点击 Aviation 旁边的+号,这样你就可以选择每一类别空中支援由哪种(以及多少)飞机组成。最
重要的是选择 Appearpoints,你必须设置它以便使用空中支援,双击这条线选择 Add,然后你就可以
输入玩家方航空兵出现的坐标(x,y),注意坐标体系是 VISTitle 而不是 Scriptpoint。VISTitle 坐标显示
在在地图编辑器窗口底部的中心。在它的右边就是 Scriptpoint 坐标,一旦你设置好了 Appearpoints,
关闭菜单 。

LessonPlanes.lua 脚本
function DebugView()
Password ("Panzerklein");
DisplayTrace("Here come the planes");
ShowActiveScri pts();
--God(0, 2);
Suicide();
end;

function PlaneTrigger()
if GetNUnitsInArea(1, "Bunker") >= 1 then
Cmd(36, 999, 0, 1100, 2070);
-- Cmd(36, 999, 0, GetScriptAreaParams("Bunker"));
Suicide();
end;
end;
function Init()
RunScript("DebugView", 1000);
RunScript("PlaneTrigger", 3000);
end;

诠释
function PlaneTrigger()
123
if GetNUnitsInArea(1, "Bunker") >= 1 then
一个触发飞机召唤的条件测试,当脚本区域 Bunker 内的 AI 敌人(Player1)单位数量大于等于 1 时
Cmd(36, 999, 0, 1100, 2070);
召唤飞机——36 是地面攻击机的代码 (参见 Calvin 的列表——译者注:地图编辑器帮助文件里也有),
999 是飞机的临时脚本代码(它可以是任何数字,但根据惯例,地图编辑者倾向于为飞机保留 99999
或 9999 编号——译者注:这是为了不和你其他单位的脚本代码冲突,应该谈不上什么惯例,数字越
长越好),0 是玩家方代码,1100,2070 是飞机前往的坐标 x,y(使用 Scriptpoint 坐标)
Cmd(36, 999, 0, GetScriptAreaParams("Bunker"));
这一行语句不会在脚本中执行,因为它的开头有两短横--。 (——译者注:LUA 的注释语法)这是一
种召唤飞机的备选方案。函数执行时将会自动得出脚本区域 Bunker 中心的坐标,不需要直接给出坐
标。
Suicide();
end;
end;
两个 end: 一个对应 if,一个对应函数主体。

巡逻教程
这节教程将示范如何建立一条巡逻路线。在这个例子里只有一个单位进行巡逻,但是也包含任何数
目。如果进行巡逻的单位具有主动攻击能力(——译者注:快捷键 A 的功能)
,它将与遭遇的任何
敌人交战,如果战斗后此单位幸存,它将继续进行巡逻。

巡逻教程地图
地图上有一辆脚本代码 100 的装甲车停在名为 StartingPoint 的脚本区域

LessonPlanes.lua 脚本

注:此脚本原本是由 Wespex 在 Blitzkrieg Portal forums 回答问题的过程中提供,同时还有一种备选


方法达到相同的结果。

function PatrolArea()
if GetNScriptUnitsInArea(100, "Starting Point") > 0 then
Cmd (3, 100, 765, 681);
QCmd (3, 100, 288, 356);
QCmd (3, 100, 545, 1145);
QCmd (3, 100, 1631, 1497);
QCmd (3, 100, 1351, 647);
RunScript("PatrolArea", 2000);
Suicide();
end;
end;

function Init()
RunScript("PatrolArea", 5000);
end;

诠释
124
function PatrolArea()
if GetNScriptUnitsInArea(100, "Starting Point") > 0 then
检查巡逻单位(脚本代码 100)是否存在并且位于初始位置(脚本区域 StartingPoin)
Cmd (3, 100, 765, 681);
命令单位(100)移动攻击(3)到坐标 x,y(765,681)
QCmd (3, 100, 288, 356);
一旦前一指令完成,命令单位移动攻击到新坐标
QCmd (3, 100, 545, 1145);
同上
QCmd (3, 100, 1631, 1479);
同上
QCmd (3, 100, 1351, 647);
仍然同上,但是最后移动指令的最终坐标必须在脚本区域 StartingPoint 之内
RunScript("PatrolArea", 2000);
重复整个脚本
Suicide();
end;
end;
两个 end: 一个对应 if,一个对应函数主体。

注:通过添加或删除 QCmd(3,ScriptID,x,y)语句,一次巡逻的循环可以包含任何数目的移动次数。重
要的是最后一次移动,单位必须回到函数第一行语句中的脚本区域。

调试脚本

调试是一个发现和消除编码缺陷(bug)的过程。在程序界, 公认的调试步骤是:
1 确认缺陷的存在
2 分离存在缺陷的原始资料
3 分析引起缺陷的原因
4 决定修正缺陷的方案
5 实施修正并测试
出了毛病的脚本需要调试: 它不运行或者运行的结果与预想的不一致。
出了毛病的脚本:当脚本触发的目标没有在游戏中显示,你必须意识到你的脚本由于一处或多处错
误而“出了毛病”。一个很好的习惯是在游戏的 Init 函数中放一个“DisplayTrace”语句, 显示一些
诸如“脚本工作正常。。。。。。 ”之类的讯息。如果脚本“OK”,这些讯息会直观地显示出来。如果没
有出现,你就可以知道脚本有缺陷。这个语句可以在脚本调试完毕后删除或改成注解(前面加两个
短横)。
提示 1:当你发现脚本出了毛病, 你不需要退出《闪电战》, 你可以在游戏仍然在运行的情况
下回到 Windows,修改脚本并保存, 然后回到游戏, 选择“重新开始任务”去再次测试这个脚本。
注意:如果你的脚本文件是保存在一个.pak 文件中, 由于这个 pak 文件被游戏和地图编辑器锁
定了, 所以你不能修改 pak 包内部的文件。 (译者注:所以你要把 bzm 文件和 lua 文件放在 maps 文
件夹下,待调试玩了在放回 pak 包)
提示 2:不要把地图放到 pak 包里除非它已经编辑完全并且调试完成。任何被地图编辑器打开
的地图,无论它是否从 pak 包里打开,但地图编辑器保存时,都是保存到 data 文件夹下(maps 文件
夹),因而很容易被遗漏在 pak 包之外,除非你记得保持你的地图 pak 包常新(译者注:呵呵,不然
125
忙乎了半天, 发布出来的地图包却是错的)。当你调试你的脚本时, 你应该要检查以下常见的错误:
1 函数没有以 "end”;; 语句结尾
2 注释语句行不正确的用了单短横“-“ 而不是双短横“--“
3 条件测试模块没有以它们自己的"end;;"语句结尾

实例
function CheckTown()
if GetNUnitsInArea(0, "Town") == 0 then
ObjectiveCha nged (0,1);
RunScript( "Objective1", 5000);
end;
上面的代码会因为"if GetNUnits..." 模块没有它自己的"end;"语句而出错。每个函数模块需要它
自己的 end;; 语句结尾。每个 if 模块需要它自己的 end;;语句结尾。
4 错误的大小写:这个 if 指令必须小写,不能输入成 Iff
5 语句没有以分号–";"结尾。注意: function 和 if 等保留字不需要以分号结尾
6 文本数值(或字符串)没有正确的结尾。如下例子,脚本会因为 GetUnitsInArea(0, "Town) 出错,
因为这个脚本地域名字 Town 没有双引号包起来。
7 在"DisplayTrace"语句内用了双引号。
例如:下面的代码不合规:DisplayTrace( "Commander, the "Tigers" have arrived."); 因为包围 Tigers
的双引号指示脚本处理器你要显示的字符串是"Commander, the "
8 用括号嵌入的函数和条件语句-“(“ 和“)”– 没有正确数量的左括号和右括号,如下面的错误
例子:
if (GetNScriptUnitsInArea (1, "finalattack") == 1 then
因为 GetNScriptUnitsInArea 函数没有右括号结尾
9 键入 Loose(); 误作 Lose(); 。这也许很容易被诱导用上了正确的拼写 Lose 但 Loose 才是正确的。
10 Win() 语句遗漏了玩家方的数字代号。
11 为节约时间,在调试时,有必要知道,以下情形不会导致脚本错误:
a 召唤不存在的援军组
b 调用不存在的函数(用 RunScript 命令)
c 调试运行结果与预期不符的脚本

有时候你会发现脚本没有如你预期的那样执行。比如,当你达到所有要求时目标却不显示完成,
或者援军不断地出现。下面是一些常见的错误,看是否会在你的脚本里找到:如果你发现一个特殊
的行动或事件(比如,援军重复地出现)不断地自行重复,那你要检查是否遗漏了 Suicide(); 语句。
这个语句(译者注:suicide 意为“自毁”)告诉脚本停止运行, 这个语句的用处是保证脚本运行平稳。

示例
function Init()
RunScript(“MyCheck”, 5000);
end;
function MyCheck()
if GetNUnitsInarea(0, “Town”) > 0 then
RunScript(Reinforcements,5000);
end;
end;

126
function Reinforcements()
Land Reinforcement(100)
end;
上面的语句每 5 秒钟运行一次函数 MyCheck 。这个函数(MyCheck )测试玩家方(0)的单
位是否有一个以上出现在地图区域“Town”。如果是,那么召唤援军组(代码为 100)的函数
Reinforcements 被调用。无论如何,在上面的编码中,只要玩家方 0 的单位出现在“Town”这个区
域,援军组 100 就会不停地重复出现。因为函数 MyCheck 没有告诉处理器停止运行,即使条件已
经履行。
在这个例子中,函数 MyCheck 的正确写法是:
function MyCheck()
fi GetN U nitsInrea(0, “Tow n”) > 0 then
RunScript(Reinforcements,5000);
Suicide();
end;
end;
这 个 Suicide(); 语 句 告 诉 脚 本 处 理 器 停 止 运 行 MyCheck 脚 本 , 当 条 件 已 经 达 到 并 且
Reinforcements 脚本已经调用。
“Objective Received: Unknown Objective”
如果相应的目标输入被你的地图配置文件 1.xml 遗漏了,这个信息会出现在你的地图上。无论
如何,这个信息完美地标示出你是否从地图编辑器直接运行的,在这种情形下,闪电战游戏 Blitzkrieg
不会处理在 scenarios\custom\missions\missionname 文件夹中的文件。 (译者注:真奇怪我的地图不能
从编辑器直接运行,只能进入游戏后选择自定义任务来选择相关地图,所以一定要先建立 1.xml 文
件,不知道那里出错了,或者汉化版地图编辑器有问题。)
如果(你用条件语句)测试在一个特定的区域的单位,而这个测试返回的结果和你预期的不一
致。那么再次检查你是否用同一个名称定义了两个或两个以上的地图区域。
如果飞机在被一个 Cmd 函数召唤后没有出现,那么检查脚本的其它地方,飞机是否被先前的
函数 DisableAviation() 禁止了。

附录 A : 闪电战脚本 script 函数列表


函数 输入值 Input Value 返回值 Return Value
AddIronMan (iScriptID)
ChangeFormation (iScriptID,iFormation)
ChangePlayer (iScriptID,iParty)
ChangeWarFog (iParty)
Cmd |GiveCommand (iAction,iScriptID,xLoc,yLoc)
DamageObject (iScriptID,fDamage)
DeleteReinforcement (iScriptID)
DisableAviation (iParty,iAviationType)
DisplayTrace (strText,params,...) 在屏幕显示文本
Draw
EnableAviation (iParty,iAviationType)
FlagReinforcement (nParty)
GetActiveShellType (iScriptID) 炮弹类型
GetAviationState (iPlayer) 特定玩家最后调用的飞机类型

127
函数 输入值 Input Value 返回值 Return Value
GetFGlobalVar (strGlobalVarName,0) 全局变量名和值
GetFrontDir (iScriptID) 特定代码单位的面对方向
GetIGlobalVar (strGlobalVarName,0) 全局变量名和值
GetMapSize 地图尺寸,单位为 scriptpoint
GetNAmmo (iScriptID) 特定脚本代码单位的弹药量
Get NAntita n kInScri (strScriptAreaName) 特定代码区域内的反坦克障碍数

GetNAPFencesInScri ptArea (strScriptAreaName) 特定代码区域内的铁丝网段数量
Get N Fen ces I nScri (strScriptAreaName) 特定代码区域内的栅栏段数量
GetNMinesInScriptArea (strScriptAreaName) 特定代码区域内的地雷数量
GetNScriptUnitsInArea (iScriptID,strScriptAreaName) 特定代码单位在区域内的数量
GetNTrenchesInScriptArea (strScriptAreaName) 特定代码区域的堑壕段数量
GetNUnitsInArea (iPlayer,strScriptAreaName) 特定方在特定区域内的单位数量
GetNUnitsInCircle (iPlayer,X,Y,Radius) 玩家方在圆圈范围内的单位数量
GetNUnitsInParty (iPlayer) 特定玩家方在地图上的单位数量
GetNUnitsInScriptGroup (iScriptID,iPlayer) 特定脚本代码单位的数量
GetNUnitsOfType (strUnitType,iPlayer) 步兵的类型
GetObjCoord (iScriptID) Object 的位置(坐标)
GetObjectHPs (iScriptID_Static) Object 的生命值
GetScriptAreaParams (strScriptAreaName) 区域的参数
GetSGlobalVar (strGlobalVarName,0) 变量名称和值
GetSquadInfo (iScriptID) 步兵班队形
GetUnitState (iScriptID) 单位状况
God (iParty,iMode)
IsEntrenched (iScriptID) 单位进入堑壕值
IsFollowing (iScriptID) 单位跟随值
IsStandGround (iScriptID) 单位站岗值
IsWarehouseConnected (iScript_StorageID) 小仓库连接到主仓库
LandReinforcement (iReinfID)
Loose
ObjectiveChanged (iObjNum,iState) 目标状态
Password (strName)
QCmd |GiveQCommand: (iAction,iScriptID,params)
RandomFloat 0 到 1 之间的小数
RandomInt (n) 0 到 n 之间的随机整数
ReserveAviation ForTimes (iParty,iTime)
RunScript (strFunctionName,iTime,iTurns)
SetCheatDifficu ltyLevel (n)
SetDifficultyLevel (n)
SetFGlobalVar (strGlobalVarName,fVar)
SetGameSpeed (n)
SetIGlobalVar (strGlobalVarName,iVar)

128
函数 输入值 Input Value 返回值 Return Value
SetSGlobalVar (strGlobalVarName,sVar)
ShowActiveScripts 在控制台显示目前脚本
Suicide
SwitchWeather
SwitchWeatherAutomatic
Trace (iState) 控制台文本
ViewZone (iState)
Win (strText,params)

129

You might also like