• 🏆 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!

[Spell] problem in reset duration of struct spell

Status
Not open for further replies.
Level 8
Joined
May 12, 2018
Messages
106
I'm making Disarm struct and function, I want the duration of disarm will be reset if same ability used on same target,
but reset duration is not working. It doesn't reset to the specified duration and the effect is immediately turned off when the spell effect stacked.
this is my script.

JASS:
scope Disarm
//Helped by Derdan

  globals
    private constant string model = "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl"
  endglobals

  struct DisarmData
    static integer index = 0
    static group IsDisarmed
  
    unit disarmtarget
    real disarmdur
    effect eff
  
    static method onInit takes nothing returns nothing
      set DisarmData.IsDisarmed = CreateGroup()
    endmethod
 
    static method create takes unit target, real duration returns DisarmData
      local DisarmData D = DisarmData.allocate()
    
      set D.disarmtarget = target
      set D.eff = AddSpecialEffectTarget(model, D.disarmtarget, "head")
      set D.disarmdur = duration

      call BlzSetUnitWeaponBooleanField(target, UNIT_WEAPON_BF_ATTACKS_ENABLED, 0, false)
      call BlzSetUnitWeaponBooleanField(target, UNIT_WEAPON_BF_ATTACKS_ENABLED, 1, false)
      call GroupAddUnit(DisarmData.IsDisarmed, target)

      if integer(D) > DisarmData.index then
        set DisarmData.index = integer(D)
      endif
      return D
    endmethod

    method onDestroy takes nothing returns nothing
      call BlzSetUnitWeaponBooleanField(.disarmtarget, UNIT_WEAPON_BF_ATTACKS_ENABLED, 0, true)
      call BlzSetUnitWeaponBooleanField(.disarmtarget, UNIT_WEAPON_BF_ATTACKS_ENABLED, 1, true)
      call DestroyEffect(.eff)
      set .eff = null
      call GroupRemoveUnit(.IsDisarmed, .disarmtarget)
      if integer(this) == DisarmData.index then
        set DisarmData.index = DisarmData.index - 1
      set this.disarmtarget = null
      endif
    endmethod

    static method SetTarget takes unit target, real duration returns nothing
      local integer i = 0
      local DisarmData D
      local real h = duration
    
      loop
        exitwhen i > DisarmData.index
        set D = DisarmData(i)
        if D.disarmtarget == target and IsUnitInGroup(D.disarmtarget, D.IsDisarmed) then
          if D.disarmdur < h then
          
            if duration < 600 then
              set D.disarmdur = 0.6
              return
            else
              set D.disarmdur = h
              return
            endif
          
          endif
      
        endif
        set i = i + 1
      endloop
    
    endmethod

  endstruct

  private function Loop takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local DisarmData D = DisarmData(GetTimerData(t))
  
    if D.disarmdur > 0 and UnitAlive(D.disarmtarget) then
      set D.disarmdur = D.disarmdur - 0.5
    elseif D.disarmdur <= 0 or GetUnitTypeId(D.disarmtarget) == 0 or IsUnitType(D.disarmtarget, UNIT_TYPE_DEAD) then
      call D.destroy()
      call ReleaseTimer(t)
    endif

    set t = null
  endfunction

  function DisarmAction takes unit u, real duration returns nothing
    local DisarmData D
    local timer t
    local unit target = u
  
    if not IsUnitInGroup(target, DisarmData.IsDisarmed) then
      set D = DisarmData.create(target,duration)
      set t = NewTimer()
      call SetTimerData(t, integer(D))
      call TimerStart(t, 0.5, true, function Loop)
    else
      call DisarmData.SetTarget(target, duration)
    endif
    set target = null
    set t = null
  endfunction

endscope

i made this referring to How to develop spells with effects over time - WC3 Modding Information Center
and using TimerUtils.
 
Last edited:
Ok, so from my understanding, you use the DisarmAction to say "I want this guy to be disarmed".
If it's already disarmed, you call the SetTarget.
In SetTarget, you for-each the structs to find the struct with the target (and also check if it is in your unit-group, something you already did in DisarmAction function).
When you have found the struct with the target, you check if disarmdur on existing struct is less than new duration, and if so, you check if new duration is less than 600, you set disarmdur to 0.6 (something I believe looks strange), otherwise you set it to h (same as new duration. You set h once, so it is always same as the new duration)

This means if you input less than 600, you get 2 "ticks" of disarm (If I read your "loop" correctly).

What value is your duration?
When you create it, you use the duration directly as the disarmdur, meaning it behaves differently from the "SetTarget" (SetTarget is actually "UpdateDurationForTarget", or something like that?)
 
Level 8
Joined
May 12, 2018
Messages
106
Ok, so from my understanding, you use the DisarmAction to say "I want this guy to be disarmed".
If it's already disarmed, you call the SetTarget.
In SetTarget, you for-each the structs to find the struct with the target (and also check if it is in your unit-group, something you already did in DisarmAction function).
When you have found the struct with the target, you check if disarmdur on existing struct is less than new duration, and if so, you check if new duration is less than 600, you set disarmdur to 0.6 (something I believe looks strange), otherwise you set it to h (same as new duration. You set h once, so it is always same as the new duration)

This means if you input less than 600, you get 2 "ticks" of disarm (If I read your "loop" correctly).

What value is your duration?
When you create it, you use the duration directly as the disarmdur, meaning it behaves differently from the "SetTarget" (SetTarget is actually "UpdateDurationForTarget", or something like that?)
Yes Set Target is for Updating Duration for target.
my writing spell's disarm duration is 4(resistant)/8(normalunit), over 600s is just for destroying disarm effect when physical dispel ability used :)
 
Status
Not open for further replies.
Top