找回密码
 注册
搜索
查看: 3328|回复: 6

→ lpc npc设定解析 →

[复制链接]
门派:不明
发表于 2008-5-23 04:32:32 | 显示全部楼层 |阅读模式
lpc npc全攻略(以sj2002为例)

npc.c本身的文件能够表示的东西其实不多,都是固定的
不讲解大家基本也能猜出个123。现就工作原理写了一下

以古墓派yang guo 这个npc为例


/kungfu/class/gumu/yang.c
  1. :--------------------------------------------------------------------------------
  2. // yang.c 杨过               //注释
  3. // By River 98.8
  4. // Modified by darken
  5. /*
  6. 如果你对c没什么了解那我就没什么办法了
  7. 至于mudos的include的搜索路径配置在mudos同目录中的config.sj中的下面设定里可以更改
  8. # the directories which are searched by #include <...>
  9. # for multiple dirs, separate each path with a ':'
  10. include directories : /include

  11. 在config.sj中还有一个设定在这里很重要就是:
  12. # This is an include file which is automatically #include'd in all objects
  13. #global include file : <config.h>
  14. global include file : <globals.h>
  15. 这里配置的是mudos在启动后每一个文件的默认设定,即所有的文件可以不用定义就是用globals.h中已经定义的变量、宏、等。
  16. globals.h的位置自然是在上面定义完的/include中寻找了,也就是sj2002中的/include/globals.h

  17. 下面对yangguo.c的语句逐一解释
  18. */
  19. #include <ansi.h>      //导入颜色设置文件,文件是/include/ansi.h
  20. inherit NPC;   //inherit也是可以达到包含的目的,这里的NPC是一个宏在globals.h中定义的代表/inherit/char/npc.c 注解1
  21. inherit F_MASTER;  //F_MASTER也是globals.h中定义的代表/inherit/char/master;注解2
  22. string ask_sword();  //定义函数,或者叫成员方法,c语言中有明确的解释
  23. int pfm_haichao();  //同上
  24. void create()   //npc的创建,其中一些默认的设定在/inherit/char/npc.c中有详细的定义
  25. {
  26.         set_name("杨过",({"yang guo","yang","guo"}));  //npc中文名称,英文id
  27.         set("title",HIW"古墓侠侣"NOR);    //头衔
  28.         set("nickname",HIY"神雕大侠"NOR);   //外号
  29.         set("long", "他就是名满天下的杨过。虽断一臂但仍遮不去一脸的英雄豪气。\n");//look的时候显示详细的描述
  30.         set("age", 39);      //年龄
  31.         set("attitude", "friendly");    //见/inherit/char/npc.c中的int accept_fight(object who)函数
  32.         set("no_bark",1);     //不接受bark命令
  33.         set("shen", 10000);     //神
  34.         set("per", 30);      //纯朴
  35.         set("str", 40);      //臂力
  36.         set("int", 30);      //悟性
  37.         set("con", 40);      //根骨
  38.         set("dex", 25);      //身法

  39. //各项数值的设定
  40.         set("max_qi", 6500);
  41.         set("max_jing", 5000);
  42.         set("neili", 13500);
  43.         set("eff_jingli", 3500);
  44.         set("max_neili", 13500);
  45.         set("jiali", 100);
  46.         set("combat_exp", 2800000);
  47.         set("unique", 1);
  48. //武功设定
  49.         set_skill("sword",300);
  50.         set_skill("dodge",300);
  51.         set_skill("strike",300);
  52.         set_skill("force", 300);
  53.         set_skill("hand", 300);
  54.         set_skill("cuff", 300);
  55.         set_skill("parry", 300);
  56.         set_skill("stick", 300);
  57.         set_skill("staff", 300);
  58.         set_skill("finger",140);
  59.         set_skill("literate", 250);
  60.         set_skill("baituo-shezhang",180);
  61.         set_skill("xiantian-gong",20);
  62.         set_skill("hamagong",300);
  63.         set_skill("medicine",120);
  64.         set_skill("jingmai-xue",80);
  65.         set_skill("qimen-baguazhen",80);
  66.         set_skill("throwing",110);
  67.         set_skill("dagou-bang",220);
  68.         set_skill("bangjue",170);
  69.         set_skill("yuxiao-jian",190);
  70.         set_skill("tanzhi-shentong",160);
  71.         set_skill("yunu-shenfa", 300);
  72.         set_skill("meinu-quanfa",300);
  73.         set_skill("xuantie-jianfa", 300);
  74.         set_skill("anran-zhang", 300);     
  75.         set_skill("quanzhen-jianfa",300);
  76.         set_skill("tianluo-diwang", 300);
  77.         set_skill("yunu-xinjing",300);
  78.         set_skill("jiuyin-zhengong",160);
  79.         set_skill("dafumo-quan",60);
  80.         set_skill("daode-jing",60);
  81.         set_skill("jiuyin-shenfa",130);
  82.         set_skill("qimen-bagua",150);
  83.         set_skill("taoism",100);

  84.         map_skill("force", "yunu-xinjing");        
  85.         map_skill("sword","xuantie-jianfa");
  86.         map_skill("stick","dagou-bang");
  87.         map_skill("staff","baituo-shezhang");
  88.         map_skill("throwing","tanzhi-shentong");
  89.         map_skill("finger","tanzhi-shentong");
  90.         map_skill("dodge", "yunu-shenfa");
  91.         map_skill("parry", "anran-zhang");        
  92.         map_skill("hand", "tianluo-diwang");
  93.         map_skill("cuff", "meinu-quanfa");
  94.         map_skill("strike", "anran-zhang");        
  95.         prepare_skill("strike","anran-zhang");

  96. //随机说话或者调用函数,在/inherit/char/npc.c中有部分的定义
  97.         set("chat_chance_combat", 30);     //随机值,注解1中详细描述
  98.         set("chat_msg_combat", ({
  99.                 (: exert_function, "xinjing" :),
  100.                 (: pfm_haichao :),    //自定义函数
  101.                 (: perform_action, "strike.xiaohun":),
  102.                 (: perform_action, "strike.anran":),
  103.         }));       //随机调用函数的设定,见注解1


  104.         create_family("古墓派",3,"男主人");
  105.         set_temp("apply/damage", 70);
  106.         set_temp("apply/dodge", 60);
  107.         set_temp("apply/attack", 60);
  108.         set_temp("apply/armor", 70);
  109.         set("inquiry", ([     

  110. //在使用ask命令的时候使用到的一些设定通过(:***:)可以在ask这个问题的时候调用***函数

  111.            "古墓" : "那日华山与众英雄诀别后和龙儿隐居于此已有数年,不闻世事,能与\n"+
  112.                     "龙儿在此长伴一世,此身足矣!",
  113.            "小龙女" : "龙儿乃我爱妻,你问她做甚?",
  114.            "玄铁剑" : (: ask_sword :),
  115.            "玄铁剑法" : (: ask_sword :),
  116.         ]));

  117.         setup();
  118.         carry_object(BINGQI_D("sword/gangjian"));  //carry_object()在/inherit/char/npc.c中有部分的定义
  119.         carry_object("/d/gumu/obj/buxue1")->wear();  // ->wear() 是在武器文件中定义的npc中不涉及
  120.         carry_object("/d/gumu/obj/pao1")->wear();
  121. }

  122. void attempt_apprentice(object ob)        //拜师要求
  123. {
  124. 。。。。。。。。。。
  125. }

  126. string ask_sword()          //自己定义的一些函数
  127. {
  128. 。。。。。。。。。。。。
  129. }

  130. int pfm_haichao()
  131. {
  132. 。。。。。。。。。。。。
  133. }
