2011-12-03 | #1 |
高级会员
注册: 08年04月11日
来自: 盘丝洞
帖子: 311
声望力: 20
声望:
50
现金:29两梁山币
资产:1245两梁山币
致谢数: 0
获感谢文章数:0
获会员感谢数:0 |
MUDLib 攻略之 F_SKILL
作者:jjgod 发表时间:2001年6月17日 18:18 -------------------------------------------------------------------------------- 发信人: fof (格斗之迷~思考中), 信区: wiz 标 题: MUDLib 攻略之 F_SKILL 发信站: 交通大学思源BBS (Wed Nov 15 00:50:18 2000), 转信 写给对 MUDLib 感兴趣的初学者们。 F_SKILL 是一个底层物件,它以 F_ 打头,所以是放在目录 /feature 中的,以 F_ 打头的宏定义的物件都是放在目录 /feature 中,无一例外。在 /include/globals.h 这个“大头文件”中是这样定义的: #define F_SKILL "/feature/skill.c" 所以如果你无论在自己编写或修改的任何程序中只要你写下了 F_SKILL (前后连接 了其他字母数字或语法错误的除外),你的程序被 load 或 update 时 F_SKILL 这个字符串都会被 "/feature/skill.c" 代替,你写 F_SKILL->faint() 就会被 代替为 "/feature/skill.c"->faint(),当然 "/feature/skill.c" 这个程序 里是没有定义 faint() 这个函数的,高兴的话可以自己给它加一个,这里是打个 比方而已。 F_SKILL 唯一地被 CHARACTER 继承(关于继承的感念我就不在这里讲了),就是 说只有 CHARACTER 才会用的着 F_SKILL ,这个 CHARACTER 又是什么呢?还是 看看“大头文件”是怎么写的: #define CHARACTER "/std/char" character 的意思是“角色”,也就是玩家角色(Player)和非玩家角色(NPC) 喽,总不会把一只香喷喷的炸鸡腿看成角色吧。说了这么多,无非想说角色这种物 件继承了 F_SKILL ,要用到 F_SKILL 。F_SKILL 这个物件对角色来说有什么用? 思考一下:单词 feature 的意思为“特征”,放在 /feature 这个目录下的物件 都具有某方面特征,更应该说是特长吧——每个 F_ 物件都被设计来专职完成一定 的工作,F_SKILL 就是专职负责 skill 方面的工作。角色不单是有 skill 这个特 征呀!没错,CHARACTER 除了继承 F_SKILL 外还继承了很多 F_SKILL ,很多很多, 扳手指都数不过来,以后再慢慢讲其他的。 平常敲 skills 命令,比如 skills guolao ,会看到以下的内容: 张果老目前所掌握的技能有以下十二项: □八卦阵法 (baguazhen) - 平平淡淡 70/ 0/ 5041 基本轻功 (dodge) - 平淡无奇 80/ 0/ 6561 内功心法 (force) - 平平淡淡 70/ 0/ 5041 基本锤法 (hammer) - 粗通皮毛 90/ 0/ 8281 □开山锤 (kaishan-chui) - 半生不熟 100/ 0/ 10201 读书识字 (literate) - 会 元 50/ 0/ 2601 拆招卸力之法 (parry) - 平淡无奇 80/ 0/ 6561 基本法术 (spells) - 平淡无奇 80/ 0/ 6561 □太乙仙法 (taiyi) - 平淡无奇 80/ 0/ 6561 扑击格斗之技 (unarmed) - 普普通通 60/ 0/ 3721 □五行拳 (wuxing-quan) - 普普通通 60/ 0/ 3721 □镇元神功 (zhenyuan-force) - 平平淡淡 70/ 0/ 5041 这一行行一列列这么整齐,却不是 F_SKILL 的功劳,:-(,不要奇怪,打个比方 就清楚了:在以上这些显示的内容中,F_SKILL 好比是肉体,其他程序好比是衣 服,一个是内因,一个是外因……faint,扯哪去了?sorry:-)还有平常最高兴 看到的“你的「基本内功」进步了!”之类的也是 F_SKILL 的功劳。 更进一步,看看 F_SKILL 定义了哪些函数,有些什么功能: (先引用些源程序凑一下字数,请不要用西红柿砸我:-D) // 神话世界·西游记·版本4.50 <- 每个程序里面都会有这两行版本信息, /* */ <- 整齐美观,值得学习 // skill.c #include <- 包含一些头文件,先不要管 #include <- mapping skills; mapping learned; mapping skill_map; mapping skill_prepare; 这四行定义了四个 mapping 类型的全局变量,全局变量的作用除了能在整个 物件内部发挥传递参数的作用外,在物件存储中还有特殊的用处,就是物件 被 save 的时候这些全局变量会全部被存储起来,物件被 load 的时候又会 被读出来,是不是很爽? 举个例子说说这些 mapping 的数据结构,以张果老为示范: 张果老目前所掌握的技能有以下十二项: □八卦阵法 (baguazhen) - 平平淡淡 70/ 0/ 5041 基本轻功 (dodge) - 平淡无奇 80/ 0/ 6561 ............ □镇元神功 (zhenyuan-force) - 平平淡淡 70/ 0/ 5041 在 F_SKILL 中: skills = ([ "dodge" : 80, "taiyi" : 80, "literate" : 50, "zhenyuan-force" : 70, "kaishan-chui" : 100, "parry" : 80, "unarmed" : 60, "wuxing-quan" : 60, "spells" : 80, "force" : 70, "hammer" : 90, "baguazhen" : 70, ]) 注:mapping 这种数据格式的特点是小括号内包含中括号,就是这样—— ([ ]) , 里边可以有很多子项,每一项都带一个冒号,冒号左边的是子项的名字,也就是双 引号括起来的字符串——可以括很多字符,汉字也可以,冒号右边是子项的内容, 这内容的数据格式是任意的,可以是字符串、整数、数组、映射(就是 mapping 的 中文名)……简直就像目录一样——目录下面可以有文件,也可以有子目录,子目 录下面又可以有文件和子目录……只要同一级内没有相同的子项名称就行;子项与 子项之间用逗号隔开。"dodge" 就是一个子项的名称了,80 就是这个子项的内容 了,把一个 mapping 写成多行是为了好看,如果你觉得写成一行更好些,可以自 便,就像这样: skills = ([ "dodge" : 80, "taiyi" : 80, "literate" : 50, "zhenyuan-force" : 70, "kaishan-chui" : 100, "parry" : 80, "unarmed" : 60, "wuxing-quan" : 60, "spells" : 80, "force" : 70, "hammer" : 90, "baguazhen" : 70 ]) 呵呵,好看吗? 继续: learned = ([ "dodge" : 0, "taiyi" : 0, "literate" : 0, "zhenyuan-force" : 0, "kaishan-chui" : 0, "parry" : 0, "unarmed" : 0, "wuxing-quan" : 0, "spells" : 0, "force" : 0, "hammer" : 0, "baguazhen" : 0, ]) skill_map = ([ "dodge" : "baguazhen", "unarmed" : "wuxing-quan", "hammer" : "kaishan-chui", "force" : "zhenyuan-force", "spells" : "taiyi", ]) skill_prepare = ([ ]) 怎么知道这四个变量的值呢?后面有四个函数,它们的返回值就是这四个变量的 内容,看: ⑴ mapping query_skills() { return skills; } ⑵ mapping query_learned() { return learned; } ⑶ mapping query_skill_map() { return skill_map; } ⑷ mapping query_skill_prepare() { return skill_prepare; } 如果你是巫师,能使用 call 命令,就可以使 call zhang guolao->query_skills() 来获得张果老身上的 skills 变量的值了。 这一行: □八卦阵法 (baguazhen) - 平平淡淡 70/ 0/ 5041 前面的“□”和“八卦阵法”还有“平平淡淡”都不是 F_SKILL 的功劳,而是 skills 这个命令做的,这个命令的源程序在文件 /cmds/usr/skills.c 中,具体 怎么处理的可以去看看源程序。还有,后面的那个数字:5041 是 FoF 的发明, 也是写在 /cmds/usr/skills.c 中的。 继续: void set_skill(string skill, int val) { ...... } 一看就知道,这个函数设置 skill 的等级,有没有见过巫师给人 call 技能? 一个命令下去就深不可测了,hoho int delete_skill(string skill) { ...... } 这个就相反了,会删除技能,有没有试过“你决定放弃继续学习基本枪法”? 虽然你敲的是 abandon hammer 命令,但实际起作用的是这个函数 varargs void map_skill(string skill, string mapped_to) { ...... } 这个函数是把高级技能 enable 到基本技能上,敲 enable 命令就会用到它了 varargs void prepare_skill(string skill, string mapped_to) { ...... } string query_skill_mapped(string skill) { ...... } string query_skill_prepared(string skill) { ...... } 这三个函数没什么好说的 varargs int query_skill(string skill, int raw) { ...... } 这个函数跟前面的 set_skill() 函数是一对儿,一个存,一个取,但是,取的 内容不一定是存的内容,因为它多了一个 int 类型的 raw 参数,如果这个参数 被省略了,或者值是 0 ,函数返回的值是一个“有效技能”,如果是一项基本 技能,就返回该技能的等级的一半加上 map 到这个技能上的高级技能的等级之 和,例如 enable hammer kaishan-chui ,query_skill(hammer) 将得到 hammer / 2 + kaishan-chui ,如果是一项高级技能,就直接返回它的等级; 如果参数 raw 的值不为 0 ,函数返回的值也直接是该技能的等级。 在游戏中,有不少地方要检查玩家的基本技能,有些地方要检查有效技能,都 是通过这个 raw 参数灵活变通的。 (未完待续) 发信人: fof (格斗之迷~思考中), 信区: wiz 标 题: MUDLib 攻略之 F_SKILL(下) 发信站: 交通大学思源BBS (Wed Nov 15 00:52:49 2000), 转信 (承上) 下面的这两个函数是关于角色死亡所受到的技能惩罚的,以前玩家死于 NPC 之 手或非命的时候,会受到技能和道行、潜能的惩罚,所有技能减一级,好惨噢! 为了减轻玩家的痛楚,鼓励大家勇敢地西行灭妖,我决定修改这个函数。看看 修改日期,至今差不多一年喽! // FoF changed 99-12-25 int skill_death_penalty() { string *sk; int i, ii, n; object obj = this_object(); if( wizardp(obj) || !mapp(skills) ) return 0; sk = keys(skills); if( sizeof(sk) == 0 ) return 0; n = 4 - obj->query("kar") / 7; //先天福缘的影响 n = n + 10 - obj->query_kar() / 5; //后天福缘的影响 if ( sizeof(sk) > 8 ) n = n + sizeof(sk) / 3; //技能数量的影响 技能数越多,受到的惩罚也越多,对于三心二意的人来说可不是好事哟 n = n > sizeof(sk) / 2 ? n : sizeof(sk) / 2; n = random(n); 受到惩罚的技能总数小于所学技能总数的一半,不痛了吧? if( !n ) return 0; for( i = 0; i < n; i ++ ) { // 把 learned 保存起来 ii = random(sizeof(sk)); skills[sk[ii]] --; obj->add("death_skill_loss/" + sk[ii], skills[sk[ii]] * skills[sk[ii]]); if( skills[sk[ii]] <= 0 ) delete_skill(sk[ii]); } skill_map = 0; return 1; } 取得真经之后如来佛会给你三根救命毫毛,可以用来“起死回生”,恢复一些 由于被 NPC 杀死或非命所损失的道行和技能,以前铁定的是一级技能或什么都 没有,现在经过修改,恢复的与损失的是等价的。 以前的所有损失,在取得真经之后得到恢复,高兴么? // FoF changed 99-12-25 int skill_death_recover() { string *sk; object obj; int i, amount; if( !mapp(skills) ) return 0; sk = keys(skills); obj = this_object(); for( i = 0; i < sizeof(sk); i ++ ) { amount = obj->query("death_skill_loss/" + sk[i]); amount += learned[sk[i]]; while ( amount >= ( skills[sk[i]] + 1 ) * ( skills[sk[i]] + 1 ) ) { // 把 learned 恢复成技能 amount -= ( skills[sk[i]] + 1 ) * ( skills[sk[i]] + 1 ); skills[sk[i]] ++; // 把损失的 learned 恢复成技能 } learned[sk[i]] = amount; } obj->delete("death_skill_loss"); return 1; } 以下这个函数是管角色技能升级的,当你敲了若干个 learn force from master 之后看到“你的「基本内功」进步了!”就是这个函数的功劳了。 升级的条件是技能的 learned 点数要超过(当前等级+1)的平方值。这里有 一个小细节,就是 int 型的参数 weak_mode ,这个参数的值不为 0 ,将会 导致即使技能的 learned 点数超过了(当前等级+1)的平方值,也不能看到 “你的「基本内功」进步了!”,而且该项技能会显示出特殊的颜色,参数 weak_mode 不为 0 的情形还不少呢:跟师父切磋、使用外功(exert)、 perform、practice、study 等情况下都有可能出现 weak_mode 不为 0 的情形, 所以看到技能的 learned 点数超过了(当前等级+1)的平方值还不升级的时 候不要奇怪。 varargs void improve_skill(string skill, int amount, int weak_mode) { int spi; if( !find_object(SKILL_D(skill)) && file_size(SKILL_D(skill) + ".c") < 0 ) error("F_SKILL: 没有这种技能(" + skill + ")!\n"); if( !weak_mode || !userp(this_object()) ) { if( !mapp(skills) ) skills = ([]); if( undefinedp(skills[skill]) ) skills[skill] = 0; } // Give learning penalty to those learning too much skills. spi = query("spi"); if( sizeof(learned) > spi ) amount /= sizeof(learned) - spi; if( !amount ) amount = 0; if( !mapp(learned) ) learned = ([ skill : amount ]); else (int)learned[skill] += amount; if( (!weak_mode || !userp(this_object())) && learned[skill] > (skills[skill] + 1) * (skills[skill] + 1) ) { skills[skill] ++; learned[skill] = 0; tell_object(this_object(), HIC "你的「" + to_chinese(skill) + "」进步了!\n" NOR); SKILL_D(skill)->skill_improved(this_object()); } } 下面这个函数是我增加的,目的是通过以内存换速度的办法来减轻战斗精灵 COMBAT_D 的负担。当时想的是用战斗升级法来替代传统的“鸡腿升级法” (就是用鸡腿打潜能来学其他技能)为 MUD 的合理化作点贡献,效果不是 很好,不过 Acool 说他曾在战斗中把 dodge 提升到七十多级而没有花任何 潜能向师父学,还有人说跟芭蕉怪打把 whip 打到了近百级的事,真是意料 之中,又是意料之外了。 不足之处请多提宝贵意见!MUD 合理化之事业无限荣光! // FoF 99-12-28 to reduce work for COMBAT_D void reset_skill_improve_point() { int amount; object ob = this_object(); if( !userp(ob) ) return; amount = random(ob->query_int()/10) + ob->query_int()/10 + random(ob->query_con()/8) + ob->query_con()/8; set_temp("combat/skill_improve_point/dodge", amount); // 9 - 18 points 一次成功躲开敌人攻击使 dodge 增长的点数,当然这个“成功”包含了强弱对比 的关系。dodge 的增长与悟性和根骨两个属性相关。 amount = random(ob->query_int()/10) + ob->query_int()/10 + random(ob->query_con()/8) + ob->query_con()/8; if( !undefinedp(skills) && !undefinedp(skills["dodge"]) ) amount += random(skills["dodge"]/20); set_temp("combat/skill_improve_point/map_dodge", amount); // 14 - 23 points map 到 dodge 上的技能即高级轻功增长的点数,除了与悟性和根骨相关外,还 与 dodge 的等级相关。 amount = random(ob->query_cps()/4) + ob->query_cps()/4; set_temp("combat/skill_improve_point/parry", amount); // 10 - 20 points 一次成功招架敌人攻击使 parry 增长的点数,当然这个“成功”也包含了强弱 对比的关系。parry 的增长与定力相关。 amount = random(ob->query_cps()/4) + ob->query_cps()/4; if( !undefinedp(skills) && !undefinedp(skills["parry"]) ) amount += random(skills["parry"]/20); set_temp("combat/skill_improve_point/map_parry", amount); // 15 - 25 points map 到 parry 上的技能增长的点数,除了与定力相关外,还与 parry 的等级 相关。 amount = random(ob->query_int()/8) + ob->query_int()/ 8 + random(ob->query_con()/5) + ob->query_con()/5; set_temp("combat/skill_improve_point/attack", amount); // 13 - 26 points 一次成功击中敌人使基本攻击技能增长的点数,当然这个“成功”也包含了强弱 对比的关系。攻击技能的增长与悟性和根骨属性相关。 amount = random(ob->query_int()/8) + ob->query_int()/8 + random(ob->query_con()/5) + ob->query_con()/5; // amount += random(ob->query_skill(skill_type, 1)/20); set_temp("combat/skill_improve_point/map_attack", amount); // 13 - 26 points map 到基本攻击技能上的高级攻击技能增长的点数,除了与悟性和根骨相关外, 还与基本攻击技能的等级相关。 } F_SKILL ENDS 看到这里,你知道角色身上有关 skill 的数据都有哪些,以及它们是怎么操作 的了吗? |
|
添加到书签 |
|
|
相似的主题 | ||||
主题 | 主题作者 | 论坛 | 回复 | 最后发表 |
mudlib加密之 MUDOS 修改篇 | Odysseus | 『 巫师天下 』 | 0 | 2011-12-03 23:25 |
关于mudlib安全性的考虑 | Odysseus | 『 巫师天下 』 | 0 | 2011-12-03 23:10 |
MudLib是什么? | Odysseus | 『 巫师天下 』 | 0 | 2011-12-03 22:31 |
MUDLIB各个目录是干什么的? | Odysseus | 『 巫师天下 』 | 0 | 2011-12-03 22:25 |
风云三MUDLIB包含自毁灭程序 | Odysseus | 『 巫师天下 』 | 0 | 2011-12-03 22:16 |