背景:
阅读文章

关于last_damage_from

[日期:2007-05-06] 来源:llm 发表时间:2001年7月11日 10:31   作者: [字体: ]

      这个问题实质上就是判断"凶手"的问题。呵呵,在现实中,这也是一个很棘手的问题,有推理还得有刑侦手段。那么在一个MUD里,如何判断一个杀人凶手呢?
    从ES2设计的结构来看是这样进行的。ES2假定了每一次的死亡都是由于战斗原因导致的。既然是战斗,那么到底是谁在最后击中被害人,那么这个凶手不就是出手的这个人了么?于是,我们可以看到:在COMBAT_D里的,只要计算后A打中B,并对B造成了伤害,并不是简单地直接减精减气,而是通过F_DAMAGE里的receive_damage()等几个函数来实现的。这里就要注意了,receive_damage()等等这几个函数都有一个第三个参数,伤害者。只有有了这个伤害者,被伤害者B身上才会有last_damage_from--A的ID。


    然后在die()的函数里,会寻找这个伤害者,只有这个伤害者在的情况下,系统才会认定有凶手,那么有凶手才是正常死亡。是正常死亡才会调用COMBAT_D里的kill_reward()函数,那么有关对死者的减值等等处理才会正常进行。

    ES2的这种设计思路太简单与绝对化了,带来了很多问题。加上不规范的编程设计方面:我不知道原作者为什么把象receive_damage()这样的函数设成参数不定状态。这样许多的新巫师在不明就理的情况下,往往会省略掉第三个参数。比如在许多的perform的伤害中,这样的情况比比皆是。所以这种情况致死的时候往往都不会准确地记录最后一次伤害者。如果之前的记录下的last_damage_from与后者一致的话还好说。不一致的话则问
题多多。其主要表现为下列:
    首先玩家可以利用这种不调用减武功减经验的的所谓"假死"来牟利。象丐帮的天魔解体、星宿的地狱炼刹。还有利用一些采用condition来控制时间的要药要钱等也会在这个漏洞出现金钱等等方面的BUG。
    其次可以利用这个方面的陷害别的玩家增加PK数。比如先向玩家攻击,即使这个玩家很小心地halt了,但只要被其击中一下哪怕只是很轻的伤,这就已经记录上了last_damage_from,然后此人就可以找一个不会记录第三个参数的减气伤害的地方直接伤害致死。OK,系统找到了last_damage_from,好那个无幸的玩家就成了杀人犯。
    三是造成混乱,大家比了一次武也许都记录上了last_damage_from,突然因其它原因致死,谣言出现:叮当被胖胖杀死了。真是莫名其妙。

    还有一个小问题就是:ES2对last_damage_from是采用的记录killer的ID,而我后来则是决定采用的是记录object.当然两者各有利弊。只是前者会产生误判,比如ID相同的玩家与NPC。同时也会有少量的漏判。比如,killer在伤害后与死亡前这段时间quit了并短时间内不上线。而后者只会有上述的漏判,却不会有错判。于是综合比较我改成了
object型.

    经过一段时间的摸索。我首先确立了一个思想中心:完全准确并毫无差错地判断"凶手"的想法是不切实际也是不可能的。就算是在MUD里的死亡也是千变万化的。战斗死亡只是一种,还有中毒,中机关,跳崖等等。我要努力的方向是"不错判"。系统找不出凶手的死亡应该是客观存在的。
    其次去除掉一些不应该死亡的漏洞。比如象打坐吐呐炼剑这些直接add("qi",-**)的地方,就不应该致死。凡是直接减精减气的地方前面都要加上判断。如果一次减20,那么在前一步不大于20就不应该执行下一步。在这样的情况下我们基本可以认定:再出现的死亡原则上都应该是正常的死亡。既然是正常的死亡,那么不管我们有没有记录到
last_damge_from,都应该是执行COMBAT_D的kill_reward()
    第三,凡是在具体文件里用到类似receive_damage()这些函数的必须要加上第三个参数。凡是在具体文件里直接调用玩家的die()时之前必须要加上对于last_damage_from的设定。指定那个凶手。关于下毒的condition里也得加上施毒的记录。
    第四,在此情况下可能还会有漏网的。比如下了毒后便quit的玩家与消失的NPC。比如又有新巫师新写了忘记加伤害者参数的新文件。因此,最关键的一步就是die()判断了找不到last_damage_from这个killer,那么我们就要强制指定一个,指定什么好呢?还是指定死者die()时所处的房间。(注意这里还要判断一下。如果死者死之前呆在另一个生物身上,则要循环找到房间),一方面我们至少到记下他死亡的地点。这样,我们就可以正常地调用kill_reward(),至多在这种死亡方式上加一个特殊的信息:
叮当很意外地死亡了。
    这种意外的死亡。较多地会出现在中毒导致的。会有很多人在毒发了半个多小时之后,没有有效地疗伤手段了便OVER了。那么死亡的这时候,先前下毒的某人在不在线是很成问题的。但是我们可以这样理解,假设在现实中,我在甲地中了某人的毒,过了很长时间在乙地死亡,是否能查清是死于甲手是很难保证的。假设甲一直在线,没有重新连线过,那自然能判断出来。但若不在线了或者重新进来了,原先记录的object自然