复制代码
门派:不明
 楼主| 发表于 2008-5-23 04:32:59 | 显示全部楼层
注解1:下面是 /inherit/char/npc.c的内容



code:--------------------------------------------------------------------------------
// npc.c
// modified by snowman@SJ

#include <command.h> //导入/include/command.h 其中是一些受伤的描述

inherit CHARACTER; // 导入/inherit/char/char.c  CHARACTER是globals.h中定义的宏 内容是#define CHARACTER /inherit/char/char.c
inherit F_CLEAN_UP; // 导入/feature/clean_up.c  功能是定期更新this_object() 其中描述了当npc设定了set("no_clean_up",1)的时候不进行更新。

object carry_object(string file)  //复制物品函数yang.c中有 carry_object("/d/gumu/obj/buxue1")->wear();
{
object ob;

file = resolve_path(0, file);
ob = unew(file);
if (ob) ob->move(this_object());
return ob;
}

object add_money(string type, int amount) //设定npc身上有多少钱,可以在npc的create()中设定add_money("gold",100);
{
object ob;

if (!clonep()) return 0;
ob = carry_object("/clone/money/" + type);
if (!ob) return 0;
ob->set_amount(amount);
return ob;
}

int accept_fight(object who)   //默认的接受fight 状况这个时候在yang.c的设定set("attitude","friendly")有了作用
{      //下面详细定义了attitude的值定义方法
string att;    //friendly是不接受fight,aggressive和killer是接受fight
      //不设定的话npc在max_qi >80%接受fight否则不接受
att = query("attitude");

if (is_killing(who->query("id"))) {
  command("say 哼!" + RANK_D->query_rude(who)+"你尽管放马过来吧!");
  return 1;
}
if (is_fighting())
  switch(att) {
   case "heroism":
    command("say 哼!" + RANK_D->query_rude(who)+"你尽管进招吧!");
    return 1;
   default:
    command("say " + RANK_D->query_respect(who)+"想倚多为胜,这不是欺人太甚吗!");
    return 0;
  }

switch(att) {
  case "friendly":
   command("say " + RANK_D->query_self(this_object())
    + "怎么可能是" + RANK_D->query_respect(who)
    + "的对手?您就别开玩笑了!");
   break;
  case "aggressive":
  case "killer":
   command("say 哼!" + RANK_D->query_rude(who)+"你尽管放马过来吧!");
   return 1;
  default:
   if (query("jing") * 100 / query("max_jing") >= 90
   && query("qi") * 100 / query("max_qi") >= 90
   && query("jingli") * 100 / query("eff_jingli") >= 80
   && query("neili") * 100 / query("max_neili") >= 80 ) {
    command("say 既然" + RANK_D->query_respect(who)
     + "赐教," + RANK_D->query_self(this_object())
     + "只好奉陪,我们点到为止。");
    return 1;
   }
}
return 0;
}

