首先就是nut的定位吧,nut的话可以称为脚本语言,也可以称为嵌入式语言,至于是什么叫法关系不大。
语法的话,和大多数脚本语言的语法一致,零难度上手
它的调用逻辑呢?其实就是客户端在特定的时机,会调用nut特定的函数,这类函数的函数名固定,暂且称这类函数为回调函数。
那么都有哪些回调函数呢?这里我以鬼剑士为例,后面会列举一些常用的回调函数。
function drawMainCustomUI_Swordman(obj),以他为例,这是一个鬼剑士的回调函数,观察它的函数名,可以分成两部分,drawMainCustomUI和Swordman,drawMainCustomUI是回调函数的公共函数名,Swordman是职业名称,既然是公共函数名,那么后面的职业名称替换成其他职业,当然也是适用的。
下面说一些常用回调函数的含义及触发时机
drawMainCustomUI_Swordman(obj):
鬼剑士在城镇或副本内都在持续循环执行,参数obj代表鬼剑士角色obj,当然也是变动的,在城镇是一类obj,在副本内是一类obj,在这类函数内可以使用一些绘制ani帧的方法
drawCustomUI_Swordman(obj):
鬼剑士在副本内持续循环执行,参数obj代表副本内的鬼剑士角色obj,同样可以使用一些绘制ani帧的方法
function onStartDungeon_Swordman(obj):鬼剑士在副本开始时,会调用一次
function onStartMap_Swordman(obj):鬼剑士在副本开始时,会调用一次
function procAppend_Swordman(obj):鬼剑士在加载ap时,会持续循环调用
function onAttack_Swordman(obj, damager, bounding_box, is_stuck):鬼剑士在体术攻击时,会触发一次调用,
obj代表鬼剑士角色obj,damager代表被攻击者obj
function onAttack_PassiveObject(passiveobj, damager, bounding_box, is_stuck):鬼剑士在特效攻击时,
会触发一次调用,passiveobj特效对象,简称为po
诸如此类的回调函数还有好几个,那么是怎么知道这些固定名称的回调函数呢,可以参考男法师的common nut,大多数官方都有使用。
补充,onStartMap_Swordman是在副本每个房间开始时,执行一次
加载的话,客户端会在一些启动的时候,将nut回调函数加载进内存,既然每一类回调函数的名称是固定的,那么遇到重复的回调函数,加载时就是后加载的优于前加载的,换句话说,就是后面的会覆盖前面的同名回调函数,也就有了合并函数这一说,合并只需要将那些同名的回调函数合并为一个函数即可。
怎么理解ap这个东西呢,可以把ap理解为给对象身上装了一个监控,可以看到他的一举一动,方便来玩弄对象。
咳咳,先看看ap方法的组成部分 sq_AppendAppendage(obj1, obj2,id,false,ap文件名, true),obj1是监控装给谁,obj2是谁装的监控,id就是监控的品牌,ap文件名呢就是监控从哪里买来的。
那么什么对象都可以装监控呢?
当然是活的对象,死了的装给你干嘛,一般就是角色或者怪物啦。
那么什么时候可以装监控呢?
除了在城镇,当然是你想啥时候装就啥时候装,开始副本、放某个技能、进入某个房间、打某个怪物等等。
那么给对象装监控有什么用呢?
当然是监视对象的一举一动了,方面后续操作。
然后我们聊一聊给对象装上监控都能干什么?
先看一看一个完整的ap文件都有哪些监控,当然不是所有监控都必须使用,主要看你想监控什么。
appendage.sq_AddFunctionName("onStart", "")
appendage.sq_AddFunctionName("onStartMap", "")
appendage.sq_AddFunctionName("proc", "")
appendage.sq_AddFunctionName("onSetHp", "")
appendage.sq_AddFunctionName("prepareDraw", "")
appendage.sq_AddFunctionName("drawAppend", "")
appendage.sq_AddFunctionName("onChangeState", "");
appendage.sq_AddFunctionName("onApplyHpDamage", "")
appendage.sq_AddFunctionName("onAttackParent", "")
appendage.sq_AddFunctionName("onDamageParent", "")
appendage.sq_AddFunctionName("getImmuneTypeDamageRate", "")
appendage.sq_AddFunctionName("onSourceKeyFrameFlag", "")
appendage.sq_AddFunctionName("onVaildTimeEnd", "")
appendage.sq_AddFunctionName("onDestroyObject", "");
appendage.sq_AddFunctionName("isEnd", "")
appendage.sq_AddFunctionName("onEnd", "")
ap的方法和回调函数一个套路,方法的前缀是固定的,客户端在解析到这些固定的方法前缀,就会在固定的时机来执行这些监控,并且呢,ap所有的方法都有一个固定的执行次序,待我一一道来!
onStart:就是ap刚开始执行一次,
onStartMap:就是进入每个副本房间执行一次
proc:代表ap所有函数都空闲,循环执行,它实际上也是阻塞的方法。
onSetHp:对象的血量有变化,执行一次
prepareDraw:欲绘制时,循环执行
drawAppend:绘制ap时,循环执行,这个方法实际上是执行对象身上所有的监控。
onChangeState:对象改变状态时,执行一次
onApplyHpDamage:对象受到伤害时,执行一次,可以获取到血量伤害值。
onAttackParent:对象攻击时,执行一次
onDamageParent:对象受到伤害时,执行一次
getImmuneTypeDamageRate:获取对象的属性攻击比率时,执行一次
onVaildTimeEnd:监控失效时,执行一次
onDestroyObject:对象受到攻击时,执行一次
isEnd:判断ap是否结束的回调方法,执行一次
onEnd:返回城镇时,执行一次
实际上,这些方法的调用都是串行的,都有一个固定的调用顺序,
甚至是对象身上的多个ap或者一个ap多个对象,也是串行的,主函数会一一依次遍历执行。
至于角色技能的nut函数,被动对象的nut函数,和ap大同小异,都是一个套路
ap类的onEnd实际在附加的时候就会执行一次
角色类procAppwnd仅在副本内循环执行,不论是附ap还是其他,对应ap类的proc。若要城镇内也执行,则可使用procpassive
: ap的onend,对象死亡或者返回城镇会触发,之后主函数会销毁该ap。
举例外加血条的时候出问题,那就简单写一下合并函数相关的小技巧吧。
首先为啥要合并函数呢?
在程序里面一个唯一的函数名,是代表一个内存地址,函数名重复的话,就会出现后加载的同名函数会覆盖先加载的函数功能,所以某些功能就莫名其妙的消失了。
那么需要合并哪些函数呢?
其实只要是正常定义的函数,不管是回调函数,还是普通函数,同名的话都会覆盖,只是回调函数是客户端在调用,有冲突的话,影响的功能比较大。
废话有点多了,开始正题,血条的回调函数我写在blood_common.nut里面,里面写了鬼剑士的回调,其他职业的类似。如果有冲突的话,要合并的就是这两个函数。
onStartMap_Swordman很好理解,就是鬼剑士在副本的每个房间开始时调用一次。
drawCustomUI_Swordman这个是鬼剑士绘制近景层的回调函数,DNF就是从内向外一层一层绘制出来的,像二觉插画,评分,血条等,一般都使用这个回调函数。
合并函数时,需要先检查你的nut脚本有没有使用过上面的两个函数,按官方的规范,回调函数一般都写在职业的common nut里面,比如鬼剑士的就在character/swordman/swordman_common.nut这个文件里调用,直接在里面搜索这两个函数名,如果能搜到,说明就是有冲突的,需要进行下一步的合并。
另外有些人的nut脚本东西比较多,也比较乱的话,可以把nut导出来,直接用notepad全局搜回调函数,当然其他带搜索的工具也可以的。具体要怎么合并函数的话,简单举个例子吧
function aaa_Swordman(obj)
{
111(obj);
}
function aaa_Swordman(obj)
{
222(obj);
}
上面的两个就是有冲突的回调函数,合并之后如下。
function aaa_Swordman(obj)
{
111(obj);
222(obj);
}
合并完之后,就不需要上面的两个有冲突的回调函数了,直接删掉使用合并后的函数即可
暂无评论内容