[心得] 怪物一般掉落物虛擬化

看板mud (網路地下城/文字遊戲)作者 (小太保)時間12年前 (2013/07/31 14:54), 編輯推噓1(101)
留言2則, 2人參與, 最新討論串1/1
先說一個概念,各 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
文章代碼(AID): #1H-BI8Yf (mud)
文章代碼(AID): #1H-BI8Yf (mud)