// This function is called by the reset() of the room that creates this
// npc. When this function is called, it means the room demand the npc
// to return its startroom.
int return_home(object home)      //这个是书剑独有的在更新npc的时候可以返回npc的默认房间函数
{        //在更新npc的时候如果npc不再自己开始设定的startroom里面就自动移动到startroom
if (home && !query("startroom")) return 0;  //可以在npc中的create()中使用set("startroom","room文件路径")来设定开始房间
if (!home && stringp(query("startroom")))
  if(!objectp(home = load_object(query("startroom")) ))
   return 0;

// Are we at home already?
if( !environment()
|| environment()==home )
  return 1;

// Are we able to leave?
if( !living(this_object())
|| is_fighting()
|| is_busy() ) return 0;

// Leave for home now.
message("vision", name() + "急急忙忙地离开了。\n",
  environment(), this_object());
if (move(home)) {
  message("vision", name() + "急急忙忙地走了过来。\n",
   environment(), this_object());
  return 1;
}
return 0;
}

// This is the chat function dispatcher. If you use function type chat
// message, you can either define your own functions or use the default
// ones.

int chat()      //这个就是有人问过的关于npc auto发pfm的设定方法了
{      
string *msg;
int chance, rnd;

if( !environment() || !living(this_object()) ) return 0;

if (query("neili")>100 && query("max_neili") > 200
&& query("race") == "人类" && !is_busy()) {
  if (query("eff_jing")
  && query("jing")*100/query("eff_jing") <= 80)
   command("exert regenerate");

  if (query("eff_qi") && query("qi") >= 0
  && query("qi")*100/query("eff_qi") <= 80)
   command("exert recover");

  if (query("eff_jingli")
  && query("jingli")*100/query("eff_jingli") <= 80)
   command("exert refresh");

  if (!is_fighting() && query_temp("embed") && random(10) < 3)
   command("remove "+query_temp("embed"));
   
  if (query("eff_qi") && query("qi") >= 0
  && query("max_qi") && !is_fighting() && !query("mute")
  && query_skill_mapped("force")
  && query_skill("force") > 50
  && query("eff_qi") < query("max_qi")
  && query("eff_qi") >= query("max_qi")/3)
   command("exert heal");
}
门派:不明
 楼主| 发表于 2008-5-23 04:33:24 | 显示全部楼层
//到这里,上面是在疗伤和yun qi yun jingli yun jing的比例设定,npc自动yun qi就是在这里设定的
//如果你把这里/* */掉hehe............  npc就不堪一击了

if( !chance = query(is_fighting()? "chat_chance_combat": "chat_chance") )
  return 0;
//上面这行是判断如果战斗的时候就调用chat_chance_combat中设定的内容,否则调用char_chance内容
// yang.c中只设定了char_chance_combat的内容所以不战斗的时候就什么也不执行return 0;
if( arrayp(msg = query(is_fighting()? "chat_msg_combat": "chat_msg")) && !is_busy()) {
//上面这行判断战斗的时候调用chat_msg_combat中的内容,否则调用chat_msg的内容
  if( random(100) < chance ) {      
//chance就是chat_chance_combat的值,有人问这个设定和pfm有什么关系
//关系就在这里,yang.c的设定是30,那么就是random(100)<30的时候执行一次chat_msg_combat的内容
//也就是1/3的机会出pfm,如果设定是100那么出pfm的频率就会很高哦!!!!!
   rnd = random(sizeof(msg));
   if( stringp(msg[rnd]) )
    say(msg[rnd]);
   else if( functionp(msg[rnd]) )
    return evaluate(msg[rnd]);
//这里判断的是chat_msg_combat设定的是字符串还是函数,如果是函数执行函数
//是字符串就用say 说出来。
//yang.c中是这样设定的
//  (: exert_function, "xinjing" , 调用exert_function函数,参数xinjing
//  (: pfm_haichao ,   调用yang.c 中定义的pfm_haichao函数
//  (: perform_action, "strike.xiaohun",
//  (: perform_action, "strike.anran", 调用perform_action函数,参数是strike.anran
//
  }
  return 1;
}
}

