pal 发表于 2004-2-9 20:55:36

CONDITION系统分析(1)(zz)

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()函数,就是每一次心跳时调用执行的函数。里面有这么几句:

  if( tick-- ) return;
  else tick = 5 + random(10);
  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文件。
程序详解:

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

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

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

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

/*清除函数 clear_condition()这个主要是在/feature/damage.c里的die()函数里调用,意思是一旦死亡,死者就会被清除所有的comdition。*/
nomask void clear_condition()
{
  conditions = 0;
}
//END
页: [1]
查看完整版本: CONDITION系统分析(1)(zz)