|
Trigger篇
Trigger,也就是触发事件编辑器,它的功能十分强大,专门编辑游戏所有的人事物的事件,例如部队进入指定区域发生怪物出现的事件,就是所谓的游戏事件。对战地图时开局每个玩家都有一定的资源和单位,都是如此出品,还有RPG地图里的剧情对话等等,包括开始时选择英雄也全部都是用它来实现的,可以说,只要是一张RPG地图的话,Trigger就是整个地图的精髓与灵魂所在。
虽然编程的基础会非常有利于触发器的使用,但是所有人都有能力使用和编辑触发,如果你没有程序经验,你可以把触发是当作"拼图游戏"。
由于触发器的范围太过于庞大
所以给出一个建议的学习路线
触发器事件基本原理→变量(数组),延迟,循环(For、Pick)的概念→触发器中英对照表→算法练习→JASS
本篇将仅包括前两部分的内容
*本篇默认你已经读过“Warcraft III World Editor教程”
http://game.ali213.net/thread-2693121-1-1.html
或者你已经了解该文的内容,以能够理解本篇的部分内容。
第一章 基本操作
第一节 界面介绍
如果你对触发器的使用界面完全不了解,建议你先阅读官方说明手册,或者动手去熟悉它。
这里只给出一个简单解释。

这里只简单介绍一下功能区,这个部分最为常用。

前三组 一般操作,都是最普通的常用操作。
第四组 唯一的一个按钮用来管理变量的,按下它可以开启变量管理器,用于变量的新增、修改、移除。
第五组 第一个文件夹管理。其实一个触发器被放在哪里没有任何影响,只是做为分类用而已。
*文件夹有注解形式,注解形式的外观会有改变。可以当做分隔线。
第二个 创建触发器。也可以复制粘贴已存在的触发器再修改名称和内容。
第三个 创建注解,注解可以用做分隔或者分类,但是有字节限制。
第六组 分别是在一个触发器中加入新的事件(Event)条件(Condition)动作(Action)。

从上往下数
第四组 用来移动触发语句。
第五组 功能开关
允许触发器用 确定选定的触发器是否生效。失效的触发器不会出现在最终编译的JASS文件。
初始化触发器打开 选中此项则触发器将在游戏初始化时被打开。未打开的触发器也可以由其他触发器在某些条件下打开。
允许功能 确定选定的功能语句是否生效。
分类是注释 设定文件佳是否为注解。
第六组 该选择将触发器转换为JASS码,虽然会变得较为难懂,但功能比触发器要多。但是显然,转换的经常很没效率。
*转换是不可逆的,除非使用还原功能。
第二节 触发器操作
一个文字版的触发如何转换成触发器呢?
假设现在网上找到了一条触发如下- Creep Drop Item
- Events
- Unit - A unit owned by Neutral Hostile Dies
- Conditions
- (Random integer number between 1 and 10) Less than or equal to 3
- Actions
- Item - Create (Random level (Level of (Dying unit)) item-type) at (Position of (Dying unit))
复制代码 1 首先,按下创建新触发按钮创造触发,并且把它命名为Creep Drop Item
2 按下创建新事件,创造一个事件,你会看到下图

在Map Initialization那一栏里往下找,直到找到你要的为止。
也可以在全部那里往下拉到部队(Unit)分类,以便使下面那栏只显示出部队类别的事件,再从中找寻。

按下OK,Event就完成添加了。
3 接着加入条件。很明显,这是一个Integer Comparison

选择图中下划线部分,选择我们想要的部分。

这是触发编辑器的结构特色,每一个事件、条件、动作下或多或少有用到函数(Function)。
每一个函数可回传一个值,其内可能又有别的函数,就是像这样一层一层地往下推。
4 这样就行了,照样加入动作就可以了。

第三节 变量操作
有时候我们会看到这样的触发:- Set Barrack Count
- Events
- Unit - Barracks 0001 <gen> Dies
- Conditions
- Actions
- Set BarracksCount = (BarracksCount - 1)
- Multiboard - Set the text for (Last created multiboard) item in column 1, row 1 to (String(BarracksCount))
复制代码 上面的Barracks 0001 <gen>后会有写个<gen>(中文版就是“情报”),代表那是指向一个地图预置的东西,而编号是由WE自动产生的。
在事件裡选到Unit - Specific Unit Event,下面的Unit按下去之后,电脑会让你选取一个已经被摆在地图上的部队,你可以摆一个兵营然后选取它,
编号或许不是0001,但是那不要紧,只要你知道那代表的是哪一个兵营即可。

下面的Set BarracksCount = (BarracksCount - 1)可在动作的Set Variable那栏找到,
可是当我们按下变量(Variable)时,可能会像下图一样,发现一个选项都没有:

