2008年8月29日星期五

MUD-人物NPC的编写-欧阳峰

[转自http://blog.sina.com.cn/s/blog_548fe95c01000bwr.html]

一个较为复杂的人物例子
// /kungfu/class/baituo/ouyang-feng.c 白驼开山祖师欧阳锋
#include     //表明这个文件要用到颜色
#inherit NPC;       //继承NPC的属性
inherit F_MASTER;     //继承可收徒的NPC属性
int check_self();     //声明,文件中有战斗行为函数的定义
int learn_message(object ob,string skill);//声明:文件中有learn_message()函数的定义
string ask_zhang(); //声明:文件中有谜题函数的定义
void create()
{
  set_name("欧阳锋", ({ "ouyang feng", "ouyang", "feng" }));
//注意,不要用set("name","")直接set_name
  set("long", "他是白驼山庄主,号称"HIW"“西毒”"NOR"的欧阳锋。\n"
    +"虽然由于习练「九阴真经」走火入魔,变得精神错乱,但\n"
  +"是他那额头上的层层紫晕,令人不得不服他是一代高手!\n");
//这就是不用@LONG&LONG的例子,所以就必须在每句尾加上“\n”的换行标志
  set("nickname", HIW"西毒"NOR); //外号,用到了颜色,所以开头没有include 这里会出错
  set("gender", "男性"); //性别,太监是无性
  set("age", 53);     //年龄
  set("shen_type",-1); //神的正负,如果没有set默认是1,用这个乘以exp/10得到神值
  set("attitude", "peaceful"); //指这个人物的好战态度
  set("str", 30); //膂力,
  set("int", 29); //悟性
  set("con", 30); //根骨
  set("dex", 28); //身法,这些先天属性,可设可不设,但要符合原著精神
  set("qi", 2500); //当前气
  set("max_qi", 2500); //最大气,就是恢复满时
  set("jing", 900); //当前精
  set("max_jing", 900); //最大精
  set("neili", 2000); //当前内力
  set("max_neili", 2000); //最大内力
  set("jiali", 50); //相当于玩家的加力jiali *
  set("combat_exp", 1500000); //经验
  set_skill("force", 200); //设置武功,这是基本内功
  set_skill("unarmed", 170); //反正一项项设,略.......
    ......
  set_skill("nilian-shengong", 200);
    ......
  map_skill("force", "nilian-shengong"); //相当于玩家的jifa
    ......
  create_family("白驼山派",1, "开山祖师");//门派头衔
  set("inquiry" ,([
    "欧阳克":"欧阳锋嘿嘿一笑:“那是我的乖侄子,你见过他了吗?”\n",
    "蛇杖":(:ask_zhang:),
  ]));
/*这个是设置当玩家ask sb about sth时的信息,“:”前就是sth,后面
则是返回的信息。这有点与房间里的set("desc_item")相似。所以也有关
于 (:ask_zhang:)的函数调用,这个函数我们在文件头已经定义过了,后
面将会有具体的内容。*/

  set("chat_chance",2); //设置随机动作的机率,这是指2%
  set("chat_msg",({ //设置随机动动作
    "欧阳锋自言自语道:“我白驼山派神功一成,定能重霸江湖!!”\n",
    "欧阳锋道:“我儿欧阳克聪慧过人,必能够重振白驼山派雄风!”\n",
    "欧阳锋道:“江湖险恶,困难重重,我才是天下第一!”\n",
  }));
  set("chat_chance_combat", 100); //这是指战斗中的随机行为,注意区别。
  set("chat_msg_combat", ({
    (: command("wield zhang") :),
    (: command("wield zhang") :), //装备武器
    (: perform_action, "staff.shewu" :),
    (: perform_action, "staff.shewu" :),//使用绝招
    (: command("unwield zhang") :),
    (: check_self :), //这是我们自定义的一个函数,在后面写着
  }) );
  setup();
  carry_object("/d/baituo/obj/shezhang");//身上的东西,加上“->wield”就是装备好了,如果没有这个,就会在身上,但没装备起来
  carry_object("/clone/misc/cloth")->wear();//这件衣服就是穿上的,也可不穿
  add_money("silver",50); //设置他身上的钱,可以gold,coin
}
void init()
{
  ::init();
  add_action("do_skills","skills");
  add_action("do_skills","cha"); //两个动作调用同一个函数do_skills
}
int do_skills(string arg)//定义do_skills函数,并表明其类型
{
  object ob ;
  ob = this_player () ; //定义ob是指的执行这个动作的人
  if( !arg && arg!="ouyang feng"&& arg!="ouyang"&& arg!="feng" )
    return 0; //如果对象不是欧阳锋,则返回调用skills的cmds指令
  if(wizardp(ob)) //return 0; 是巫师的话返回调用skills的cmds指令
  if (ob->query("family/master_name")!="欧阳锋")
    return 0; //师父不是欧阳锋的话返回调用skills的cmds指令
  if(!ob->query_skill("nilian-shengong",1))//如果没学过逆练神功
  {
    write("欧阳锋目前所学过的技能:\n"+
" 基本内功 (force) - 深不可测 200/ 0\n"+
"□蛤蟆功 (hamagong) - 深不可测 200/ 0\n"+
......\n"); //略
    return 1; //参考前面的懂了这里retrun 0和return 1的意思吗?
  }
  else //相反则是学过
  {
    write("欧阳锋目前所学过的技能:\n"+
" 基本内功 (force) - 深不可测 200/ 0\n"+
"□逆练神功 (nilian-shengong) - 深不可测 200/ 0\n"+
.......
\n"); //这时才让他的徒弟能查看欧的逆练神功级别
    return 1;
  }
}

void attempt_apprentice(object ob)//这个函数的原型就是在前面定义的inherit F_MASTER里
{
  if((int)ob->query("combat_exp")<100000) color="#009999">//条件一,经验要大于100000
  {
    message_vision("欧阳锋冷冷地对$N道:“这点经验就想来拜师?!”\n",ob);
    return; //因为这是一个void函数,直接return,面不是return 1之类的
  }
  if((int)ob->query_skill("hamagong",1)<60) color="#009999">//条件二,蛤蟆功大于60级
  {
    message_vision("欧阳锋冷冷地对$N道:“武功不错,先跟我的弟子学些的入门武功吧!”\n",ob);
    return;
  }
  message_vision("欧阳锋拍拍$N的头,微微点了点头。\n",ob); //过滤完了就通过
  command("recruit " + ob->query("id"));
  return;
}
int check_self() //即我们自定义战斗中行为
{
  int max_qi,eff_qi,qi; //命名三个变量
  object me;
  me = this_object(); //不多说了吧
  max_qi = me->query("max_qi");
  eff_qi = me->query("eff_qi");
  qi = me->query("qi"); //对三个变量进行初始定义
  if((int)(qi*100/max_qi)<30 color="#009999">//就是说欧受伤到一定程度
  {
    if((int)me->query_temp("powerup")) //如果已经在提升战斗力状态
    {
      ....... //将干什么什么
      return 1;
    }
    ......; //否则就怎么怎么
    return 1;
  }
}

string ask_zhang()//定义解谜中的关于蛇杖的函数
{   //string与int都可以,区别在于string函数return的是字符串
  object me,weapon,obj,obn;
  mapping fam;
  me = this_player();
  if(!(fam = me->query("family"))|| fam["family_name"] != "白驼山派") //不是白驼弟子
    return "\n欧阳锋冲你阴阴地一笑:“你是不是想尝尝我西域灵蛇毒的厉害?”\n";
  if((int)me->query_skill("xunshe-shu",1)<50) color="#009999">//驯蛇术太低
    return "\n欧阳锋拍拍你的头说:“你的驯蛇术还不到家,现在用蛇杖太危险!”\n";
  if( !me->query("weapon")||(string)me->query("weapon/type")!= "杖") //没有自铸的杖
    return "\n欧阳锋说道:“要想炼蛇杖,必须要有一根自铸的杖,你先找欧冶子铸杖吧!\n";
  if( me->query("weapon/she")) //已经有了蛇杖
    return "\n欧阳锋怒道:“小子也敢戏弄老夫,明明已有蛇杖,还要问什么?滚!!!\n";
  if( me->query_temp("dixi-wan")) //已经要了药丸
    return "\n欧阳锋大怒:“贪得无厌的家伙,拿了还想拿,再这样,老夫一杖叫你上西天!\n";
//到此为止,一切不符合解谜的条件都过滤完了,则开始执行
  obn=new("/d/baituo/obj/dixi-wan"); //要取出的东西的路径文件名,相当于clone
  obn->set("sign",me->query("id")); //东西上设上给的人的记号
  obn->move(me); //这个东西放进问的人的身上
  me->set_temp("dixi-wan",1); //问的人做记号,以防他再去要,看前面
return "\n欧阳峰仰天哈哈一笑后,缓缓说道:“我灵蛇杖法奇妙无比,配合蛇杖上灵蛇\n"
"的攻击,可使对手防不胜防,我这有一颗通灵地犀丸,你拿去找蛇奴,他会知道的!”\n"
HIC"说完欧阳锋递过来一颗鸽蛋大小的药丸。\n"NOR;
}

int learn_message(object ob,string skill) //定义学武功的条件
{
  if((skill=="nilian-shengong")&&(!ob->query_skill("nilian-shengong",1)))
  {
    message_vision("欧阳锋阴阴地对$N说道:“你如何能从我这学会这种没有一点功基的武功?”\n",ob);
    return 0;
  }
  else return 1;
}

没有评论: