找回密码
 点一下
查看: 4856|回复: 17

关于攻击伤害事件的捕捉

[复制链接]
发表于 2008-8-30 00:16:13 | 显示全部楼层 |阅读模式
写在前面:我一直踌躇着没发帖,是因为这个系统具体说来并不是我原创的,而且原创者至今健在(zhuzeitou),由他来发帖是最好不过。可惜原创者似乎并没有意识到,所以我就来代劳了。

    因为WE本身的缺陷,单位被攻击事件很不精确,而想真正意义上捕捉到攻击伤害的事件都有一定的难度,需要付出不小的代价。方式是多种多样的,我要介绍的方法,只是其中的一种——捕捉BUFF。只要找到一个合适的技能,能够在对目标攻击造成伤害的时候附带一个BUFF,那么就能够在单位受到伤害的事件中通过BUFF来判断受到的是物理攻击伤害,还是技能伤害。
    最开始的时候,我选择的是减速之球+几率释放暗影突袭的方法来为攻击附带BUFF,不过有个很大的缺陷,因为魔兽自身的BUG,减速之球技能需要给单位下达巡逻或者攻击指令才会生效,而单位的自动攻击,即使发动几率是100%,也是不会触发的。解决办法只有捕捉单位获得攻击目标后强制下达攻击指令,效率很低。。。
    后来偶然在zhuzeitou的一个演示中发现了他用腐蚀之球附加BUFF,我才把目光投向其他技能。当然其实腐蚀之球,就是一个很好的选择,虽然没有了几率(我们可以通过随机数来设置),但还能获得攻击伤害值。所以后面的演示中,全部采用腐蚀之球。
    攻击附带BUFF的问题解决了,那么怎么来捕捉攻击伤害呢?下面以Dota里面的经典技能——并列(攻击时一定几率产生镜像)的实现来具体说明。
    首先以腐蚀之球的技能为模板新建一个技能(这里取名 攻击捕捉),再新建一个魔法效果(这里取名 攻击捕捉BUFF),设置攻击捕捉的魔法特效为攻击捕捉BUFF。以上步骤是为捕捉攻击事件做准备。现在再以力量之书为模板新建一个物品(这里取名 幻象之书),模型改成".mdx",技能改成幻象权杖那个技能,然后建立一个T如下:
[trigger]
AttackEvent
    事件
    条件
        ((触发单位) 拥有 攻击捕捉BUFF ) 等于 TRUE
    动作
        单位 - 删除 攻击捕捉BUFF  从 (触发单位)
        如果所有条件成立则做动作1,否则做动作2
            If - 条件
                (随机整数,最小值: 0 最大值: 99) 小于 50
            Then - 动作
                英雄 - 创建 幻象之书 给 (伤害来源)
            Else - 动作

[/trigger]
上面的是随机数,就是模拟50%的几率生成镜像。
你也许会说,这个T怎么没有事件?那么现在我们要为他添加事件了。
由于万恶的暴雪不提供全局单位受到伤害的事件,所以我们必须为每个单位注册一次受到伤害的事件,新建两个触发,具体如下:
[trigger]
对战初始化
    事件
        地图初始化
    条件
    动作
        自定义代码: set bj_wantDestroyGroup = true
        单位组 - 选取 ((可用地图区域) 内的所有单位) 内所有单位做动作
            Loop - 动作
                触发器 - 为 AttackEvent <预设> 添加事件: (单位 - (选取单位) 接受伤害)

[/trigger]

[trigger]
New
    事件
        单位 - 单位进入 (可用地图区域)
    条件
    动作
        触发器 - 为 AttackEvent <预设> 添加事件: (单位 - (进入的单位) 接受伤害)

[/trigger]
OK,一个无BUG的50%并列诞生!你可以为任何单位添加上 攻击捕捉 这个技能,来测试一下。
演示图如下:

WorldEditTestMap.w3x

21 KB, 下载次数: 139

评分

参与人数 1威望 +55 收起 理由
喀尔硫司之瞳 + 55 辛苦费~~

查看全部评分

 楼主| 发表于 2008-8-30 00:16:31 | 显示全部楼层
