找回密码
 点一下
查看: 4659|回复: 24

全法球模拟----演示(期待你的参与)

[复制链接]
发表于 2009-6-4 18:00:36 | 显示全部楼层 |阅读模式
上一个演示就搁浅掉吧,确实技术含量很低,真是对不住大家,这几天做了个别的演示。

话说前几天逛Ga途中被一同学发现,对我说,你怎么还在搞这个啊,现在会做图了吗?鉴于之前失败的惨痛经历,我的回答是相当的心虚,其实对于我这种没有审美没有创意没有毅力的人要做出成品图说真的确实不容易。但是不甘心还是有一点的,想到之前我曾经在Ga说过要做一个全法球的模拟(嗯嗯,说到这个还是要先谢谢libla当时对我的帮助呢),但是当时由于水平还不行所以搁浅了,那么做一下这个算是挑战加履行诺言了吧。

说到全法球模拟的初衷,就是想用模拟的手段来做出彼此之间不会冲突的法球效果,不仅不同的法球之间可以共存,而且同类的法球的效果也可以同时发挥作用。原理呢大家都知道,就是侦测单位受到伤害然后根据英雄佩戴的物品运行相应的效果,所以核心代码简单到不足百行,大概十来分钟就完成了,那我就先把代码贴出来吧。当然,首先要说明的是,我还是保持风格,使用数组存储系统而不用缓存,并非我诚心要把代码搞的复杂,既然作为我的挑战项目,我自然是要用我认为更好的技术。第一个是单位受到伤害后所运行的代码:

[codes=jass]
library Msphere

................

globals
    //这个数组一会再介绍
    private integer array _data

    //这几个东西就是用于在运行filterfunc时稍稍提高效率,因为每次都GetTriggerUnit()或者GetEventDamageSource()毕竟是没有全局变量快的
    private integer _this
    private unit _Triunit
    private unit _Souunit
    private player _Souply

    //这两个数组是将单位持有的物品形成链表,然后我们可以依次获取到要运行的filterfunc
    private integer array _itemq
    private integer array _itemh
endglobals

private function _unitD takes nothing returns boolean
    local unit ux=GetTriggerUnit()
    local real x
    local real y
    local filterfunc T
    local item H
    local integer I
    local integer ix
    //'B000'是演示中所有物品技能的魔法效果,有了它也就是说单位被持有法球的英雄攻击了
    if GetUnitAbilityLevel(ux,'B000')>0 then
        call UnitRemoveAbility(ux,'B000')
        //这r的代码作用依上所述
        set _Triunit=ux
        set _Souunit=GetEventDamageSource()
        set _Souply=GetOwningPlayer(_Souunit)
        //这个函数_get()是拉链Hash中的一个函数(包括_get(),_sto(),_del()),作用翻看之前有关Hash的帖子吧,或者下载演示自行研究
        set ix=_itemh[_get(0,_Souunit)]
        set x=GetUnitX(ux)
        set y=GetUnitY(ux)
        loop
            exitwhen ix==0
            //依据ix获得了英雄的第一个法球物品
            set I=f[ix]
            //函数_iget()它只是另一个Hash表
            set _this=_iget(GetItemTypeId(H))
            //_data[]含有该法球的所有数据,因为我们以_this作为指针,在运行filterfunc后获取数据
            set I=_data[_this]
            //既然得到了filterfunc了,我们就以函数GroupEnumUnitsInRange()来运行它
            call GroupEnumUnitsInRange(G0,x,y,50,T)
            //好了,下一个法球
            set ix=_itemh[ix]
        endloop
    endif
    set ux=null
    return false
endfunction

.............

endlibrary
[/codes]

关于上面代码调用的两个函数,_get()和_iget()(请不要计较它们的名字了- -),我说了它们都是Hash表,前者是拉链Hash,它更适合频繁的添加删除句柄这样的场合,后者是双重Hash,它所适合的是初始化既完成或者只添加不删除句柄的场合,更加详细的关于它们的使用方法就不是本贴的讨论范围了,所以pass。下一段代码是单位获取、丢弃物品是触发的动作:

[codes=jass]
library Msphere

................
//怎么解释呢...大家结合上一段函数自行理解吧,pass。
private function _item takes nothing returns boolean
    local item it=GetManipulatedItem()
    local integer ix=_iget(GetItemTypeId(it))
    local integer n
    local integer m
    if ix!=0 then
        if GetTriggerEventId()==EVENT_PLAYER_UNIT_PICKUP_ITEM then
            set ix=_sto(0,it)
            set n=_get(0,GetManipulatingUnit())
            set m=_itemh[n]
            set _itemq[m]=ix
            set _itemh[ix]=m
            set _itemq[ix]=n
            set _itemh[n]=ix
        else
            set ix=_get(0,it)
            set n=_itemq[ix]
            set m=_itemh[ix]
            set _itemh[n]=m
            set _itemq[m]=n
            call _del(ix)
        endif
    endif
    return false
endfunction

.............

endlibrary
[/codes]

下来的一段就是法球的效果及数据的注册了,千万注意,物品ID一定不要重复。呃,惭愧的是我现在只做了4个火焰的法球效果就来发帖了,但还是老话,承诺更新!

[codes=jass]
library Msphere

................
//话说vJ好与不好我说了也不算,但是文本宏和库确实很实用,不会的同学不妨查看教程,了解一些。
//! textmacro zhuce2 takes ID,n1
set ix=_isto($ID$,2)
set _data[ix]=I
set _data[ix+1]=$n1$
//! endtextmacro
//! textmacro zhuce3 takes ID,n1,n2
set ix=_isto($ID$,3)
set _data[ix]=I
set _data[ix+1]=$n1$
set _data[ix+2]=$n2$
//! endtextmacro
//! textmacro zhuce4 takes ID,n1,n2,n3
set ix=_isto($ID$,4)
set _data[ix]=I
set _data[ix+1]=$n1$
set _data[ix+2]=$n2$
set _data[ix+3]=$n3$
//! endtextmacro
//函数_zhuce()是法球类型及其数据的注册函数,具体效果请参考相应的filterfunc
private function _zhuce takes nothing returns nothing
    local boolexpr T
    local integer I
    local integer ix
    //以下为“烈焰”的注册,参数依次为物品ID,伤害半径,伤害值
    set T=Filter(function _fire1)
    set _fire1b=Filter(function _fire1f)
    //! runtextmacro zhuce3("'I000'","175","10")
    //! runtextmacro zhuce3("'I001'","225","20")
    //! runtextmacro zhuce3("'I002'","275","30")
    //以下为“燃灰”的注册,参数依次为物品ID,附加伤害,爆破半径,爆破伤害
    set T=Filter(function _fire2)
    set _fire2b=Filter(function _fire2f)
    //! runtextmacro zhuce4("'I003'","1","150","30")
    //! runtextmacro zhuce4("'I004'","5","175","10")
    //! runtextmacro zhuce4("'I005'","6","200","70")
    //以下为“燃灰·改”的注册,参数依次为物品ID,附加伤害
    set T=Filter(function _fire3)
    //! runtextmacro zhuce2("'I009'","5")
    //! runtextmacro zhuce2("'I00A'","10")
    //! runtextmacro zhuce2("'I00B'","15")
    //以下为“焚烧”的注册,参数依次为物品ID,伤害半径,伤害,伤害次数
    set T=Filter(function _fire4)
    set _fire4b=Filter(function _fire4f)
    //! runtextmacro zhuce4("'I008'","300","10","3")
    //! runtextmacro zhuce4("'I00C'","325","30","4")
    //! runtextmacro zhuce4("'I00D'","350","50","5")
endfunction

.............

endlibrary
[/codes]

好了,通过以上的3段代码,我就生成了4类共12个法球,具体的filterfunc大家可以自己下载演示查看。
我在下一楼就具体说说演示中法球的具体的效果了。

全法球模拟_演示V0.12.w3x

91 KB, 下载次数: 145

目前8法球,承诺更新

评分

参与人数 1威望 +24 收起 理由
血戮魔动冰 + 24

查看全部评分

 楼主| 发表于 2009-6-4 18:00:51 | 显示全部楼层

演示中法球效果的具体介绍,目前数量8

[codes=jass]
//===========================================================
//法球名称:烈焰        法球类型:火焰
//        击中目标后,以其为圆心,对x码之内的敌人造成y点伤害。
//攻击类型:英雄
//! define fire1_at ATTACK_TYPE_HERO
//伤害类型:火焰
//! define fire1_dt DAMAGE_TYPE_FIRE
//特效路径:
//! define fire1_s "Abilities\\\\Spells\\\\Items\\\\AIfb\\\\AIfbSpecialArt.mdl"
//特效附着点
//! define fire1_s1 "chest"
//=============================================================
具体来说呢,和魔兽自带的火焰之球是完全一样的,就是在攻击目标以后会对周围的单位造成一个固定的伤害。英雄在持有多个该法球的情况下,效果会叠加,也就是说,当单位拥有'I000'和'I001'时,将对175码内的敌人造成30伤害,而175-225之间的敌人是20伤害。
[/codes]

