收藏 分享(赏)

闪电战1脚本编写基础教程-[闪电战论坛].doc

上传人:myw993772 文档编号:8288250 上传时间:2019-06-18 格式:DOC 页数:13 大小:112.50KB
下载 相关 举报
闪电战1脚本编写基础教程-[闪电战论坛].doc_第1页
第1页 / 共13页
闪电战1脚本编写基础教程-[闪电战论坛].doc_第2页
第2页 / 共13页
闪电战1脚本编写基础教程-[闪电战论坛].doc_第3页
第3页 / 共13页
闪电战1脚本编写基础教程-[闪电战论坛].doc_第4页
第4页 / 共13页
闪电战1脚本编写基础教程-[闪电战论坛].doc_第5页
第5页 / 共13页
点击查看更多>>
资源描述

1、1序 言 闪电战 1 发行之时,地图编辑器与资源编辑器作为“赠品”与游戏一同打包。然而编辑器的帮助文件内容有限,而且完全没有介绍如何通过编码(脚本)控制自定义任务内的事件。全靠累积玩家们在各个论坛上分享的发现,我们才能找出如何发挥编辑器的最大效能。单从脚本语言 LUA 方面来看,同样是依靠准确解码、反复试错以及广泛开放的发现共享才得以完善。数量众多的个人玩家以“破解”Lua 为己任来制作自定义地图,为跟随者开创了一条更为平坦的道路。直到这些先驱人物在“闪”界隐退,每一位玩过或尝试过制作自定义地图的玩家都应该感谢那些慷慨分享心得的编码破译者大量的辛勤劳作。 破译编码过程中产生的重要贡献之一是 C

2、alvin 的 Blitzkrieg Guideto Programming Lua Functions。它提供了一份闪电战 1 中使用脚本函数的列表以及如何运用这些函数的指导。它对于编写闪电战脚本的人是十分必要的。这个指南像是一本 LUA 词典,但它没有提供如何将这些术语组合成可用脚本的浅易说明。(Calvin 提供了一个例子,但是这个例子不能被称为“ 简介”所以脚本编写的新手最好忽略它。 )Calvin 的 Blitzkrieg Guideto Programming Lua Functions 可以在 Blitzkrieg Portal 下载。 Wespex 是第一位制作完整编辑地图指南

3、的人,为此他编辑了地图,编写了脚本,并且打包了可以与其他玩家分享的自定义游戏。这个指南(再版很多次并最终与 Calvin 的指南合并)是任何希望制作自定义地图玩家的入门教程。在发布这个指南之后,Wespex 在 BKP 论坛就脚本编写提供了非常广泛的问题答疑。这些指南和答疑最有价值的特征是在脚本范例中提供了全面的注释,不仅提供了制成的脚本,还解释了脚本运作的原理。如果说现在绝大多数脚本编写者是靠这个指南启蒙应该是不失公允的。 这个基础教程的编写是为了响应 BKP 论坛上的一些评论以及解决很多地图编辑者在开始尝试脚本编写时所面临的困难。本教程阐述 Lua 的基本原理并展示如何为自定义游戏的某个基

4、本要点编写脚本。我将尝试揭开某些技术术语的神秘面纱。 考虑要点 像每一个刚开始编写 Lua 的人那样,我非常熟悉入门的巨大障碍以及脚本无效时的那份挫败感。无论如何,有些事情应该记在我们的脑子里: Lua 是一种语言,你必须学会单个词句的意思以及如何运用他们来“涂鸦” 。即使你聪明绝顶, 这也并不意味你可以不用认真学习词汇和语法就来编写 Lua 脚本。和人类语言不同,即使你在 Lua 语句中犯了一个微不足道的错误,它也将彻底无法被程序理解。开始编写 Lua 时的大多数挫败感是来源于那些“一点不起作用” 的脚本, “这几乎不可避免的是你的错误!”自然的反应一般是说:“程序不在运转 ”或者“我的电脑