上面已经说了最基本的攻击捕捉,这次就说说很多人的梦想——创造属于自己的攻击事件~
给每个单位添加 攻击捕捉 这个技能,就能够捕捉所有单位攻击产生伤害的事件了。
还是以上图的技能和触发器为基础,说说怎么实现属性(敏捷)决定闪避几率,抱歉这可能要用到一点JASS
触发如下:
  1. function H2I takes handle i returns integer
  2.     return i
  3.     return 0
  4. endfunction
  5. function GetStoredUnit takes string i,string key returns unit
  6.     return GetStoredInteger(bj_lastCreatedGameCache,i,key)
  7.     return null
  8. endfunction
  9. function SetAssailable takes nothing returns nothing
  10.     local timer localtimer = GetExpiredTimer()
  11.     local string str = I2S(H2I(localtimer))
  12.     call SetUnitInvulnerable(GetStoredUnit(str,"unit"),false)
  13.     call FlushStoredMission(bj_lastCreatedGameCache,str)
  14.     set localtimer = null
  15. endfunction
复制代码
[trigger]
对战初始化
    事件
        地图初始化
    条件
    动作
        游戏缓存 - 创建游戏缓存,使用文件名: MapName.w3v
        自定义代码: set bj_wantDestroyGroup = true
        单位组 - 选取 ((可用地图区域) 内的所有单位) 内所有单位做动作
            Loop - 动作
                触发器 - 为 AttackEvent <预设> 添加事件: (单位 - (选取单位) 接受伤害)
                单位 - 添加 攻击捕捉  给 (选取单位)
[/trigger]
[trigger]
New
    事件
        单位 - 单位进入 (可用地图区域)
    条件
    动作
        触发器 - 为 AttackEvent <预设> 添加事件: (单位 - (进入的单位) 接受伤害)
        单位 - 添加 攻击捕捉  给 (进入的单位)
[/trigger]
[trigger]
AttackEvent
    事件
    条件
        ((触发单位) 拥有 攻击捕捉BUFF ) 等于 TRUE
    动作
        设置 TempUnit = (触发单位)
        单位 - 删除 攻击捕捉BUFF  从 TempUnit
        如果所有条件成立则做动作1,否则做动作2
            If - 条件
                (随机实数,最小值: 0.00 最大值: 1.00) 大于 (1.00 / (1.00 + (0.06 x (转换 (敏捷 对 TempUnit (包括 加成)) 为实数))))
            Then - 动作
                漂浮文字 - 创建漂浮文字:未击中 在 (伤害来源) 头顶Z轴偏移 0.00 处,字体大小: 10.00 ,颜色值:(100.00%, 0.00%, 0.00%) ,透明度: 0.00%
                漂浮文字 - 设置 (最后创建的漂浮文字) : 禁用 永久显示.
                漂浮文字 - 设置 (最后创建的漂浮文字) 的移动速率为 54.00 ,方向为 90.00 度
                漂浮文字 - 设置 (最后创建的漂浮文字) 的生命周期为 3.00 秒
                漂浮文字 - 设置 (最后创建的漂浮文字) 的消逝时间点为 1.00 秒
                单位 - 设置 TempUnit 无敌的
                自定义代码: set udg_TempTimer = CreateTimer()
                自定义代码: call StoreInteger(bj_lastCreatedGameCache,I2S(H2I(udg_TempTimer)),"unit",H2I(udg_TempUnit))
                自定义代码: call TimerStart(udg_TempTimer,0,false,function SetAssailable)
            Else - 动作
[/trigger]
这个演示,能够让单位的闪避几率和敏捷相关,几率公式等于护甲减伤公式
其中的JASS部分,只是为了在设置单位无敌躲避攻击伤害后立即使单位复原。
由于腐蚀之球是法球类技能,所以采用攻击捕捉系统的话,就不要使单位具有其他法球技能了。一般的法球,都可以通过捕捉攻击事件来完美模拟,当然也有一些是模拟不了的。
这些是完全不能模拟或者不能完全模拟的:弹幕攻击,弹射攻击,溅射攻击,直线攻击(其他的一时想不起来了),其中弹幕攻击是最大的遗憾,完全不能模拟。
关于球体技能的冲突,如果想了解更多,可以参考这个帖子
http://www.islga.org/bbs/read.php?tid=578
回复

