作者laechan (小太保)
看板mud
标题[分享] 用一个字串处理所有任务标记
时间Thu Jun 14 16:17:21 2012
假设某游戏有 100 个任务,那可以简单用一个字串来代表
"111111101110110100010101100100100001010001000......"
为此我们必须先定义一个 array 类似底下
string *quests=({
"与村里的人们打招呼",
"猎杀20只怪物",
.
.
});
则上面字串的第一个字元"1"就代表玩家已完成「与村里的
人们打招呼」的这项任务(或成就)。
则我们需要几个函数来处理,底下就简单以 set_quest 为
例,ppl 代表玩家,quest_name 代表任务名称,quest 为
存在玩家 ppl 身上的标记(ppl->query("quest"))
void set_quest(object ppl,string quest_name)
{
int i,s;
string tmp,new_tmp;
// 先依 quest_name 找出是第几个任务
i = member_array(quest_name,quests);
if(i==-1) return 0;
// 读取玩家身上的 quest 标记
tmp = ppl->query("quest");
// 1.先判断该字串的长度, 若长度较小要补 0
// 例如原先字串是 "1001" 而现在所解的是第 8 个任务
// 则 "1001" 要先变成 "10010000"
s=strlen(tmp);
if(s<i+1)
while(s++<=i)
tmp+="0";
// 2.再将这个任务标记设进去
if(tmp[i..i]=="0")
new_tmp=tmp[0..i-1]+"1";
}
而 check 的方法也很简单
int check_quest(object ppl,string quest_name)
{
int i;
string tmp;
// 一样是先依 quest_name 找出是第几个任务
i = member_array(quest_name,quests);
if(i == -1) return -1;
// 然後一样读取玩家身上的 quest 标记
tmp = ppl->query("quest");
// 然後先判断玩家没解过这个任务的情况
// 首先字串长度小於 i+1 的情况肯定没解过
if(strlen(tmp)<i+1)
return 0;
// 再来就是 tmp[i..i] = 0 的情况也是没解过
if(tmp[i..i]=="0") return 0;
// 能来到这里自然就是有解过啦
return 1;
}
至於 list_quest 则如下..
void list_quest(object ppl)
{
string tmp,str="任务的已解/未解列表:\==============================\n";
int sp,sq,i;
tmp=ppl->query("quest");
sp = strlen(tmp);
sq = sizeof(quests);
for(i=0;i<sq;i++)
{
if(i<=sp)
{
if(tmp[i..i]=="1")
str+=sprintf("%-20s 已解\n",quests[i]);
else
str+=sprintf("%-20s 未解\n",quests[i]);
}
else
str+=sprintf("%-20s 未解\n",quests[i]);
}
str+="==============================\n");
write(str);
}
这麽做有以下几个好处..
一、用一个字串就解决所有任务的标记。
二、字串长度 100 看似很长,不过跟玩家 data 档案大小比起来
其实还好。
三、wiz 可以制作方便的工具
foreach(ppl in users())
write(ppl->query("name")+" "+ppl->query("quest")+"\n");
马上能列出线上玩家的 quest 字串,就能做即时的简易比对
,如下..
laechan 1110010100101010101010101010
norr 11001010101010101000010010010001010
highelf 10001010100101001000101010
. ^ ^ ^ <- 这三人都有解过的任务
.
四、它一样可以做前置任务的判断
例如要解第 i 个任务,需要先解第 x 个任务跟第 y 个任务
,那只需要判断 tmp[x..x]==1 && tmp[y..y]==1 即可,在前
置任务的判断上相当地简易。
一点心得,分享给各位。
Laechan
--
※ 发信站: 批踢踢实业坊(ptt.cc)
※ 编辑: laechan 来自: 210.61.157.53 (06/14 16:17)
1F:推 eplis:强烈建议变数命名要有意义且初始化 06/14 16:58
2F:→ eplis:其实也可以用两个字串,一个代表解过一个未解过 06/14 16:59
3F:→ eplis:每个任务有唯一的qid,不是让开发者更容易辨识吗 06/14 16:59
4F:→ eplis:一堆1001010感觉不方便看是哪一个任务 06/14 17:00
5F:→ eplis:若是要用一个字串,我会建议用map之类的方式来做而不是array 06/14 17:02
这是以节省储存空间为考量,以这种方式要新增新的任务
也方便,quests 多添加一个元素,函数即会自动替玩家的
quest 参数初始化(在呼叫到 set_quest 时)。
基本原则是
1.每个任务的阵列顺序是确定的
2.但是每个任务的相对顺序是可以自订的
3.任务标记平常「其实一点用也没有就只是储存用而已」
,因此只需要在用到时(例如在做 list 时)呼叫出来处
理即可. 就算是 111010101010101 只要呼叫专门处理函
数即可马上处理成为看得懂的资料.
※ 编辑: laechan 来自: 122.117.11.103 (06/14 18:29)