[codes=jass]
//=================================================================
//法球名称:燃灰        法球类型:火焰
//      每次攻击都带有火焰伤害并附加一个持续3秒的Buff。第一次攻击造成
//      x点伤害,第二次攻击的附加伤害会是第一次的两倍,第三次为三倍,
//      以此类推,最多十倍。单位存在该Buff时死亡将产生爆破,对周围y码
//      敌人(不包括建筑物)造成z点伤害。
//攻击类型:魔法
//! define fire2_at ATTACK_TYPE_MAGIC
//伤害类型:火焰
//! define fire2_dt DAMAGE_TYPE_FIRE
//特效路径:
//! define fire2_s "Abilities\\\\Spells\\\\Other\\\\Incinerate\\\\FireLordDeathExplode.mdl"
//==================================================================
魔兽中的燃灰技能有Bug,所以这个相对来说还是比较需要的。先来说下爆破效果吧,就是取所有效果的最大值,当英雄持有'I003'和'I004'时,敌对单位的死亡将造成175码范围的30点伤害。而伤害的累加我做了限制,首先是不能高于初始的十倍,当英雄装备如上法球时,最大会有50的初始伤害。另一个情况就是叠加次数和初始伤害的关系,若单位持有'I003'攻击了2次,共有2点的额外伤害,此时装备'I004'攻击,因为两物品的同时作用额外伤害将增加6,即到达8,然后第4次叠加增加到14,5-20,6-26,7-32,...,但是如果是先携带'I004'攻击两次,然后装备'I003',由于额外伤害于叠加次数的比值会超过5,因为只有5的成长。
好了,不用你说,我也对这样的限制感到不快,那么请看下一个法球。
[/codes]

[codes=jass]
//=====================================================================
//法球名称:燃灰·改         法球类型:火焰
//          每次攻击都会造成额外x点火焰伤害并附加一个持续3秒的Buff,额外
//          的伤害可以累加。
//攻击类型:魔法
//! define fire3_at ATTACK_TYPE_MAGIC
//伤害类型:火焰
//! define fire3_dt DAMAGE_TYPE_FIRE
//=====================================================================
在Buff的存在期间,每次攻击额外伤害都会一直叠加,如果携带'I009'的话就是5、10、15、20,增加了'I00A'之后就是35、50、65、...无上限,当然了,目前还只是做效果,法球之间能力的平衡还未有考虑,比如将Buff的持续时间修改为2,这个东西就会弱很多呢。
[/codes]

[codes=jass]
//=====================================================================
//法球名称:焚烧         法球类型:火焰
//         击中目标后,对其及其周围x码敌人造成y次伤害,每次z点。
//攻击类型:混乱
//! define fire4_at ATTACK_TYPE_CHAOS
//伤害类型:火焰
//! define fire4_dt DAMAGE_TYPE_FIRE
//=====================================================================
模仿的是兽族投石车的被动技能,击中一个目标后会对一定范围内的敌人造成y次z点伤害,但是这个可以叠加的,呃,怎样叠加么?简单来说就是各种叠加都可以,每个英雄会叠加,每个法球会叠加,每次攻击也会叠加。
[/codes]

[codes=jass]
//=============================================================
//法球名称:幽魂         法球类型:生命
//          攻击会将x%的伤害值转化为生命,在生命值已满的情况下将
//          对被攻击者造成额外y%的伤害。
//攻击类型:无
//伤害类型:无
//特效路径:
//! define life1_s "Abilities\\\\Spells\\\\Undead\\\\CarrionSwarm\\\\CarrionSwarmDamage.mdl"
//特效附着点:
//! define life1_s1 "origin"
//=============================================================
首先,法球的吸取、伤害百分比是简单相加的。另一方面,若一个物品吸取、伤害分别为10%、30%时,当吸取的生命值为30点,而单位只少了10点生命,则会对被攻击单位造成(30-10)*30%/10%,诸如此类。
[/codes]

[codes=jass]
//==============================================================
//法球名称:魂守         法球类型:生命
//         攻击会将x%的伤害值转化为生命,在生命值已满的情况下可以
//         获得“魂守”效果,将吸取的生命值积蓄下来用来抵消伤害,最
//         多可以抵消y点。
//攻击类型:无
//伤害类型:无
//=============================================================
这个所谓的“魂守”效果就是wow中MS的蛋壳,处理方法就是用0秒的计时器加血,吸血效果同上。
[/codes]

