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

[JASS] native cooldown don't work

Status
Not open for further replies.
Level 4
Joined
Aug 2, 2015
Messages
63
how to use these native correctly because when i use it , it doesn't works well
Code:
native BlzEndUnitAbilityCooldown                   takes unit whichUnit, integer abilCode returns nothing
 
Level 20
Joined
May 16, 2012
Messages
635
If you are using this native inside a "EVENT_PLAYER_UNIT_SPELL_EFFECT" event then it will not work, since you cannot change an ability cooldown from its usege event. The way i got around it is to just use a timer to reset the desired ability cooldown after a very short delay like 0.01 seconds. See my example below:

JASS:
scope Atemporal initializer Init

private function Reset takes nothing returns nothing
    //Loading the stuff that was saved into the hashtable
    local timer t = GetExpiredTimer()
    local unit caster = LoadUnitHandle(udg_HeroHash, GetHandleId(t), 1)
    local integer abilCode = LoadInteger(udg_HeroHash, GetHandleId(t), 2)

    //Reset the ability cooldown for the unit
    call BlzEndUnitAbilityCooldown(caster, abilCode)
  
    //Flushing the child keys of the hastable, so it do not leak
    //Also very important to pause the timer before destroying it when using hashtables
    call FlushChildHashtable(udg_HeroHash, GetHandleId(t))
    call PauseTimer(t)
    call DestroyTimer(t)
  
    //And again, null handle type locals
    set t = null
    set caster = null
endfunction

private function Conditions takes nothing returns nothing
    //the caster
    local unit caster = GetTriggerUnit()
    //the ability triggering the event
    local integer abilCode = GetSpellAbilityId()
     // Checks if the ability being cast is an Ultimate ability, in my map ultimates requires level 10
    local boolean ultimate = (BlzGetAbilityIntegerField(BlzGetUnitAbility(caster, abilCode), ABILITY_IF_REQUIRED_LEVEL) >= 10)
    //Heal potions in my map have no cooldown, so i'm leaving them out.
    local boolean healPotion = (abilCode == 'AIre')
    //I've created this trigger to fit an item that gives the wearer 15% chance to reset an ability cooldown after casting it (5% for Ultimate abilities)
    //Also the item has an active ability itself, that will reset all abilities cooldowns, so i dont want that its effect reset it self
    local boolean self = (abilCode == 'A019')
    //The timer that will reset the ability if its within its chance to be reseted.
    local timer t

    //if not the item ability
    if self then
        call UnitResetCooldown(caster)
    //if the triggering unit has the item and its not healing pot ability being used (you could easily adjust this if else block to suit your needs)
    elseif (UnitHasItemOfType(caster, 'I08U') > 0 and not healPotion) then
        //checking if its an ultimate ability and the 5% chance being taken into account
        if (ultimate and GetRandomReal(1, 100) <= 5) then
            //HERE is where the magic needs to happen. Like i said, you cannot use the new native within the event actions,
            //but after a verry shot delay you can so i'm using a non-looping timer with very short time to reset the ability
            //By saving the unit and the ability being cast in a hashtable i can access them later to be used with the native
            //If you dont know how Hashtables works, i suggest you give a quick search in Hive, there's plenty of resources
            //explaining it.
            set t = CreateTimer()
            call SaveUnitHandle(udg_HeroHash, GetHandleId(t), 1, caster)
            call SaveInteger(udg_HeroHash, GetHandleId(t), 2, abilCode)
            call TimerStart(t, 0.01, false, function Reset)
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\RitualDagger\\RitualDaggerTarget.mdl", caster, "origin"))
        elseif (not ultimate and GetRandomReal(1, 100) <= 15) then
            //Same as above, but for non Ultimates, so with a higher chance of triggering
            set t = CreateTimer()
            call SaveUnitHandle(udg_HeroHash, GetHandleId(t), 1, caster)
            call SaveInteger(udg_HeroHash, GetHandleId(t), 2, abilCode)
            call TimerStart(t, 0.01, false, function Reset)
            call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl", caster, "origin"))
        endif
    endif
    //VERY IMPORTANT** Do not use a Timer with 0 cooldown, or else your unit will be stuck casting the ability until it ran out of mana
    //Always null local variables that are of a handle type in JASS or else you will leak its reference.
    //udg_HeroHash is a hashtable that i created, substitute for your own
    set t = null
    set caster = null
endfunction
//===========================================================================
private function Init takes nothing returns nothing
    //This is a function provided in a library to reduce the amount of code necessary to create Player Event trigger
    // you can find it here: https://www.hiveworkshop.com/threads/snippet-registerplayerunitevent.203338/
    //of course you could use the followin as well
    /*
    set YourTrigger = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(YourTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(YourTrigger, Condition(function Conditions))
    */
    call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions)
endfunction

endscope

Read from bottom to top for better understanding
 
Status
Not open for further replies.
Top