• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

How can I make shield spell absorbing physical damage?

Status
Not open for further replies.
Level 8
Joined
May 12, 2018
Messages
106
I am using Bribe's Damage Engine and TimerUtils(),
I wrote the struct without big problems, but I don't know how to connect the damaged event and the effect. I need your help.
My purpose is to turn off the trigger when Buff is gone or absorbs 200 physical damages, and the same spell is cast for same target that already working, the physical damage absorption is updated to 200.
This is my script.
I would appreciate it if you could check there are any leaks or they are cleaned completely.
JASS:
scope AntiPhysicShell initializer init

  globals
    private constant integer SpellId = 'A026'
    private constant integer BuffId = 'B00M'
    private constant real period = 0.5
    private constant real amount = 200.0
    private group g = CreateGroup()
  endglobals

  private constant function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == SpellId
  endfunction

  private struct Data
    static integer index = 0
    unit target
    boolean hasbuff = false
    real absorb

    static method create takes unit t returns Data
      local Data D = Data.allocate()
      set D.target = t
      set D.absorb = amount
      call GroupAddUnit(g, t)
      if integer(D) > Data.index then
        set Data.index = integer(D)
      endif
      return D
    endmethod

    method onDestroy takes nothing returns nothing
      call UnitRemoveAbility(.target, BuffId)
      call GroupRemoveUnit(g, .target)
        set .hasbuff = false
        set .target = null
        if integer(this) == Data.index then
            set Data.index = Data.index - 1
        endif
    endmethod

    static method SetTarget takes unit target returns nothing
        // this method will search in all the active structs which of them has the  target unit, so it can update the caster properly...
        local integer i = 0
        local Data D
        loop
            exitwhen i > Data.index
            set D = Data(i)
            if D.target == target and D.hasbuff then
                set D.target = target
                set D.absorb = amount
                return
            endif
            set i = i + 1
        endloop
    endmethod

  endstruct

  private function Loop takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local Data D = Data(GetTimerData(t))
    if not D.hasbuff and GetUnitAbilityLevel(D.target, BuffId) > 0 then
        set D.hasbuff = true
    endif
    if D.hasbuff and GetUnitAbilityLevel(D.target, BuffId) > 0 then
    endif
    if ( D.hasbuff and GetUnitAbilityLevel(D.target, BuffId) < 1 ) or D.absorb <= 0 then
        call D.destroy()
        call ReleaseTimer(t)
    endif
    set t = null
  endfunction

  private function Actions takes nothing returns nothing
    local Data D
    local timer t
    local unit u = GetSpellTargetUnit()
    if not IsUnitInGroup(u, g) then
        set D = Data.create(u)
        set t = NewTimer()
        call SetTimerData(t, integer(D))
        call TimerStart(t, period, true, function Loop)
    else
        call Data.SetTarget(u)
    endif
    set t = null
    set u = null
  endfunction

  private function init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
    set t = null
  endfunction

endscope
 
Status
Not open for further replies.
Top