Re: [wizs] 幾個東西

看板mud_sanc (Sanctuary - 聖殿)作者 (揮淚斬馬雲)時間2周前 (2025/02/08 04:45), 2周前編輯推噓0(004)
留言4則, 1人參與, 2周前最新討論串3/3 (看更多)
再來講任務的隨機性部份,因為這篇可能有點長就跟前一篇切開。 (前一篇也可能還有啥要補充的) 任務受限於我在撰寫時的架構,使得它之後要弄一些東西時變得礙 手礙腳(比方 nonseq 就是一例)。後面我也想了很多方法要來突破 這些架構上的障礙,最近才想到怎麼做。 首先是任務進行中的 input_to 做法,這個我在 /open/cmds/quest/l/l002 有實驗過是可行的,然後鍊金術士轉職 任務 l011 也有這樣的應用: write("請十秒內回答將空格應輸入的符號列出:\n"+datas[0]); input_to("cala_over",0,ppl,datas[1],0,str); 因為任務的隨機性裡頭很常遇到「讓玩家先做出某種選擇,然後才 依玩家的選擇產生不同的路線或結果」這樣的情況,所以這部份先 提(包括範例在哪)。 那簡單的說,假設我們希望任務第 n 步驟有隨機性,這裡提供一個 超級簡單的做法,就是「自訂第 n 步驟」即可,就是土法煉鋼去模 擬第 n 步驟的進行。 以 quest 指令進行第 n 步驟的流程是 1. stepn_check 2. 通過 stepn_check 後的對話演示 3. stepn_end 玩家會獲得完成第 n 步驟的任務標記 那所謂 土法煉鋼去模擬第 n 步驟的進行 的意思就是 1. stepn_check 這裡就直接呼叫所在房間的某函數 2. 讓某函數利用 call_out 去跑任務對話 然後在某函數裡面 wiz 就想做什麼變化都可以 3. stepn_end 玩家會獲得完成第 n 步驟的任務標記 然後把 選擇 跟 土法煉鋼寫函數 切開,弄成兩個步驟,比方先在 前一步驟讓玩家選擇,然後才進行下一步驟跑自定函數,並在自定 函數中依玩家在前一步驟的選擇,跑不同的流程或結果。 然後不管如何玩家都會獲得完成任務第 n 步驟的標記,因此若想讓 玩家在前一步驟依選擇的不同,可能某些選擇是無法完成該任務步 驟時,那就應該在前一個流程的選擇那邊,就直接擋掉。 比方玩家選 1 或選 2 是錯的,那就要在選擇後就直接擋掉,或是 亦可在選擇後的次一步驟的 stepn_check 時擋掉。 (畢竟 stepn_check 函數也可以自訂) 接著是模擬對話,語速通常兩秒跑一次,因此先把一串對話打好 mixed chats=({ "對話1", "對話2", . . . }); i=0; foreach(tmp in chats) call_out("show_talk",i++2,tmp); void show_talk(string tmp) { write(tmp); } 以上是最基本的土法煉鋼對話模擬,那建議參考 /open/cmds/quest/quest_data/quest_data.c 的 heart_beat 函數中關於 msg_buf 的部份: msgs=msg_buf[tmps[i]]; jj=sizeof(msgs); for(ii=0;ii<jj;ii++) { if(msgs[ii][0] && msgs[ii][1] && environment(msgs[ii][0])==msgs[ii][1]) tell_object(msgs[ii][0],""+msgs[ii][2]+"\n"); 也就是玩家若提早離開房間,是否仍持續顯示,wiz 可自行 決定,預設的 msg_buf 是玩家若提早離開房間就不會再繼續 看到對話。 然後隨機性指的就是,比方第 n 步驟,透過土法鍊鋼,就能 告知玩家,任務指定要的東西或是需達成的條件,擁有兩種以 上可能的情況,這時玩家若不完整看完對話,就可能有不知道 到底要達成的是哪一種的情況,但沒關係,可以在 n+1 步驟 的 check 告知 第 n+1 步驟: stepX_check,這裡先判斷第 n 步驟 npc 要玩 家滿足的條件或是要取得的東西是什麼,然後就 在這裡告訴玩家即可。 這樣玩家就算跳過對話(第 n 步驟已完成),也可以透過 quest 指令得知剛剛那個步驟,它要滿足的條件或取得的東西是什麼。 雖然麻煩了些,但土法鍊鋼應用在這部份上面好處多多,可突 破 quest 既有架構的先天限制,並且可讓 wiz 隨心所欲。 我最近就會將這東西應用在 /open/cmds/quest/l/l013 絕頂改 裝上頭: . . $N讀完 Page.49 後,將書本闔上後放回原位。 $N: 以蘋果做成的美味甜點嗎......## step6_npc=/u/l/laechan/special/mob/zero## step6_msg= $M: 你來啦? 吾輩一直在等你哪 $N: 是的,魔女大人,這就是以蘋果做成的美味甜點。 $M: 喔喔,這...這是!! (≧▽≦)b $M雙眼發亮,很快地收下了你準備的蘋果派 . . 目前零固定要求玩家獻上蘋果派,但若自寫函數來模擬第 5 步 驟,就可以要求玩家獻上不同的東西,然後 step6_check() { 先讀取 step5 裡頭它隨機要求的東西是什麼; 再判斷玩家是否滿足條件: 若不滿足就告知玩家需滿足什麼條件; } 以零那格的寫法因為零不是 NPC 因此自訂函數我寫在零上面, 或是零所在的那格都可以。 這東西因為與鍊金術士有關,若寫好我也會回鍊金術士討論串 那篇文,來說明絕頂改裝任務改版後的流程說明。 到時就有範例,然後 wiz 也可以先自行實驗,雖說目前僅止於 理論,但應該是可行的,就任務標記要自行追加,以及要用一 些欄位來紀錄隨機這部份,比方魔女要求蘋果派時,如何讓這 個要求被記住: 1. 建議仍是用 record_data 2. 或是 myhome 的 my_data 3. 或是撰寫玩家可重新回到隨機前狀態或是重接任務的機制 說到這個,讓玩家重接任務或是倒回第 n 步驟,建議可使用 void init() 的指令宣告方式,看要寫在哪,提示玩家可透過去哪裡下什麼 指令來重新接取這個任務、或是倒回第 n 步驟。若以這東西 的存在為前提時,則比方蘋果派的任務就能設定在 temp_data 區,玩家知道三種要求的東西裡面,蘋果派最難,他希望能放 棄重選時,玩家只要去某地方下某指令即可。 (當然前提是玩家必須知道去哪裡、下什麼指令) Laechan -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.33.120.231 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/mud_sanc/M.1738961155.A.C61.html 補充,讀取、設定任務標記的做法 quest query laechan l013 quest: ({ "l013", 5, 0, "2023/07/01", 1688199903 }) UNDEFINED 任務編號 l013 完成了第幾步驟 5 該任務是否done 0 若是 1,該任務除非有 repeat 參數不然不能再接 任務更新標記 "2023/07/01" 任務完成時間 1688199903 這兩個也可能顛倒,反正平常用不到 在 /open/cmds/quest/quest_data/quest_data.c 裡頭 主要看 quested 函數: varargs mixed quested(string kind,string names,string quest_num,mixed vars) { switch(kind) { case "set": // 採嚴格設定法,沒有列入的參數均不准設 if((string)vars[0]=="times" && intp(vars[1])) set_quest_data(names,quest_num,qq[1],vars[1],qq[3]); else if((string)vars[0]=="steps" && intp(vars[1])) set_quest_data(names,quest_num,vars[1],qq[2],qq[3]); else return -1; case "check": // 第一種 check: 確認 names 有沒有解過 quest_num, 以及有沒有滿足解到幾次 if((string)vars[0]=="times") // 第二種 check: 確認 names 是否已經解 quest_num 解到第 n 步驟 // vars 沒給第二參數時就預設判斷有沒有解第一步驟 if((string)vars[0]=="steps") 該 quested 可用 questing 全域函數來呼叫,後面接的參數都一樣, 所以以 set 為例,語法是 questing("set","玩家id","任務編號", ({"times",1 })); // 設定任務解了幾次 ({"steps",5 })); // 設定任務已解了第幾步驟 以 check 為例,語法市 questing("check","玩家id","任務編號", ({"times",1 })); // 該任務已解次數是否為 1 ({"steps",5 })); // 該任務是否已解到第 5 步驟 check 可不需要第 2 參數,比方 questing("check","玩家id","任務編號",({"times"})); // 判斷有無解過 questing("check","玩家id","任務編號",({"steps"})); // 判斷有無完成第1步驟 以上供參,也是備忘,因為我自己很容易忘記這些東西^^; ※ 編輯: laechan (114.33.120.231 臺灣), 02/08/2025 10:08:16 我剛剛看 quested 函數,裡面有關於 msg_buf 的部份 case "msg_buf": switch(names) { case "add": if(ob=find_player(quest_num)) { if(tmp_ob=environment(ob)) { if(stringp(vars)) add_msg_buf(ob,tmp_ob,({vars})); else if(arrayp(vars)) add_msg_buf(ob,tmp_ob,vars); } } break; } break; 我原本以為這是 query msg_buf,但反正它只有 "add",或許我之後 會新增 query 的部份,理論上是 questing("msg_buf","query","任務編號",({可能第幾步驟})); 說到這個我想起我好像有寫任務對話總覽的指令 quest check_msg 腳本編號 msg 確認 j=quest_ob->query_quest_steps(); for(i=1;i<=j;i++) { if(steps>0 && steps!=i) continue; if(tmps=quest_ob->query_quest_msg(i)) 看起來就是若已讀取了 quest_ob 物件就直接取得 steps 及 msg, 反之,若不想讀 quest_ob 就以 questing 呼叫,而寫在questing 內的判斷就必須包含 steps 的可用範圍判斷。 ※ 編輯: laechan (114.33.120.231 臺灣), 02/08/2025 12:06:28

02/08 12:06, 2周前 , 1F
大概是這樣,連同上一篇,我都列入2025的發展重點
02/08 12:06, 1F

02/08 12:07, 2周前 , 2F
然後還有個東西,任務串OX,但這個我想等實作出來再寫
02/08 12:07, 2F

02/08 12:08, 2周前 , 3F
我後來想了一下說它是任務也不太對,它只是借用任務
02/08 12:08, 3F

02/08 12:08, 2周前 , 4F
的殼,至於怎麼借殼我還在研究
02/08 12:08, 4F
文章代碼(AID): #1dfd43nX (mud_sanc)
討論串 (同標題文章)
文章代碼(AID): #1dfd43nX (mud_sanc)