找回密码
 点一下
查看: 3613|回复: 16

使用触发器+数据来建立任意伤害计算公式的通用方案(甚至可以实现暴击,伤害转移,war3

[复制链接]
发表于 2013-4-23 20:53:01 | 显示全部楼层 |阅读模式
关于使用触发器+数据来建立任意的伤害计算公式的方法我在群里就说过。

但是很可惜的是,今天问起来没人记得。虽然War3 Mod还在制作中。不过我这里就做个简单的教程来说明下War3 Mod中实现War3攻防公式的方法。

同样的方法不仅仅适用于实现War3的攻方系统,还可以延伸到任意的自定义伤害计算方案。比如把本该由A受到的伤害转嫁到B上等等。

由于可以使用触发器,所以公式本身的计算不成问题。要点主要有2个:

1.如何获得原伤害(即伤害效果没有被单位本身的防御力或者削减前的伤害值)。

2.如何把原伤害妥善地抹消掉。


3.获取原伤害,基于原伤害x来通过自定义公式计算出目标应受到的伤害y。(这部分无难度)


基本上我们只需要获得原伤害值,然后把原伤害抹消掉,然后再用触发器来基于原伤害计算我们想要制造的实际伤害,然后用伤害单位函数来伤害目标即可。

这两个问题单独来看都不是问题。只是整合起来会有问题。由于SC2触发器的机制的原因,伤害在结算之前是无法被触发器获取的。而伤害一旦造成,就无法被抹消了。有人可能会说,直接把被扣掉的血加上去不就完了,但是假如原伤害100,直接把目标打死了,然后你想要实现的公式的计算结果又不会让目标死亡,那怎么办。由于触发器响应事件的时候,伤害已经结算完毕。所以你就算这时候加血也没用了,目标已经死了,各种事件也已经被引发了。

所以,看起来不通过数据编辑器里的buff这个东西,是无法抹消一个伤害的。


但是,抹消了伤害后我们还是得获得原伤害值啊。获取方案呢?

而我们来看看触发器“受到的触发伤害值”这个函数返回的是什么值?是计算护甲前还是计算护甲后。

有一个非常简单的方法可以验证。让6攻击的陆战队员去攻击1防的单位,这个函数响应事件后会返回5。答案:是扣掉护甲后的。


所以我们可以得出结论,“受到的触发伤害值”这个函数获得的是最终结算后的伤害。因此一旦伤害被buff吸收掉后,该函数返回的值是0,因而我们无从从中计算原伤害值。这个结论正确吗?



答案是:正确——但仅仅是在1.5以前!

我对大家的健忘表示十分的失望,这一改动我在1.5和2.0都各自提过一次,但是没有人记得这件事吗?

在上面这个6攻对1防的例子里,无论是1.5前1.5后,这个函数返回的数值都是5。

但是,这个例子的前提是目标身上没有吸收伤害的buff存在。

在1.5后,“受到的触发伤害值”这个函数的返回值会一并算上被buff吸收掉的部分!

所以,如果1防的目标单位身上有个吸收50%伤害的buff,那么让6攻的陆战队员去打他,返回值是多少呢?

2?6?

答案不是2,也不是6。而是5

为什么?因为6-(6/2)-1+(6/2)=2+3=5


橙色部分是实际伤害,而蓝色部分是被行为吸收掉的伤害。两者之和为5。(1.5前为2,因为当时不会算上被吸收部分,只计算实际伤害)

你可能注意到(6/2)这项前后消掉了。那我们是不是可以把上面的公式简化为6-1=5? 也就是说“受到的触发伤害”这个函数的返回值直接就是(原伤害 减 防御力),而完全不论被buff吸收掉的多少。

答案是,不能这么简单地进行简化。

原因:

1]存在最低伤害机制

2]就算攻击小于防御,也不会反而加血

举一个简单例子就能证明为什么不能这么简单地简化:

现在我用6攻击力的陆战队员打一个带100%伤害吸收buff的1防目标。那么函数返回结果会是什么?

答案是,因为6攻击力全部被buff吸收去了,所以返回值是6而不是5。

再来,6攻打一个100%伤害吸收的7防目标?

