Mud 版 (精华区)

发信人: anderson (危峦快剑), 信区: Mud
标  题: LPC中文介绍(1)
发信站: 紫 丁 香 (Wed May 13 18:57:38 1998), 转信


以下文章转自XO,特此声明: 
Subject: 新巫师入门(转寄) 
X-Forwarded-By: start (酒虫) 
X-Disclaimer: 天地创造 对本信内容恕不负责。 


此文是lnwm发于technology板 

嗯,下面是我给6666的新巫师们的一篇入门读物,大家可以看看。 
是我从清华BBS巫师版弄来的,是台湾人写的,有些词语我改 
成大家比较熟悉的,很多地方加了注,可能更好懂一些。 


这篇说明是为了新上任的巫师所写的, 我假设读著这篇说明文件的 
新巫师已经读过 help new_wiz 中的内容, 并对巫师专有的指令如 clone, 
update, cd, ls, cp... 等能熟练地加以使用, 但对如何开始写作自己 
的区域感到茫然, 不知所措的新进巫师  

[在开始制作之前] 

让我们大略看一下在 LP MUD 中, 世界的构成方式 这个世界是由 
(目前大陆上玩的 mud ,包括 xkx,fy,es2 都是 lp mud 
即所谓战斗 mud。---lnwm 注。) 
一个个的对象 (object) 所组成, 每个对象有一个对应的程序来描 
(比如你在mud里见到的每个房间,每个npc,每个物品,甚至 
你自己,都是一个 object,都是一段程序。----lnwm 注。) 
述它的特性 我们可以藉由写作一段程序来创造出一个全新的对象, 可 
以利用 update 来更新对象所属的程序, 用 clone 来实际造出一个可 
(比如你敲 update here,就是将你现在所在的房间更新,这里需要强调 
的是,所谓更新,就是将硬盘里这个文件编译后形成一段代码,这段代 
码是存在在内存中的。因此当你修改了一个房间,那只表明你在硬盘上 
改动了这个文件,你必须做一下 update ,将它编译放入内存,你的修 
改才正式生效。hehe,当然,编译有错误例外。----lnwm 注。) 
用的对象 . 
(clone其实就是 update,只不过它update的是一个物品或npc,这个物品 
或npc还需要有地方放,所以clone就是 update+move。---lnwm注。) 

在这里, 我们有各式各样的对象, 但是可以将之区分为三大类: 房 
间 (ROOM), 物品 (OBJECT), 与生物 (LIVING)  在我们制作区域的惯 
(这个OBJECT不过是个名词以和ROOM LIVING区分,和我们mud的 
object是两码事。---lnwm 注。) 
例上, 我们习惯将房间的档案直接摆在区域的目录下, 生物与物品则摆 
(区域的习惯放置位置是根目录下的 /d 目录。特别是大陆的, 
你可以在 /d下找到所有的房间和npc-------lnwm 注.) 
在这个区域中名为 npc 及 obj (也有人喜欢用 object 或 item 
为名, 看个人习惯 ) 的子目录中 。 

以下我将以这三大类对象来分别说明该如何实作出区域 

[如何制作房间] 

一个房间必定继承了 ROOM (inherit ROOM), 这是在 
(对,如果你要写一个房间,那么首先要做的就是在这个程序 
的开头写上 
inherit ROOM; 
在有些时候,比如在xkx里,你 
可能还要加上一句 
#include 
因为房间的门是定义在那里的。---lnwm注。) 
mudlib.h中被 #define 好的一个档案, 它表示一个特别的档案, 所 
有的房间都必须继承它. 才能拥有属於房间的一切特性  
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^! 

一个房间有三个非常重要的函数: create(), init(), 与 refresh() 
这三个函数会在某些特定的时机被系统所呼叫, 并且可以由你自行改写 
, 以达成千变万化的效果 。 

[create 函数] 

  create() 是房间在一被创造出来时必定要呼叫的一个函数, 通常我 
(如果你学过C语言,那么在lpc中,void create() 
就相当于 void main(),即主函数。---lnwm注。) 
们都在里面做一大堆设定初值的动作 随便找一个房间来看, 我们可以 
发现 create() 函数中总是有一大堆的 set("something", somevalue); 
这些 set 的意义在此不详述, 你可以自己猜, 也可以问问较资深的巫 
师 . 
(在我们这个mud中,你可以敲help STD_ROOM来看看这些设置是干什么 
的。---lnwm注。) 

有时你的房间并不直接继承 ROOM 而是继承了一个有继承 ROOM 的 
特别房间, 像是商店或是公会房间什麽的 这时候你所写的 create() 
(在我们的mud中,钱庄就是个典型的例子,在钱庄的前面,你必须 
inherit SHOP; 
这个SHOP就是在ROOM的基础上加了钱庄的公用功能。---lnwm注。) 

[init 函数] 

