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

BlzUnitDisableAbility Resets Cooldown?

So, I plan to use this particular native to let me disable my ability while the spell is on progress. However, I find it resets the cooldown even when it is about 1/6 of the cooldown is spent while the ability is disabled. I am thinking to just hide the UI, but it kind of makes the user forget they had this ability in the first place until it reappears.

Specific case for me is disabling without hiding, like as following:
  • Unit - For (Triggering unit), Ability KarmaRet_Ability, Disable ability: True, Hide UI: False
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Does it really reset the cooldown? Or is it a UI issue? I know the UI doesn't update properly in some cases.

Assuming it gets resets, a good solution would be to create a system that basically extends these functions. Something like this:
vJASS:
library DisableAbilityExtension

globals
    private hashtable AbilHash = InitHashtable()
    private timer AbilTimer
endglobals

private function DoNothingCallback takes nothing returns nothing
endfunction

function DisableAbilityEx takes unit u, integer abilId, boolean isDisabled returns nothing
    local real cd = 0.0

    if isDisabled then
        // Store the cooldown if necessary before disabling it
        set cd = BlzGetUnitAbilityCooldownRemaining(u, abilId)

        if cd > 0.0 then
            set AbilTimer = CreateTimer()
            call TimerStart(AbilTimer, 1000000, false, function DoNothingCallback)
            call SaveTimerHandle(AbilHash, GetHandleId(u), abilId, AbilTimer)
        endif

        call BlzUnitDisableAbility(u, abilId, true, false)
    else
        // Enable it and start the cooldown if necessary
        call BlzUnitDisableAbility(u, abilId, false, false)

        set AbilTimer = LoadTimerHandle(AbilHash, GetHandleId(u), abilId)
        if AbilTimer != null then
            set cd = TimerGetElapsed(AbilTimer)
            call PauseTimer(AbilTimer)
            call DestroyTimer(AbilTimer)
            if cd > 0.0 then
                call BlzSetUnitAbilityCooldown(u, abilId, GetUnitAbilityLevel(u, abilId) - 1, cd)
            endif
        endif
    endif
endfunction

endlibrary
Edit: I didn't test it, but I think this code will work as a replacement.
Edit 2: Updated again, I'm pretty confident this works.
 
Last edited:
Seems to functionally resets the cooldown in my tests. I'll put the script into test.

Oh yeah, for note, this is checked on 1.31, so might not apply to other patches.

EDIT 3:

The one used in this test map
JASS:
globals
 hashtable AbilHash = InitHashtable()
endglobals

function DisableAbilityEx takes unit u, integer abilId, boolean isDisabled returns nothing
 local real cd = BlzGetUnitAbilityCooldownRemaining(u, abilId)

 if isDisabled then
  // Store the cooldown before disabling it
  call SaveReal( AbilHash, GetHandleId(u), abilId, cd )
  call BlzUnitDisableAbility(u, abilId, true, false)
 else
  // Enable it and start the cooldown
  call BlzUnitDisableAbility(u, abilId, false, false)
  if cd > 0.00 then
   call BlzSetUnitAbilityCooldown( u, abilId, GetUnitAbilityLevel(u, abilId) - 1, LoadReal(AbilHash, GetHandleId(u), abilId) )
  endif
 endif
endfunction

EDIT 2:
Definitely still broken. I'm attaching my map now. Look at KarmaRetCast and KarmaRetDamage for the relevant triggers. The spell has 60 seconds cooldown.
 

Attachments

  • KarmaRetribution.w3x
    117 KB · Views: 1
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
I updated the code again, see my previous post.

What I originally had and what you just posted above is incomplete. I realized I did it wrong a minute after posting.

Edit:
I edited the original post again because I found another mistake! Alright, I'm tapping out for now.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Seems to persist for me with the newest code. It is a weird pickle. Hide ability works extremely well though, which just confuses me even further.
Have you tried disabling the ability after a delay?
  • Wait 0.01 seconds
  • Unit - For (Triggering unit), Ability KarmaRet_Ability, Disable ability: True, Hide UI: False
I think the issue could be that you're disabling it in response to a cast event. I have a feeling that the cooldown doesn't get reset, it's that the cooldown doesn't even start in the first place because a disabled ability can't be put on cooldown.
 
Last edited:
Have you tried disabling the ability after a delay?
  • Wait 0.01 seconds
  • Unit - For (Triggering unit), Ability KarmaRet_Ability, Disable ability: True, Hide UI: False
I think the issue could be that you're disabling it in response to a cast event. I have a feeling that the cooldown doesn't get reset, it's that the cooldown doesn't even start in the first place because a disabled ability can't be put on cooldown.
This solved the issue. Seems the lack of direct event on cooldown is an interesting thing altogether.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
This solved the issue. Seems the lack of direct event on cooldown is an interesting thing altogether.
I imagine it's because the internal code for managing an ability hasn't actually run yet so something like this is happening internally:
vJASS:
function UnitStartsEffectAbility takes nothing returns nothing
 // set event response variables
 // invoke user-made "starts the effect of ability" events
 // -> ALL of your own logic runs here
 // start cooldown of ability
endfunction
And your code gets injected before the start cooldown part of the function. Then internally the start cooldown function has a check to see if an ability is disabled or not before trying to adjust the cooldown, and if it is, it returns early without doing anything.
 
Top