使用道具 举报

 楼主| 发表于 2008-8-30 00:17:10 | 显示全部楼层

Re

这帖说一下关于全局伤害事件的注册
前面的演示,都是采用简单的添加事件,没有垃圾回收。主要是因为如果采用动态注册的话,销毁的时机很难选择,很可能同一单位注册两次。而演示中经常出现的那些无泄露的伤害显示系统,一般都没实际用过,有不少BUG的。一般这类系统的做法,都是初始化每个单位注册一个触发,然后新进入游戏地图的单位也都注册一个触发,死亡时销毁触发。在实际应用的时候,有以下几点问题:英雄复活是不会触发进入区域事件的,所以英雄死亡不能销毁相应触发,但英雄的镜像必须销毁。此外,因为操纵死尸、复活技能重新站起来的单位,不会触发进入区域事件,必须重新手动注册。
所以,我更推荐简单的添加事件的做法。如果担心事件过多影响效率,可以在事件到达一定数量后销毁触发器,重新注册一次。

WorldEditTestMap.w3x

22 KB, 下载次数: 53

回复

使用道具 举报

 楼主| 发表于 2008-8-30 00:17:25 | 显示全部楼层
占楼~~
回复

使用道具 举报

发表于 2008-8-30 00:29:53 | 显示全部楼层
分清物理攻击还是魔法攻击的演示早就有了
回复

使用道具 举报

发表于 2008-8-30 00:44:33 | 显示全部楼层
腐蚀之球是法球,会被覆盖的
回复

使用道具 举报

 楼主| 发表于 2008-8-30 00:46:31 | 显示全部楼层
寒……
回复

使用道具 举报

发表于 2008-8-30 02:23:53 | 显示全部楼层
那个闪避用无敌不太好吧.....我觉得给单位加血比较好
回复

使用道具 举报

 楼主| 发表于 2008-8-30 02:25:18 | 显示全部楼层
加血闪不掉重击
回复

使用道具 举报

发表于 2008-8-30 08:16:52 | 显示全部楼层
要的就是闪不掉嘛
连魔法效果都无视 很邪恶啊
回复

使用道具 举报

发表于 2008-8-30 11:08:41 | 显示全部楼层
额额,我是路过的………………
要模拟的话可以彻底一点,重击也用模拟,那样就可以与模拟的闪避共存而不用无敌了~~
回复

使用道具 举报

发表于 2008-8-30 20:38:32 | 显示全部楼层
地图上的单位都很多,而拥有攻击附加伤害这样的单位并不多。
进行全图单位伤害注册,不是好办法。像Dota,有好几个技能,
都是会在攻击时附加一个伤害,但是,正常情况,只有一个单位
拥有这种技能。而这一个单位,在同一时间,也只能攻击一个目标,


比如dota,选好英雄,把双方塔都删掉,主基改为无敌。
几分钟后,地图上小兵就会很多。这时,基本没有办法进行游戏了,
因为很卡。。

技能注册触发
    事件: 单位学习技能
    条件: 技能是<捕捉攻击伤害>
    动作: 新建触发器:准备攻击
           为新触发器添加事件: 触发单位注意到范围内的目标
                                (一个单位对另一个单位进行攻击前,这个事件会发生的。)
               
   
准备攻击触发
    事件:    单位注意到范围内的目标
    动作:    新建触发器:伤害接收触发
            为新触发器添加事件:目标单位受到伤害
            为新触发器添加事件:逝去的时间为1秒
            为新触发器添加动作:
                如果:触发事件是:触发单位受到伤害&&触发单位拥有Buff
                那么:确认普通攻击被捕捉,禁用当前触发,删除Buff,删除当前触发,之后运行自定义处理
                如果:触发事件是:近去的时间为1秒
                那么:这个单位1秒内没有受到来自有附加伤害的单位的攻击,可能是那个单位死亡或改变目标了,不再捕捉。
                      禁用当前触发,删除当前触发
   
   