// Default chat function: Let the npc random move to another room.
// hehe.............又发现个好东西的定义吧
// npc随机走动的函数根据自己所在的房间出口用go **来走,和pfm的频率设定基本相同
int random_move()
{
mapping exits;
string *dirs;
object me = this_object();

if( !environment()
|| !mapp(exits = environment()->query("exits"))
|| me->is_fighting() || me->is_busy()
|| me->query("jingli") < me->query("eff_jingli") / 2 ) return 0;

dirs = keys(exits);
if (sizeof(dirs) < 1) return 0;
set_temp("random_move", 1);
command("go " + dirs[random(sizeof(dirs))]);
}

// Default chat function: Let the npc exert his/her enabled force
int exert_function(string func)  //刚才在chat()中定义的随机pfm调用的函数就在这里,这个是yun **
{
if (!living(this_object()) || is_busy() || is_exert()) return 0;
"/cmds/skill/exert"->main(this_object(), func);
}

int perform_action(string func)  //这个是pfm **
{
if (!living(this_object()) || is_busy() || is_perform()) return 0;
"/cmds/skill/perform"->main(this_object(), func);
}


==============================================
为了便于理解贴上globals.h


code:--------------------------------------------------------------------------------
#ifndef _GLOBALS_H_
#define _GLOBALS_H_

// globals.h
// this file will be automatically included by the driver
#define private protected

// Improve function
#define move_to_ob(ob)  move(resolve_path(__DIR__, ob))
#define new_ob(str)     new(resolve_path(__DIR__, str))
#define replace_program(x)

