战役制作新时代——翔鹰Z系列 新AI效果示例(第一弹)
翔鹰Z系列 新AI效果示例
前言
翔鹰版Z系列作为正在普及中的新版本帝国,其为战役制作所带来的便利,不仅仅是可视化的密铺以及新增的几个触发效果,通过Userpatch的新AI语句,可以在战役中达成许多意想不到的新效果。原版征服者的AI由于缺少变量交互,可用AI发掘的变量效果有限,但是在Z版本的时代,不会AI编辑,作为战役制作者的您就肯定OUT了。所以在开始展示新效果之前,我们先做一点AI知识的小普及,也方便大家能够更好的理解下面的教程。
帝国时代2征服者的AI由两个文件组成,分别是扩展名为.per的AI文本文件,和另一个文件同名,但扩展名为.ai的空文件。将两个文件同时放入帝国目录下的AI文件夹,便可以在地图编辑器的玩家选项卡设置电脑玩家的AI性格。.per文件中的AI语句有固定的语法,形式上与各种计算机语言程序类似,但框架内容十分简单,有基础英文水平的制作者肯定可以很快上手。
众所周知,帝国的触发系统由条件和效果组成,满足一定的条件就达成一定的效果。这点上AI也是一样的。.per文件中,触发所对应的是规则,即defrule,每一个AI都是由众多的defrule组成的,规则中包含的事实和动作,也就相当于触发中的条件和效果,AI语句中最基本的单元如下所示:
(defrule
(事实语句)
=>
(动作语句)
)每个规则就相当于一个触发,我们在这个触发里添加条件(事实)和效果(动作),决定AI的运作,就是这么简单。
看到这里,估计大家已经想到了。既然AI和触发如此相近,那么AI中所特有的事实和动作是否可以转换为触发的条件和效果呢?答案是肯定的。但是能转换多少,效果如何,要看AI和触发的交互性,而新AI语句的进步与突破,恰恰就是在交互性上。
那么,让我们进入正题,看看AI中的哪些好东西可以被用于战役制作上,又能实现什么样的效果吧!
改变玩家名称
使用up-change-name动作可以实现在游戏过程中修改电脑玩家的名称。
设想战役开始时,某个电脑的玩家名称为“王国军”,但随着剧情展开,可以在游戏中突然变为”叛军“甚至是”匪徒“,用玩家名称的改变来显示剧情的进展,是不是一个很神奇的效果呢?
示例:
在游戏中,剧情进行到一定阶段,王国军将叛变为叛军。此时通过触发进贡给玩家“王国军” 1 单位黄金;并在对应玩家的AI中添加语句:(defrule
(gold-amount >= 1) ;如果玩家的黄金数量大于等于1
=>
(up-change-name "叛军") ;改编玩家名称为叛军,注意引号必须为英文引号
(cc-add-resource gold -1) ;通过作弊减少1单位黄金,可以不要
(disable-self) ;关闭规则,只执行一次
)
——————————————
读取指定单位的数据
想必在帝国中检测单位或建筑物的生命值,一直都是困扰着战役制作者很久的难题。现在有了新AI语句up-object-data,这个问题将得到很简单的解决。而且这条语句不仅仅可以用于检测单位的生命值,指定单位的射程、速度、携带资源、是否驻扎于其他物件,甚至是所处在地图上的坐标都可以被检测。这些数据可以在事实语句中直接调用,十分方便。
示例1:
检测玩家指定单位是否驻扎在其他物件中。
在任意电脑玩家的AI中添加语句:
(defrule
(true) ;无条件直接执行
=>
(up-set-target-by-id c: 1) ; 将地图上ID为1的单位设置为要检测的单位。单位ID可以用Aokts打开场景文件后看到,如果要检测的单位ID不是1,此处改为对应ID即可。
)
(defconst Object-data-garrisoned17) ; 读取单位数据时,17号数据对应的是单位的驻扎状态,但是直接在语句中写下读取“17”,AI语句的可读性就会变差,之后修改和更正都不方便,所以此处定义“Object-data-garrisoned”这个直观可读的词语来代替17这个编号。
(defrule
(up-object-data Object-data-garrisoned== 1) ;读取上面指定单位的驻扎数据,0为未驻扎,1为已驻扎。
=>
(chat-to-all "单位驻扎于其他位置!" ) ;对所有玩家送出聊天信息。
(disable-self) ;关闭动作,只执行一次。如果需要循环检测,可以去掉本句和上面发送聊天信息的语句,并加入(cc-add-resource wood 1)等增加资源的语句,然后和触发系统配合做出更丰富的效果。
)
示例2:
在RPG战役中实现血量计效果,当主角的生命值小于100时攻击力会增加,大于等于100时复原。这里使用的是比较复杂的循环检测,并和触发效果进行了配合。
首先在任意电脑玩家的AI中添加语句:
(defconst Object-data-hitpoints 10) ; 读取单位数据时,10号数据对应的是单位的当前HP,此处定义“Object-data-hitpoints”这个直观可读的词语来代替10这个编号。
(defrule
(true) ;无条件直接执行
=>
(up-set-target-by-id c: 2) ; 将地图上ID为2的单位设置为要读取数据的单位。
)
(defrule
(true);无条件直接执行
=>
(set-goal 1 0) ; 设定信号1的初始值为0。值为0代表单位生命值大于等于100的情况,值为1代表单位值小于100的情况,以此来开启和关闭相应的规则,由于AI语句中不能像触发系统一样直接激活关闭触发,所以通过信号值来区分状态是AI设计中常用的技巧。
(disable-self);不循环,只设定一次。
)
(defrule
(goal 1 0) ;如果信号1的值为0,即单位HP大于等于100的情况。
(up-object-data Object-data-hitpoints < 100) ;在这种情况下,如果单位的HP小于100。
=>
(chat-to-all "生命值小于100,攻击上升!" ) ;送出聊天。
(cc-add-resource wood 1) ;AI玩家增加1单位木材,之后通过触发检测来增加攻击
(set-goal 1 1) ;将信号值调整为1,因为目前是HP小于100的情况。这也使本规则不会循环执行。
)
(defrule
(goal 1 1) ;如果信号1的值为1,即单位HP小于100的情况。
(up-object-data Object-data-hitpoints >= 100) ;在这种情况下,如果单位的HP恢复到了100以上。
=>
(chat-to-all "生命值大于100,攻击恢复!" )
(cc-add-resource food 1) ;AI玩家增加1单位食物,之后通过触发检测来减少攻击
(set-goal 1 0) ;将信号值调整为0,即生命值大于等于100的情况。
)
然后进入地图编辑器,新建触发:
触发1:开启循环
条件:堆积属性——AI玩家木材资源1
效果:进贡——AI玩家到大地之母,木材99999
效果:改变对象攻击力——主角,任意值
触发2:开启循环
条件:堆积属性——AI玩家食物资源1
效果:进贡——AI玩家到大地之母,食物99999
效果:改变对象攻击力——主角,负任意值
在聊天信息中显示变量
试想,在RPG战役中可以看到如下聊天信息——
系统:您现在的等级是XX级。
系统:您已经杀死了XXX个敌人!
甚至是……系统:您目前的生命值是XX点。
这些曾经需要用触发穷举才能检测的数据,如今用一段AI语句即可实现。因为在新版本中,up-chat-data-to-all这条语句可以在聊天信息中显示AI检测到的事实变量。不得不说这是一个非常重要的技术突破。
那么这些数据如何得到呢?这里要提到另外两条非常有用的语句:up-get-fact和up-get-object-data。他们的作用分别是“读取AI玩家的事实数据并储存”以及“读取指选定单位的物件数据并储存”。
示例:
在RPG战役中实现一个功能,输入数字1后,可以随时通过聊天信息显示主角的等级、杀敌数、生命值。
这里用到的up-get-fact系列命令可以保存多个变量,但是这里仅使用一个变量就可以完成。
首先需要按照传统的方法设置好等级系统,并用将相应数据储存在AI玩家的资源栏中,例如AI玩家的木材代表等级、AI玩家的石头代表杀敌数。
然后在对应玩家AI中添加语句
(defconst Data 101) ; 定义一个名叫“Data”的变量来储存单位的等级(木材)、单位的杀敌数(石头)以及单位的当前生命值,他的编号为101,这个编号有合法的范围值,此处设置为101,供参考。
(defconst wood-amount 6) ; 定义“wood-amount”来代替6这个编号。
(defconst stone-amount 7) ; 定义“stone-amount”来代替7这个编号。
(defconst object-data-hitpoints 10) ; 定义“object-data-hitpoints”来代替10这个编号。
(defrule
(true) ;无条件直接执行
=>
(up-set-target-by-id c: 3) ; 将地图上ID为3的单位设置为要读取数据的单位。
)
(defrule
(true);无条件直接执行
=>
(set-goal 2 0) ; 设定信号2的初始值为0。此处我们用信号法来实现分阶段读取和输入数字效果循环。因为新版AI中goal信号的数量增加到了512个(1~512),尽可随意使用。
(disable-self) ; 不循环
)
(defrule
(taunt-detected 1 1) ;检测到玩家输入数字1
(goal 2 0) ;如果信号2的值为0。此处两条件的需要同时满足才会执行下面的动作。
=>
(acknowledge-taunt 1 1) ;注销玩家输入的数字1,以便循环输入
(up-get-fact wood-amount 0 Data) ;读取木材数,参数为0(无视),并储存在Data变量中。
(up-chat-data-to-all "您现在的等级是 %d 级" g: Data) ; 此处与c语言类似,%d为格式语句,对应后面的g:Data,也就是将Data的值输出。g: 是新AI语句中类型操作符的一种,用语标记符号类型,代表的是目标。c: 为常数,s: 为策略值,此处使用g: 。
(set-goal 2 1) ; 改变信号2的值为1。这条规则虽然没加(disable-self),但是由于信号值改变也不会循环执行,下面我们去检测石头数量。
)
(defrule
(goal 2 1) ; 如果信号2的值为1
=>
(up-get-fact stone-amount 0 Data) ;读取石头数,参数为0(无视),并储存在Data变量中。
(up-chat-data-to-all "您已经杀死了 %d 个敌人" g: Data) ; 同上,输出Data值。
(set-goal 2 2) ; 改变信号2的值为2。下面去检测生命值。
)
(defrule
(goal 2 2) ; 如果信号2的值为2
=>
(up-get-object-data object-data-hitpointsData);读取指定单位的当前HP,并储存在Data变量中,此处不需要参数项。
(up-chat-data-to-all "您目前的生命值是 %d 点" g: Data) ; 同上,输出Data值。
(set-goal 2 0) ; 改变信号2的值为0,这时我们又可以输入1来开启检测了,是不是很方便?
)
第一弹的效果示例先给大家带来三个用AI实现的效果教程,如果大家感觉不好理解,我会考虑出一期视频专门讲解,在此要感谢yty兄在去年就汉化好的脚本编写参考——UserPatch 1.3版,我只不过是把yty兄的成果自己消化之后再展现给大家,也希望能够抛砖引玉,看到更多的朋友分享自己的研究成果,也算是为春节即将发布的新翔鹰版作一个小小的预热,感谢大家。 示例里面所有的代码都可以点击代码框最下面的“复制代码”,然后粘贴到不动的AI等其他现有AI内直接使用。当然要注意对应单位ID和属性的修改。
这里列出后两个效果中其余可用于检测事实语句:
物件数据常数
(defconst object-data-id 0) 编号
(defconst object-data-type 1) 类型
(defconst object-data-class 2) 类别
(defconst object-data-category 3) 分类
(defconst object-data-target 7) 目标
(defconst object-data-point-x 8) 点横坐标
(defconst object-data-point-y 9) 点纵坐标
(defconst object-data-hitpoints 10) 生命值
(defconst object-data-maxhp 11) 最大生命值
(defconst object-data-range 12) 射程
(defconst object-data-speed 13) 速度
(defconst object-data-dropsite 14) 资源放置点
(defconst object-data-resource 15) 资源
(defconst object-data-carry 16) 携带资源
(defconst object-data-garrisoned 17) 驻扎
(defconst object-data-garrison-count 18) 驻扎单位数
(defconst object-data-status 19) 状态
事实编号常数
(defconst game-time 0) 游戏时间
(defconst population-cap 1) 人口上限
(defconst population-headroom 2) 人口空间
(defconst housing-headroom 3) 住房空间
(defconst idle-farm-count 4) 废弃农田数
(defconst food-amount 5) 食物数
(defconst wood-amount 6) 木材数
(defconst stone-amount 7) 石头数
(defconst gold-amount 8) 黄金数
(defconst escrow-amount 9) 储备资源数
(defconst commodity-buying-price 10) 购买商品价格
(defconst commodity-selling-price 11) 卖出商品价格
(defconst dropsite-min-distance 12) 资源放置点最小距离
(defconst soldier-count 13) 士兵数
(defconst attack-soldier-count 14) 进攻士兵数
(defconst defend-soldier-count 15) 防御士兵数
(defconst warboat-count 16) 战船数
(defconst attack-warboat-count 17) 进攻战船数
(defconst defend-warboat-count 18) 防御战船数
(defconst current-age 19) 当前时代
(defconst current-score 20) 当前分数
(defconst civilization 21) 民族
(defconst player-number 22) 玩家编号
(defconst player-in-game 23) 玩家在游戏中
(defconst unit-count 24) 单位数
(defconst unit-type-count 25) 某类单位数
(defconst unit-type-count-total 26) 某类单位总数
(defconst building-count 27) 建筑数
(defconst building-type-count 28) 某类建筑数
(defconst building-type-count-total 29) 某类建筑总数
(defconst population 30) 人口
(defconst military-population 31) 军事人口
(defconst civilian-population 32) 经济人口
(defconst random-number 33) 随机数
(defconst resource-amount 34) 资源数量
(defconst player-distance 35) 玩家间距
(defconst allied-goal 36) 同盟目标
(defconst allied-sn 37) 同盟战略数字
(defconst resource-percent 38) 资源数量的100倍
(defconst enemy-buildings-in-town 39) 城中敌人建筑数
(defconst enemy-units-in-town 40) 城中敌人单位数
(defconst enemy-villagers-in-town 41) 城中敌人村民数
(defconst players-in-game 42) 玩家数
(defconst defender-count 43) 防御者数
(defconst building-type-in-town 44) 城中某类建筑数
(defconst unit-type-in-town 45) 城中某类单位数
(defconst villager-type-in-town 46) 城中某类村民数
(defconst gaia-type-count 47) 某类自然单位数
(defconst gaia-type-count-total 48) 某类自然单位总数
(defconst cc-gaia-type-count 49) 全图某类自然单位数
杀敌那个准确么?我记得杀死比率经常出错的 枫叶の飘零 发表于 2014-1-29 06:48 static/image/common/back.gif
杀敌那个准确么?我记得杀死比率经常出错的
这个取决于触发了,不要用最传统的角落建立物件法,改成AOKTS直接进贡隐藏资源杀敌数就会精确很多。 最后一个效果lingfeng老师看到该会有多高兴{:155:} 受教受教……,感谢T神 旧时代还不会的纯路过围观 这个强大的似乎无所不能了? qs 发表于 2014-1-29 11:31 static/image/common/back.gif
这个强大的似乎无所不能了?
目前AI的优势在于判断多样化,但缺点依然是无法直接作用于单位,必须通过资源法或信号,和触发建立联系,再通过触发作用于单位。这一过程中,还是会受到触发本身功能的限制。。。。。如果未来UP版本能突破这个瓶颈。。。那战役将会是另一个新天地。。。 春田一九零三 发表于 2014-1-29 11:36 static/image/common/back.gif
目前AI的优势在于判断多样化,但缺点依然是无法直接作用于单位,必须通过资源法或信号,和触发建立联系, ...
在理!~ 呀收藏~
@lingfeng 太强悍了!忍不住就水了! {:155:} Ru43 发表于 2014-1-29 07:44 static/image/common/back.gif
最后一个效果lingfeng老师看到该会有多高兴
新的研究领域~
居然见到了可检测的当前生命值 表示敬意 条顿武士怎么变成萌妹子了{:157:}另外,宣传Z版蛮重要的 太特么强大了…强大到恶心的程度…重大利好…
尤其是对擅长rpg的作者而言…可应用之处很多 突然发现自己还是存在于无AI的世界当中……编写AI什么的……好难{:7_262:} {:151:}这是让战役党提升境界的节奏… 我了个丢丢 发表于 2014-2-2 17:05 static/image/common/back.gif
突然发现自己还是存在于无AI的世界当中……编写AI什么的……好难
我可以+2嗎?
= =
页:
[1]
2