[心得] 怪物一般掉落物虛擬化
先說一個概念,各 mud 幾乎都有技能系統,其使用的欄位也幾
乎都是 skill 這個欄位,例如..
me->set("skill/barefist",100);
me->add("skill/barefist",200);
me->delete("skill/barefist");
me->query("skill/barefist");
現在假設從前從前從前,技能是「實體物件」,而身上某技能
的技能值多少=身上帶了多少該技能的物件數。
那麼從實體物件的增減→技能值的增減,就是所謂虛擬化的過
程。
=======================================================
傳統上,要撰寫打死什麼怪物會掉什麼東西,一般是先寫好該
物品(物件),然後設定怪物身上有這個東西,則玩家打死怪物
時物品自然掉落、或被玩家撿起如 get all from corpse。
那假設今天怪物的一般掉落物多到幾百種,而且每個都可堆疊
,則允許玩家儲存這些資料時就會造成資料檔肥大、以及登入
時載入物品的 loading 過重。
可堆疊
http://www.wmon.com.tw/RO/photo/window/guide_ui05.gif

解決的方法很多(例如仿 shop 做法),這裡分享其中一種。
首先,每隻怪物的完整檔名都是由目錄+檔名組成,而一隻怪
物可設定會掉多種物品各自的掉落機率,也就是說:
{ 路徑, 檔名, 掉落物, 機率 } 是一串有效識別集合。
依上面的東西來決定物品掉落物設定集資料庫的資料結構,就
是如下的例子
mapping drop_data=
([
// 第一層: 目錄
"/area/maintown/mob/":([
// 第二層: 小黑狗的檔名(無.c)
"black_dog":([
// 第三層: 掉落物與其機率
"犬齒":30,
"狗肉":10,
.
.
]),
]),
]);
那麼,一個很直覺的想法就是,當玩家打死小黑狗時,
在怪物的 die() 函數區一定會有讀資料庫的段落如下
玩家 被打死的怪物檔名
drop_sys->check_drop( ppl, base_name(mob));
這個 object drop_sys 就是指怪物掉落物管理系統,
而這個系統裡就宣告了如上的 mapping 資料。
這時候 check_drop 函數的內容就大致如下
int check_drop(object ppl,string mob_file)
{
string *drops=([]);
string mob_path,tmp,ob_name;
int s;
tmp=mob_file;
s=strlen(mob_file);
while(s-->0)
{
if(mob_file[s..s]="/")
{
mob_path=mob_file[0..s];
mob_file=tmp[s+1..strlen(tmp)-1];
}
}
// 將 "/area/maintown/mob/black_dog" 拆成
// "/area/maintown/mob" 及 "black_dog"
// 則馬上就可判斷該怪物是否有設定掉落物品
if(!drop_data[mob_path]) return 1;
if(!drop_data[mob_path][mob_file]) return 1;
// 通過這裡代表該怪物有設定掉落物品,則以仿
// RO 的物品掉落為例
drops=keys(drop_data[mob_path][mob_file]);
foreach(ob_name in drops)
{
// 當判斷到 所設定的掉落機率 > random(100) 時
if((int)drop_data[mob_path][mob_file][ob_name]>random(100))
ppl->get_drop(ob_name);
}
return 1;
}
所謂仿 RO 指的是打死 RO 的怪物會掉不只一種物品,而且
每種物品的掉落機率彼此是獨立的。
而 get_drop 就依各家 mud 的寫法不同而有不同。假設今天
是將資料放在玩家資料欄 obs 上面並仿技能資料的話,大致
如下..
int get_drop(string ob_name)
{
add("obs/"+ob_name,1);
write("你得到了一個"+ob_name+"!\n");
return 1;
}
或許你會說那就直接 add("obs/"+ob_name,1); 就好了為什
麼還要刻意呼叫函數來做?這是因為函數可以做一些彈性的
設計,例如..
int get_drop(string ob_name)
{
// 只有玩家身上攜帶的該物總數小於 99 才會實際增加
if((int)query("obs/"+ob_name)>=99)
{
write(HIR"你已經攜帶了 99 個以上的"+ob_name+"了!"NOR"\n");
return 1;
}
// 當玩家沒這東西時,只有玩家身上攜帶的物品種類數小於 99 才會實際增加
if(!query("obj/"+ob_name) && sizeof(keys(query("obs")))>=99)
{
write(HIR"你已經攜帶了 99 種以上的物品,不能再帶任何新物品了!"NOR"\n");
return 1;
}
// 其它彈性判斷例子,例如雖執行到可掉落拳法秘笈,但是有設定
// 拳法根基(技能 barefist)必須達到 500 才可以取得時就不讓他取得
if(ob_name=="barefist tips" && query("skill/barefist")<500)
return 1;
.
.
add("obs/"+ob_name,1);
write("你得到了一個"+ob_name+"!\n");
return 1;
}
而既然可以寫 get_drop 函數,自然也可以寫其它函數來處
理 obs 這個欄位的資料。
然後,玩家打到怪物掉落物時,一定會想看自己身上有哪些
掉落物,以及其數量各多少,假設觀看的指令叫 ob,如下..
> ob
你的物品欄帶著 9 種物品:
╔══════════╦══════════╦══════════╗
║ 1.牙齒 ( 10)║ 2.尾巴 ( 95)║ 3.翅膀 ( 10)║
║ 4.魔物心臟 ( 98)║ 5.硬角 ( 45)║ 6.外皮 ( 84)║
║ 7.尖刺 ( 39)║ 8.鼻環 ( 99)║ 9.大鉗 ( 35)║
╚══════════╩══════════╩══════════╝
其程式段如下
msg="╔══════════╦══════════╦══════════╗\n";
keys_obs=keys((mapping)me->query("obs"));
i=0;
foreach(ob_name in keys_obs)
{
i=i+1;
msg+=sprintf("║%2d.%10s (%3d)",i,ob_name,
me->query("obs/"+ob_name));
if(i%3==0)
msg+="║\n";
}
msg+="╚══════════╩══════════╩══════════╝\n";
而當玩家想要將物品賣給商店時,至少要有該物品的單價等
資料,這就是另一個物品設定集資料庫的內容,最簡單的物
品資料庫如下..
mapping obs_data=
([
// 第一層: 物品名字
"狗肉" :([
// 第二層: 設定資料
"value":10, // 比方十文錢
"cant_sell":1, // 比方有設定該參數代表不能賣
.
.
]),
]);
則賣給商店時
if(obs_data[ob_name]["cant_sell"])
{
write(HIR"你不能將"+ob_name+"賣給商店喔!"NOR"\n");
return 1;
}
me->add("obs/"+ob_name,-1);
v=(int)obs_data[ob_name]["value"];
me->add("wealth",v);
write("你賣掉一個"+ob_name+"得到了 "+v+" 文錢。\n");
到這裡,物品就可被打到、可觀看、也可賣掉了。
本系統的重點
1.需設定適當的資料結構(各家做法不同)
2.給玩家的指令、以及給 wiz 使用的指令要分開
=> 這純粹是個人經驗,分開比較好。但基本上它們都是對
同一個資料庫做處理
3.要先評估好日後的設定規模。規模越小設計可越彈性,規模
越大,設計要越謹慎並最好有完整的前期測試(以發現問題)
4.要經常以日後易於增刪、易於修改、易於維護的思考角度去
設計系統與指令
5.當設定量達到一定規模時要做一下資料檔的備份
本系統的好處(不管是哪一家 mud)
1.減少實體物件佔用記憶體及玩家資料檔的空間
2.掉落物品資料不管是要讀取資料還是做增刪改均十分容易
3.可方便控管玩家身上的怪物掉落物品
a.集中資料庫管理(且易於備份保存)
b.物品資料變更容易,一變更即套用(如價格)
c.容易做相關必要限制(如攜帶量)
d.可將資料庫 export 結果釋出給玩家,方便玩家製作打
怪掉落物品資料
4.幾乎不需編寫各物品的實體物件,節省時間及寶貴的人力
以上一點心得,跟大家分享,其它細節就不贅述。
Laechan@Sanc
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 210.61.157.53
推
07/31 19:52, , 1F
07/31 19:52, 1F
→
08/06 00:13, , 2F
08/06 00:13, 2F
mud 近期熱門文章
PTT遊戲區 即時熱門文章
28
63