// Important directories
#define COMMAND_DIR     "/cmds/"
#define CONFIG_DIR      "/adm/etc/"
#define DATA_DIR        "/data/"
#define HELP_DIR        "/help/"
#define INC_DIR         "/include/"
#define LOG_DIR         "/log/"
#define SAVE_EXTENSION  ".o"

// Daemons
#define ALIAS_D         "/adm/daemons/aliasd"
#define BAN_D           "/adm/daemons/band"
#define CHANNEL_D       "/adm/daemons/channeld"
#define CHAR_D          "/adm/daemons/chard"
#define CHINESE_D       "/adm/daemons/chinesed"
#define COMBAT_D        "/adm/daemons/combatd"
#define COMMAND_D       "/adm/daemons/commandd"
#define EMOTE_D         "/adm/daemons/emoted"
#define FINGER_D        "/adm/daemons/fingerd"
#define FTP_D           "/adm/daemons/ftpd"
#define INQUIRY_D       "/adm/daemons/inquiryd"
#define IP_D  "/adm/daemons/ipd"
#define LOG_D  "/adm/daemons/logd"
#define LOGIN_D         "/adm/daemons/logind"
#define MONEY_D         "/adm/daemons/moneyd"
#define MAP_D          "/adm/daemons/mapd"
#define NATURE_D        "/adm/daemons/natured"
#define PIG_D           "/adm/daemons/pigd"
#define PROFILE_D       "/adm/daemons/profiled"
#define RANK_D          "/adm/daemons/rankd"
#define SECURITY_D      "/adm/daemons/securityd"
#define SMTP_D          "/adm/daemons/smtpd"
#define TASK_D          "/adm/daemons/taskd"
#define UPDATE_D        "/adm/daemons/updated"
#define VIRTUAL_D       "/adm/daemons/virtuald"
#define WEAPON_D        "/adm/daemons/weapond"
#define QUEST_D   "/adm/daemons/questd"

//directories
#define ARMOR_D(x)      ("/clone/armor/" + x)
#define BINGQI_D(x)     ("/clone/weapon/" + x)
#define CLASS_D(x)      ("/kungfu/class/" + x)
#define CONDITION_D(x)  ("/kungfu/condition/" + x)
#define FOOD_D(x)       ("/clone/food/" + x)
#define MEDICINE_D(x)   ("/clone/medicine/" + x)
#define MISC_D(x)       ("/clone/misc/" + x)
#define NPC_D(x)        ("/clone/npc/" + x)
#define SKILL_D(x)      ("/kungfu/skill/" + x)

// Clonable/Non-inheritable Standard Objects
#define COIN_OB         "/clone/money/coin"
#define CORPSE_OB       "/clone/misc/corpse"
#define EXPLORE_OB       "/clone/misc/explore_ob"
#define GOLD_OB         "/clone/money/gold"
#define LOADUSER_OB     "/clone/user/loaduser"
#define LOGIN_OB        "/clone/user/login"
#define MAILBOX_OB      "/clone/misc/mailbox"
#define MASTER_OB       "/adm/single/master"
#define SILVER_OB       "/clone/money/silver"
#define SIMUL_EFUN_OB   "/adm/single/simul_efun"
#define USER_OB         "/clone/user/user"
#define VOID_OB         "/clone/misc/void"

// Inheritable Standard Objects
#define BANK            "/inherit/room/bank"
#define BULLETIN_BOARD  "/inherit/misc/bboard"
#define CHARACTER       "/inherit/char/char"
#define COMBINED_ITEM   "/inherit/item/combined"
#define EQUIP           "/inherit/misc/equip"
#define FIRE_ITEM       "/inherit/item/fire_item"
#define FORCE           "/inherit/skill/force"
#define HOCKSHOP        "/inherit/room/hockshop"
#define ITEM            "/inherit/item/item"
#define LIQUID          "/inherit/food/liquid"
#define MONEY           "/inherit/item/money"
#define NPC             "/inherit/char/npc"
#define PILL            "/inherit/medicine/pill"
#define POWDER          "/inherit/medicine/powder"
#define ROOM            "/inherit/room/room"
#define SKILL           "/inherit/skill/skill"