5、出毛病了”。但有 99.9%的可能是你犯下了一个拼写或语法错误。制作自己的地图并看到自编脚本运转是非常有趣的;但让脚本运转起来并不总是有趣的。即使 BKP 论坛上最优秀的脚本编写者也承认在调试自己的作品时仍然遇到大量挫折。并非每个人都有足够耐心只为了一个错位的字母、一个遗漏的括号或一个多余的分号来逐行检查脚本。如果想要编写脚本你必须接受这个事实,没有任何人能替你简化它。一旦你已经了解 Lua 的基础,最佳学习方法是打开一张你喜欢的地图并且逐行研究它的脚本(在手边准备一份 Calvin 的指南。译者注:或 liukun1982 翻译的 script 帮助文档)以弄清具体的原理。 如果你想测试一些

6、新脚本或从其他编写者那里“借” 来的脚本,不要在你乐于为傲的 26X26 地图上进行测试。制作一张4X4 的测试地图,放上最少的单位,仅测试脚本中对你来说是新鲜内容的代码块。如果脚本不运行,你可以很快发现问题而不需要检查一大堆其他不相干的东西来判断是否存在冲突。这是本教程所采用的方针。如果你确实遇到了困难(在浏览了BKP 写的抓虫须知(本书第 33 页)与这些教程以后) ,你可以在论坛中进行搜索,大多数问题已被讨论过了。如果你仍然无法找到答案,你可以在地图编辑问答专栏发布求助贴。如果你的问题明确具体(最好复制粘贴一些你的脚本) ,那些脚本编写的大侠们将会给我们这些小菜鸟提供迅速而有益的答复。

7、基础教程使用 以下每一节教程都配套一份与教程同名的地图(.bzm)与脚本(.lua)文件。所有.bzm 文件和.lua 文件应被复制粘贴到闪电战的 DataMaps 文件夹。这也是你用来保存自定义地图与脚本的路径。为了学习每一节教程,你可以用地图编辑器打开地图,用 SciTE 编辑器打开脚本。当你阅读完教程并看完地图和脚本内容以后,你可以按下地图编辑器工具栏右上角的RunBlitzkrieg 按钮看看脚本在游戏中是如何执行的。 前五节课程的每张地图都是建立在前一张地图的基础之上,地图和脚本一步步升级。最后两节课程是独立的,涵盖了BKP 论坛中经常提到的问题。本教程推荐你下载Blitzkrieg

8、SciTEEditor。它非常有效,是免费软件,体积不大,没什么理由不用。它不能替你编写脚本,当脚本无法运行时它也不能替你找出错误。但在编写与检查脚本时它对你很有帮助,所以还是下载吧!Blitzkrieg SciTE Editor (译者注:由于这个编辑器在处理中文时默认以半角格式处理,所以退格删除中文时只删除半个,从而出现乱码。建议中文的地图编写者最好加装汉化补丁,从而能完美支持在脚本中输入中文。 ) 注:使用 SciTEEditor 给文件命名时你必须使用一个.lua后缀否则它会被保存为.xml 格式。 基本原理 脚本是一个 lua 文件。在地图编辑器上有一个“ 扳手加字母A”的按键,点击

9、这个按键(译者注:设置脚本文件名)输入脚本名称,来把地图和相应的 lua 脚本文件联系起来。 脚本包含一系列的指令,叫做 functions(函数) ,当地图运行时,这些函数使事件发生。函数可以很简单,可以只是(指令电脑)在特定时间完成一个事件, 或是更复杂的,测试某个条件,并根据结果做出不同的事情。 注意: 附录 A 给出了一个闪电战特有函数列表 为了使函数和地图配合,地图上的单位,步兵班,建筑等必须指定一个脚本代码(ScriptID) ,在地图编辑器中,在左边选择 Objects 界面,双击单位调出“单位属性窗口”,然后双击“ScriptID”文本框并输入一个代码( ID) ,然后关闭属性