返回值还是6。而不是-1,也不是游戏设置的最小伤害值0.5


所以,在这种情况下,显而易见的。我们找到了一个解决问题的绝好方案:

我们只要给所有单位都放一个持久的100%伤害吸收buff,问题就都解决了。

因为伤害会自动被buff吸收掉。而函数却还能捕捉到伤害事件和原伤害值(因为在100%吸收的情况下,原伤害=被吸收的伤害值+实际伤害(必为0)+被护甲削减的部分伤害值(必为0)=函数返回值)

好了,接下去还等什么呢?直接用计算出你想要造成的伤害,然后往目标身上丢就好了。



嗯,于是问题都解决了。

……其实还没。这里还有几个小地方要注意。由于目标100%吸收伤害,所以用触发器来造成伤害也会被吸收,要避免这一点就只有2个法子。

一个在制造伤害的动作前后删除并添加伤害吸收buff。但这法子不怎么推荐,因为每次响应伤害事件的时候都要重复地给目标单位删除和添加buff,实在很消耗多余的运算量。

所以更好的方案莫过于用一个专门的伤害效果来制造触发伤害。反正触发器里的“制造伤害”动作在指定伤害效果后可以设置额外的伤害值。所以伤害值方面不用顾虑(再不济我们还可以动态修改那个专用伤害效果的属性)。然后,我们只要修改那个我们拿来获取并抹消原伤害的100%吸收伤害buff,给它的"排除"属性加上一条,让他不响应这个触发器专用伤害就行了。这样我们用触发器制造伤害的时候甚至不需要去来回删除并添加buff。

还有一些其他的问题,诸如,伤害响应(包括吸血效果,加成效果等等)。如果原单位有个吸血能力,那么在原伤害被吸收的时候依然能吸到血。但是接下去我们又用触发器再制造伤害的话,岂不是吸了两次血了?所以,我们要修改那个专用伤害的标旗,让他不响应任何行为和吸血效果。因为这些效果都已经由原伤害引发过了,我们不想让他引发第二次。

另外,伤害加成这些标旗也都去掉,护甲削减百分比也改为0。因为我们通过触发器算出的伤害已经是最终伤害,我们不想再次计算目标的护甲,或者各种伤害加成了。另外的一些注意事项可以根据你的地图和公式来具体分析,比如修改伤害效果的死亡类型来达到目标的多种死法等等。


好了,虽然说明原理的时候很复杂,但是其实整个过程非常之简单不是吗?

一个100%吸收伤害的buff+一个钩了一大堆标旗的伤害效果。

仅仅靠一个buff和一个效果就解决了所有问题,可喜可贺呢。大家鼓掌

(啪嗒啪嗒)

用这个法子别说是复刻war3的攻防系统了,各种自定义伤害修改效果都能实现,暴击效果,伤害转移效果什么的更不在话下,还不快去试试。







附:

最后可能有人要问,说起来既然“受到的触发伤害值”这个函数在1.5以后变化了,那如果我只想要获得目标单位“实际受到的伤害值”那要怎么办呢?

实际上暴雪也已经考虑到了这一问题,在2.0以后,触发器里增加了一条新函数“被吸收的触发伤害值”。这个函数仅仅返回触发伤害中被buff吸收掉的部分。这样,用“受到的触发伤害值”去减去“被吸收的触发伤害值”就能得到“实际受到的伤害”了。

评分

参与人数 1印象 +10 收起 理由
alexries + 10

查看全部评分

发表于 2013-4-23 21:01:34 来自手机 | 显示全部楼层
刚刚看了一遍了,涨知识了。不过有些地方还是没明白。再研究研究。
回复

使用道具 举报

发表于 2013-4-23 21:04:52 | 显示全部楼层
有一种被绕晕了的感觉,再看看。
空人君,不要抢我的沙发……

点评

我不是故意的啦  详情 回复 发表于 2013-4-23 21:49
其实头目摆弄出来的很多简单轻松的系统,背后的原理却非常复杂哦。 最典型的例子就是那个相位技术。今天这个教程的原理其实算是最简单的一个了。 我也许会把把这个做进GAx3里面,这样用户只需要基于原伤害x来提  详情 回复 发表于 2013-4-23 21:09
回复