[codes=jass]
//======================================================================
//法球名称:蚀骨          法球类型:生命          创意指导:libla
//          渗透性的攻击,会将x%因护甲而抵消的物理伤害继续施加给被攻击单位。
//攻击类型:无
//伤害类型:无
//特效路径:
//! define life3_s "Abilities\\\\Spells\\\\Items\\\\OrbCorruption\\\\OrbCorruptionSpecialArt.mdl"
//特效附着点:
//! define life3_s1 "chest"
//测试用攻击类型:英雄
//! define life3_at ATTACK_TYPE_HERO
//测试用伤害类型:普通
//! define life3_dt DAMAGE_TYPE_NORMAL
//测试用伤害值:
//! define life3_dm 50
//======================================================================
制作方法如7楼libla所说,但是单位受到伤害事件侦测到的伤害值最小貌似是1,所以我本来想的用1伤害来测试是行不通的。然后就修改了下代码,可以用一个较大值来测试(这个值越大得到的结果越精确,其实这个精确是针对超高防御的,比如我现在使用的50,如果单位可以抵消掉的伤害不超过98%,它就是很精确的了),测试掉的血会及时返回的,单位不会因为这个测试而死亡,当然前提是不要太大。哦,补充一点,测试用的攻击、伤害类型要和携带法球的单位类型一致才可以。最后,百分比依然是可以叠加的,这个法球还真是高防单位的克星呢。
[/codes]

[codes=jass]
//===============================================================
//法球名称:击退           法球类型:无          创意指导:libla
//          攻击有x%几率击退单位y码。
//攻击类型:无
//伤害类型:无
//特效路径:
//! define jitui_s "Abilities\\\\Weapons\\\\CannonTowerMissile\\\\CannonTowerMissile.mdl"
//! define jitui_s1 "Abilities\\\\Weapons\\\\LichMissile\\\\LichMissile.mdl"
//===============================================================
几率的叠加效果是X=1-(1-x1)*(1-x2)*(1-x3)*...,最后拾取的物品的触发优先级高。被击退的单位不能穿山崖,在其100码之内并处于其移动方向±60°范围内的单位将阻挡其移动。
[/codes]

本人系无审美无创意,但是这次至少想有一点毅力,更新到自己满意为止,当然了,如果大家有好的想法也请在这里提出来,只有集思广益才能做出号称“全”法球的效果呢。
回复

使用道具 举报

发表于 2009-6-4 18:03:32 | 显示全部楼层
不错…………只可惜我现在还不能评分………………哎…………
支持~~
回复

使用道具 举报

发表于 2009-6-4 19:43:55 | 显示全部楼层
支持~~
提个创意,无视护甲的法球、击退法球
回复

使用道具 举报

发表于 2009-6-5 00:05:19 | 显示全部楼层
这样会不会太麻烦了
直接用马甲单位携带真技能呢?
回复

使用道具 举报

 楼主| 发表于 2009-6-5 12:57:52 | 显示全部楼层
引用第2楼血戮魔动冰于2009-06-04 18:03发表的  :
不错…………只可惜我现在还不能评分………………哎…………
支持~~

呵呵,如果可以提供一些创意就是对我最大的鼓励捞。
引用第3楼libla于2009-06-04 19:43发表的  :
支持~~
提个创意,无视护甲的法球、击退法球

嗯,谢谢libla兄,击退已经上传,关于无视护甲的法球我不知道怎么做呢。能否提供下思路呢?
引用第4楼n多无名人士于2009-06-05 00:05发表的  :
这样会不会太麻烦了
直接用马甲单位携带真技能呢?

情况不是这样的,演示的目标包括模拟掉所有魔兽自带的法球效果,但是并不限于此,很多效果还是自己设计的。
回复

使用道具 举报

发表于 2009-6-5 15:20:23 | 显示全部楼层
VJ看着累, 不用VJ就好了
回复

使用道具 举报

发表于 2009-6-5 16:34:05 | 显示全部楼层
每次受到伤害自己伤害自己,获得护甲减免百分比,然后把受到的伤害除这个百分比

我也不想专门去学VJ,所以赞成楼上的
回复

使用道具 举报

发表于 2009-6-5 16:49:59 | 显示全部楼层
楼主有空的话欢迎来给我当苦工~
回复

使用道具 举报

发表于 2009-6-5 16:58:45 | 显示全部楼层
LS有空的话欢迎来给我当苦工
回复

使用道具 举报

发表于 2009-6-5 17:08:15 | 显示全部楼层
显然lss是没有空地
回复

使用道具 举报

发表于 2009-6-5 17:49:40 | 显示全部楼层
那么LS肯定有空
回复

使用道具 举报

发表于 2009-6-5 18:35:11 | 显示全部楼层
说了lss没有了

-楼下必然是偶的苦力
回复

使用道具 举报