10、窗口。 提示:做一个笔记记录哪个代码是哪个单位。有的地图制闪电战 1 脚本编写基础教程 2作者常常在脚本的开头写下他们的编码方式。 提示:一个很有用的方法,是给予玩家单位和敌方单位以不同字头的代码(如 100s 和 200s) 很多函数要用到脚本区域(ScriptAreas 也译作脚本范围) 。用地图编辑器左边的 MapTools 按键来定义这些脚本区域: 选择“脚本范围工具 ”,并且拖动鼠标在在地图上定义一个(方形或圆形)区域,然后输入这个区域的名称。编写脚本时必须准确的使用这个“脚本区域名称” , 包括大小写和空格等都要一样。 提示:给你的脚本区域一个独特而有明确含义的名字,这样你不会在脚

11、本中混淆。 (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 语言中,

12、他们有固定的用法,并且只能那样用。其中一些词语的用法在下面的教程中会详细解说。按照规则, 这些保留字要用小写。这里也有一些闪电战的特定保留字,象“RunScript”,“LandReinforcement”,“Win” and“Loose” 等。这些必须正确书写- 首字母大写和其它字母小写。Calvin 的指南就像一部字典,可用来指导我们怎样正确书写这些词语。 提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor) ,那么所有的保留字,如果你的拼写正确,会变成蓝色并且以浅蓝背景高亮显示。 脚本编写者所定义的事件(函数)的名称叫“names”。它们可以是任意数字和字母

13、,但不能以数字开头。按照规则,我以大写字母开头为(函数)名称。举例来说, 在第一课我写的: function MoveCar() 在这里“function” 是保留字,而“MoveCar”是名称 提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor) ,那么(保留字是蓝色而)名称是黑色的。 当一个函数的名称确定以后,它就可以在后面被脚本调用。当它被再次使用时,必须放在双引号内作为字符串被调用。如我在第一课中写的:RunScript(“MoveCar”, 3000) 这里“RunScript” 是闪电战专用保留字, “MoveCar”是字符串,代表我在脚本中定义的一个

14、函数。一个绝对的要点是这个字符串要被正确的键入, 和之前的函数名完全一样,否则不会被脚本认可。由于这个原因,用复制粘贴函数名和字符串是最好的办法,可以防止键入错误。在使用双引号时,在引号和字符串的头以及引号和字符串的尾之间不许有任何空格。 提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor) ,那么当引号的位置正确时,字符串显示为紫色文字。如果你看到紫色背景的高亮显示,说明双引号输入有错(少了一半) 。注意,这个 脚本编辑器不会检查你键入的字符串正确与否函数和保留字是要用参数来限定的。要明白这个参数的作用,想象函数和保留字就像有人大声对你喊“做” ,但这没有任何意

15、义,直到你被告知做什么,什么时候做,做的频率多少,这些就是限定函数去做的参数。 在 Lua 中参数总是被放在一对括号内,如 RunScript(“MoveCar”, 3000) 保留字“RunScript”需要知道运行哪个函数,什么时候运行。这两个在括号内的参数, 被定义为运行字符串“MoveCar”以及值(value )为 3000 (这个在后面的教程中解释). 提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor) ,这个数值会显示为淡蓝色。当有超过一个的以逗号隔开的参数,来赋予这个字符串或值,很重要的一点, 如果这个逗号漏写了,脚本将不能运行。有些保留字或函数

16、不用任何的参数定义,那就是说它们对于脚本是不解自明的,不需要用例如什么,哪里,何时,频率如何等来定义。没有参数的保留字或函数的括号是空的,但这对括号仍然必须保留。比如 Suicide() 以及函数名后的括号。漏掉一个空括号是脚本不运行的一个常见原因。缩排是脚本编写者经常用到的(在编辑器中按 Tab 键) ,但这不是必须的也不会对脚本有影响。当然它们非常有助于使语句有条理。我会在举例中用我自己的方法, 而脚本编写者有它们自己的方法。按照规则,脚本的每一行结尾要有一个分号“;” , (除了某些情形下如一个保留字将直接对下一行执行操作-这在下面的第三课会解说)备注:有时候也会包括在脚本中,用于帮助脚

