|
楼主 |
发表于 2011-7-12 04:30:04
|
显示全部楼层
本帖最后由 chyj4747 于 2014-11-24 14:30 编辑
第十三章:单位组&玩家组
单位组这个数据类型在J中是:group(本意是组、团队)
玩家组是:force(本意是力量)
虽然同是“组”,中文可以用单位和玩家来区别,但是英文不行,写成unit_group和player_group的话不仅占地方而且写起来很麻烦。所以玩家组就用force这个词,在这里就是“势力”的意思。
这两个数据使用方法其实差不多,这里主要讲group的使用。
首先,如果什么都不做,魔兽中是没有group这个东西的,所以我们要做的第一件事是新建一个单位组。
之前我们已经见过了新建单位的写法,新建单位组也是类似:CreateGroup();也就是凡是新建,基本都是用Create这个单词。
在J中,几乎所有的数据都可以当做变量,所以单位组的申明可以在globals里,也可以使用local:
- globals
- group g=CreateGroup()
- endglobals
- 或者
- function G takes nothing returns nothing
- local group g=CreateGroup()
- set g=null
- endfunction
复制代码
注:若以局部变量的方式,则记得要排泄。
PS:两种方式需要根据不同的情况灵活使用。
单位组的作用呢就是可以让我们只发布一次命令就让一堆单位按这个命令行动,而不再是对这些单位一个个发布命令。当然还有其它的好处,之后遇到的时候就会明白的。
先看下如何往单位组里加单位以及移除单位:
首先我们需要一个单位组:
- globals
- group g=CreateGroup()
- endglobals
复制代码
于是我们就有了一个新建的空单位组。
- globals
- group g=CreateGroup()
- endglobals
-
- function add_del takes nothing returns nothing
- call GroupAddUnit( g, gg_unit_hpea0000 )
- call GroupRemoveUnit( g, gg_unit_hpea000 )
- endfunction
复制代码
注:gg_unit_hpea0000是已经在地图上放置的农民,大家放置时的编号可能不同。
在add_del这个函数中调用的两个本地函数的意思就是为一个单位组添加/删除单位。
Add:加;Remove:移除、去除
这两个函数需要的参数相同,都需要一个已经存在的单位组,一个将被添加/删除的单位。
但是添加单位这个函数的缺陷很明显,一次只能添加一个,如果有一群单位的话一个个添加就太繁琐了。
这种时候就要使用“选取范围内所有单位”这个函数:
- native GroupEnumUnitsInRange takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing
复制代码
注:看不懂函数名的同学请回顾前面几章,已经教了很多次翻译函数名的方法了,之后也不再逐一翻译了。
boolexpr filter:这个参数是布尔表达式,简单来说就是一个判断对错的函数。
这个本地函数的意思是往一个group里添加以(x,y)为圆心范围radius之内且符合filter的所有单位。
那如果不要条件呢?可以这么写:
- call GroupEnumUnitsInRange( group, 0, 0, 100, null )
复制代码
null在这里就表示无条件,也就是添加范围内的所有单位。
添加完单位后就需要对这个单位组里的单位发布命令了:
我们先转化“单位组-选取(单位组)内的单位做动作”这个T动作到J看下函数
转化后发现是这么个东西,再到function list查一下,原来这个函数是调用了ForGroup这个函数,另外还有一个变量以及调用了DestroyGroup(删除单位组)这个函数。
也就是T中的这个选取单位组做动作在做完动作后直接删除了这个单位组,但是这么写其实会降低运行效率,因为多调用了一次ForGroup这个函数。反正这个函数也是调用了ForGroup和DestroyGroup,我们直接写这两个函数就行了,而且这样写的另一个好处是什么时候删除单位组是我们自己掌控的。
注:ForGroupBJ并不是无用,当需要选取比如某个玩家的所有单位做一次动作的时候用这个函数写起来就比较省力了。
ForGroup这个函数除了单位组外,还需要一个code,也就是我们需要另外写一个函数,其功能就是让这个单位组内的单位做动作。当然了,这个code是“被使用”,所以要放在前面。
先了解下下面这两个函数的作用,之后看实例来理解吧……
(其实是我没想到好的讲解方法。。)
这两个函数都不需要参数:
GetEnumUnit():相当于T中的“选取单位”,在选取单位组做动作时用来在动作函数中获取被选取的单位。
GetFilterUnit():相当于T中的“匹配单位”,在选取符合条件的单位添加到单位组时用来在条件函数中获取被选取的单位。
我们直接看一个实例:
山丘之王的雷霆一击大家都知道吧(不知道的同学请使用人族首发山丘之王学习第二个技能打一盘常规战……),现在我们想知道山王敲地板时有多少单位在该技能范围内(不包括友军)。
PS:暂时只考虑一级的雷霆一击,不然可能要用到还没学的东西。
先想下我们需要什么事件,既然是在山王施放雷霆一击时显示单位数,则我们需要山王开始放技能事件。不过由于山王不是一开始就放在地图上的,我们不能使用指定单位事件,只能使用任意单位事件。
触发器就叫“LTYJ”(Lei Ting Yi Ji)吧……
- function InitTrig_LTYJ takes nothing returns nothing
- local trigger trig=CreateTrigger()
- call TriggerRegisterAnyUnitEventBJ( trig, )
- call TriggerAddCondition( trig, Condition( function ))
- call TriggerAddAction( trig, function )
- set trig=null
- endfunction
复制代码
注:TriggerRegisterAnyUnitEventBJ就是“触发器注册任意单位事件”,不过这是个BJ函数。
在“物体编辑器”中找到“雷霆一击”,按Ctrl+D查看编号;或者在T中写一个含有该技能的动作然后转J查看。得到该技能的编号是:‘AHtc’。顺便看下一级雷霆一击的范围,是250码。
然后补上Condition:
- function LTYJ_Condition takes nothing returns boolean
- return GetSpellAbilityId() == ' AHtc '
- endfunction
-
- function InitTrig_LTYJ takes nothing returns nothing
- local trigger trig=CreateTrigger()
- call TriggerRegisterAnyUnitEventBJ( trig, )
- call TriggerAddCondition( trig, Condition( function ))
- call TriggerAddAction( trig, function )
- set trig=null
- endfunction
复制代码
注:GetSpellAbilityId()就是获取施放的技能的ID,无需参数,如果是T的话就相当于在“条件”中判断施放技能是否为是雷霆一击。
再补上动作部分,我们需要先选取山王周围250范围内的非友军单位(确定了“动作”的名字,就顺便把初始化函数里的事件条件动作也补上,我这里事件用的是“发动技能效果”):
- function LTYJ_Condition2 takes nothing returns boolean
- return IsUnitEnemy( GetFilterUnit(), GetTriggerPlayer() ) == true
- endfunction
-
- function LTYJ_Action takes nothing returns nothing
- local group g=CreateGroup()
- local unit u=GetTriggerUnit()
- call GroupEnumUnitsInRange( g, GetUnitX(u), GetUnitY(u), 250, Condition(function LTYJ_Condition2) )
- set g=null
- set u=null
- endfunction
-
- function LTYJ_Condition takes nothing returns boolean
- return GetSpellAbilityId() == ' AHtc '
- endfunction
-
- function InitTrig_LTYJ takes nothing returns nothing
- local trigger trig=CreateTrigger()
- call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
- call TriggerAddCondition( trig, Condition( function LTYJ_Condition ))
- call TriggerAddAction( trig, function LTYJ_Action )
- set trig=null
- endfunction
复制代码
接着就是显示单位组中的单位数量
有一个BJ函数叫CountUnitsInGroup,在T里就是获取“某单位组中的单位数量”,大家直接用这个就行,不过这里使用ForGroup,其实CountUnitsInGroup也调用了ForGroup。
我们先加上ForGroup,顺便先为其准备一个空代码:
- function LTYJ_Action2 takes nothing returns nothing
- endfunction
-
- function LTYJ_Condition2 takes nothing returns boolean
- return IsUnitEnemy( GetFilterUnit(), GetTriggerPlayer() ) == true
- endfunction
-
- function LTYJ_Action takes nothing returns nothing
- local group g=CreateGroup()
- local unit u=GetTriggerUnit()
- call GroupEnumUnitsInRange( g, GetUnitX(u), GetUnitY(u), 250, Condition(function LTYJ_Condition2) )
- call ForGroup( g, function LTYJ_Action2 )
- set g=null
- set u=null
- endfunction
-
- function LTYJ_Condition takes nothing returns boolean
- return GetSpellAbilityId() == ' AHtc '
- endfunction
-
- function InitTrig_LTYJ takes nothing returns nothing
- local trigger trig=CreateTrigger()
- call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
- call TriggerAddCondition( trig, Condition( function LTYJ_Condition ))
- call TriggerAddAction( trig, function LTYJ_Action )
- set trig=null
- endfunction
复制代码
再往LTYJ_Action2中添加我们需要的动作,也就是数数(由于还没学过哈希表,所以用全局变量计数,若局部变量的话无法叠加,因为在一个函数里用完就自动被清除了);
最后添加显示最后的结果到ForGroup下面:
- globals
- integer n=0
- endglobals
-
- function LTYJ_Action2 takes nothing returns nothing
- set n = n+1
- endfunction
-
- function LTYJ_Condition2 takes nothing returns boolean
- return IsUnitEnemy( GetFilterUnit(), GetTriggerPlayer() ) == true
- endfunction
-
- function LTYJ_Action takes nothing returns nothing
- local group g=CreateGroup()
- local unit u=GetTriggerUnit()
- call GroupEnumUnitsInRange( g, GetUnitX(u), GetUnitY(u), 250, Condition(function LTYJ_Condition2) )
- call ForGroup( g, function LTYJ_Action2 )
- call DisplayTextToPlayer( Player(0), 0, 0, I2S(n) )
- set g=null
- set u=null
- endfunction
-
- function LTYJ_Condition takes nothing returns boolean
- return GetSpellAbilityId() == ' AHtc '
- endfunction
-
- function InitTrig_LTYJ takes nothing returns nothing
- local trigger trig=CreateTrigger()
- call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
- call TriggerAddCondition( trig, Condition( function LTYJ_Condition ))
- call TriggerAddAction( trig, function LTYJ_Action )
- set trig=null
- endfunction
复制代码
注:别忘了把WE里触发器的名字改成初始化函数使用的名字,忘了的同学请回顾触发器写法那两章。
大家自己想几个简单的题目练习下吧,主要熟悉下GroupEnumUnitsInRange和ForGroup这两个函数。
比如选取一定范围内的单位然后改变他们的移动速度,改变速度这个函数可以在T中“动作”的“单位”里找到,然后转J看下就知道了。
本章完~
回导航楼 |
|