ES2 MUD LIB :: 東方故事二(ES2) 天朝帝國 mudlib 瀏覽展示
/doc/build/npc
□ 如何編寫人物(NPC)
我想大多數 LPmud 巫師第一個學會的大部分是寫房間﹐接下來就是 NPC﹐NPC 的
寫作方式不同的 mud 差別很大﹐不像房間的寫法大同小異﹐因為 NPC 的設定方式
往往隨著 mud 的故事背景而異﹐所以我們就廢話少說﹐開始介紹 es2 的 NPC 設定
程序吧。
□ NPC 設計─初級
// example NPC
#include
inherit F_VILLAGER;
void create()
{
set_name("村姑", ({ "woman" }));
set_race("human");
set_class("commoner");
set_level(1);
set("long", "一個相貌「普通」的村姑。\n");
setup()
}
上面這段程式就是一個簡單的 NPC﹐雖然簡單﹐不過卻包含了不少重要的觀念﹐且讓我
一一解釋﹕
#include
這一行是所有 NPC 必須的﹐也許你會覺得奇怪﹐為什麼 NPC 沒有像房間一樣繼承一個
NPC 的標準物件﹐去看看 /include/npc.h 就會明白﹐因為 npc.h 已經幫你繼承了﹐
在 es2 mudlib 裡﹐像 NPC、武器、防具、物品等這些「可以複製」的物品將會採用類
似的繼承結構﹐你將會發現這些物件的寫法都是 #include 一個 xxx.h 並且選擇性地繼
承一些 F_xxx 的物件。
inherit F_VILLAGER;
這一行繼承的 F_VILLAGER 我把它稱為「行為控制模組」﹐es2 的 NPC 可以藉由定義一
些函數來控制 NPC 對一些事件的反應﹐像是說話、戰鬥、交易等等﹐傳統的 mudlib 常
常把這些反應定義在 NPC 的標準物件裡﹐然後在 create() 中用各種設定值來使用﹐這
種方法不但彈性不高(你只能設定參數﹐像 set("killer", 1) 之類..)﹐ 而且容易因為
遊戲制度的改變而需要修改﹐並且增加記憶體的負荷。在 es2 中諸如此類的設定都藉由
定義函數來代替﹐而且為了節省因為定義這些函數所需的程式佔用的空間﹐將這些定義
NPC 反應的函數收集成一個個的模組供巫師使用。
一個 NPC 「不一定」要繼承行為控制模組﹐如果你不希望這個 NPC 對那些事件有反應的
話﹐或者你可以選擇性的自己定義這些函數﹐通常一個區域會有許多行為模式相近的 NPC
﹐你也可以自己寫成一個行為控制模組供不同的 NPC 繼承使用。
set_name()、set_race()、set_class()、set_level() 這幾個函數顧名思義﹐分別是設定
NPC 的名稱、種族、職業及等級﹐除了 set_name() 之外﹐其他幾個都要看你的 mud 遊戲
設定哪些種族跟職業而定﹐原則上只有 set_name() 是必須的﹐其他的如果不設定﹐系統
應該會在 setup() 裡幫你用內定值補齊。
set("long", "...");
這一行是設定 NPC 的敘述﹐讓玩家 look 這個 NPC 時提供一些描述﹐es2 裡像 NPC 及所
有從遊戲觀點而言「看得見摸得著」的物件都會利用 name()、short()、long() 這三個﹐
自定函數來取得一個物件的外觀﹐並且﹐我們規定 set("name", ...)、set("short",...)
及 set("long", ...) 是設定這些外觀的「靜態」值﹐用 NPC 做例子﹐你所設定的 long
敘述在玩家實際去看的時候﹐系統可能會幫你加上他的受傷狀況、身上的裝備等「動態」
資訊﹐而容器、留言版等其他物件也有各自不同的動態資訊。
在此建議你將所有的 set() 及 set_temp() 等屬性設定放在 set_name()、set_race() 等
特殊函數設定之後﹐並且用一個空行隔開﹐如上面那段程式﹐理由是在有些 mud 上﹐屬性
設定是可以所有複製物件「共用」的(即記憶體只存一份﹐供所有複製物件 query使用以節
省記憶體)﹐有些 mud 的管理者會要求你用﹕
if( !clonep() ) {
set("long", "...");
set("xxx", "...");
.....
}
的格式來設定屬性﹐關於這種設定的理由跟優劣﹐請參考有關 set_default_object() 的
說明﹐這裡只建議你將這些設定和前面的特殊函數設定分開以示區分。
最後一行的 setup() 應該不需要詳細解釋了﹐這個函數是讓系統幫你檢查前面的設定或補
足你沒有設定的東西﹐記得一定要加入這一行。
By Annihilator (04/24/96)