17、本编写者明白或提示某些事情或者告诉其他人写的是什么。一条备注开始和结束于至少两条短横,如“-NOTE-”(译者注:只需要开头的两条短横;备注 可以是中文但短横等标点必须是英文标点)。备注不会被脚本读取,所以在行首和行尾(译者注:只需要在行首)键入两个短横可以使这一命令行丧失功能。这一点在测试脚本过程中非常有用。 提示:如果使用闪电战脚本编辑器(theBlitzkriegSciTEeditor) ,这个备注会显示为绿色。 第一节 编写一个函数并使它运行 这一课介绍怎样使一个单位从它的初始位置移动到定义的新位置 第一节的地图 打开地图,这里有一辆小轿车(ScriptID 为 100)(双击单位可查

18、看 ID 号) 和轿车将要到达的一栋建筑 Lesson1.luaScript 脚本 function MoveCar() Cmd(0, 100, 916, 1516); Suicide(); end; function Init() RunScript(“MoveCar“, 3000); end; 3注意: 这个脚本以后缀为 lua 的文件保存,你可以复制粘贴这个脚本的语句到你自己写的脚本中。一定不要用微软的Word 软件来编写脚本,因为 Word 允许插入不同内码的文字,而这会导致游戏运行过程中止(即忽然退出) 。 解说 function MoveCar() 建立一个名叫“MoveCar”的

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

20、运行这个叫 “MoveCar”的函数(不要忘记双引号) 和何时运行(游戏开始后 3000 毫秒也就是 3 秒) end; 结束语句。 注意:可以在 Calvin 的指南或 liukun1982 翻译的 script 中找到Cmd 命令列表 第二节 添加第二个有多项命令的函数 这一节 介绍使第二个单位在与第一个单位不同的时间点,做一系列移动。 第二节地图 这里有一辆小轿车(ScriptID100 ), 一辆卡车(ScriptID101), 一棵树和一个纪念碑。卡车将绕过纪念碑驶向建筑。 Lesson1.luaScript 脚本 function MoveCar() Cmd(0, 100, 916

21、, 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); Suicide(); end; function MoveTruck()

22、一个新函数,起名 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; 注意:第二个函数也可以象

23、下面的脚本一样由第一个函数来调用。这是经常被用到的手法,适用于第二个函数肯定在第一个函数被执行之后被调用。这样做的好处是不用同一时间调用很多函数,而是只在需要时才调用特定的函数,从而可以减少 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); Su

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

25、70); QCmd(0, 101, 1100, 1890); Suicide(); end; function Init() RunScript(“MoveCar“, 3000); 现在这个运行“MoveTruck”的命令可以从 Initfunction 中去掉了。end; 第三节 测试一个条件(是否具备) 这一节将介绍测试一个条件是否达到特定值从而触发一个新的应激行动。这是在闪电战地图中非常有用并且常用的程序设计。 第三节地图 这个地图上,在房子周围,有一个名为“Farm”的脚本区域,和两个脚本代码(ScriptID)为“103” , “104”的步兵班. 这两个步兵班隶属于援军组“103”

