作者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)
1F:推 justinj :了解.... 08/12 10:28
2F:→ laechan :测试时开两个法师(其中一个能张设Lv1),然後不同时间 08/12 10:30
3F:→ laechan :施展 spells,看魔法阵ob 的 heart_beat能否正常执行 08/12 10:30
4F:推 justinj :可以同时执行了...不过之前有设定的show变成自已看到 08/12 10:34
5F:→ laechan :你指哪一部份? 08/12 10:34
6F:→ 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 的设定,都先打开讯息接收。
7F:→ justinj :刚刚看到另一个bug...放魔法阵时人移动就没下文了 08/12 10:36
8F:推 justinj :不过快速移回来还是有的....来看一下按spells移动.. 08/12 10:39
9F:推 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;
}
这里就会判断你人在不在,不在的话就不会有熟练度。
10F:推 justinj :没魔力还是可以硬放spells,有熟练度的... 08/12 10:53
因为没有做 if(sp < k) 的判断,已补上。
if(sp<k)
return notify_fail("spells: 你的 sp 剩余值已经无法让你继续练习了喔.\n");
11F:推 justinj :然後"因张设者不在而消失了。"这句在人在那格但因sp 08/12 11:04
12F:→ justinj :了时来看就怪怪的...应该多加个施法者没魔力.. 08/12 11:05
13F:→ justinj :没了.. 08/12 11:05
再观察看看。
另外,纪录一下取得的熟练度,然後你也可以对熟练度公式
或其它数值公式做个建议。
Laechan
※ 编辑: laechan 来自: 117.19.98.233 (08/12 11:27)