三、下面就是上面说的与cnd同名.c文件--具体设定文件。一般每一种condition种类都要对应一个文件。里面只有一个update_condition()函数,通过/feature/condition.c这个程序来调用它的这个函数,可以添加一些效果或信息,比如,中毒的就会减精减气。但最主要是就每调用一次,将键名为这个cnd的内容值减少1点或多点。然后到了设定的点数,一般是到了0之后,会出现一些特殊的现象。象做牢的到了0就会被放出来,等等。
下面看一个例子:少林的做牢的condition的详解:
- //kungfu/condition/bonze_jial.c
- #include
- #include
- /*参照前面调用这个函数的/feature/condition.c文件,就可以发现,调用它的时候会传递一个玩家与他的名为bonze_jia1的这个condition的值*/
- int update_condition(object me, int duration)
- {
- if (duration < 1)
- //如果这个点数参数小于1,就表示做牢时间够了
- {
- me->move("/d/shaolin/guangchang1");
- //从牢房里直接移到少林大门口
- message("vision","只听乒地一声,你吓了一跳,定睛一看,\n"
- "原来是一个昏昏沉沉的家伙从大门里被扔了出来!\n",environment(me), me);
- tell_object(me, HIY "只觉一阵腾云驾雾般,你昏昏沉沉地被扔出了少林寺!\n" NOR);
- //出一些信息
- me->set("startroom", START_ROOM);
- return 0;
- }
- //如果不小于1,则设定减去一点,返回1,下次还会再执行
- me->apply_condition("bonze_jail", duration - 1);
- return 1;
- }
复制代码
到这里,condition的三大部分介绍完了,我们就以这少林寺的做牢为例,看一看condition执行调用的流程。
程序大约是在松林里被僧兵抓住后,进了戒律院,这个房间文件会通过apply_condition()这个函数在玩家身上被加上了名为bonze_jail的condition。于是玩家身上会多了这样的一个映射:
condition([({"bonze_jial":35},.....)])
那么通过前面的文件,就会看到,由于我们玩家是继承了char.c文件,每一个心跳中,就会检查tick,如果tick为1时,那么就会开始调用update_conditon()函数了。
这个函数首先取出玩家身上conditions映射中的关键词组成一个数组cnd:
cnd = ({"bonze_jial",......});
首先发现了bonze_jia1,于是开始到/kungfu/condition/目录下寻找名为bonze_jial.c的文件,也就是上面帖出的第三部分的文件,如果没有找到这个文件就会被记录进/log/condition.err文件里,有的话,开始传递时这个玩家与这个conditon的值,开始执行bonze_jial.c里的update_condition()函数 。第一次执行时duration也就是35,只要它大于或等1,就会被减出一点,返回值是1。会在下次tick为1的心跳是再次呼叫。这样经过若干次调用后,duration已经等于0了,那么也就是durtion < 1,于是me被move到少林的广场,出现信息:只听乒地一声,你......me又被覆盖了startroom然后返回值为0。玩家身上就会被删除这个condition。由于返回是0,那么/feature/condition.c文件里的update_condition()函数就会删除玩家身上的这个bonze_jia1的内容。
除了做牢之外,通过这样的随机调用,可以实现象毒这样不定时发作的特殊效果,每调用一次就让玩家减一些精呀气之类的,却出现一些恐怖的中毒信息症状之类的。其实,你还以设计一些特殊的毒,不但在发作的过程中伤害人体。而且要求必须在这段时间找到解毒方法或解药,否则,一旦到了最后一两点还没有彻底解毒,这个人就OVER死翘翘。呵呵,看起来有点恐怖呀,实际上我觉得这样才是最符合实际情况的呢!
采用condition处理的好处就在于,这个属性是加在玩家身上的,通过在游戏中的心跳进行调用。如果玩家离了游戏就不会调用得到。一旦玩家进入游戏中又会开始继续执行。这比call_out()一旦主呼叫者或呼叫中的参数失也就无法继续执行的缺点要灵活得多。此外,它由心跳调用,不管玩家在做什么事情,它都可以即时地主动反馈情况。
而如果你无需即时反映变化,比如说去领工资,只需要规定玩家在一定时间的间隔之内不能领两次工资的话。可以在第一次领的时候,在玩家身上记下领的时间,第二次再去领时,将当前时间与记录时间进行上减,看间隔够不够就行。象这样子就很简单,也几乎没有任何系统负责,比采用condition林节约得多。而如果你需要有时间一到就立即通知玩家去领下一次工资的话。那就必须要采用conditon。
它的缺点也显而易见,放在每一次的心跳里呼叫。如果一个MUD系统里的生物与玩家身上的condition过多过长的话,系统的负担也是不小的。
最后谈一谈有关的BUG。许多新巫师没有正确或完全理解condition的用法,就开始大范围地使用。在一些不应该用的地方也使用condition。举例,在某一个可以使玩家得到金钱等东西地方,设定任何玩家都必须间隔在线一定的时间才能去拿一次。如果这个通过condition来实现。就有可能利用死亡后清除所有condition的特点,让一个玩家反复去死亡再立即重新去拿钱拿东西。象这种情况,你或者要修改死亡后会清除所有condition,或者就不能采用它来做那些拿钱等东西的效果。
其二,象上面所讲的少林监狱的condition文件中,就隐藏着一个BUG。因为在XKX的文件里,少林的监狱并非是一定要等时间到了才会被放出来,可以通过贿赂狱卒,走五行洞先出来。而这样的话,一旦这个conditon到了最后的时候,不论这个玩家在哪里,都会被一下子Move到少林广场,然后出现你被扔出监狱等的字样。仔细想一想:如果MUD有不让你随便带东西或正常出来的地方,那么你就可以通过这个BUG跑到这种地方,把那些不能带出的东西放在身上,专心等时间一到,就会象乘飞机一样,一下子从那个地方飞到少林的广场。(例如谁与争锋里演武场)
解决方法很简单,只要在if(duration < 1)下面再加一个条件:
if(environment(me)->query("short")=="监狱")
才会move玩家出现信息。否则直接reuturn 0;就解决了。
最后,举一个毒的例子进行详解作为结束吧:
- // /kungfu/condition/ice_poison.c
- #include
- #include
- inherit F_CLEAN_UP;
- int update_condition(object me, int duration)
- {
- if( duration < 1 ) return 0;
- if( !living(me) )
- //如果对象不是清醒着,出的信息
- {
- message("vision", me->name() + "浑身颤抖,痛苦地哼了一声。\n", environment(me), me);
- }
- else//否则就清醒着
- {
- tell_object(me, HIB "忽然一阵奇寒从丹田升起,沁入四肢百骸,你中的寒冰绵掌发作了!\n" NOR );
- message("vision", me->name() + "的身子突然晃了两晃,牙关格格地响了起来。\n",environment(me), me);
- }
- me->receive_wound("qi",15 + random(10));
- me->receive_wound("jing", 10);
- //伤一定的精与气
- me->apply_condition("ice_poison", duration - 1);
- //这个值减一点
- if ( (int)me->query_temp("powerup") )
- {
- me->add_temp("apply/attack", -(int)(me->query_skill("force")/3));
- me->add_temp("apply/dodge", -(int)(me->query_skill("force")/3));
- //降低他的攻击力与躲避力
- me->delete_temp("powerup");
- //结束他的powerup
- }
- if( duration < 1 ) return 0;
- //如果到了0,就返回,什么也不做,表示毒发结束,好了
- return CND_CONTINUE;
- }
复制代码 |