简单的人物原则上只要有 set_name<名字> 、 combat_exp <经验>就行了,当然我们总得稍微多添一点了。
inherit NPC;
void create()
{
set_name(<中文名>, ({ <英文id> }) );
set("title", <头衔>);
set("gender",<男性、女性或是无性>);
set("age", <年龄>);
set("long", <人物的长相描述>);
set("combat_exp", <人物的实战经验>);
set("attitude", <好战态度>);
set("neili", <内力值>);
set("max_force", <最大内力>);
你想让这个人物能够时不时说点什么或动点什么,就要
set("chat_chance", <随机动作概率的百分比>);
set("chat_msg", ({
"随机的动作或语言的描述"
........
}) );
这时,如果还想让对玩家ask它时有些特殊的反应的话,就得:
set("inquiry", ([
"ask的关键词": "回答的话",
.......
]) );
物品要比上面两类更要简单一点,看懂了这些,再去调几个物品的文件,自己看看也就明白了。好了,现在你可以自己对自己写一个工作室,也可以在里面放一个傻乎乎的书童了。接下来我们就要深一步,了解文件中更富有变化。更有意思的基本函数之二:
init() 函数
init()函数就是在有玩家或 npc等的活物进入房间时(可以是走进来,扔进来或clone 进来)被触发,从而实现函数功能。也就是说,如果你要对进入房间的玩家做一些动作,比如弄晕他或给他中毒、或者向他问好、显示出一些特殊的信息等等,那么就在init()函数里对那个玩家进行操作。
在 init() 中最常见的的函数莫过於add_action("function", "action")了,它的作用是在进来的生物身上添加上一个指令 (注意, 系统只认指令的第一个单词), 并在玩家下达这个指令时去呼叫那个名称的函数:举例而言, 如果我们写了这样的 init():
init()
{
add_action("do_climb", "climb");
}
就是说,当玩家走进这个房间时, 系统会帮他多出 climb 这个指令,当他下达了climb tree 这个指令时, 系统会去寻找 do_climb() 这个函数, do_climb()这个函数当然是你去写了。同时, 系统会将玩家所输入的 "climb"这个指令后面的所有文字,作为一个检查的变量(是不是有些深了?没关系,看不懂就跳过去,知道是这么个意思就行了)传给 do_climb()。你可以将 do_climb这个函数宣告为
int do_climb(string arg)
这样一来,当玩家下达 climb tree,或是 climb the red wall这种指令时,"tree"或是 "the red wall"就会被存进变量 arg 之中供do_climb进行检查处理。如果判断后面的变量与我们设计的无关,也就是说,比如我们希望玩家应该是climb red tree,那么就应该写:
if(arg!="red tree") return 0;
“!=”就是不等于的意思,“!”代表不、否定的意思。return 传回的是 1,就表示通过;是0,则表示函数处理中止。所以,这句判断名就是当后面跟的那个变量不是“red tree”时,函数的处理就终止。反过来,你就可以设计并设置,条件符合时会发生的事,然后别忘了,在最后加上一句return 1;
在这里,我们给有一些基础的巫师开一个小灶,看不懂的就跳过去看下一段。有时有些新巫师会发现一个有点费些思量的事,就是当我们所加的add_action()的指令同时也是系统提供的cmds指令时,一般add_action的指令将优先于cmds进行执行。比如kill是一个cmds指令,但在你现在写的房间程序中将要进行某种程度的限制。一般的做法就是加add_action("do_kill","kill"),那么,玩家一旦在这里发出kill指令,将首先寻找do_kill()这个函数,进行变量的检查。比如,发现玩家的某些条件不符合就给出类似“这里不允许对杀”的信息后return 1;就表示判断通过了,也就意味着这个指令已被你写的这个函数处理掉了。如果你在某个条件后给出“你心中一动,杀机已起,小小的一个地方立刻激荡出无边的战气”后return 0; 这就是告诉系统,我这个kill指令并没有完,刚才只是增加kill更多的信息,此后系统就会寻找本来的那个kill的cmds指令,也就是正式执行,这被称之为重载。(有点绕人?多想想,想通了后很有用的)
在你的函数检查到玩家输入的变量有问题时 (例如你要他们climb red tree, 但他们却输入了一些错误的指令如 climb three 之类的),你可以象上面一样直接return 0;终止这个函数,系统就会显现出“什么?”的错误信息。而如果你想给他们一些特别的、有些意思或提示性的错误讯息时, 你可以用 notify_fail(".....")来代替0写这个讯息, 比如:
return notify_fail("你想爬什么?\n");
return notify_fail()就是用来取代return 0的东西,这就是想让返回的错误信息更加丰富、或者有效而已。所以我们最常用的写法是:
if (条件不合)
return notify_fail(错误讯息);
if (另一个条件不合)
return notify_fail(另一个错误讯息);
.............................
(所有可能导致错误的输入都过滤光了 开始真正干活的部份.... )
..............................
return 1;
人物的、物品的init()与 ROOM 中的init()函数类似, 但物品中被呼叫的机会多了许多, 主要有下列的几种情况:
1,物品摆在房间中, 有一个玩家走进来,这很好理解;
2,一个物品突然出现在某个玩家所在的房间中,这就是象别人丢下的,机关触发出来的,或者是巫师变出来的;
3,一个物品突然出现在某个玩家的物品栏中,象别人给你的,你买到的东西,通过机关直接触发到身上的;
这些 action 会生效的场合归结起来很简单, 就是: 「玩家用 look 或是 i 指令看得到这个物品的时候」,但是同一个房间中他人或 npc身上的东西时不算,装在袋子的东西不算。
废话少说,下面还是拿出例子进行逐句的解释,这也是新巫师最需要的。首先说明:在文件中“//”后面跟的就是注释语句,凡是这一行“//”后的东东,程序在执行时概不理会。而“/*”也是表示后面是注释名,只不过它表示后面所有行的东东都是程序不必理会执行的语句,一直到“*/” 结束。用在注释行较多的地方。这里为了区别,我们把教材中注释用淡一些的颜色标出。
// Room: /d/wuxi/ximen.c //无锡西城门 程序开头注明一下 文件类型和绝对路径和中文名
// llm by 99/05/21 //继续注释 谁写的和编写时间 有时是修改时间
#include <ansi.h> //表明它继承了定义颜色的文件,后面不要分号
#include <room.h> //表明它继承了定义房间的文件,因为门在这个文件里
string look_pai(object me); //声明一下这个文件里有一个函数的原型定义
inherit ROOM; //表明它是继承 ROOM 类
void create() //开始创建函数vo