CarlGJung 发表于 2016-2-21 18:49:58

关于hastable教程的疑问

这个教程里的一个演示,然而如何声明unit target?
globals
hashtable HT = null
endglobals

function Init takes nothing returns nothing
call FlushParentHashtable( HT )
set HT = InitHashtable()
endfunction

function Damage_Act takes nothing returns boolean
local integer parentKey = GetHandleId( GetTriggeringTrigger() )
local unit source = LoadUnitHandle( HT, parentKey, 1 )
local unit target = LoadUnitHandle( HT, parentKey, 2 )
call FlushChildHashtable( HT, parentKey )
call TriggerRemoveCondition( GetTriggeringTrigger(), LoadTriggerConditionHandle( HT, parentKey, 3 ) )
call DestroyTrigger( GetTriggeringTrigger() )
set source = null
set target = null
return false
endfunction

function Damage takes unit source, unit target returns nothing
local trigger t = CreateTrigger()
local integer parentKey = GetHandleId( t )
local boolexpr cond = Condition( function Damage_Act )
call SaveUnitHandle( HT, parentKey, 1, source )
call SaveUnitHandle( HT, parentKey, 2, target )
call TriggerRegisterUnitEvent( t, target, EVENT_UNIT_DAMAGED )
call SaveTriggerConditionHandle( HT, parentKey, 3, TriggerAddCondition( t, cond ) )
set t = null
set cond = null
endfunction

CarlGJung 发表于 2016-2-21 20:30:24

好吧,无需声明unit target

CarlGJung 发表于 2016-2-21 20:31:54

要求是:
takes unit source, unit target, real damage
当target受到来自source的伤害(此伤害必须大于20.0)时,source对target额外造成此次伤害40%的伤害
伤害函数:
call UnitDamageTargetBJ( source, target, damage, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC )
此效果从函数被调用开始,target受到5次符合要求的伤害之后,效果消失。
要求:利用hashtable给trigger绑定参数。并且要求对trigger进行排泄。


那么伤害函数写在哪里?

CarlGJung 发表于 2016-2-21 21:40:43

globals
    hashtable hs=InitHashtable()
endglobals
//con的作用是判断条件是否成立,同时执行伤害动作
function con takes nothing returns boolean
    local integer i=GetHandleId(GetTriggeringTrigger())
    local integer js=LoadInteger(hs,i,4)
    //js,为条件达成次数
    local unit u=LoadUnitHandle(hs,i,1)
    local real r=GetEventDamage()
    local real ra=r*.4
    //ra为伤害值的40%
   call UnitDamageTargetBJ(u,gg_unit_hpea_0067,ra,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNIVERSAL)
   //命令单位对gg_unit_hpea_0067造成伤害
    if r>1 then
    //如果条件成立(伤害值大于1),js自增1
      call SaveInteger(hs,i,4,js+1)
      call BJDebugMsg(R2S(r))
    endif
    if js==3then
    //当js等于3时,移除触发器条件,摧毁触发器
      call FlushChildHashtable(hs,i)
      call TriggerRemoveCondition(GetTriggeringTrigger(),LoadTriggerConditionHandle(hs,i,3))
      call DestroyTrigger(GetTriggeringTrigger())
    endif
    set u=null
    return false
endfunction

function InitTrig_ts takes nothing returns nothing
    local trigger t=CreateTrigger()
    local integer i=GetHandleId(t)
    local boolexpr cond=Condition(function con)
    local unit u=GetEventDamageSource()
    call SaveUnitHandle(hs,i,1,u)
    call TriggerRegisterUnitEvent(t,gg_unit_hpea_0067,EVENT_UNIT_DAMAGED)
    call SaveTriggerConditionHandle(hs,i,3,TriggerAddCondition(t,cond))
    set t=null
    set cond=null
endfunction

CarlGJung 发表于 2016-2-21 21:41:57

嗯,我自己做了一个,但是call UnitDamageTargetBJ(u,gg_unit_hpea_0067,ra,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNIVERSAL)并不会被执行

chyj4747 发表于 2016-2-22 00:07:27

你的问题出在触发逻辑上

函数InitTrig_ts里:
local unit u=GetEventDamageSource(),触发器才刚刚创建,连事件都没注册哪来的伤害来源,所以这里相当于u=null
最后没有u=null,也就是没有排泄,当然因为这里声明u的时候本来就是null,所以也没有泄露
触发条件的话应该是不需要移除的,以前有前辈做过测试,动作才会泄露,需要移除,反正我条件从来都不移除的

函数con里:
local unit u=LoadUnitHandle(hs,i,1)改为GetEventDamageSource()
if js==3then,这么写的话相当于在第四次就结束了,而不是你说的五次后结束
并没有判断受到的伤害是否大于20

另外以防万一问下,这个InitTrig_ts你是开始时直接注册的呢还是游戏中动态注册?
如果是开始时直接注册的,那么这个触发整个游戏就只能用一次,也就是5次效果后就不会再发动了

CarlGJung 发表于 2016-2-22 09:45:17

本帖最后由 CarlGJung 于 2016-2-22 09:49 编辑