26、( reinforcement group 103103b a 大于 b a=b a 大于或等于 b a=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“,

27、 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 开始运行函数 Objec

28、tive0Complete,这个函数会显示目标完成的信息 Suicide() end; function Objective0Check() - NEW - if (130, “Trench“) =1 then 和 GetNUnitsInArea 语句不同,GetNScriptUnitsInArea 计算的是代码为 130 的成员在脚本区域“Trench” 内的数量 SetIGlobalVar(“Mission0“, 1); 当条件符合,以指定的参数保存一个变量的名称和值。这里名称是“Mission0”,值是“1”,这个值可以是任意整数。 (译者注:名称也可以是任意的,只要作者自己明白指的是什

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

30、 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; 第五节 归纳 这一节我们将综合前面

31、的教程内容:目标条件、不同种类的条件测试以及多样的援军呼叫。教程中将示范 if else 以及if elseif 语句的用法,加入胜利和失败条件并且调用全局变量来测试这些条件是否已经符合。下面的例子换上不同的脚本区域和脚本代码以及不同的条件测试可以作为很多单人地图的基础。 第五节地图,基于第四节地图 Lesson5.lua 脚本 function DebugView() Password (“Panzerklein“); DisplayTrace(“Lua really isnt scary any more!“); 7ShowActiveScripts(); -God(0, 2); Suic

32、ide(); 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,

33、 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(“SquadMo

34、ve“, 2000); Suicide(); end; function SquadMove() Cmd(3, 103, 2530, 2850); Cmd(6, 104, 10); Suicide(); end; function Objective0Check() if GetNScriptUnitsInArea(103, “Trench“) = 1 then SetIGlobalVar(“Mission0“, 1); Suicide(); end; end; function Objective0Complete() if GetIGlobalVar(“Mission0“, 0) = 1

35、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(“

36、HeavyArmourDeploy“, 30000); Suicide(); end; function Objective1Complete() - NEW - if GetNUnitsInParty(1) 0 then Cmd(3, 106, GetScriptreaParam s(“Trench”); else Cmd(3, 106, 393, 3777); Suicide(); end; end; function USCounterattack() - NEW - if GetNUnitsInArea(1, “Trench“) 105 0 then 测试敌方(1)在区域 Trench

37、 中的单位数量是否大于 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 GetNUnitsInAre

38、a(1, “Trench“) = 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() if GetNUnitsInArea(1, “Bunker“) = 1 then 一个触发飞机召唤的条件测试,当脚本区域 Bunke

39、r 内的 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(“Bu

40、nker“); 这一行语句不会在脚本中执行,因为它的开头有两短横-。 (译者注:LUA 的注释语法)这是一种召唤飞机的备选方案。函数执行时将会自动得出脚本区域 Bunker 中心的坐标,不需要直接给出坐标。 Suicide(); end; end; 两个 end: 一个对应 if,一个对应函数主体。 巡逻教程 这节教程将示范如何建立一条巡逻路线。在这个例子里只有一个单位进行巡逻,但是也包含任何数目。如果进行巡逻的单位具有主动攻击能力(译者注:快捷键 A 的功能) ,它将与遭遇的任何敌人交战,如果战斗后此单位幸存,它将继续进行巡逻。 巡逻教程地图 地图上有一辆脚本代码 100 的装甲车停在名为

41、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,

42、100, 1351, 647); RunScript(“PatrolArea“, 2000); Suicide(); end; end; 10function Init() RunScript(“PatrolArea“, 5000); end; 诠释 function PatrolArea() if GetNScriptUnitsInArea(100, “Starting Point“) 0 then 检查巡逻单位(脚本代码 100)是否存在并且位于初始位置(脚本区域 StartingPoin) Cmd (3, 100, 765, 681); 命令单位(100)移动攻击(3)到坐标 x,y(7

43、65,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)语句,

44、一次巡逻的循环可以包含任何数目的移动次数。重要的是最后一次移动,单位必须回到函数第一行语句中的脚本区域。 调试脚本 调试是一个发现和消除编码缺陷(bug)的过程。在程序界, 公认的调试步骤是: 1 确认缺陷的存在 2 分离存在缺陷的原始资料 3 分析引起缺陷的原因 4 决定修正缺陷的方案 5 实施修正并测试 出了毛病的脚本需要调试: 它不运行或者运行的结果与预想的不一致。 出了毛病的脚本:当脚本触发的目标没有在游戏中显示,你必须意识到你的脚本由于一处或多处错误而“出了毛病” 。一个很好的习惯是在游戏的 Init 函数中放一个“DisplayTrace”语句, 显示一些诸如“脚本工作正常。 。

45、。 。 。 。 ”之类的讯息。如果脚本“OK”,这些讯息会直观地显示出来。如果没有出现,你就可以知道脚本有缺陷。这个语句可以在脚本调试完毕后删除或改成注解(前面加两个短横) 。 提示 1:当你发现脚本出了毛病, 你不需要退出闪电战 , 你可以在游戏仍然在运行的情况下回到 Windows,修改脚本并保存, 然后回到游戏, 选择“ 重新开始任务”去再次测试这个脚本。 注意:如果你的脚本文件是保存在一个.pak 文件中, 由于这个 pak 文件被游戏和地图编辑器锁定了, 所以你不能修改 pak 包内部的文件。 (译者注:所以你要把 bzm 文件和 lua文件放在 maps 文件夹下,待调试玩了在放回

46、 pak 包) 提示 2:不要把地图放到 pak 包里除非它已经编辑完全并且调试完成。任何被地图编辑器打开的地图,无论它是否从pak 包里打开,但地图编辑器保存时,都是保存到 data 文件夹下(maps 文件夹) ,因而很容易被遗漏在 pak 包之外,除非你记得保持你的地图 pak 包常新(译者注:呵呵,不然忙乎了半天, 发布出来的地图包却是错的) 。当你调试你的脚本时, 你应该要检查以下常见的错误: 1 函数没有以 “end”; 语句结尾 2 注释语句行不正确的用了单短横“-“ 而不是双短横“-“ 3 条件测试模块没有以它们自己的“end;“语句结尾 实例 function CheckTo

47、wn() if GetNUnitsInArea(0, “Town“) = 0 then ObjectiveCha nged (0,1); RunScript( “Objective1“, 5000); end; 上面的代码会因为“if GetNUnits.“ 模块没有它自己的“end;“语句而出错。每个函数模块需要它自己的 end; 语句结尾。每个 if 模块需要它自己的 end;语句结尾。 4 错误的大小写:这个 if 指令必须小写,不能输入成 Iff5 语句没有以分号“;“ 结尾。注意: function 和 if 等保留字不需要以分号结尾 6 文本数值(或字符串)没有正确的结尾。如下例子

48、,脚本会因为 GetUnitsInArea(0, “Town) 出错,因为这个脚本地域名字Town 没有双引号包起来。 7 在“DisplayTrace“ 语句内用了双引号。 例如:下面的代码不合规:DisplayTrace( “Commander, the “Tigers“ have arrived.“); 因为包围 Tigers 的双引号指示脚本处理器你要显示的字符串是“Commander, the “8 用括号嵌入的函数和条件语句-“(“ 和“)” 没有正确数量的左括号和右括号,如下面的错误例子: if (GetNScriptUnitsInArea (1, “finalattack“)

49、= 1 then 因为 GetNScriptUnitsInArea 函数没有右括号结尾 9 键入 Loose(); 误作 Lose(); 。这也许很容易被诱导用上了正确的拼写 Lose 但 Loose 才是正确的。 10 Win() 语句遗漏了玩家方的数字代号。 11 为节约时间,在调试时,有必要知道,以下情形不会导致脚本错误: a 召唤不存在的援军组 b 调用不存在的函数(用 RunScript 命令) c 调试运行结果与预期不符的脚本 有时候你会发现脚本没有如你预期的那样执行。比如,当你达到所有要求时目标却不显示完成,或者援军不断地出现。下面是一些常见的错误,看是否会在你的脚本里找到:如果你发现一个特殊的行动或事件(比如,援军重复地出现)不断地自行重复,那你要检查是否遗漏了 Suicide(); 语句。这个语句(译者注:suicide 意为“自毁” )告诉脚本停止运行, 这个语句的用处是保证脚本运行平稳。 示例 function Init() RunScript(“MyCheck”,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报