使用道具 举报

 楼主| 发表于 2013-4-23 21:09:22 | 显示全部楼层
娜渃卟Ran 发表于 2013-4-23 21:04
有一种被绕晕了的感觉,再看看。
空人君,不要抢我的沙发……

其实头目摆弄出来的很多简单轻松的系统,背后的原理却非常复杂哦。

最典型的例子就是那个相位技术。今天这个教程的原理其实算是最简单的一个了。

我也许会把这个做进GAx3里面,这样用户只需要基于原伤害x来提供一个公式就可以自定义伤害公式。这样不需要了解背后的原理就能应用了。

回复

使用道具 举报

发表于 2013-4-23 21:11:38 | 显示全部楼层
本帖最后由 四夕水草肃 于 2013-4-23 21:12 编辑

全部存档记录嗯。

头目所有的教学与演示花音都要完全吃透并且根据需要加入自定义的功能。
回复

使用道具 举报

发表于 2013-4-23 21:21:21 | 显示全部楼层
原本也考虑过这么做,但是一直担心触发器效率的问题..
因为触发器不是有个事件响应上限么,是10000还是多少来着?
如果地图作者是习惯用“伤害事件”来触发各种效果的话,这个事件的触发就非常频繁了

点评

出于科学发展观,任意伤害事件不应该出现一个以上。 放一起处理就好了。  详情 回复 发表于 2013-4-23 21:23
回复

使用道具 举报

 楼主| 发表于 2013-4-23 21:23:16 | 显示全部楼层
逸名 发表于 2013-4-23 21:21
原本也考虑过这么做,但是一直担心触发器效率的问题..
因为触发器不是有个事件响应上限么,是10000还是多少 ...

出于科学发展观,任意伤害事件不应该出现一个以上。

放一起处理就好了。正常来说一个地图会有一万个单位同时受到伤害吗?显然不会,所以不用担心啦。

既然要“完全地自定义伤害公式”的话,不用触发器是不可能的。数据编辑器根本没有能让你输入公式的地方。
回复

使用道具 举报

发表于 2013-4-23 21:49:41 来自手机 | 显示全部楼层
娜渃卟Ran 发表于 2013-4-23 21:04
有一种被绕晕了的感觉,再看看。
空人君,不要抢我的沙发……

我不是故意的啦
回复

使用道具 举报

发表于 2013-4-23 22:42:19 | 显示全部楼层
本帖最后由 逸名 于 2013-4-23 22:46 编辑

按照头目的方法做了一个小测试,实现起来比想象中的方便。
目前测试地图中大概有200个单位的时候没出问题(测试图地形小。。装不下更多单位了)
可以考虑加入到地图的伤害系统中呢
(图片好大?怎么传了这么久...)
Screenshot2013-04-23 22_26_40.jpg
花音罚我写300字,表示300字压力相当大啊...
一张测试图可以抵消这300字吗?
CustomDamage_Test.SC2Map (13.71 KB, 下载次数: 80)

对了,忘了描述一下测试图
按“空格”键可以刷雷兽和Zealot,雷兽的护甲是5,Zealot的护甲是1,雷兽有8层“暴击”BUFF,Zealot1层,光堂3层(没记错吧)
1点护甲减免10%的伤害,1层暴击BUFF提升10%的暴击率,暴击伤害是1.5~2.5倍




点评

弱弱的问下,这两处是不是设置错误了?问下战斗: 伤害响应 - 几率为1时,最小伤害如何抹除?  详情 回复 发表于 2013-4-25 11:40
回复

使用道具 举报

发表于 2013-4-23 23:37:40 | 显示全部楼层
也就是WAR3 MOD攻防系统完全需要通过触发来实现咯?
回复

使用道具 举报

发表于 2013-4-24 19:39:51 | 显示全部楼层
头目太厉害了!!!!!!!正在犯愁这部分呢!!
回复

使用道具 举报

发表于 2013-4-24 20:07:40 | 显示全部楼层

裤子还在很土的玩数据编辑器

回复

使用道具 举报