这表示你尚未建立变量,按下编辑变量(Edit Variables)以后,会出现一个让你设定变量的视窗,
按下建立新变数,输入你要的名称和类型。
建立一个整数(Integer)变量后按OK,此时变量那个视窗就会出现选择项目了。
第二章 事件条件行为
事件(Event)
事件表示触发的启动条件。
一个触发器相当于 “当Event时,如果满足Condition,则做Action”
所有的Event之间,是或的关系。任何一个Event发生,都会启动触发器。
事件中如果含有“Map initialization”(近战初始化),都会在游戏载入(loading)时执行。当开始一个游戏,出现一个Loading画面和一个在动的Loading光条时,电脑就是在载入地形、放置饰物、摆设部队,同时执行这些被设定要在初始化执行的触发。
*请注意有些触发是无法在载入时执行的,可以用Time - Elapsed game time is 0.00 seconds让它在游戏开始之后立刻执行。
条件(Condition)
条件是触发器的需求,决定行动的运作与否。
条件之间是与关系,所有的条件必须都是“True”(真) ,才能让一个触发的行动运作。
大部分事件所涵盖的范围过于广泛,但不是所有类似的事情你都想要做C,所以条件存在的意义就是要过滤出想要的事件,来决定是否执行行为部分。
举个例子来说,有个触发是这样的:- Complement
- Events
- Unit - A unit Dies
- Conditions
- ((Dying unit) is A Hero) Equal to True
- Actions
- Player - Add 100 to (Owner of (Dying unit)) Current gold
复制代码 ((Dying unit) is A Hero) Equal to True这个条件可以判断死亡的部队是否为英雄。
这样的话一个部队死亡了,而它刚好是个英雄,则条件((Dying unit) is A Hero) Equal to True符合,就成功启动触发会给死者100黄金做为补偿。
而如果死亡的部队不是英雄,则条件((Dying unit) is A Hero) Equal to True就不能成立,那启动失败,就什么也不会做。
行为(Action)
Action是一个触发的主要内容,它指明了触发成功启动后要做哪些事。
可以是杀死某部队、在某两点间制造效果、调整某个玩家的属性等。
行为可以让设计者全面控制游戏中所发生的事。
Action是触发中唯一的必要内容。(一个没有Action的触发什么也不做,写出来做什么?)
而且触发器不是一定要从事件启动,触发可以直接被其他的触发器直接调用。- *Trigger - Run (checking conditions)
- *Trigger - Run (ignoring conditions)
复制代码 第三章 程序概念
第一节 变量
变量是程序中数据的临时存放场所。在代码中可以只使用一个变量,也可以使用多个变量,变量中可以存放单词、数值、日期以及属性。由于变量让你能够把程序中准备使用的每一段数据都赋给一个简短、易于记忆的名字,因此它们十分有用。
通俗的讲,内存可以当作一条街。
定义一个变量就是给街上一间房子挂上门牌。(很明显门牌是不能重复的,不然邮递员会抗议的)
设置变量呢,就是找到那间房子,把东西放进房子里去。
修改变量的值,就好像去找到那间房子,把原来的东西丢弃,再放进一个新的东西。
最特殊的是取出,因为电脑的世界和现实世界不太一样,电脑拿完东西使用以后,东西并不会消失,房子里仍然永远还有一份。
OK,那变量做什么呢?
简单的讲,变量是一个暂存区。
如果我要在4分钟的时候创造一个英雄,10分钟的时候要给他一个伴读。那么10分钟的时候,我怎么告诉电脑我6分钟前创造的是哪个英雄呢?
如果不找个地方把英雄的名字写下来,除非时间倒流,不然是肯定找不到了。
so,写下来,放进一个变量,10分钟终于到来,我就可以去那间房子里找我之前做过些什么了。
触发器中的变量,有些是我们手动设立的,也有一些是自动建立的。比如Last created Unit、Last created special effect等等。当用触发器创造部队时,B社内部的函数会自动的创造一个部队,并且把它存到Last created Unit,以便接下来对它进行操作。假设创造了一个大法,Last created Unit指的是那个大法,我再创造一个大法,这时Last created Unit指的是那个新的大法,此时我就无法对之前的那个大法操作了,除非在他被创造后先用一个变量记下来: Set xxx = Last created Unit,再创造新的单位,就可以用xxx找到那个旧的大法了。
第二节 数组
在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。
用前面的例子来说明,就是有复数的房子属于同一个业主,于是业主给自己的房子挂上门牌以后还要在内部给它们一间一个索引。
数组可以用于某些固定的存储结构(比如真三中每个玩家的的英雄),也可以配合循环和随机数。- 比如要制作“每1分钟,就在基地随机产生1个 步兵、火枪兵、骑士、或法师”,可以先建立一个部队类型的阵列UnitType[],并且在初始化时,分别设定UnitTypeArr[0]=步兵、UnitTypeArr[1]=火枪兵、UnitTypeArr[2]=骑士、UnitTypeArr[3]=法师、...。然后就能写“每1分,在基地产生1个UnitTypeArr[Random integer number between 0 and 3] ”;如果要它轮流产生,可以写“每分,设定i = i mod 4 + 1,在主堡产生1个UnitTypeArr[i] ”;要每分钟4种都出,可以用循环:“每分钟,for Integer i = 0 to 3,在主堡产生1个UnitTypeArr[i] ”。
复制代码 上例中UnitTypeArr[]就像是一个Table, 可以抽取其中一个或几个,甚至全部:
编号 | 0 | 1 | 2 | 3 | 4 | 5 | ... | 资料 | 步兵 | 火枪兵 | 骑士 | 法师 | (空) | (空) | ... |
触发器阵列标号是从0开始(几乎所有程序都从0开始,同一般人的习惯不同,请注意),8191结束,即xxx[0..8191],总共8192个。
第三节 分支
to be or not to be.
简单的讲。这6个单词13个字母,就是分支。
就像是在道路上遇到了分叉,是直行还是右拐?就取决于程序走到分叉时所碰上的条件了。
这里我们还是用上一文使用的树木重生的例子。(前文已有连接)
Condition是条件,只要满足条件,就是to be,否则就是不满足条件,也就是not to be。
当选中的物体“不是白杨树而且不是夏树” 就会执行THEN中的子句,在本例就是nothing。
当是其中任何一种时,条件失败,此时执行ELSE中的子句,也就是将这个物体加入复活记数的Trigger Res中。
Trigger的分支包括两个功能语句,它们功能其实是一样的,区别仅仅在于他们的表现形式。
前文例子中的是多条件的版本,但实际上也可以利用单条件版本和逻辑式实现,如下

