魔兽争霸地图编辑器AI制作.docx
《魔兽争霸地图编辑器AI制作.docx》由会员分享,可在线阅读,更多相关《魔兽争霸地图编辑器AI制作.docx(30页珍藏版)》请在冰豆网上搜索。
![魔兽争霸地图编辑器AI制作.docx](https://file1.bdocx.com/fileroot1/2023-2/26/a143c2f4-d9f9-42aa-a6f2-f72506064ea5/a143c2f4-d9f9-42aa-a6f2-f72506064ea51.gif)
魔兽争霸地图编辑器AI制作
AI脚本初级教程
?
?
?
?
?
?
?
?
?
?
【什么是jassAI?
】:
jassAI是用纯jass编写的AI程序,可以用新建文本文档写或jass工具编写.真三AI以及DOTAAI也是由AI脚本编写.
【AI脚本使用方法】:
①运行地图编辑器
②打开你最爱的对战地图,将它以另外一个名字保存(最好放在另外一个文件夹里面)
③按F12(或者点Modules(模块)菜单,然后选择Importmanager(输入管理器))
④在Importmanager(输入管理器)中选择File->Importfile(文件->输入文件)
⑤选择刚刚建立好的**.ai.文件
⑥鼠标右击已经导入的文件,选择Modifyfileproperties(修改文件属性)
⑦将文件的后缀名改为.ai
?
?
◥?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
【代码放置】:
在文本文档中AI程序代码应如下放置
+ShingoJassHighlighter0.41
globals
//这个放全局变量
endglobals
functionblablatakesblablareturnsblabla
//自定义函数
endfunction
functionmaintakesnothingreturnsnothing
//主程序在这
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级的为例子
枷锁LV4MP185闪电LV4MP160蛇棒LV2350
一个连招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也没有什么用。
为了知道每个英雄都拥有什么技能,我们创建了一个游戏缓存(gamecache)来保存它。
在演示地图中我的触发器在地图的初始化部分创建了一个游戏缓存并将它保存在全局变量udg_GameCache中。
需要注意的是缓存必须在我们使用它之前初始化,所以我在地图的初始化时间中创建了它。
在我的地图中我写了一个函数SetupSkills.在这个AI触发器的InitTrig函数中我使用了库函数ExecuteFunc来开启另外一个线程执行这个函数。
这是为了防止地图的初始化时间太长。
jass:
Copycode
我的SetupSkills函数如下:
functionSetupSkillstakesnothingreturnsnothing
localstringh//Createalocalstringvariable
//Paladin//Herewe’llinitialisethePaladin’sskills,repeatthisforallotherheroes
seth=UnitId2String('Hpal')//StorethereturnedvalueofUnitId2String(‘Hpal’)inthelocal
callStoreInteger(udg_GameCache,h,"BaseSkill1",'AHhb')//OneofhisbaseskillsisHolyLight,storeitas“BaseSkill1”
callStoreInteger(udg_GameCache,h,"BaseSkill2",'AHds')//StoreDivineShieldas“BaseSkill2”
callStoreInteger(udg_GameCache,h,"BaseSkill3",'AHad')//StoreDevotionAuraas“BaseSkill3”
callStoreInteger(udg_GameCache,h,"UltimateSkill",'AHre')//StoreResurrectionashis“UltimateSkill”
…//RepeatforeachHero.
endfunction
接着是我的AI触发器的InitTrig部分:
functionInitTrig_AItakesnothingreturnsnothing
localintegeri=0
setgg_trg_AI=CreateTrigger()
loop
exitwheni>11
callTriggerRegisterPlayerEventLeave(gg_trg_AI,Player(i))
seti=i+1
endloop
callTriggerAddAction(gg_trg_AI,functionPlayerLeaves)
callExecuteFunc("SetupSkills")
endfunction
为英雄开启AI系统
为了控制AI我们使用了一个定时器(timer).我写了一个函数StartAI来获取一个单位的类型:
英雄(请在演示地图中查看这个函数)。
这个函数只是创建一个定时器,并且"绑定"在这个英雄身上,并且开启这个定时器。
这是演示地图中的空的AILoop函数和StartAI函数(这里给的只是一个框架,等下我们将展示一些动作函数,但是你起码必须先把function和endfunction写上去以保证WE不报错):
jass:
Copycode
functionAILooptakesnothingreturnsnothing
endfunction
functionStartAItakesunitheroreturnsnothing
localtimerm=CreateTimer()
callAttachObject(m,"hero",hero)
callTimerStart(m,0,false,functionAILoop)
setm=null
endfunction
注意,我的这个StartAI函数通过将periodic参数设置为false来达到使定时器只执行一次的目的(以后我们还会来讨论它的).
现在,你就可以在你的英雄选择系统中当由电脑控制的玩家选择英雄时调用这个函数,并且在玩家离开游戏的时候执行这个函数。
检测玩家是否拥有一个英雄,如果它拥有,调用这个函数来开启那个英雄的AI系统。
例如:
jass:
Copycode
functionPlayerLeavestakesnothingreturnsnothing
localplayerp=GetTriggerPlayer()
callDisplayTextToForce(bj_FORCE_ALL_PLAYERS,GetPlayerName(p)+"hasleftthegame.")
ifudg_Hero[GetPlayerId(p)]!
=nullthen
callStartAI(udg_Hero[GetPlayerId(p)])
endif
setp=null
endfunction
注意:
这个函数将使AI系统控制离开的玩家的英雄,但是这也不是必要的,你也可以做别的事情。
使这个AI做些什么
当定时器终止的时候我们希望它做了这些事情:
●如果英雄死亡,等待他复活。
●如果英雄将要死亡,命令他移动到地图中心的生命泉水。
●如果英雄状态良好,检测是否有敌人在附近。
如果有,则命令英雄攻击它。
否则就检测是否有物品在附近,如果有的话,发送一个巧妙的命令让英雄拣起它。
然后命令英雄巡逻到地图的一个随机坐标。
●如果英雄是活着的而且有未使用的技能点,学习一个技能。
我们由变量的声明开始。
注意在我函数里面的实变量"e",它定义了在定时器再次启动前所经过的时间,这样我们就可以在英雄死亡的时候等待短一点的时间,而在他攻击的时候等待长一点的时间。
这个变量初始化值为5。
jass:
Copycode
局部变量的声明:
functionAILooptakesnothingreturnsnothing
localstringa=GetAttachmentTable(GetExpiredTimer())
localunith=GetTableUnit(a,"hero")
localrecti
locallocationr
localrealx=GetUnitX(h)
localrealy=GetUnitY(h)
localgroupg
localboolexprb
localboolexprbe
localunitf
localstringo=OrderId2String(GetUnitCurrentOrder(h))
localreall=GetUnitState(h,UNIT_STATE_LIFE)
localreale=5
…
我们由检测英雄是否死亡开始,如果他死亡了,设置"e"为1.5(因为在复活以后等待5秒的时间太长了,我们并不想这样).
当英雄的生命值"l"为0时,设置"e"为1.5来使定时器更加频繁的检测英雄是否复活.
…
ifl<=0then
sete=1.5
endif
…
接着我检测英雄的生命是否低于最大生命值的20%.如果是的,命令英雄移动到生命泉并且设置"e"为3.
当英雄的生命值少于最大生命值的20%时,命令英雄移动到生命泉的位置。
…
iflcallIssuePointOrder(h,"move",GetUnitX(gg_unit_nfoh_0001),GetUnitY(gg_unit_nfoh_0001))
sete=3
…
如果英雄的状态良好,检测他是否处在一个普通命令中(防止它打断了通魔技能).如果是一个标准命令,我们再检测在500的半径内是否有敌人存在.如果存在敌人,简单的发出一个攻击命令(不要改变"e"的值,5秒对于这个情况刚刚好).
jass:
Copycode
functionAIFilterEnemyConditionstakesnothingreturnsboolean
returnGetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0andIsPlayerEnemy(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
setg=CreateGroup()
setb=Condition(functionAIFilterEnemyConditions)
callGroupEnumUnitsInRange(g,x,y,500,b)
setf=FirstOfGroup(g)
iff==nullthen
…
else
callIssueTargetOrder(h,"attack",f)
endif
callDestroyGroup(g)
callDestroyBoolExpr(b)
endif
…
如果没有敌人存在,再检测物品.如果发现物品,再检测是否为一个提升状态的物品.如果不是,检测英雄物品栏是否有空栏,有的话就命令英雄将它拣起来.
jass:
Copycode
functionAISetItemtakesnothingreturnsnothing
setbj_lastRemovedItem=GetEnumItem()
endfunction
functionAIItemFiltertakesnothingreturnsboolean
returnIsItemVisible(GetFilterItem())andGetWidgetLife(GetFilterItem())>0
endfunction
functionAIHasEmptyInventorySlottakesunitureturnsboolean
returnUnitItemInSlot(u,0)==nullorUnitItemInSlot(u,1)==nullorUnitItemInSlot(u,2)==nullorUnitItemInSlot(u,3)==nullorUnitItemInSlot(u,4)==nullorUnitItemInSlot(u,5)==null
endfunction
…
iff==nullthen
seti=Rect(x-800,y-800,x+800,y+800)
setbe=Condition(functionAIItemFilter)
setbj_lastRemovedItem=null
callEnumItemsInRect(i,be,functionAISetItem)
ifbj_lastRemovedItem!
=nulland(GetItemType(bj_lastRemovedItem)==ITEM_TYPE_POWERUPorAIHasEmptyInventorySlot(h))then
callIssueTargetOrder(h,"smart",bj_lastRemovedItem)
else
…
endif
callRemoveRect(i)
callDestroyBoolExpr(be)
…
如果物品栏没有空位,或者没有发现物品,则命令英雄到一个随机地点寻找新的目标.
…
else
setr=GetRandomLocInRect(bj_mapInitialPlayableArea)
callIssuePointOrderLoc(h,"patrol",r)
callRemoveLocation(r)
…
收藏分享
linzefei发短消息
加为好友
linzefei(橙zi174)当前离线
我从来没出现过
主题108精华2积分50383阅读权限120在线时间3947小时最后登录2012-9-11
荣誉版主
UID101045帖子6181EXP5影币1445威望141荣誉1贡献4金币1156注册时间2007-3-14
沙发
发表于2008-11-1605:
45|只看该作者
[-制图理论-]对于传统PVE,RPG地图设计的一些看法
现在我们需要检测的是英雄是否有未使用的技能点(将这个函数与进攻/拣取物品/前进到随机地点等模块分开).
如果英雄有未使用的技能点,调用函数来使英雄学习技能.在