发表于 2009-6-6 00:08:58 | 显示全部楼层
给4只英雄都买了6个物品以后 发现... 卡了
回复

使用道具 举报

 楼主| 发表于 2009-6-6 01:29:56 | 显示全部楼层
引用第6楼actboy168于2009-06-05 15:20发表的  :
VJ看着累, 不用VJ就好了
其实只用到了文本宏、预定义和库,没有用别的vJ的功能了,感觉除了我的代码写的烂之外,语法应该不会有影响的...吧。
引用第7楼libla于2009-06-05 16:34发表的  :
每次受到伤害自己伤害自己,获得护甲减免百分比,然后把受到的伤害除这个百分比
呵呵,学习了,现在正在做。
引用第8楼eff于2009-06-05 16:49发表的  :
楼主有空的话欢迎来给我当苦工~
唉,很显然,苦工根本就不适合我...
引用第13楼Conflux于2009-06-06 00:08发表的  :
给4只英雄都买了6个物品以后 发现... 卡了
这个真的是一个很糟糕的问题吖。我刚才也试验了下,4个英雄装了6个不同的法球然后一起冲上去A,刚开始确实卡,其实即使一个英雄携带6法球刚开始也会卡一下,但是等所有效果都出现了以后,之后就很流畅了。
还请Conflux重新试一下,如果确定是一直都很卡的话,我会考虑把特效消减些,代码也会尽力优化的。
回复

使用道具 举报

 楼主| 发表于 2009-6-6 16:16:28 | 显示全部楼层
Conflux 还没有回话,我就先说点自以为是的话吧。触发第一次运行以及filterfunc第一次运行的时候可能都会占用较大的资源,所以第一次携带大量的法球造成了“卡”应该是正常情况,而且其中有一个法球是击退效果,这个效果开启了一个0.02秒周期的计时器,貌似也很容易“卡”。
但是呢,在我这里测试,所有的第一次之后,过程就很流畅了,我希望你们的运行结果也是这样。

现在说一下这个演示的一些问题,得益于TimerDataSystem,演示得以摆脱缓存,但也正是因为如此,地图中可能存在计时器滥用的情况,毕竟很多伤害或者加血效果或者特效都必须是在0秒(其实是魔兽的最小时间周期)之后创建才能很好的避免bug的存在。简单的如第一个法球“烈焰”,但英雄携带6个“烈焰”时,如果没有很好的判断,那么它的火焰特效就将在每个被伤害的单位身上创建6次,我的做法是在触发中依次比较伤害半径,触发的末尾就会得到最大半径,可是在不修改函数_unitD()的前提下,我很难知道什么时候是触发的末尾,因此只好使用0秒的计时器来获取最终的半径。排除掉必须使用计时器的情况之外,我把几乎所有可以使用计时器来解决问题的地方都使用了计时器,目的为了方法的统一而提升写代码的效率,但是确实可能有些滥用的情况。

上面的是一方面,演示中一个潜在的bug就是触发和计时器到期之间的一些间隙会造成全局变量的混乱,这个我已经尽量避免,冲突可能性大和比较重要的地方我使用了数组来处理,并且在代码中也有一定的容错机制,但是毕竟可能会有一些疏漏。目前的代码还很少,我尚能仔细检查,等以后法球的种类多了以后,若大家发现了bug,请一定要告知我。

关于libla说的无视护甲的法球也算是一个例子,因为对单位造成伤害会截断当前的代码,所以我的代码书写起来也是格外的小心,我仔细测试了下,目前来看应该没有bug了,但也烦请感兴趣的同学帮忙测试下吧。还有,继续征集法球的创意,谢谢大家。
回复

使用道具 举报

发表于 2009-6-6 17:02:06 | 显示全部楼层
感觉最大的问题还是物理伤害的判断,目前好像只能用硬化皮肤来区分
回复

使用道具 举报

 楼主| 发表于 2009-6-8 01:29:04 | 显示全部楼层
引用第16楼dmcn于2009-06-06 17:02发表的  :
感觉最大的问题还是物理伤害的判断,目前好像只能用硬化皮肤来区分
不同的处理方法有不同的困难,如果想实现演示里的功能同时还保留魔兽原版法球的效果,那样确实比较困难。
但是,如果我们不再使用原来的法球,所有的效果都是用模拟的话,那么我就只需要一个法球,物理伤害的判断简直就是直观了。
回复

使用道具 举报

发表于 2009-6-11 10:26:21 | 显示全部楼层
这个很有趣~支持一下
回复

使用道具 举报

发表于 2009-6-11 12:01:23 | 显示全部楼层
恩。偶有个办法,用马甲打。。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-25 09:46 , Processed in 0.325904 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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