看板 mud_sanc 關於我們 聯絡資訊
今天將針對 justin 反映的問題做修正,底下重點部份我會標 上顏色。 位於 can_use({}) 名單內的人 cast magic-cycle.1 時 #define MAX_LV 1 if(!wizardp(ppl)) { if(lv>=MAX_LV && !wizardp(ppl) && member_array(ppl->query("name"),can_use)==-1) { return (int)call_other("/d/spell/magic-cycle2.c","start_skill",tar,lv); } ^^^^^^^^^^^^^^原先的魔法陣 // 會略過上面的判斷往下走 再施放間隔時間設定 sp=30; // 基本 30 秒 // 這個公式的意思是 // 1.runes最高以9900判別, magic-heart最高也是以9900判別(每50算一個class) // magic-cycle最高以1000判斷(每100算一個class) // 所以假設其中一個滿, 就會出現 sp*0 = 0 的情況即無施放間隔 // 2.最大值則是 9900 x 198 x 10 = 19602000, 這即是分母值 // 3.假設 runes 5000, magic-heart 5000, magic-cycle 500 // sp = 30 x 4900 x 98 x 5 / 19602000 = 3.67 → 3 or 4 秒 sp=(sp*(9900-(int)ppl->query("skill/runes"))*(198-sk/50)* (10-(int)ppl->query("skill/magic-cycle")/100))/19602000; if(ppl->query("adv_guild")) // 進階職業再施放間隔均減半 sp=1+sp/2; // 但即使 sp 是 0 還是得設 ppl->set_temp("time_record/magiccycle_times",sp+t); 張設所需時間設定 // 大魔導士無條件張設時間為 1 if((string)ppl->query("adv_guild")=="magemaster") t=1; // 秘印賢者無條件張設時間為 2 else if((string)ppl->query("adv_guild")=="sage") t=2; else { t=1+lv; // 越高等的魔法陣耗費的時間越多, Lv1 基本 2 秒 if(ppl->query("skill/magic heart")<5000) // 魔力操控術未達 5000 t=t+1; if(ppl->query("skill/runes")<5000) // 戎文未達 5000 t=t+1; if(ppl->query("stat/mag")<5000) // 魔力未達 5000 t=t+1; if((string)ppl->query_wp_type()!="wand") // 沒有拿杖 t=t+1; } } else t=1; // wiz 都是 1 秒張設 張設訊息 這部份沒有實作,舉例的話如下.. 舞吧!眾多的岩礪們,遵從我們過去、現在、未來三女神的盟約,  為我們張設出巨大的魔法陣吧! (然後n秒後才張設成功)  大魔導士的則類似底下  只見小太保輕彈了一下手指,地面上隨即浮現了巨大的魔法陣! (1秒就張設成功) 魔法陣的共設 #define MAGIC_CYCLE_NAMES ({\ "=== 攻擊法術練習魔法陣 ===",\ }) ob=clone_object(__DIR__+"magic-cycle_ob"); // 先召喚 ob->set("who_clone",ppl); // 設定召喚者(物件) ob->set("dest_times",(15-t)*60+time()); // 設定消失時間( time()+n ) ob->set("level",lv); // 設定張設等級 ob->set_living_name("magic_cycle_lv"+lv); // 設定魔法陣living_name(加lv) ob->set("id",({"magic_cycle_lv"+lv})); // 設定魔法陣 id(加lv) ob->set_name(MAGIC_CYCLE_NAMES[lv-1]); // 設定魔法陣名稱 ob->create(); // 然後才呼叫 create 初始化 魔法陣 Lv1 str="主職法師的玩家可在這個魔法陣內練習攻擊法術,指令是 spells。\n"; ob->set("long",str); // 設定魔法陣的 long(look 魔法陣時看的) ob->move(env); // 將魔法陣移到 env(所以不能在 recall 處召喚) ob->set_heart_beat(1); // 啟動魔法陣心跳 obs=all_inventory(env); // 抓取該房間的所有物件 str=ppl->query("chi_name")+"以純熟的魔力召喚出了一道 Lv.1 的魔法陣.\n"+str; obs-=({ppl}); // 扣掉自己 foreach(ob2 in obs) { // 只有主職為法師的玩家才看的到(因為這是給主職練習用的) if(ob2 && userp(ob2) && (string)ob2->query("pri_guild")=="mage") { // 將該玩家加進可練習的名單(也就是只有在魔法陣張設時在房間的玩家才能練) obs2+=({ob2->query("name")}); tell_object(ob2,str); // 只有此時在房間、且主職是 mage 的人才看的到 } } // 底下把施展者也加進來 write(ppl->query("sex_name")+"以純熟的魔力召喚出了一道 Lv.1 的魔法陣.\n"+ str); obs+=({ppl}); // 然後設定只有誰才能 spells ob->set("who_can_spells",obs2); spells 設定部份 只有誰才能 spells delay_calls=(mixed)query("who_can_spells"); if(ppl!=(object)query("who_clone") && // 施展者預設一定可以 member_array(ppl->query("name"),delay_calls)==-1) return notify_fail("spells: 你不在被允許\的可練習名單內喔.\n"); spells 施展前限制 if((string)ppl->query("pri_guild")!="mage") return notify_fail("spells: 你必須是主職法師才能使用這個指令喔.\n"); if(ppl->query_temp("casting")>0) return notify_fail("spells: 你要等一會兒喔.\n"); t=time(); if(ppl->query_temp("time_record/magic_cycle_lv1_times")>t) return notify_fail("spells: 你要等一會兒喔.\n"); if(ppl->query_attackers()) return notify_fail("spells: 你不能在戰鬥中喔.\n"); // 施展語法 if(sscanf(str,"%d %s",num,sname)==2); else return notify_fail("語法: spells 連擊數 法術名稱.\n"); // 目前只有六大法術供 spells 練習 if(sname!="fire" && sname!="ice" && sname!="thunder" && sname!="wind" && sname!="earth" && sname!="light") return notify_fail("請下 spells 指令觀看使用說明喔.\n"); if(ppl->query("skill/"+sname)<100) return notify_fail("spells: 你的 "+sname+" 技能值至少要有 100 喔.\n"); if(num<1 || num>99) return notify_fail("spells: 你一次只能擊出 1~99 發的法術喔.\n"); // 暫定的公式(因為這個條件低了點) if(num>(int)ppl->query("stat/mag")/10) return notify_fail("spells: 你最多一次只能擊出 "+ (int)ppl->query("stat/mag")/10+" 發的法術喔.\n"); if(!ppl->query_temp("magic heart")) return notify_fail("spells: 你在練習法術的時候必須先 heart magic 喔.\n"); 計算 spells 的 sp 消耗量以及再施展時間 sp=ppl->query("sp"); k=ppl->query("skill/magic heart"); // magic heart 達 5000 就承認為最大值(最大節省判斷) if(k>5000) k=5000; k=k/50; // num = 玩家指定的連擊數, 連擊數越高, 消耗以平方計 // k x num^2 為基本消耗值, magic heart 達 5000 時可減少一半消耗 k=1+k*num*num*(200-k)/200; // 過度消耗法力的情況 // 這個就是紅線區設定, 消耗值大於玩家剩餘sp的 110% if(k>(sp*11)/10) { k=40; // 強制將再施展時間設為 40 秒 ppl->set("sp",1); // 強制將玩家的 sp 設為 1 } // 這個就是黃線區設定, 即消耗值雖然 > 剩餘sp值 但還不算過份 else if(k>sp) { k=15; // 強制將再施展時間設為 15 秒 ppl->set("sp",1); // 強制將玩家的 sp 設為 1 } // 這個就是綠線區設定, 指定的連擊數在安全範圍內 else { ppl->add("sp",-k);// 扣掉該扣的 sp 值(這行忘記加,已補上) k=3+num/10; // 因為 num 最大 99,所以 k = 3 + 99/10 約 12~13 秒 } // spells 期間禁止施展其它特攻 ppl->set_temp("casting",k); ppl->set_temp("time_record/magic_cycle_lv1_times",k+tt); 理論上黃線區的效益最好, *11/10 的部份也應可再往上調成像 *13/10 這樣. 這裡亦發現了一個錯誤,上面我有用 delay_calls 暫存 who_can_spells, 結果用完後我沒有將它初始化,這個 bug 也已修正。 if(query("delay_calls/"+tt)) delay_calls=(mixed)query("delay_calls/"+tt); else delay_calls=({}); delay_calls+=({ ({"show_start_spells_msg",ppl}) }); set("delay_calls/"+tt,delay_calls); spells 的第一階段訊息排程設定 if(!catch(spell=find_object_or_load("/d/spell/"+str))) { tt=tt+1; delay_calls=({}); if(query("delay_calls/"+tt)) delay_calls=(mixed)query("delay_calls/"+tt); delay_calls+=({ ({"call_start_skill",spell, // 模擬呼叫 start_skill (int)ppl->query("skill/"+sname)/100,ppl}) }); set("delay_calls/"+tt,delay_calls); } spells 的第二階段訊息排程設定 delay_calls=({}); if(query("delay_calls/"+tt)) delay_calls=(mixed)query("delay_calls/"+tt); delay_calls+=({ ({"show_spells_msg", // 對著天空大喊:N 發 XXXX ! ppl,skill_name(sname),num}) }); set("delay_calls/"+tt,delay_calls); spells 的第三階段訊息排程設定 delay_calls=({}); if(query("delay_calls/"+tt)) delay_calls=(mixed)query("delay_calls/"+tt); delay_calls+=({ ({"magic_cycle_lv1", // 擊中魔法陣後的訊息 ppl,sname,ppl->query("skill/"+sname),num}) }); set("delay_calls/"+tt,delay_calls); 原本最初始還有一個階段就是『魔法啟動關鍵語』,例如  小太保:『拉斯‧泰爾‧瑪‧斯吉爾‧馬吉斯泰爾!』 這部份先略過(因為它不是重點)。 施展者因 spells 練習者(包括自己)的魔法擊中障壁而耗損的 sp 值 // 魔法陣張設者會消耗的 sp = 連擊數 x 玩家練習的法術的技能值 / 10 // 比方 99 x 1000 / 10 = 9900 who_clone->add("sp",-(num*sk)/10); 練習者會得到的熟練度 // 熟練度 = 1 + (連擊數平方)/10 + random(連擊數) // 這意思基本上是你給的連擊數越高越好 // 但是你給的連擊數太高有可能就會讓你跨到紅線區 // 這是一種牽制型設定 num=1+(num*num)/10+random(num); ppl->improve_skill(sname,num); 原本熟練度增加的程式段我是 // 掉的,已實裝。 做了一些 bug 修正,justin 你可以再 try try。 Laechan -- ※ 發信站: 批踢踢實業坊(ptt.cc) ※ 編輯: laechan 來自: 117.19.98.233 (08/12 10:06)
justinj :了解.... 08/12 10:28
laechan :測試時開兩個法師(其中一個能張設Lv1),然後不同時間 08/12 10:30
laechan :施展 spells,看魔法陣ob 的 heart_beat能否正常執行 08/12 10:30
justinj :可以同時執行了...不過之前有設定的show變成自已看到 08/12 10:34
laechan :你指哪一部份? 08/12 10:34
justinj :spells 99 fire只能自己看到.... 08/12 10:36
void show_spells_msg(object ppl,string names,int num) { show(ppl,this_object(),"\n$N對著天空大喊:"HIW+num+ " 發 "HIW+names+HIW" !!"NOR"\n"); } 我自己試的結果是我可以看到其它人的 spells 訊息,那因為 它是呼叫 show 去處理,你可以檢查一下 no_environment_msg 及 no_damage_msg 的設定,都先打開訊息接收。
justinj :剛剛看到另一個bug...放魔法陣時人移動就沒下文了 08/12 10:36
justinj :不過快速移回來還是有的....來看一下按spells移動.. 08/12 10:39
justinj :果然只要按cast或spells移動就沒下文了....來看別的. 08/12 10:42
heart_beat() { . . case "show_spells_msg": // 執行 n 連擊那裡 if(tmps2[1] && environment(tmps2[1])==env) show_spells_msg(tmps2[1],tmps2[2],tmps2[3]); break; } 快速移回可以再看到的原因,是因為 heart_beat 是週期呼叫, 你在週期時間內來回就不會受影響,如果剛好在它執行排程時你 剛好離開,那就看不到訊息。 但即使看不到訊息它還是會執行到排程結束,單一人的排程結束 時會呼叫最終函數 magic_cycle_lv1, 這時它會判斷.. magic_cycle_lv1() { . . if(!ppl) return 1; if(environment(ppl) != environment(this_object())) return 1; } 這裡就會判斷你人在不在,不在的話就不會有熟練度。
justinj :沒魔力還是可以硬放spells,有熟練度的... 08/12 10:53
因為沒有做 if(sp < k) 的判斷,已補上。 if(sp<k) return notify_fail("spells: 你的 sp 剩餘值已經無法讓你繼續練習了喔.\n");
justinj :然後"因張設者不在而消失了。"這句在人在那格但因sp 08/12 11:04
justinj :了時來看就怪怪的...應該多加個施法者沒魔力.. 08/12 11:05
justinj :沒了.. 08/12 11:05
再觀察看看。 另外,紀錄一下取得的熟練度,然後你也可以對熟練度公式 或其它數值公式做個建議。 Laechan ※ 編輯: laechan 來自: 117.19.98.233 (08/12 11:27)