init() 函数被呼叫的时机在於有生物 (npc及玩家) 进入这个房 
(这里的意思是,当有玩家或npc等活物进入房间时,可以是走进来, 
扔进来,或clone进来,房间中的这个init()函数就被触发,函数 
实现的功能就被实现。----lnwm注。) 
间的时候 这时有个常用的函数 this_player() 会传回走进房间的这 
个人, 或是npc。 this_player() 的概念容後再谈, 你现在只要记住这 
个函数在每个生物走进来时都会被呼叫一次就可以了  
(这里的意思是,如果你要对进入房间的玩家做一些动作,比如弄晕他 
或给他中毒等时,那么就在init()函数里对 this_player()作操作 
就可以了,this_player()就是触发init()函数的玩家。---lnwm注。) 


在 init() 中最常见的的函数莫过於 add_action("function", "action"); 
了 它的作用是在进来的生物身上添加上一个指令 (注意, 系统只认指 
令的第一个字), 并在玩家下达这个指令时去呼叫 "function" 中所给 
定名称的函数 举例而言, 如果我们写了这样的 init(): 

init() 

add_action("do_climb", "climb"); 


当玩家走进这个房间时, 系统会帮他多出 climb 这个指令 当他下达 
(如果这个指令不是cmds,那么在没有 
add_action的房间里就不会存在。) 
了 climb tree 这个指令时, 系统会去寻找 do_climb() 这个函数, 并 
(do_clone()这个函数当然是你去写了 
---lnwm注。) 
加以执行。 同时, 系统会将玩家所输入的 "climb" 这个指令後的所有 
文字以字串类型的变量传给 do_climb()  你可以将 do_climb 这个函 
数宣告为 
int do_climb(string arg)  
(注意,这个带函数类型和参数类型的函数才是完整写法。---lnwm注。) 

这样一来, 当玩家下达 climb tree, 或是 climb the red wall 这种指令时, 
"tree" 或是 "the red wall" 就会被存进字串变量 arg 之中供你处理 。 

由 add_action() 所宣告的函数必定要是一个整数类型的函数, 因 
为系统会根据这个函数的传回值采取不同的动作 如果你传回的是 0, 
那麽系统会认定这个命令与你这个处理函数无关, 而对其他也有 climb 
命令的函数一个一个尝试著去执行, 直到所有的 climb 命令都传回 0。 

(这段话很重要,当你要玩家在使用某个cmds时出现其他的用处, 
比如你要玩家eat一个果子不仅仅涨食物,而且涨别的东西,那么 
你就要在果子上用 add_action来给eat赋予更多的内容,然后在你 
处理eat的那个函数最后 return 0; 
这就是告诉系统,我这个指令并没有完,系统就会寻找本来的 
那个 eat 命令的功能函数,也就是加上食物。 
这称为重载。----lnwm注。) 

若你的函数传回值为 1, 表示这个指令已经由你所写的函数处理掉 
了, 系统不会再尝试著往下面继续寻找其他的 climb 指令  
(给出一个例子。 
void init() 

add_action("do_eat","eat"); 


int do_eat( string arg ) 

object me; 
me=this_player();//触发指令的玩家。 

if (arg!="果子") 
return notify_fail("你要吃什么?\n"); 
//notify_fail() 就是 return 0 

me->set("str",1000); //这里是你要使这个果子与众不同的地方。 
return 0; //这里使这个果子和其他食物一样仍然可以涨 
//食物,你可以试试 return 1 
//那样你发现你的果子吃了不涨食物。 

----lnwm 注。) 

在你的函数侦测到玩家输入的变量有问题时 (例如你要他们 climb 
tree, 但他们却输入了一些错误的指令如 climb three 之类的)  想 
给他们一些特别的错误讯息时, 你可以用 notify_fail(string errormsg) 
来写这个讯息, 如 notify_fail("climb what?\n"); notify_fail() 
这个函数也是 int 类型, 固定会传回 0, 所以我们最常用的写法是: 

if (条件不合) 
return notify_fail(错误讯息); 
if (另一个条件不合) 
return notify_fail(另一个错误讯息); 
............................. 

开始真正干活的部份.... 
return 1; 
(可以参考一下上面的例子。---lnwm注。) 

[refresh() 函数] 

refresh 呼叫的时机是系统定时 (约每半个小时一次) 呼叫 主 
要的用途在於房间中npc 物品的再生 如果你改写了 refresh() 
函数, 千万记得要串接 ::refresh(), 否则可能导致严重的後果 (门 
一打开就不会自动关上, npc打死後也不会再生... 

由於有 set("objects", (["name1" : "file1", "name2" : 
"file2",... ]) ); 这种写法的存在 (在 create() 里面这麽写) 所 
(set("objects",([]))用来在房间里放东西,比如 
npc或物品什么的。---lnwm注。) 
以 refresh() 被用到的机会不多了  (因为 set("objects", ) 这 
个写法可以帮你作出自动定时 refresh npc 物品) 但是在制作一 
些必须定时回复原始状态的小机关时, 仍然有必要用到这个函数  
( refresh 函数用到的地方并不是很多,因为它太僵硬,要十分 
固定的半个小时(准确的是24分钟)才被调用一次,可以用在 
一些周期较长的秘密中。---lnwm注。) 

--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.118.226.67]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.591毫秒