【魔兽we制图RPG制图相关】求帮翻译一段jass脚本

当前位置: >>
魔兽争霸地图编辑器.AI制作
AI 脚本初级教程 ?????????? 【什么是 jass AI?】 :jass AI 是用纯 jass 编写的 AI 程序,可以用新建文本文档写或 jass 工具编写.真三 AI 以及 DOTA AI 也是由 AI 脚本编写. 【AI 脚本使用方法】 : ①运行地图编辑器 ②打开你最爱的对战地图,将它以另外一个名字保存(最好放在另外一个文件夹里面) ③按 F12(或者点 Modules(模块)菜单,然后选择 Import manager(输入管理器)) ④在 Import manager(输入管理器)中选择 File -&Import file (文件 -& 输入文件) ⑤选择刚刚建立好的**.ai.文件 ⑥鼠标右击已经导入的文件,选择 Modify file properties(修改文件属性) ⑦将文件的后缀名改为.ai ??◥?????????????????????????????????????????????????? 【代码放置】 :在文本文档中 AI 程序代码应如下放置 + Shingo Jass Highlighter 0.41globals // 这个放全局变量 endglobals function blabla takes blabla returns blabla // 自定义函数 endfunction function main takes nothing returns nothing //主程序在这 Endfunction[教程] 用 T 编写简单的 AI,让你的电脑变的强大起来 (菜鸟必看) 首先要知道一点,对于 1 般的 RPG,对战的 AI 是没有用处的,如果加了对战 AI,电脑就只会造房 子出兵,显然这个是我们不需要的 如果 1 个电脑单位没有任何 AI,那么它就只拥有以下基本功能,对于旁边的敌人会主动的攻击, 会自动放单体的杀伤魔法,(要说明的是,只会随便选择一个单位放技能,而没有针对性),敌人 比较多的时候也会放群体的杀伤魔法,也会使用加血的技能和魔法,这些是不需要特殊的 AI 的就可以办到的. 电脑的没有 AI 的缺点有以下几点 1,不会逃跑 2,不会学习技能 3.不会针对某个特别单位使用技能 4,不会使用部分物品和特殊的技能 ^^^^^^ 我现在就把 ORC3C 电脑英雄的沉没的 AI 简单的给大家介绍一下 基本的方法是这样 一般的说,ORC 的电脑的沉没对冽炎风暴,火焰雨,暴风雪等持续的魔法更有效 基本的方法是这样: 事件: 任意单位发动技能效果 条件:满足任意的下面一个条件 释放的 技能是 暴风雪 释放的 技能是 火焰雨 释放的 技能是 烈炎风暴 释放的 技能是 ^^^^^^^ 动作:选择 触发单位 为圆心 范围 800 满足条件 (匹配的单位是 英雄 为 TRUE) (匹配 单位控制者是 电脑) (匹配单位是 死亡 为 FLASE) (匹配单位是 是触发单位所有者的 敌人 为 TRUE) (匹配的单位所持有的 沉没权仗是 被持有的) 的单位做动作 LOOP 让选择的 单位使用 选择单位 所持有的 沉没权仗 到 触发单位的位置 就可以实现 AI 的沉默效果,一定要加 (匹配单位控制者是 电脑),否则玩家单位也会被强制 使用物品 下面偶在讲个 DOTA 的里面暗影萨满的多个技能连杀的 T 以暗影萨满 11 级的为例子 枷锁 LV4 MP 185 闪电 LV4 MP 160 蛇棒 LV2 350 一个连招 3 个魔法一共要消耗 700 点魔法 假使撒满身上有风仗,魔法充足 下面如下的写 T 触发 1__________________________________________________________ 事件:任意单位被攻击 条件:被攻击的单位是英雄为真 被攻击的单位的生命值低于 70% 被攻击的单位是攻击单位的敌人 被攻击的单位是死亡 为 假 动作: : 设置变量 A= 被攻击的单位 //(为其他的 T 记录) 选择 触发单位 为圆心 范围 800 满足条件 (匹配的单位的类型是 暗影撒满 为 TRUE) (匹配单位控制者是 电脑) (匹配单位是 死亡 为 FLASE) (匹配单位是 是触发单位所有者的 敌人 为 TRUE) (匹配的单位所持有的 飓风权仗是 被持有的) 的单位做动作 LOOP 让选择的 单位使用 选择单位 所持有的 飓风权仗 到 被攻击的单位 设置变量 B= 选择的单位 //(为其他的 T 记录) 命令 B 使用 暗影猎手_毒蛇守卫 到 A 所在的点 开启触发器 2 开启触发器 4 触发 2__________________________________________________________初始关闭 事件:每 0.2 事件 条件: 动作: 选择 A 为圆心 范围 200 满足条件 (匹配的单位的类型是 毒蛇守卫 LV2 为 TRUE) (匹配 单位控制者是 电脑) (匹配单位是 死亡 为 FLASE) (匹配单位是 是触发单位所有者的 敌人 为 TRUE) 的单位做动作 LOOP 命令 选取的单位 发布 攻击 到 A 触发 3__________________________________________________________ 事件:任意单位死亡 条件:死亡的单位类型是 毒蛇守卫 LV2 动作: 关闭 触发 2 触发 4__________________________________________________________初始关闭 事件:每 0.2 事件 条件: 动作: 选择 B 为圆心 范围 600 满足条件 (匹配的单位的类型是 暗影撒满 为 TRUE) (匹配单 位控制者是 电脑) (匹配单位是 死亡 为 FLASE) (匹配单位是 是触发单位所有者的 敌人 为 TRUE) 的单位做动作 LOOP 命令 B 发布 人族 龙鹰骑士_空中锁链 到 A 触发 5__________________________________________________________ 事件:任意单位 开始释放技能 条件:释放的技能是 枷锁 动作:关闭 触发 4 触发 6__________________________________________________________ 事件:任意单位 释放技能结束 条件:释放的技能是 枷锁 动作:命令 B 发布 中立 那家海女巫_叉状闪电 到 A 命令 B 发布 中立 攻击 到 A几个组合的 T 就可以让电脑使用出强大的组合技能,就就是基本 T 做的 AI 下面的几页帖子在继续写其他的方面的 AI 呵呵[教程] 如何创建一个魔兽 RPG 的 AI 系统(转) ...从某地方挖出的 如何创建一个魔兽 RPG 的 AI 系统 作者:Blade.dk 翻译:通魔作坊?onlyxuyang 译文: 这篇文章将帮助你制作一个简单但是十分酷的英雄对战地图的人工智能。 这个你将学习的人工智能系统不是非常完美。我们将创建的是一个可以攻击其它英雄、 可以自己拣物品、学习和使用技能的人工智能系统,但是还是无法与人类玩家相比。 但是,当你学习了基础的知识以后你应该可以自己改进它。 前提需要: JASS 基础----这篇文章使用 JASS 来制作示例,所以你必须了解 JASS。在理论上它也可以在 T 中做出来,但是我不推荐那样做,因为用 T 来制作可能导致内存泄露、大量不必要的代码 以及在 T 中是无法使用 JASS 的返回值 BUG 和游戏缓存系统的。如果你不熟悉 JASS,请预先 补充一下你自己的 JASS 知识。你同样必须知道什么是代码行,如果你不知道的话,请补充自 己的知识。 基于游戏缓存以及返回值 BUG 的系统 注意事项: -我们将要制作的 AI 系统达不到人类的水平,但是比什么都没有强。而且我认为当你理解了 基础以后可以自己改进它。 -你不用完全按照我说的做; 我按做我的想法做, 但是如果你的想法更好或者你觉得自己的做 法更舒服,请按照你自己的想法做。我并不完美,这篇文章也不可能完美,但是我希望它可 以对你有所帮助。 -你可以使用在我的演示地图里面的 AI 系统而不自己动手 (如果你那样做了, 请告诉我一声) , 但是我建议你自己动手写, 因为地图可能很复杂而且你可以自己动手写一个 AI 系统中学到更 多的知识。 初始化部分: 首先在 WE 中创建一个触发条件为&玩家 1-玩家 1(红色)离开游戏&的触发器, 然后把它转换为 JASS。我们需要这个触发器来监视玩家离开游戏,那样我们才能为这个玩家开启人工智能。 现在它只监视一号玩家离开游戏,所以我们在正式地图中需要使用一个循环来监视从 0-11 号的玩家。 我们希望这个 AI 系统可以使用技能。听起来似乎很难,其实很简单。我们只需要使英雄学习 技能,那么他们就可以自己使用。 注意:电脑控制的英雄释放自定义技能的情况总是和它释放这个自定义技能的基础技能的情 况相同(这里翻译的有点含糊不清, 自定义技能的基础技能的意思是....基础技能是游戏本身 带有的技能, 自定义技能都是以某个基础技能为基础的...这样说做过图的大大应该可以明白 吧?).所以如果你的自定义技能是以沉默为基础技能的, 电脑控制的英雄就会在对战地图中应 该使用沉默的情况使用这个技能。 千万不要将技能以&通魔(Channel)&为基础, 因为电脑从来 不会使用它们,即使改变技能的 OrderString 也没有什么用。 为了知道每个英雄都拥有什么技能,我们创建了一个游戏缓存(game cache)来保存它。 在演示地图中我的触发器在地图的初始化部分创建了一个游戏缓存并将它保存在全局变量 udg_GameCache 中。需要注意的是缓存必须在我们使用它之前初始化,所以我在地图的初始 化时间中创建了它。 在我的地图中我写了一个函数 SetupSkills.在这个 AI 触发器的 InitTrig 函数中我使用了库 函数 ExecuteFunc 来开启另外一个线程执行这个函数。 这是为了防止地图的初始化时间太长。 jass: Copy code 我的 SetupSkills 函数如下: function SetupSkills takes nothing returns nothing local string h // Create a local string variable // Paladin // Here we’ll initialise the Paladin’s skills, repeat this for all other heroes set h = UnitId2String('Hpal') // Store the returned value of UnitId2String(‘Hpal’) in the local call StoreInteger(udg_GameCache, h, &BaseSkill1&, 'AHhb') // One of his base skills is Holy Light, store it as “BaseSkill1” call StoreInteger(udg_GameCache, h, &BaseSkill2&, 'AHds') // Store Divine Shield as “BaseSkill2” call StoreInteger(udg_GameCache, h, &BaseSkill3&, 'AHad') // Store Devotion Aura as “BaseSkill3” call StoreInteger(udg_GameCache, h, &UltimateSkill&, 'AHre') // Store Resurrection as his “UltimateSkill” ? // Repeat for each Hero. endfunction 接着是我的 AI 触发器的 InitTrig 部分: function InitTrig_AI takes nothing returns nothing local integer i = 0 set gg_trg_AI = CreateTrigger( ) loop exitwhen i & 11 call TriggerRegisterPlayerEventLeave( gg_trg_AI, Player(i) ) set i = i + 1 endloop call TriggerAddAction( gg_trg_AI, function PlayerLeaves ) call ExecuteFunc(&SetupSkills&) endfunction为英雄开启 AI 系统 为了控制 AI 我们使用了一个定时器(timer).我写了一个函数 StartAI 来获取一个单位的类型: 英雄(请在演示地图中查看这个函数)。这个函数只是创建一个定时器,并且&绑定&在这个英 雄身上,并且开启这个定时器。 这是演示地图中的空的 AILoop 函数和 StartAI 函数(这里给的只是一个框架,等下我们将展 示一些动作函数, 但是你起码必须先把 function 和 endfunction 写上去以保证 WE 不报错) : jass: Copy code function AILoop takes nothing returns nothing endfunction function StartAI takes unit hero returns nothing local timer m = CreateTimer() call AttachObject(m, &hero&, hero) call TimerStart(m, 0, false, function AILoop) set m = null endfunction注意, 我的这个 StartAI 函数通过将 periodic 参数设置为 false 来达到使定时器只执行一次 的目的(以后我们还会来讨论它的). 现在,你就可以在你的英雄选择系统中当由电脑控制的玩家选择英雄时调用这个函数,并且 在玩家离开游戏的时候执行这个函数。检测玩家是否拥有一个英雄,如果它拥有,调用这个 函数来开启那个英雄的 AI 系统。例如: jass: Copy code function PlayerLeaves takes nothing returns nothing local player p = GetTriggerPlayer() call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, GetPlayerName(p)+& has left the game.&) if udg_Hero[GetPlayerId(p)] != null then call StartAI(udg_Hero[GetPlayerId(p)]) endif set p = null endfunction注意:这个函数将使 AI 系统控制离开的玩家的英雄,但是这也不是必要的,你也可以做别的 事情。 使这个 AI 做些什么 当定时器终止的时候我们希望它做了这些事情: ●如果英雄死亡,等待他复活。 ●如果英雄将要死亡,命令他移动到地图中心的生命泉水。 ●如果英雄状态良好,检测是否有敌人在附近。如果有,则命令英雄攻击它。 否则就检 测是否有物品在附近,如果有的话, 发送一个巧妙 的命令让英雄拣起它。 然后命令英雄巡 逻到地图的一个随机坐标。 ●如果英雄是活着的而且有未使用的技能点,学习一个技能。 我们由变量的声明开始。 注意在我函数里面的实变量&e&, 它定义了在定时器再次启动前所经 过的时间,这样我们就可以在英雄死亡的时候等待短一点的时间,而在他攻击的时候等待长 一点的时间。这个变量初始化值为 5。 jass: Copy code 局部变量的声明: function AILoop takes nothing returns nothing local string a = GetAttachmentTable(GetExpiredTimer()) local unit h = GetTableUnit(a, &hero&) local rect i local location r local real x = GetUnitX(h) local real y = GetUnitY(h) local group g local boolexpr b local boolexpr be local unit f local string o = OrderId2String(GetUnitCurrentOrder(h)) local real l = GetUnitState(h, UNIT_STATE_LIFE) local real e = 5 ?我们由检测英雄是否死亡开始,如果他死亡了,设置&e&为 1.5(因为在复活以后等待 5 秒的 时间太长了,我们并不想这样). 当英雄的生命值&l&为 0 时,设置&e&为 1.5 来使定时器更加频繁的检测英雄是否复活. ? if l &= 0 then set e = 1.5 endif ? 接着我检测英雄的生命是否低于最大生命值的 20%.如果是的, 命令英雄移动到生命泉并且设 置&e&为 3. 当英雄的生命值少于最大生命值的 20%时,命令英雄移动到生命泉的位置。 ? if l & GetUnitState(h, UNIT_STATE_MAX_LIFE)/5 then call IssuePointOrder(h, &move&, GetUnitX(gg_unit_nfoh_0001), GetUnitY(gg_unit_nfoh_0001)) set e = 3 ? 如果英雄的状态良好, 检测他是否处在一个普通命令中(防止它打断了通魔技能).如果是一个 标准命令,我们再检测在 500 的半径内是否有敌人存在.如果存在敌人,简单的发出一个攻击 命令(不要改变&e&的值,5 秒对于这个情况刚刚好). jass: Copy code function AIFilterEnemyConditions takes nothing returns boolean return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(GetAttachedUnit(GetExpiredTimer(), &hero&))) endfunction ? else if ((o == &smart&) or (o == &attack&) or (o == &patrol&) or (o == &move&) or (o == &stop&) or (o == &hold&) or (o == null)) then set g = CreateGroup() set b = Condition(function AIFilterEnemyConditions) call GroupEnumUnitsInRange(g, x, y, 500, b) set f = FirstOfGroup(g) if f == null then ? else call IssueTargetOrder(h, &attack&, f) endif call DestroyGroup(g) call DestroyBoolExpr(b) endif ?&0and如果没有敌人存在,再检测物品.如果发现物品,再检测是否为一个提升状态的物品.如果不是, 检测英雄物品栏是否有空栏,有的话就命令英雄将它拣起来. jass: Copy code function AISetItem takes nothing returns nothing set bj_lastRemovedItem=GetEnumItem() endfunction function AIItemFilter takes nothing returns boolean return IsItemVisible(GetFilterItem()) and GetWidgetLife(GetFilterItem()) & 0 endfunction function AIHasEmptyInventorySlot takes unit u returns boolean return UnitItemInSlot(u, 0) == null or UnitItemInSlot(u, 1) == null or UnitItemInSlot(u, 2) == null or UnitItemInSlot(u, 3) == null or UnitItemInSlot(u, 4) == null or UnitItemInSlot(u, 5) == null endfunction ? if f == null then set i = Rect(x-800, y-800, x+800, y+800) set be = Condition(function AIItemFilter) set bj_lastRemovedItem=null call EnumItemsInRect(i, be, function AISetItem) if bj_lastRemovedItem != null and (GetItemType(bj_lastRemovedItem) == ITEM_TYPE_POWERUP or AIHasEmptyInventorySlot(h)) then call IssueTargetOrder(h, &smart&, bj_lastRemovedItem) else ? endif call RemoveRect(i) call DestroyBoolExpr(be) ?如果物品栏没有空位,或者没有发现物品,则命令英雄到一个随机地点寻找新的目标. ? else set r = GetRandomLocInRect(bj_mapInitialPlayableArea) call IssuePointOrderLoc(h, &patrol&, r) call RemoveLocation(r) ?收藏 分享linzefei 发短消息 加为好友 linzefei (橙 zi 174)当前离线 我从来没出现过 主题 108 精华 2 积分 50383 阅读权限 120 在线时间 3947 小时 最后登录
荣誉版主UID101045 帖子 6181 EXP5 影币 1445 威望 141 荣誉 1 贡献 4 金币 1156 注册时间
沙发 发表于
05:45 | 只看该作者 [ - 制图理论 - ]对于传统 PVE,RPG 地图设计的一些看法 现在我们需要检测的是英雄是否有未使用的技能点(将这个函数与进攻/拣取物品/前进到随 机地点等模块分开). 如果英雄有未使用的技能点,调用函数来使英雄学习技能.在我的演示地图中,我是用一个函 数来保存将要让英雄学习的技能的,使用的是下面这个模式: jass: Copy code function AILearnSkill takes unit h, string a returns nothing local integer i = GetTableInt(a, &LearnSkillOrder&)+1 if i == 1 or i == 4 or i == 8 then call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), &BaseSkill1&)) elseif i == 2 or i == 5 or i == 9 then call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), &BaseSkill2&)) elseif i == 3 or i == 7 or i == 10 then call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), &BaseSkill3&)) elseif i == 6 then call SelectHeroSkill(h, GetStoredInteger(udg_GameCache, UnitId2String(GetUnitTypeId(h)), &UltimateSkill&)) endif call SetTableInt(a, &LearnSkillOrder&, i) endfunction ? if GetHeroSkillPoints(h) & 0 and l & 0 then call AILearnSkill(h, a) endif ? 现在所需要做的是使定时器在&e&秒之后再次开启: ? call TimerStart(GetExpiredTimer(), e, true, function AILoop) ? 最后我们将局部变量设置为空: ? set h = null set i = null set r = null set g = null set b = null set f = null set be = null ?最后需要注意的事情 这些就是英雄 AI 系统的基础,它并不完美,但是它可以做为你的起点. 这个系统一点都不复杂,这样可以让你更加彻底的明白我的意思. 当你完成了一个属于你自己的 AI 系统时,尝试一下在你的系统中加入一个或者多个以下特 征: --尝试使它可以寻找周围最虚弱的敌人. --尝试在杀死特殊的敌人时让不同的 AI 玩家合作. --当大部分战斗都以生命泉为中心的时候,让英雄离开生命泉. --让 AI 玩家根据情况的不同说出不同的话(比如在杀死你的时候 AI 玩家会说&死吧~可怜的孩 子&) 完 我的帖子总索引 求工具以及下载属性领取贴 那个`` TOPlinzefei 发短消息 加为好友 linzefei (橙 zi 174)当前离线 我从来没出现过 主题 108 精华 2 积分 50383 阅读权限 120 在线时间 3947 小时 最后登录
荣誉版主UID101045 帖子 6181 EXP5 影币 1445 威望 141 荣誉 1 贡献 4 金币 1156 注册时间
板凳 发表于
18:59 | 只看该作者 [ - 魔兽制图 -]全屏天赋系统 接某教程2)线程(Threads) (这部分属于 AI 部分, 作为入门者做一般性了解就行了, 因为 AI 都是纯 JASS 写的, 也 没有真正好的 AI EDITOR. 本人也对此一知半解, 关于 AI 的文章也不多, 没什么好参考的.) 线程只应用于 AI 脚本(AI JASS), 不能用于触发器脚本(Trigger Jass). 通常, 当 AI 脚本开始运行时只创建一个线程, 创建更多的线程可以用 comman.j 的本地函数: + Shingo Jass Highlighter 0.41 native StartThread takes code func returns nothing调用 call StartThread(function myfunc) 将创建一个从函数 myfunc 开始执行的线程. 每个玩家最多可以拥有 6 个线程, 包括一开始执行的主线程. 当一个玩家有 6 个线程数 时, 调用 StartThread()的语句将被忽略. 线程不能回收, 当你为某玩家创建了 5 个自定义 线程, 将无法为该玩家创建更多的线程. 当新线程创建时, 线程立即生效. 当线程让步执行时, 创建此线程的父线程将继续执 行. 在同一玩家中的所有线程都共享全局状态(包括变量). 即是修改某个全局变量, 修改后 的值在此玩家的所有线程中都是可见的. 线程在以下的情况让步执行, 返回父线程 a) 当线程中的操作码(opcode)超出限制, 线程会自动休眠 1 秒 b) 当线程中用使用 Sleep(n), 线程将休眠 n 秒, 然后继续执行. 线程在以下情况会中止, 返回父线程 a) 如果 call StartThread(null)中, 线程中止 b) 当线程的主函数返回, 线程中止. (StartThread()中之间调用的函数就是主函数.) c) 当线程中使用没有声明的变量, 线程中止. 在使用之前, 变量必须声明. d) 当线程中出现零为被除数时, 线程中止 e) 线程主函数出现语法错误. 注意: 虽然 AI 脚本可以使用大部分 common.j 的库函数, 但有些类型的函数在 AI 不能正 常工作, 如: a) 返回字符串类型(string)的本地函数, 如 I2S(), SubString()等 b) 需要以 code, trigger, boolexpr 等类型数据为参数的本地函数, 如触发器函数, 队列函数(ForGroup, 等) 注意: AI 中不可以使用 Blizzard.j 的函数, 触发器中也不可以使用 common.ai 的函数, AI 和触发器都可以使用 common.j 的函数(当然, 对于 AI, 还受上面所说的限制) common.ai 和 common.j 是写 AI 时可以调用和参考库文件, 要研究 AI, 先去读这 2 个文 件. 3) 跨脚本通讯(Inter-Script Communication) 在游戏中, 可能会有多个独立的 Jass 脚本文件同时运行. 比如在对战地图中的游戏, 运行触发器脚本文件的同时, 也可能运行了每个电脑玩家的 AI 脚本文件. 每个脚本文件之 间的全局变量不是共享的. 所以, 一个电脑玩家的 AI 脚本中设置的全局变量不会影响另一 个电脑玩家的 AI 脚本的执行. 触发器脚本也不可以和 AI 脚本共享全局变量. 但可以用传递命令的方法进行脚本之间 的数据交换. 命令由一对数值型数据(integer)组成: 命令值(command value)和数据值 (data value).+Shingo Jass Highlighter 0.41 从触发器脚本向 AI 脚本发出通讯命令, 可以使用 common.j 中定义的以下本地函数: native CommandAI takes player num, integer command, integer data returns nothing 参数: player num integer command integer data//玩家 //命令 //命令数据以下是 AI 中使用的 common.j 函数, 注意: 每个电脑玩家都会有独立的 AI 脚本, 所以, 以下函数都没有要求玩家作为函数参数. 每个电脑玩家都有命令堆来堆放接受到的命令. 想知道有多数个命令堆放在命令堆, 可 以用下面的函数: native CommandsWaiting takes nothing returns integer 参数: 无 返回: 命令堆的命令数(integer) 获得存放在命令堆中最顶端的命令(): //返回命令 native GetLastCommand takes nothing returns integer //返回命令数据 native GetLastData takes nothing returns integer 上面 2 个函数都不会移除命令堆中的命令, 要移除堆中的命令, 可以用: native PopLastCommand takes nothing returns nothing4) 队列(Enumerations) 虽然 JASS 不能自定义数据结构(因为 JASS 缺少指针操作符), 但 API 库中提供了一些实 现队列操作的函数. 如一组单位为单位组(group), 一组玩家为势力(force), 虽然一组可破 坏物没有明确定义它的数据类型, 但也可以用 API 函数来操作. 单位组和势力的操作函数很类似. 单位组处理函数 // 初始化单位组 native CreateGroup takes nothing returns group // 在指定单位组中增加指定单位 native GroupAddUnit takes group whichGroup, unit whichUnit returns nothing // 在指定单位组中移除指定单位 native GroupRemoveUnit takes group whichGroup, unit whichUnit returns nothing 势力处理函数 // 初始化势力 native CreateForce takes nothing returns force // 在指定势力中增加指定玩家 native ForceAddPlayer takes force whichForce, player whichPlayer returns nothing // 在指定势力中移除指定玩家 native ForceRemovePlayer takes force whichForce, player whichPlayer returns nothing JASS 不能直接操作队列里面的元素, 它是通过 callback 类型的函数来实现对队列的操 作: // 对指定单位组中的每个单位都运行指定 callback 函数 callback // (对应 GUI 语言的 For Each Unit in &Group&) native ForGroup takes group whichGroup, code callback returns nothing // 对指定势力中的每个玩家都运行指定 callback 函数 callback // (对应 GUI 语言的 For Each Player in &Force&) native ForForce takes force whichForce, code callback returns nothing 输入上面两个函数的 callback 函数必须是无参数无返回值函数(takes nothing returns nothing) 同样, 操作可破坏物也可以用在区域内的可破坏物作为队列, 可以以用类似的方法: // 在指定区域 r 内符合指定过滤器 filter 的都运行指定 callback 函数 actionFunc // (过滤器见下节的讲解) native EnumDestructablesInRect takes rect r, boolexpr filter, code actionFunc returns nothing 在 callback 函数, 可以用下面的函数获得队列中的下一个元素: // 获得单位组中的下一个单位 // (对应 GUI 语言的 Pick Every Unit in &Group&) constant native GetEnumUnit takes nothing returns unit // 获得势力中的下一个玩家 // (对应 GUI 语言的 Pick Every Player in &Force&) constant native GetEnumPlayer takes nothing returns player // 获得可破坏物组中的下一个可破坏物 // (对应 GUI 语言的 Pick Every Destructables in &Region&) constant native GetEnumDestructable takes nothing returns destructable 注意: AI 中不支持队列函数的使用.这是杀死单位组中所有单位的实例: // 这是 callback 函数, 无参数并无返回值 function KillGroupCallback takes nothing returns nothing // 获得单位组中的下一个单位 local unit nextUnit = GetEnumUnit() // 杀死该单位 call KillUnit(nextUnit) endfunction // 调用 ForGroup // 对单位组 groupToKill 中的每个单位都运行函数 KillGroupCallback call ForGroup(groupToKill, function KillGroupCallback) 另一个经常是用的例子是在队列中查找特定条件的元素. 不幸的是, 因为 JASS 只支持 callback 函数来处理队列中的元素, 所以只有用全局变量来保存不同单位的属性. 下面是 找出单位组里生命最高的单位的例子: //定义全局变量 globals //用于储存两单位比较后较高的生命值, 初始化为 0 real mostLifeSoFar //用于储存两单位比较后有较高生命值的单位, 初始化为 null unit unitWithMostLifeSoFar endglobals //比较单位生命值的 callback 函数 function MostLifeCallback takes nothing returns nothing //获得单位组中的下一个单位 local unit nextUnit = GetEnumUnit() //获得单位属性 - 生命 //UNIT_STATE_LIFE 是 common.j 中定义的常量 local real life = GetUnitState(nextUnit, UNIT_STATE_LIFE) //比较生命值 if life & mostLifeSoFar then //把较大的生命值储存 set mostLifeSoFar = life //把有较大生命的单位储存 set unitWithMostLifeSoFar = nextUnit endif endfunction ... //初始化全局变量的值为空值 set mostLifeSoFar = 0 set unitWithMostLifeSoFar = null //调用 ForGroup //对单位组 myGroup 中的每个单位都运行函数 MostLifeCallback 比较生命 call ForGroup(myGroup, function MostLifeCallback) //上句运行后, 全局单位类型变量 unitWithMostLifeSoFar 便指向单位组 myGroup 中最高生命的单位, 或: //如果单位组 myGroup 是空组, 那么 unitWithMostLifeSoFar 便是空值 null ...当然, 实现队列操作, 也可以用数组的方法来处理. 但, 数组不能使用紧接着要说的队 列过滤器, 也不能定义数组中包含数组. 这些都是队列所拥有的优势, 如可以有数组型的单 位组(相当于数组中包含数组), 也可以用队列过滤器. 5)队列过滤器(Filters) 队列过滤器用于在队列中增加符合条件的元素. 比如, 在创建一个法力小于 20 的单位 组时, 便可以用队列过滤器(Filters)来创建. +Shingo Jass Highlighter 0.41 //在单位组中增加指定单位名为 unitname, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsOfType takes group whichGroup, string unitname, boolexpr filter returns nothing //在单位组中增加指定玩家为 whichPlayer, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsOfPlayer takes group whichGroup, player whichPlayer, boolexpr filter returns nothing //在单位组中增加指定玩家为 whichPlayer, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsOfTypeCounted takes group whichGroup, string unitname, boolexpr filter, integer countLimit returns nothing //在单位组中增加指定区域为 r, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsInRect takes group whichGroup, rect r, boolexpr filter returns nothing //在单位组中增加 countLimit 个指定区域为 r, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsInRectCounted takes group whichGroup, rect r, boolexpr filter, integer countLimit returns nothing //在单位组中增加在指定点坐标范围之内, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsInRange takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing //在单位组中增加在指定点范围之内, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsInRangeOfLoc takes group whichGroup, location whichLocation, real radius, boolexpr filter returns nothing //在单位组中增加指定个数, 在指定点坐标范围之内, 并符合队列过滤器 filter的单位 native GroupEnumUnitsInRangeCounted takes group whichGroup, real x, real y, real radius, boolexpr filter, integer countLimit returns nothing //在单位组中增加指定个数, 在指定点范围之内, 并符合队列过滤器 filter 的单 位 native GroupEnumUnitsInRangeOfLocCounted takes group whichGroup, location whichLocation, real radius, boolexpr filter, integer countLimit returns nothing //在单位组中增加被指定玩家选中, 并符合队列过滤器 filter 的单位 native GroupEnumUnitsSelected takes group whichGroup, player whichPlayer, boolexpr filter returns nothing 类似地, 对于势力也有相应的操作函数 //在势力中增加符合队列过滤器 filter 的玩家 native ForceEnumPlayers takes force whichForce, boolexpr filter returns nothing //在势力中增加指定个数, 并符合队列过滤器 filter 的玩家 native ForceEnumPlayersCounted takes force whichForce, boolexpr filter, integer countLimit returns nothing // Add all units that are allies of 'whichPlayer' that satisfy 'filter' //在势力中增加和指定玩家同盟, 并符合队列过滤器 filter 的玩家 native ForceEnumAllies takes force whichForce, player whichPlayer, boolexpr filter returns nothing //在势力中增加和指定玩家敌对, 并符合队列过滤器 filter 的玩家 native ForceEnumEnemies takes force whichForce, player whichPlayer, boolexpr filter returns nothing 以上函数中 boolexpr filter 在本章第 1)节触发器中有提到, 通常可以使用过滤器 (filterfunc).过滤器跟触发器的条件函数(conditionfunc)类似. 创建过滤器可以用以下语 句: native Filter takes code func returns filterfunc 其中参数函数 code func 必须是无参数返回值为布尔值的函数(takes nothing returns boolean), 过滤器用于在创建队列时增加额外的条件. 在过滤器中, 可以使用下面的函数获 得下一个待查的单位/玩家/不可破坏物: //获得下个待查单位 constant native GetFilterUnit takes nothing returns unit //获得下个待查玩家 constant native GetFilterPlayer takes nothing returns player //获得下个待查可破坏物 constant native GetFilterDestructable takes nothing returns destructable 我们来看个创建一个法力小于 20 的单位组例子: //过滤函数, 是无参数返回值为布尔值的函数 function LessThan20ManaCallback takes nothing returns boolean //获得下个检查的单位 local unit nextUnit = GetFilterUnit() //检查待查单位的法力是否小于 20 //小于 20 则返回 true, 否则返回 false return GetUnitState(nextUnit, UNIT_STATE_MANA) & 20 endfunction ... //创建过滤器, 过滤函数是 LessThan20ManaCallback local filterfunc myFilter = Filter(function LessThan20ManaCallback) //在单位组中增加指定区域, 符合过滤条件的单位 call GroupEnumUnitsInRect(myGroup, someRect, myFilter) // Destroy the filter if we are not going to use it again //不再使用过滤器, 销毁过滤器, 避免内存泄漏 call DestroyFilter(myFilter)
更多搜索:
All rights reserved Powered by
文档资料库内容来自网络,如有侵犯请联系***。

参考资料

 

随机推荐