作者laechan (小太保)
看板mud_sanc
标题[wizs] quest 脚本新增 next 参数流程
时间Thu Jan 17 13:06:18 2013
laechan 希望我有空时可以写一个 quest 脚本新增参数的
流程,所以我以新增 next 参数为范例。
> quest query laechan l008
quest: ({ "l008", 1, 0, "2012/12/24" })
UNDEFINED
目前 quest 资料用了 4 个栏位,因此 next 使用第 5 个
栏位,并做弹性判断。
底下讲解修改流程供 wiz 参考。
一、/cmds/std/_quest.c 指令先做备份
二、找到 quest read 的程式段落
// finished 2011/09/28
if(sscanf(str,"read %s",term)==1)
因为 next 接的数值是整数,就找同样是整数的段落
else if(t1=="steps" || t1=="times" || ...
补上 || t1=="next") 即可。
这样 quest read 时就会在 脚本.c 档补上这一行
quest_data["next"]=xxxx; // 代表经过几秒可再接一次
三、因为 next 是「经过几秒可再接一次」,所以合理的
想法,就是当玩家「完成该任务」时,判断脚本是否
有 next 参数,有的话就在 quest data 补上第五个
数值,该数值 = 「任务完成时间 + next 值」。
然後,因为玩家先前没这个参数,所以假设该任务是
可重覆接的,在玩家重新接该任务时..
if(size>4 && data[4]>time())
不能接该任务;
通过上述判断就代表可接。
因此先找 _quest.c 里面完成任务的段落..
tmp=quest_ob->query_quest_date();
// 2.然後就马上设定玩家已解过该步骤
// 但是若有 repeat 参数就不做任何变更(可重覆第 s1 步骤)
if((int)quest_ob->query_quest_repeat()!=s1)
{
if(s1>=ss)
{
quest_data_ob->set_quest_data(t1,qstr,0,tt+1,tmp);
上面的意思就是说,如果s1(目前解到第几步骤) >= ss(该
任务设定的步骤值 steps),意思就是如果已经解到最後一
个步骤了,就做:
┌完成次数值+1
↓
quest_data_ob->set_quest_data(t1,qstr,0 ,tt+1,tmp);
↑
└步骤值归 0
所以简易的做法就是将 quest_data_ob 的 set_quest_data
函数宣告为 varargs,在 quest_ob 新增 query_quest_next()
函数,然後宣告 next_value:
next_value=(int)quest_ob->query_quest_next();
再做底下的动作..
if(next_value > 0)
quest_data_ob->set_quest_data(t1,qstr,0 ,tt+1,tmp,next_value);
else
quest_data_ob->set_quest_data(t1,qstr,0 ,tt+1,tmp);
让 set_quest_data 函数判断有无 next_value 值。
_quest.c 指令可先做上述修改,改完先放着。
四、修改 /open/cmds/quest/quest_d.c
因为只是新增函数所以可以不备份修改。
找到底下程式段
// 回传该 quest 的 steps 设定
int query_quest_steps();
在它底下新增两行
再找到 query_quest_steps 函数区,复制它,新增一
个 query_quest_next 函数。
int query_quest_next()
{ return (int)quest_data["next"]; }
改完後一样先放着。
五、修改 /open/cmds/quest/quest_data/quest_data.c
找到 set_quest_data 函数,将其修改为底下..
varargs void set_quest_data(string names,string quest_num,string steps,
int times,string dates,int next_value)
{
object ob;
if(!catch(ob=find_object_or_load(__DIR__+"quest_data_"+names[0..0])))
ob->set_quest_data(names,quest_num,steps,times,dates,next_value);
}
改完一样先放着。
六、修改 /open/cmds/quest/quest_data/sample.c
这个档就是各 quest_data_X.c 继承的共通档,也是
set_quest_data 的实际作用函数所在物件。
一样找到 set_quest_data 如上面做法,将其宣告为
varargs 并补上 next_value
函数分两部份,一部份是读现存的纪录去改值,一部
份是新增一条纪录串存进去,两部份都要改..
tmps[i]=({quest_num,steps,times,dates,time()+next_value});
tmps+=({ ({quest_num,steps,times,dates, time()+next_value }) });
改完後 update sample.c 确定可 update 过,就可把
所有的 quest_data_X.c 也全部 update
(/open/cmds/quest/quest_data/tmp 档有 macro,
复制贴上即可)
然後再 update -R quest_data.c 及 quest_d.c
七、接着再回头改 _quest.c
这次要改的就是玩家接该任务时必须判断是否有 next
参数存在。
做法就是,我们知道每个 quest 都会优先判断是否有
stepX_check 的存在,而 next 的判断会「更优先於」
stepX_check,因此先找 stepX_check
tt=(int)tmps[2];
// 1.先执行 timeX_check 判断然後才执行 stepX_check 判断
if(s1>=ss && function_exists("time"+(tt+1)+"_check",quest_ob) &&
call_other(quest_ob,"time"+(tt+1)+"_check",me,mob,key)>0)
return notify_fail("");
else if(function_exists("step"+s1+"_check",quest_ob) &&
call_other(quest_ob,"step"+s1+"_check",me,mob,key)>0)
return notify_fail("");
在这一段上面补上底下的东西即可
next_value=(int)quest_ob->query_quest_next();
if(next_value>0)
if(sizeof(tmps)>4)
if((int)tmps[4]>time())
return notify_fail("quest: 你要再过 "+((int)tmps[4]-time())+
" 秒才能再接这个任务喔!\n");
这意思就是说,若玩家该 quest_data 没有第五个参数,
就不做 next 判断;若有第五个参数,就看该参数的值是
否比 time() 大,大的话代表还在 CD 时间。
改完後 update _quest.c 即可。
八、最後就是 reload 所有的 quest_ob。
quest reload 物件重载
这样即可完成新增 next 参数的所有工作。
这样做的好处,就是让 _quest.c 主管任务进行的相关流程判
断,让 quest_ob 负责做为任务脚本的各参数读取,然後再让
quest_data_ob 去做玩家任务资料的读取及储存。
如此一来,当我们在脚本新增一个参数时,我们就知道..
_quest.c 修改对应的相关的读取及判断
quest_ob 新增该参数的读取函数
quest_data_ob 新增该参数的读值及储存
而且通常新增参数是不需要去动 quest_data_ob 的,这次是
因为 next 参数必须被存进玩家的任务资料里才需要动到。
quest 系统并不复杂,只是要先了解它是分成上述三个部份,
以及每个部份主要负责做什麽事情,这样就足够了。
以上有问题可发问。
belldandys.
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 210.61.157.53