chyj4747 发表于 2016-2-22 00:07
你的问题出在触发逻辑上

函数InitTrig_ts里:

GA居然还有人!谢谢解答!“local unit u=GetEventDamageSource(),触发器才刚刚创建,连事件都没注册哪来的伤害来源”这个错误,我真揪不出来......
我试验了N次,都达不到演示里的效果,不知道他究竟是怎么做的(蛋疼的教程!)。
local unit u=LoadUnitHandle(hs,i,1)这个只是照搬教程写的。
我不明白的是:作者用的都是局部变量,不知道他怎么进行局部变量的传递的,事件里用局部变量的话(指定单位伤害事件里,作者用局部变量target,来作为触发事件的单位),该怎么激活事件。但我想达到教程里的效果只能用全局变量

CarlGJung 发表于 2016-2-22 09:46:06

本帖最后由 CarlGJung 于 2016-2-22 09:47 编辑

chyj4747 发表于 2016-2-22 00:07
你的问题出在触发逻辑上

函数InitTrig_ts里:

关于伤害判断,我判断的是伤害大于1(方便测试)——r>1.至于动态注册.......我现在只希望这个触发能达到正常的效果,所以没考虑

CarlGJung 发表于 2016-2-22 20:37:23

chyj4747 发表于 2016-2-22 00:07
你的问题出在触发逻辑上

函数InitTrig_ts里:


啊呀,看了下动态注册触发器的教程,和这个演示有点像,难道正确的姿势是动注册吗?

chyj4747 发表于 2016-2-22 23:22:38

假设LZ要的效果是发动技能产生的:
比如,对目标发动技能后,30秒内5次伤害会造成40%额外伤害
globals
    hashtable HT = InitHashtable()
endglobals

function Trig_testDmged takes nothing returns boolean
    local trigger trg = GetTriggeringTrigger()
    local boolean do_destroy = false
    local integer pkey = GetHandleId(trg)
    local unit source         // 伤害来源
    local integer count         // 计数器
    local real dmg            // 受到的伤害
    local real rate = 0.4       // 系数
    if GetTriggerEventId() == EVENT_UNIT_DAMAGED then
      // 单位受到伤害
      set source = LoadUnitHandle(HT, pkey, 0)
      set dmg = GetEventDamage()
      if dmg > 1 and GetEventDamageSource() == source then
            // 伤害大于1且伤害来源是施法者
            call DisableTrigger(trg) // 防止下面的造成伤害动作反复触发受伤事件造成死循环
            call UnitDamageTarget(source, GetTriggerUnit(), dmg*rate, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
            call EnableTrigger(trg)
            
            set count = LoadInteger(HT, pkey, 1) + 1
            if count >= 5 then
                set do_destroy = true
            else
                call SaveInteger(HT, pkey, 1, count)
            endif
      endif
      set source = null
    else
      // 30秒到期
      set do_destroy = true
    endif
   
    if do_destroy then
      // 销毁触发器
      call FlushChildHashtable(HT, pkey)
      call DestroyTrigger(trg)
    endif
   
    set trg = null
   
    return false
endfunction

function Trig_testAct takes nothing returns boolean
    local trigger trg
    local integer pkey
    if GetSpellAbilityId() == '1234' then // 1234换成自定义技能ID
      set trg = CreateTrigger()
      set pkey = GetHandleId(trg)
      call SaveUnitHandle(HT, pkey, 0, GetTriggerUnit()) // 绑定施法者
      call SaveInteger(HT, pkey, 1, 0) // 计数器,记录技能效果触发的次数
      call TriggerRegisterUnitEvent(trg, GetSpellTargetUnit(), EVENT_UNIT_DAMAGED) // 注册施法目标受伤事件
      call TriggerRegisterTimerEvent(trg, 30, false) // 注册30秒到期事件,即技能效果结束
      call TriggerAddCondition(trg, Condition(function Trig_testDmged))
      set trg = null
    endif
    return false
endfunction

//===========================================================================
function InitTrig_test takes nothing returns nothing
    local trigger trg = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(trg, Condition(function Trig_testAct))
    set trg = null
endfunction

CarlGJung 发表于 2016-2-23 19:23:50

chyj4747 发表于 2016-2-22 23:22
假设LZ要的效果是发动技能产生的:
比如,对目标发动技能后,30秒内5次伤害会造成40%额外伤害

泪奔啊!多方求助无人解答,想不到是在貌似已经死了的GA得到了解答!真是太感谢你了!辛苦你写这么长的代码!————果然是动态注册,我刚开始试着补全这个演示时,完全不知道动态注册是什么鬼,然后,就卡了五天————直到今天.......

chyj4747 发表于 2016-2-23 22:28:30

CarlGJung 发表于 2016-2-23 19:23
泪奔啊!多方求助无人解答,想不到是在貌似已经死了的GA得到了解答!真是太感谢你了!辛苦你写这么长的代 ...

死是没死,人还是有几个在的,只不过因为人少,所以都是隔两天才来看看,不像几年前论坛都是隔几小时刷新一次的,现在玩魔兽的都没多少人了,更别说WE了
页: [1]
查看完整版本: 关于hastable教程的疑问