但是可以很明显的看出如果这个条件无限制的扩大,结果就是这个语句会非常的繁琐。
多条件IF的存在就是为了这样的情景准备的。
*但请注意的是多条件IF的Condition之间是AND关系,而不象单句时可以选择。
*同时单句IF的THEN和ELSE都只能执行一条功能语句。

第四节 循环
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。
一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。
循环语句是由循环体及循环的终止条件两部分组成的。
在Trigger中,B社提供了2种循环,分别是FOR和PICK。从这里开始涉及部分JASS入门知识
1 FOR循环
Loop Test
Events
Player - Player 1 (Red) types a chat message containing -test as An exact match
Conditions
Actions
Visibility - Disable fog of war
For each (Integer A) from 0 to 3, do (Actions)
Loop - Actions
Game - Display to (All players) the text: (String((Integer A)))
Visibility - Disable black mask
这个程序在输入-test时启动执行0到3一共4次Game - Display to (All players) the text: (String((Integer A)))
可以看看转换成JASS的情况如下
function Trig_Loop_Test_Actions takes nothing returns nothing
call FogEnableOff( )
set bj_forLoopAIndex = 0 //FOR的初值赋给循环控制记数器
set bj_forLoopAIndexEnd = 3 //FOR的结束值
loop //循环体
exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd //相当于break,当循环控制记数器超过结束值结束循环
call DisplayTextToForce( GetPlayersAll(), I2S(GetForLoopIndexA()) )
set bj_forLoopAIndex = bj_forLoopAIndex + 1 //递增循环控制记数器
endloop //循环体的结束标志
call FogMaskEnableOff( )
endfunction
//===========================================================================
function InitTrig_Loop_Test takes nothing returns nothing
set gg_trg_Loop_Test = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_Loop_Test, Player(0), "-test", true )
call TriggerAddAction( gg_trg_Loop_Test, function Trig_Loop_Test_Actions )
endfunction
2 PICK循环
这是一个由B社提供的特殊循环,它可以寻找到一群满足相同条件的单位或者玩家或者饰物。
它的格式类似如下
Pick Test
Events
Player - Player 1 (Red) types a chat message containing -test as An exact match
Conditions
Actions
Visibility - Disable fog of war
Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
Loop - Actions
Unit - Kill (Picked unit)
Visibility - Disable black mask
当转换成JASS时Loop - Actions所包括的功能语句会被打包进一个子函数模块,
而Pick every unit in (Units in (Playable map area)) and do (Actions)转换结果则是- call ForGroupBJ( (PICK的单位),(Loop - Actions包含的行为))
复制代码 即- call ForGroupBJ( GetUnitsInRectAll(GetPlayableMapRect()), function Trig_Pick_Test_Func002A )
复制代码function Trig_Pick_Test_Func002A takes nothing returns nothing
call KillUnit( GetEnumUnit() )
endfunction
function Trig_Pick_Test_Actions takes nothing returns nothing
call FogEnableOff( )
call ForGroupBJ( GetUnitsInRectAll(GetPlayableMapRect()), function Trig_Pick_Test_Func002A )
call FogMaskEnableOff( )
// ↑单位 ↑执行打包的子函数模块
endfunction
//===========================================================================
function InitTrig_Pick_Test takes nothing returns nothing
set gg_trg_Pick_Test = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_Pick_Test, Player(0), "-test", true )
call TriggerAddAction( gg_trg_Pick_Test, function Trig_Pick_Test_Actions )
endfunction
[ 本帖最后由 安妮罗杰 于 2009-5-3 23:20 编辑 ] |
|