发表于 2013-4-25 11:40:23 | 显示全部楼层
逸名 发表于 2013-4-23 22:42
按照头目的方法做了一个小测试,实现起来比想象中的方便。
目前测试地图中大概有200个单位的时候没出问题( ...

弱弱的问下,这两处是不是设置错误了?问下战斗: 伤害响应 - 几率为1时,最小伤害如何抹除?
000000.JPG

点评

嗯,测试的时候把注意力都放在debug窗口上,没有注意到数据... 这样的结果其实给单位造成2次伤害了。最小伤害可以去除,勾上“修改最小伤害”就好了 修改的3个地方:  详情 回复 发表于 2013-4-25 14:46
回复

使用道具 举报

发表于 2013-4-25 14:46:34 | 显示全部楼层
hgzerg 发表于 2013-4-25 11:40
弱弱的问下,这两处是不是设置错误了?问下战斗: 伤害响应 - 几率为1时,最小伤害如何抹除?

嗯,测试的时候把注意力都放在debug窗口上,没有注意到数据...
这样的结果其实给单位造成2次伤害了。最小伤害可以去除,勾上“修改最小伤害”就好了
修改的3个地方:
1.png

2.png

CustomDamage_Test.SC2Map (13.7 KB, 下载次数: 60)
回复

使用道具 举报

发表于 2013-6-21 15:17:49 | 显示全部楼层
本帖最后由 逸名 于 2013-6-21 18:26 编辑

在实际使用这套“自定义伤害”系统的过程中遇到了几个细节上的小问题,与大家分享一下:(以楼上的演示图为例)
1.最好不要勾上伤害效果EDamage_NULL中的“无行为响应”。因为计算后的伤害值通常还不是最终伤害,比如目标单位身上有一个“减免20%任意伤害”的BUFF时,如果勾上了“无行为响应”,这个BUFF的免伤效果将不会生效。

2.如果目标单位身上有一个这样的BUFF:“减免20%的任意伤害,受到5次伤害后失效”。那么就要注意一个问题,你的一次攻击伤害和EDamage_NULL也许会令这个BUFF被响应了两次,也就是说原本这个BUFF能够承受5次攻击,而现在只能承受2.5次。解决办法很简单,BUFF的响应是有顺序的,确保B_DamageNULL是你添加到单位身上的第一个BUFF,或者确保B_DamageNULL位于单位行为列表的第一位,那么B_DamageNULL会覆盖掉其他的伤害修正BUFF(即令其他的伤害修正BUFF在承受攻击伤害时不被响应,只在承受EDamage_NULL时被响应)

3.如果你在地图中需要定义不同的伤害分类,比如“远程伤害”、“近战伤害”、“法术伤害”,并且存在这样的技能效果:“令目标受到的远程伤害提升50%”。那么你必须新建3个不同伤害类型的EDamage_NULL效果,来对应3个分类伤害的伤害响应。
4.补充一点刚发现的问题,如果地图中有发射飞弹类型的攻击或者非引导类型的持续性伤害,最好在触发中加一个判断条件“造成伤害的单位为活体状态”,否则在使用“伤害单位”这条动作的对目标造成伤害,而伤害源单位已经死亡的时候会出错。也可以用其他的办法来避免这个错误,这个方法会导致单位在死亡后其飞弹的伤害或持续性伤害失效。

回复

使用道具 举报

发表于 2013-8-7 13:50:24 | 显示全部楼层
由头目的测试可以得出一个结论:星际2的伤害计算是先计算buff吸收,然后其结果才参与护甲系统的计算。虽然看起来这并不重要,但是真正要做好数据平衡的话必须要了解,因为不同的顺序会造成明显不同的结果。比如说,某单位有100点生命,吸收伤害90%,护甲抵消10点伤害,假设给他造成100的伤害的话,如果按照前边提到的方法,最终这个单位不会受到伤害(当然不考虑最小伤害的话),因为100*10%-10=0,但是如果先计算护甲系统的话则会这样:(100-10)*10%=9,最终受到9点伤害,被打十多次就挂了。
回复

使用道具 举报

发表于 2013-9-8 01:04:59 | 显示全部楼层
看起来比YDWE强上很多,虽然我也不懂得YD触发的原理...
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-11-22 03:49 , Processed in 0.214579 second(s), 34 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表