// User IDs
#define BACKBONE_UID    "Backbone"
#define ROOT_UID        "Root"

// Features
#define F_ACTION                "/feature/action.c"
#define F_ALIAS                 "/feature/alias.c"
#define F_APPRENTICE            "/feature/apprentice.c"
#define F_ATTACK                "/feature/attack.c"
#define F_ATTRIBUTE             "/feature/attribute.c"
#define F_AUTOLOAD              "/feature/autoload.c"
#define F_BANKER                "/feature/banker.c"
#define F_BOAT                  "/feature/boat.c"
#define F_CLEAN_UP              "/feature/clean_up.c"
#define F_COMMAND               "/feature/command.c"
#define F_CONDITION             "/feature/condition.c"
#define F_DAMAGE                "/feature/damage.c"
#define F_DBASE                 "/feature/dbase.c"
#define F_DEALER                "/feature/dealer.c"
#define F_EDIT                  "/feature/edit.c"
#define F_EQUIP                 "/feature/equip.c"
#define F_FINANCE               "/feature/finance.c"
#define F_FOOD                  "/feature/food.c"
#define F_LINEUP                "/feature/lineupquery.c"
#define F_LIQUID                "/feature/liquid.c"
#define F_MASTER                "/inherit/char/master.c"
#define F_MESSAGE               "/feature/message.c"
#define F_MORE                  "/feature/more.c"
#define F_MOVE                  "/feature/move.c"
#define F_NAME                  "/feature/name.c"
#define F_PILL                  "/feature/pill.c"
#define F_REPORT                "/feature/report.c"
#define F_SAVE                  "/feature/save.c"
#define F_SKILL                 "/feature/skill.c"
#define F_SSERVER               "/feature/sserver.c"
#define F_TASK                  "/feature/task.c"
#define F_TEAM                  "/feature/team.c"
#define F_TREEMAP               "/feature/treemap.c"
#define F_UNIQUE                "/feature/unique.c"
#define F_VENDOR                "/feature/vendor.c"

// Profiling switches
//
// If you changed any of these defines, you'll need reboot to make it
// in effect.

#undef PROFILE_COMMANDS

// Mathematic
#define ABS(x)                  ((x) >= 0 ? (x) : -(x))
#define MAX(a, b)               ((a) > (b) ? (a) : (b))
#define MIN(a, b)               ((a) < (b) ? (a) : (b))
#define SGN(x)                  ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0))
#define SWAP(x, y)  (x ^= y ^= x ^= y)

#endif
门派:不明
 楼主| 发表于 2008-5-23 04:33:44 | 显示全部楼层
feature/clean_up.c


code:--------------------------------------------------------------------------------
// clean_up.c
// by Annihilator@ES2
// Adapted for XKX by Xiang (12/15/95)

int clean_up()
{
object *inv;
int i;

if( !clonep() && this_object()->query("no_clean_up") ) return 1;

if(userp(this_object())) return 1;

// If we are contained in something, let environment do the clean
// up instead of making recursive call. This will prevent clean-up
// time lag.
if(environment()) return 1;

inv = all_inventory();
for(i=sizeof(inv)-1; i>=0; i--)
  if(userp(inv)) return 1;

destruct(this_object());
return 0;
}

-----------------------------转载自《新世纪书剑论坛》
门派:不明
发表于 2008-5-30 05:58:04 | 显示全部楼层
这个可真是。。。又臭又长。。以前也没这么仔细看过npc.c
门派:不明
发表于 2009-10-9 18:43:19 | 显示全部楼层
请问让某地更新后随机出现个npc  该怎么写呢
发表于 2013-2-16 12:22:01 | 显示全部楼层
偶然发现我的大作被转到这里来了,哈哈
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|书剑永恒MUD ( 闽ICP备14012032号|闽公网安备 35050202000162号 )

GMT+8, 2025-7-27 09:06 , Processed in 0.032900 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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