作者laechan (小太保)
看板mud_sanc
標題[wizs] magic_cycle_ob.c
時間Fri Aug 12 09:58:40 2011
今天將針對 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)