消失了。那么标为意外地死亡也是一种很正常的现象。
    从观念上来说:不应该有"真死"与"假死"的区分。死就是一种。

    以上看法请指正。

--------------------------------------------------------------------------------
作者:Super  发表时间:2001年7月11日 23:16

我的看法与阁下不太一样。。
last_damage_from 所记录的是 *受害者* 最后一次被伤害的伤害人的ID。
而这个变数呢,我认为可以用一个call_out,或者是几次心跳周期来清除。
比如说3s或者是3次心跳,然后在判断的时候只需要判断last_damage_from是否
为空就OK了,last_damage_from的这个设想本身是非常好的。
只不过我们没有应用好它罢了。。

--------------------------------------------------------------------------------
作者:llm  发表时间:2001年7月12日 08:55

从字面意义上来说:last_damage_from解释为"最后一次伤害来自于....",应该记录的是实施伤害者,如果说是被伤害者我想应该命名为last_damage_to或直接last_damage
更妥吧!
当然对于判断凶手的处理可以有很多种,从被害者身上查是一种从伤害者身上查也是一种。但super所说的这种我没听懂。既然是记被伤害者,那么记在被伤害者身上是毫无意义的,因为不就是它自己嘛!那么好,记在实施伤害者身上。如果甲放毒伤害了六个人,这个参数显然只记最后一个人,这六人先后毒发死亡,是否只能判断甲杀了一人?
    还有关于延时清空的意思我都没听明白,希望能详细讲讲,也许我一个人钻进自己的想法空间里出不来,呵呵。

--------------------------------------------------------------------------------
作者:darks  发表时间:2001年7月12日 09:02

可以拿来作为自己的设计用途
不过ES的设计肯定如llm所说 我也同意弊端很多
怎么用确实每个人都有不同的理解,比如我就觉得对于基本技能 很多mud都是误解
包括潜能和exp的设定,也是一种弯曲理解
不过ES是ES 没必要一定和他一样 这个我是认同的
所以最好说想怎么设定 而不要说个具体的东西出来。
last_damage_From是什么 我就可以说不知道 我写个 l_d_f 可以吗?
这就是我的意思。

--------------------------------------------------------------------------------
作者:darks  发表时间:2001年7月12日 09:27

别拿last_damage_from出来 我不知道这是什么 呵呵 一般情况下我会和llm一样去理解它当作是ES的一个设定 那么我觉得你的理解是有错误的 llm倒是正确的

如果不是的话,那么还可以理解,设定是最重要的。不能说是用qi不是用kee就有什么问题。

如果真的要做到死亡多样化,还需要比较仔细的设定
比如设定 last_pk_from 什么的
如果真的想用 last_damage_from 嘻嘻 使用mapping可以吗?
我一般都是先想好体现的结果 然后去设计流程 至于ES,以前还考虑考虑,现在根本不在乎了。虽然还是在受到习惯的制约。

对于ES死亡的处理,因为ES不在乎那么多死法,所以当初的设定是非常合实际的。
而死亡涉及到很多的流程和函数,不是单单修改一个地方就能体现全面的。

比如调用die()这个函数的方式,也许可以叫凶手呼叫被害者的die来实现明确的判定。反正思路很多,不是做不到,只是想不想做的问题。毕竟,基于ES的,难免要受到ES的限制。

--------------------------------------------------------------------------------
作者:Super  发表时间:2001年7月12日 09:45

其实我所说的ES里面的这个last_damage_from设置得好,就是说。
用这种机制去判断一个是被谁杀的是个很好的方法。
其实last_damage_from怎么拼是个无关紧要的事,关键是我们要很好的把这个机制利用起来。

其次我说的那种定时清除last_damage_from的方法。。
打个比方吧。
在heart_beat()里面,if (t == 3) {t=0;delete_temp("last_damage_from");}
然后每心跳一次,t++
这样我们在判断一个人是怎么死亡的时候很容易就可以判断出来。
if (!query_temp("last_damage_from")) return 不知道怎么死的。
if (!find_object(query_temp("last_damage_from"))) return 杀你的人已经不在了。
//这里还可以另外记录下杀你的人的ID,以供以后使用。
if (userp(find_object(query_temp("last_damage_from")))) return 杀你的人是....
else return 杀你的人是NPC

另外对于施毒的死亡,我们则可以用一个跟毒一样的东西来控制,也是用心跳。
在heart_beat()里面追加last_damage_from的时候,我们可以判断是否是用毒。
是用毒的话,则可以不清除last_damage_from,或者是延长清除期。

我说last_damage_from的意思只不过是想说,ES的这种判断死亡的机制是非常不错的。
我想楼上二位大侠可能是误解我的意思了。

--------------------------------------------------------------------------------
作者:jjgod  发表时间:2001年7月12日 21:17

不妨把 F_DAMAGE 改造一下。其中,全局变量:
static object last_damage_from = 0;
static string last_damage_name = 0;

varargs int receive_damage(string type, int damage, object who)
中:
        if (who != last_damage_from)
        {
                last_damage_name = (who ? who->name(1) : 0);
                last_damage_from = who;
        }
die 函数中则是根据这两个来找,yi,似乎没有什么分别,还有一些
改动,别的 MUD 不太适用。

尊重作者 转载请注明出处52mud.com

收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容      
本文评论   [发表评论]   全部评论 (0)
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论