北大侠客行MUD论坛

 找回密码
 注册
搜索
热搜: 新手 wiki 升级
查看: 8064|回复: 0

CONDITION系统分析(1)(zz)

[复制链接]
发表于 2004-2-9 20:55:36 | 显示全部楼层 |阅读模式
CONDITION系统分析(1)

  condition是利用系统的心跳来解决关于在一个不算太长的时间里,定时触发种现象的解决方法。在MUD中,为了解决定时触发某种现象,一般有两种方法,一种是通过call_out()延时呼叫,另一种就是通过心跳。在spock翻译的LPC及教材中曾对这两种方法进行了比较,好象是说:如果时间较长的话采用心跳比较好,时间短的话采用call_out()。紧接着又说了句,其个人看不出这两者有什么必要的区别,反正稀里糊涂的。不过,在实际运用中,两者都有不同的效果,大家看明白了本文之后,可以有自己的理解,并进行正确的选择。
  call_out(other_fun,t)这个外部函数就是起一种延时呼叫的作用,后面必须要加第一个参数,指定延时呼叫的函数名,第二个参数表示延时几秒,再之后加上的参数可以作为呼叫的那个函数的参数。象这一个也就是设定在t秒钟后,呼叫other_fun这个事先指定的函数,你可以在这个函数里设定好应该进行的事情。比如,你在一个玩家进入监狱后,要做牢五分钟,如果一定要用call_out()进行的话,你可以设定成:
call_out("out_jianyu",300,ob);
  意思就是在300秒后呼叫out_jianyu()这个函数,ob作为这个玩家的变量传递过去,然后在这个函数里进行将玩家从牢中放出来,告诉他做牢结束等等处理。但是,有的巫师看到这里,就会问了,如果五分钟没到,这个玩家退出游戏了怎么办?对,如果这个玩家退出游戏,这个call_out()一到时间就会找不到这个操作对象,如果程序写得不好就容易出错,即使是不会出错,那个玩家再次进入游戏后也就无法继续刚才的延时过程,也就不能够出牢。于是,对于要跨起离线前后的象做牢这类的事,大多都是采用condition。
  condition的处理方法,就是在开始的时候在玩家身上设定一定的点数的记号,这些记号会通过save()保存进玩家的档案中。然后通过系统的心跳,每一次心跳就执行一次这个固定的condition的函数,函数每被执行一次就减一点记号,直至这个记号为0后,就可以触发某种效果。比如做牢,就在进牢时设定一定点数,每一次心跳减一点,减为0时,将玩家放出。由于这个记号在玩家身上,因此,在玩家离线时不会发生到有关函数对这个玩家的操作。
  在ES系列MUD中。一个完整的condition系统包括三个部分:
一、首先就是调用或者说是触发它的程序,也就是/inherit/char/char.c这个
文件,这是所有玩家与NPC都共同继承的文件,在里面的heart_beat()函数,就是每一次心跳时调用执行的函数。里面有这么几句:

  1.   if( tick-- ) return;
  2.   else tick = 5 + random(10);
  3.   cnd_flag = update_condition();
复制代码

解释:tick是这个文件里的一个全局变量,假设它只要>1,那么tick--就不会等于0,那么tick值就会减1,并且立即return;中止这个函数向下执行。假想如此这样经过几次减1之后,终有一次tick--就会为0,那么这时,程序就不会中止而是执行下一句的else。这时,tick被重新赋值为5+random(10)。并执行update_condition()函数,update_condition()是一个什么函数呢?在char.c里怎么也找不到。
  那么我们再回头看看char.c这个文件的开头,就会看到,这个文件已经继承了/feature/condition.c文件,update_condition()这个函数正是在这个文件里面。所以下面我们就开看这个文件。
  附:由于大多数MUD里的心跳是每两秒调一次,5+random(10)是5至14次,因此可以看出每一个condition被调用的时间是平均19秒。知道了这此,你才能更加有数地设定一些毒的发作时间,一些做牢的时间长短了。

