lpc npc全攻略(以sj2002为例)
npc.c本身的文件能够表示的东西其实不多,都是固定的
不讲解大家基本也能猜出个123。现就工作原理写了一下
以古墓派yang guo 这个npc为例
/kungfu/class/gumu/yang.c
code:--------------------------------------------------------------------------------
// yang.c 杨过 //注释
// By River 98.8
// Modified by darken
/*
如果你对c没什么了解那我就没什么办法了
至于mudos的include的搜索路径配置在mudos同目录中的config.sj中的下面设定里可以更改
# the directories which are searched by #include <...>
# for multiple dirs, separate each path with a ':'
include directories : /include
在config.sj中还有一个设定在这里很重要就是:
# This is an include file which is automatically #include'd in all objects
#global include file : <config.h>
global include file : <globals.h>
这里配置的是mudos在启动后每一个文件的默认设定,即所有的文件可以不用定义就是用globals.h中已经定义的变量、宏、等。
globals.h的位置自然是在上面定义完的/include中寻找了,也就是sj2002中的/include/globals.h
下面对yangguo.c的语句逐一解释
*/
#include <ansi.h> //导入颜色设置文件,文件是/include/ansi.h
inherit NPC; //inherit也是可以达到包含的目的,这里的NPC是一个宏在globals.h中定义的代表/inherit/char/npc.c 注解1
inherit F_MASTER; //F_MASTER也是globals.h中定义的代表/inherit/char/master;注解2
string ask_sword(); //定义函数,或者叫成员方法,c语言中有明确的解释
int pfm_haichao(); //同上
void create() //npc的创建,其中一些默认的设定在/inherit/char/npc.c中有详细的定义
{
set_name("杨过",({"yang guo","yang","guo"})); //npc中文名称,英文id
set("title",HIW"古墓侠侣"NOR); //头衔
set("nickname",HIY"神雕大侠"NOR); //外号
set("long", "他就是名满天下的杨过。虽断一臂但仍遮不去一脸的英雄豪气。\n");//look的时候显示详细的描述
set("age", 39); //年龄
set("attitude", "friendly"); //见/inherit/char/npc.c中的int accept_fight(object who)函数
set("no_bark",1); //不接受bark命令
set("shen", 10000); //神
set("per", 30); //纯朴
set("str", 40); //臂力
set("int", 30); //悟性
set("con", 40); //根骨
set("dex", 25); //身法
//各项数值的设定
set("max_qi", 6500);
set("max_jing", 5000);
set("neili", 13500);
set("eff_jingli", 3500);
set("max_neili", 13500);
set("jiali", 100);
set("combat_exp", 2800000);
set("unique", 1);
//武功设定
set_skill("sword",300);
set_skill("dodge",300);
set_skill("strike",300);
set_skill("force", 300);
set_skill("hand", 300);
set_skill("cuff", 300);
set_skill("parry", 300);
set_skill("stick", 300);
set_skill("staff", 300);
set_skill("finger",140);
set_skill("literate", 250);
set_skill("baituo-shezhang",180);
set_skill("xiantian-gong",20);
set_skill("hamagong",300);
set_skill("medicine",120);
set_skill("jingmai-xue",80);
set_skill("qimen-baguazhen",80);
set_skill("throwing",110);
set_skill("dagou-bang",220);
set_skill("bangjue",170);
set_skill("yuxiao-jian",190);
set_skill("tanzhi-shentong",160);
set_skill("yunu-shenfa", 300);
set_skill("meinu-quanfa",300);
set_skill("xuantie-jianfa", 300);
set_skill("anran-zhang", 300);
set_skill("quanzhen-jianfa",300);
set_skill("tianluo-diwang", 300);
set_skill("yunu-xinjing",300);
set_skill("jiuyin-zhengong",160);
set_skill("dafumo-quan",60);
set_skill("daode-jing",60);
set_skill("jiuyin-shenfa",130);
set_skill("qimen-bagua",150);
set_skill("taoism",100);
map_skill("force", "yunu-xinjing");
map_skill("sword","xuantie-jianfa");
map_skill("stick","dagou-bang");
map_skill("staff","baituo-shezhang");
map_skill("throwing","tanzhi-shentong");
map_skill("finger","tanzhi-shentong");
map_skill("dodge", "yunu-shenfa");
map_skill("parry", "anran-zhang");
map_skill("hand", "tianluo-diwang");
map_skill("cuff", "meinu-quanfa");
map_skill("strike", "anran-zhang");
prepare_skill("strike","anran-zhang");
//随机说话或者调用函数,在/inherit/char/npc.c中有部分的定义
set("chat_chance_combat", 30); //随机值,注解1中详细描述
set("chat_msg_combat", ({
(: exert_function, "xinjing" :),
(: pfm_haichao :), //自定义函数
(: perform_action, "strike.xiaohun":),
(: perform_action, "strike.anran":),
})); //随机调用函数的设定,见注解1
create_family("古墓派",3,"男主人");
set_temp("apply/damage", 70);
set_temp("apply/dodge", 60);
set_temp("apply/attack", 60);
set_temp("apply/armor", 70);
set("inquiry", ([
//在使用ask命令的时候使用到的一些设定通过(:***:)可以在ask这个问题的时候调用***函数
"古墓" : "那日华山与众英雄诀别后和龙儿隐居于此已有数年,不闻世事,能与\n"+
"龙儿在此长伴一世,此身足矣!",
"小龙女" : "龙儿乃我爱妻,你问她做甚?",
"玄铁剑" : (: ask_sword :),
"玄铁剑法" : (: ask_sword :),
]));
setup();
carry_object(BINGQI_D("sword/gangjian")); //carry_object()在/inherit/char/npc.c中有部分的定义
carry_object("/d/gumu/obj/buxue1")->wear(); // ->wear() 是在武器文件中定义的npc中不涉及
carry_object("/d/gumu/obj/pao1")->wear();
}
void attempt_apprentice(object ob) //拜师要求
{
。。。。。。。。。。
}
string ask_sword() //自己定义的一些函数
{
。。。。。。。。。。。。
}
int pfm_haichao()
{
。。。。。。。。。。。。
}
=============================================
注解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");
}
//到这里,上面是在疗伤和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
=============================================
/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[i])) return 1;
destruct(this_object());
return 0;
}
尊重作者 转载请注明出处52mud.com