伤害接收触发
    事件:触发单位受到伤害
          逝去的时间为1秒
    动作:
          如果:触发事件是:触发单位受到伤害&&触发单位拥有Buff&&伤害来源拥有伤害附加的技能
                那么:确认攻击被捕捉,禁用当前触发,删除当前触发,之后运行自定义处理
                如果:触发事件是:近去的时间为1秒
                那么:这个单位1秒内没有受到来自有附加伤害的单位的攻击,可能是那个单位死亡或改变目标了,不再捕捉。
                      禁用当前触发,删除当前触发
回复

使用道具 举报

发表于 2008-8-30 20:39:18 | 显示全部楼层
[codes=javascript]
function showimage(imgpath,value){
    if (value == '') {
        value = 'none.gif';
    }
    document.images.useravatars.src = imgpath + '/face/' + value;
    document.register.regicon.value = value;
}
function regcheck(formct){
    if (formct.regname.value=='' || formct.regpwd.value==''){
        alert('会员名或密码为空,请填写');
        return false;
    }
    return checkpwd();
    formct.regsubmit.disabled=true;
}
function checkpwd(type){
    var pwd = getObj('regpwd').value;
    if (pwd.length<regminpwd){
        var msg = '密码最小值不能小于'+regminpwd;
    } else if (regmaxpwd>0 && pwd.length>regmaxpwd) {
        var msg = '密码最大值不能大于'+regmaxpwd;
    } else if (parseInt('0')>0 && getObj('regname').value==pwd) {
        var msg = '请将帐号与密码设置为不同值';
    } else {
        var msg = '';
    }
    if (type==1) {
        getObj('pwd_info').innerHTML = '<font color="red">'+msg+'</font>';
    }
    if (getObj('regpwdrepeat').value && (type==1 || msg=='')) {
        msg = checkpwdrepeat(type);
    }
    if (msg) {
        if (type!=1) {
            alert(msg);
        }
        return false;
    }
}
function checkpwdrepeat(type){
    if (getObj('regpwdrepeat').value==getObj('regpwd').value) {
        var msg = '';
    } else {
        var msg = '两次输入的密码不一致,请检查后重试。';
    }
    if (type==1) {
        getObj('pwdrepeat_info').innerHTML = '<font color="red">'+msg+'</font>';
        return '';
    } else {
        return msg;
    }
}
function checkemail(){
    var email = document.getElementById("regemail").value;
    var myReg = /^[-a-zA-Z0-9_\\.]+@([0-9A-Za-z][0-9A-Za-z-]+\\.)+[A-Za-z]{2,5}$/;
    if(myReg.test(email)){
        document.getElementById("email_info").innerHTML = "";
    } else{
        document.getElementById("email_info").innerHTML = "<font color=\\"red\\">Email 格式错误!</font>";
    }
}
[/codes]
回复

使用道具 举报

发表于 2008-8-30 21:50:00 | 显示全部楼层
11# 要用jass的吧
回复

使用道具 举报

发表于 2008-8-30 22:09:52 | 显示全部楼层
12楼的js为什么要发在这里呢??
回复

使用道具 举报

 楼主| 发表于 2008-8-30 22:14:03 | 显示全部楼层
其实全局伤害事件不卡的
11楼那样,很容易造成新建的触发器堆积
比如在攻击未发出的时候按S
回复

使用道具 举报

发表于 2008-8-30 22:43:08 | 显示全部楼层
近战伤害 捕捉用荆棘光环是最好的     

因为这光环可以模拟,

捕捉伤害就非常简单了,


远程的以前想到的,   现在一时想不起来了,           游戏开始了.......先闪...


libla考虑下吧.     这光环捕捉近战伤害竟是如此简单
回复

使用道具 举报

发表于 2008-8-30 22:44:57 | 显示全部楼层
没必要一棒打两只鸟,   

再找个好点的远程东西.    判断时弄些东西在  "否者" 这个语句里  一样可以兼顾远近两种
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-2 15:00 , Processed in 0.235869 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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