二、下面就是主程序,feature目录下的condition.c文件。
程序详解:

  1. #include "condition.h"//继承一些宏定义
  2. mapping conditions;//定义一个映射集

  3. /*更新函数 update_condition()
  4.   这个函数首先要检查玩家身上的每一个condition是否有效,如果出现了无效的condition,它会记录进/log/condition.err这个文件里,经常性地检查一下这个文件,可以发现并排除相当多的错误,因为一旦有一个错误,会在每一次的心跳中经常性地发生。然后它会按照condition的名字,也就是str这个变量去/kungfu/condition(某些MUDLIB下的路径是/daemon/condition)目录下去 寻找同名的.c文件进行执行。*/
  5. nomask int update_condition()
  6. {
  7.   mixed *cnd, err;
  8.   int i, flag, update_flag;
  9.   object cnd_d;
  10.   if( !mapp(conditions) || !(i=sizeof(conditions)) ) return 0;
  11. //判断玩家有无condition的映射,没有就中止,毕竟不会每人都会有
  12.   cnd = keys(conditions);
  13. //从这个映射中把关键词取出组成一个数组,实际上就是不同condition的名字
  14.   update_flag = 0;//初始化这个变量
  15.   while(i--)
  16. //如果有1个以上的condition,就会一个个地循环执行
  17.   {
  18.     cnd_d = find_object(CONDITION_D(cnd));
  19. //到放condition的目录下寻找这个文件名,这个目录路径有宏定义的文件指定,一般在XKX风格里大多是kungfu/condition/下,xyj等放在/daemons/condition/下
  20.     if( !cnd_d )//如果没有的话,再尝试
  21.     {
  22.       err = catch(call_other(CONDITION_D(cnd), "???");//强制检验
  23.       cnd_d = find_object(CONDITION_D(cnd));//再次寻找
  24.       if( err || !cnd_d )//如果强制检验与再次寻找中仍找不到,表示不存在这个condition
  25.       {
  26.         log_file("condition.err",sprintf("Failed to load condition daemon %s, removed from %O\nError: %s\n",CONDITION_D(cnd), this_object(), err) );
  27. //记录下来
  28.         map_delete(conditions, cnd);
  29. //删除玩家身上的这个condition
  30.         continue;//继续循环下一个
  31.       }
  32.     }
  33.     flag = call_other(cnd_d, "update_condition", this_object(), conditions[cnd]);
  34. //这个就开始执行这个conditon的设定文件里的update_condition()函数了,flag就是返回值,这个要看下面的具体设定文件的详解
  35.     if( !( flag & CND_CONTINUE ) )
  36.       map_delete(conditions, cnd);
  37. //返回值为0就表示这个conditon完毕了,就删掉
  38.     update_flag |= flag;
  39.   }
  40.   if( !sizeof(conditions) ) conditions = 0;
  41. //检查一个也没有了,就清零
  42.   return update_flag;
  43. }

  44. /*改变大小函数 apply_codition(cnd,info),通过这个函数将玩家身上名叫的cnd的condition的值设为info,info可以为0,所以可以得用这个函数对玩家身上的condition进行增减。 */
  45. nomask void apply_condition(string cnd, mixed info)
  46. {
  47.   if( !mapp(conditions) )
  48.     conditions = ([ cnd : info ]);
  49. //如果没有的话,就添加上,以cnd为键名,info为内容值
  50.   else
  51.     conditions[cnd] = info;
  52. //有的话,直接改变内容值
  53. }

  54. /*取值函数 query_codition(cnd)通过这个函数,可以调出某个玩家身上名叫cnd的这种condition的值有多少。*/
  55. nomask mixed query_condition(string cnd)
  56. {
  57.   if( !mapp(conditions)||undefinedp(conditions[cnd]) )
  58.     return 0;
  59. //如果没有conditions或者没有这个cnd的condition,就返回为0
  60.   return conditions[cnd];//否则返回具体值
  61. }

  62. /*清除函数 clear_condition()这个主要是在/feature/damage.c里的die()函数里调用,意思是一旦死亡,死者就会被清除所有的comdition。*/
  63. nomask void clear_condition()
  64. {
  65.   conditions = 0;
  66. }
  67. //END
复制代码
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大侠客行MUD ( 京ICP备16065414号-1 )

GMT+8, 2024-4-26 07:21 PM , Processed in 0.009091 second(s), 14 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表