Cooldown system issues

Nexor

...
Reaction score
74
I've made with some help a cooldown system and I want the Heroes to decrease the cooldown by every cast to a minimum time of cooldown. the only issue is that it decreases everytime with 1 no matter what values I write there.
I tried to decrease it with 0.001 or set the value to value*0.99 but again, decreases with 1 and the function runs twice :S it's really strange.
Here's what I got:

JASS:
library LearnAbilities initializer InitTrig_Cooldown_set_and_fire uses CDSys
globals
    private constant integer HASH = 8192
    private real array ABIL
    real array abil
    private integer array INDEX
    integer array index
endglobals

private struct abil
    static method operator []= takes integer id, real value returns nothing
        set ABIL[id-(id/HASH)*HASH] = R2I(value)   // This was the issue should be value instead of R2I(value)
    endmethod
    static method operator[] takes integer id returns real
        return ABIL[id-(id/HASH)*HASH]
    endmethod
endstruct

private struct index
    static method operator []= takes integer id, integer value returns nothing
        set INDEX[id-(id/HASH)*HASH] = value
    endmethod
    static method operator[] takes integer id returns integer
        return INDEX[id-(id/HASH)*HASH]
    endmethod
endstruct


function Trig_Learn_ability_Actions takes nothing returns nothing
    local integer abi = GetLearnedSkill()
    local integer i = index[abi]
    local real abil_id = abil<i>
    local integer fake = &#039;A003&#039;
    
    if abil_id != 0 then
        debug call BJDebugMsg(&quot;Ability Id: &quot;+I2S(abi))
        debug call BJDebugMsg(&quot;Index: &quot;+I2S(i))
        debug call BJDebugMsg(&quot;Cooldown: &quot;+R2S(abil_id))
        if i == 1 then
            set fake = &#039;A003&#039;
        elseif i == 2 then
            set fake = &#039;A000&#039;
        elseif i == 3 then
            set fake = &#039;A001&#039;
        elseif i == 4 then
            set fake = &#039;A002&#039;
        endif
        call UnitAddCooldown(HERO, i, abi,fake,abil_id)
    endif
endfunction

function Trig_Cooldown_Add_Actions takes nothing returns nothing
    local integer abi = GetSpellAbilityId()
    local integer i = index[abi]
    local real abil_id = abil<i>
    call RunCooldown( GetTriggerUnit(), abi)
    call Cooldown(GetTriggerUnit(), i, abil_id)
    
    call BJDebugMsg(&quot;Old CD: &quot;+R2S(abil[index[abi]]))
    set abil[index[abi]] = abil[index[abi]] * 0.9999
    call BJDebugMsg(&quot;New CD: &quot;+R2S(abil[index[abi]]))
    
    call TriggerSleepAction( 0.20 )
    call SetUnitManaPercentBJ( GetTriggerUnit(), 100 )
endfunction

//===========================================================================
//===========================================================================
function InitTrig_Cooldown_set_and_fire takes nothing returns nothing
    local trigger t1 = CreateTrigger(  )
    local trigger t2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t1, EVENT_PLAYER_HERO_SKILL )
    call TriggerAddAction( t1, function Trig_Learn_ability_Actions )
    call TriggerRegisterAnyUnitEventBJ( t2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( t2, function Trig_Cooldown_Add_Actions )
    set t1 = null
    set t2 = null
    
    set index[&#039;AHtb&#039;] = 1
    set abil[index[&#039;AHtb&#039;]] = 5.
    set index[&#039;AHtc&#039;] = 2
    set abil[index[&#039;AHtc&#039;]] = 10.
    set index[&#039;AHav&#039;] = 3
    set abil[index[&#039;AHav&#039;]] = 15.
    
endfunction
endlibrary</i></i>



Okay I solved the issue with the 1 thing, but the function still runs twice and I don't know why :S:S
 

Viikuna

No Marlo no game.
Reaction score
265
Post the whole code pls, so we can see what UnitAddCooldow does.

EDIT. Actually, i KNOW THE REASON.

lols caps. Your initializer function has InitTrig prefix, so it might be that its called twice. Once by Blizzards InitTrig thingies, and once by JassHelpers code initializer thingy, which exists so we wouldnt have to type that InitTrig alla time.

Add one BJDebugMsg to your initializer.
 

Nexor

...
Reaction score
74
okay, here's what I got so far, it's a very long code :S

JASS:
library CDSys initializer Cooldown_set_and_fire requires PUI, ABC

    globals
        constant integer MAX_ABILITY = 6
        constant real SCROLL_CD = 5
        private constant string Effect       = &quot;Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl&quot;
        private constant string Attach       = &quot;origin&quot;
        private constant boolean Text_Bool   = true   //Display text when cooldown is ready
        private string CD_Text               = &quot;|r is ready to use!&quot; // Text after cooldown runs (local player)
        private constant real NewCooldownMod = 0.02
    endglobals
    
    private struct CD
        private static integer pui_unit
        private static thistype pui_data
        private static integer i
        unit u
        timer array t [MAX_ABILITY]
        integer array abil [MAX_ABILITY]
        integer array abil2 [MAX_ABILITY]
        integer array lv [MAX_ABILITY]
        real array dur [MAX_ABILITY]
        boolean array t_ready [MAX_ABILITY]
        integer array numberofuses [MAX_ABILITY]
        
        static method operator [] takes unit whichunit returns thistype
            set thistype.pui_data = thistype(GetUnitIndex(whichunit))
            if thistype.pui_data.u != whichunit then
                if thistype.pui_data.u != null then
                    set thistype.i = 1
                    loop
                    exitwhen thistype.i &gt; MAX_ABILITY
                        set thistype.pui_data.abil[thistype.i] = 0
                        set thistype.pui_data.abil2[thistype.i] = 0
                        set thistype.pui_data.lv[thistype.i] = 0
                        set thistype.pui_data.dur[thistype.i] = 0.
                        set thistype.pui_data.t_ready[thistype.i] = true
                        set thistype.pui_data.numberofuses[thistype.i] = 0
                        set thistype.i = thistype.i + 1
                    endloop
                endif
                set thistype.pui_data.u = whichunit    
            endif
            return thistype.pui_data
        endmethod
        
        //Never call create or destroy on this struct.
    endstruct
    
    globals
        private CD d
        private integer pos
    endglobals
    
    private function NewCooldown takes unit whichunit, integer whichslot, real cd returns real
        return cd - (NewCooldownMod*CD[whichunit].lv[whichslot])
    endfunction
    
    private function UnitRemoveCooldown takes unit whichunit, integer whichslot returns nothing
        set d = CD[whichunit]
        call UnitRemoveAbility(d.u,d.abil[pos])
        set d.abil[whichslot] = 0
        set d.abil2[whichslot] = 0
        set d.dur[whichslot] = 0
        set d.lv[whichslot] = 0
        set d.t_ready[whichslot] = true
    endfunction
    
    private function RemoveCD takes nothing returns nothing
        set d = GetTimerStructA(GetExpiredTimer())
        set pos = GetTimerStructB(GetExpiredTimer())
        call SetPlayerAbilityAvailable(GetOwningPlayer(d.u),d.abil[pos],true)
        
        if d.abil2[pos] != 0 then
            call UnitRemoveAbility(d.u,d.abil2[pos])
            call DestroyEffect( AddSpecialEffectTarget(Effect, d.u, Attach)) 
            if Text_Bool then
                call DisplayTimedTextToPlayer(GetOwningPlayer(d.u), 0,0,5, &quot;|cffffcc00&quot;+GetObjectName(d.abil[pos])+CD_Text)
            endif
        else
            call UnitRemoveCooldown(d.u,pos)
        endif
        call PauseTimer(d.t[pos])
        set d.t_ready[pos] = true
        call UnitResetCooldown(d.u)
    endfunction
    
    private function AddCD takes nothing returns nothing
        set d = GetTimerStructA(GetExpiredTimer())
        set pos = GetTimerStructB(GetExpiredTimer())
        call SetPlayerAbilityAvailable(GetOwningPlayer(d.u),d.abil[pos],false)
        if d.abil2[pos] != 0 then
            call UnitAddAbility(d.u,d.abil2[pos])
        else
            call UnitRemoveAbility(d.u,d.abil[pos])
        endif
        call PauseTimer(d.t[pos])
        set d.t_ready[pos] = false
        call TimerStart(d.t[pos],d.dur[pos],false,function RemoveCD)
    endfunction
    
    function TimerReady takes unit whichunit, integer whichslot returns boolean
        set d = CD[whichunit]
        return d.t_ready[whichslot]
    endfunction
    
    function UnitAddCooldown takes unit whichunit, integer whichslot, integer abil, integer abil2, real duration returns nothing
        set d = CD[whichunit]
       if d.t[whichslot] == null then
            set d.t[whichslot] = CreateTimer()
            call SetTimerStructA(d.t[whichslot],d)
            call SetTimerStructB(d.t[whichslot],whichslot)
        endif
        set d.abil[whichslot] = abil
        set d.abil2[whichslot] = abil2
        set d.dur[whichslot] = duration
        set d.lv[whichslot] = GetUnitAbilityLevel(d.u,d.abil[whichslot])
    endfunction
    
    function Cooldown takes unit whichunit, integer whichslot, real duration returns nothing
       set d = CD[whichunit]
       if d.t[whichslot] == null then
            set d.t[whichslot] = CreateTimer()
            call SetTimerStructA(d.t[whichslot],d)
            call SetTimerStructB(d.t[whichslot],whichslot)
        endif
        set d.dur[whichslot] = duration
        set d.t_ready[whichslot] = false
        set d.lv[whichslot] = GetUnitAbilityLevel(d.u,d.abil[whichslot])
        call PauseTimer(d.t[whichslot])
        call TimerStart(d.t[whichslot],.0,true,function AddCD) //Allow the spell to be casted
    endfunction
    
    function ResetCooldown takes unit whichunit, integer whichslot returns nothing
        set d = CD[whichunit]
        if d.abil[whichslot] &gt; 0 and TimerGetRemaining(d.t[whichslot]) != 0 and d.t_ready[whichslot] == false then
            call PauseTimer(d.t[whichslot])
            call TimerStart(d.t[whichslot],.0,false,function RemoveCD)
        endif
    endfunction
    
    function ResetCooldownAll takes unit whichunit returns nothing
        local integer i = 1
        set d = CD[whichunit]
        loop
            exitwhen i &gt; MAX_ABILITY
            call ResetCooldown(d.u, i)
            set i = i + 1
        endloop
    endfunction

globals
    private constant real MIN_MULT = 0.75  // Minimum multiplier for cooldown reduction
    private constant integer HASH = 8192
    public real array ABIL
    public integer array INDEX
    public integer array ITEM
    public real array CDMOD
    real array cdmod
    integer array item_type
    real array abili
    integer array index
endglobals

public struct abili
    static method operator []= takes integer id, real value returns nothing
        set ABIL[id-(id/HASH)*HASH] = value
    endmethod
    static method operator[] takes integer id returns real
        return ABIL[id-(id/HASH)*HASH]
    endmethod
endstruct

public struct cdmod
    static method operator []= takes integer id, real value returns nothing
        set CDMOD[id-(id/HASH)*HASH] = value
    endmethod
    static method operator[] takes integer id returns real
        return CDMOD[id-(id/HASH)*HASH]
    endmethod
endstruct

public struct index
    static method operator []= takes integer id, integer value returns nothing
        set INDEX[id-(id/HASH)*HASH] = value
    endmethod
    static method operator[] takes integer id returns integer
        return INDEX[id-(id/HASH)*HASH]
    endmethod
endstruct

public struct item_type
    static method operator []= takes integer id, integer value returns nothing
        set ITEM[id-(id/HASH)*HASH] = value
    endmethod
    static method operator[] takes integer id returns integer
        return ITEM[id-(id/HASH)*HASH]
    endmethod
endstruct
    
    function RestartCooldown takes unit whichunit, integer whichslot returns nothing
        set d = CD[whichunit]
        if d.abil[whichslot] != 0 and abili[whichslot] &gt; 0 then
            call Cooldown(whichunit, whichslot, d.dur[whichslot])
        endif
    endfunction
    
    function RestartCooldownAll takes unit whichunit returns nothing
        local integer i = 1
        set d = CD[whichunit]
        loop
            exitwhen i &gt; MAX_ABILITY
            if d.abil<i> != 0 and abili<i> &gt; 0 then
                call RestartCooldown(d.u, i)
            endif
            set i = i + 1
        endloop
    endfunction
    
    function AddCooldown takes unit whichunit, integer whichslot, real time returns nothing
        set d = CD[whichunit]
        if d.abil[whichslot] &gt; 0 and TimerGetRemaining(d.t[whichslot])+time &gt; 0 then
            call PauseTimer(d.t[whichslot])
            //set d.dur[whichslot] = time
            if time != 0 then
                call TimerStart(d.t[whichslot],TimerGetRemaining(d.t[whichslot])+time,false,function RemoveCD)        
            endif
        endif
    endfunction
    
    function MultiplyCooldown takes unit whichunit, integer whichslot, real multi returns nothing
        set d = CD[whichunit]
        if d.abil[whichslot] &gt; 0 and multi &gt; 0.0 then
            call PauseTimer(d.t[whichslot])
            //set d.dur[whichslot] = time
            if TimerGetRemaining(d.t[whichslot])*multi &gt; 0 then
                call TimerStart(d.t[whichslot],TimerGetRemaining(d.t[whichslot])*multi,false,function RemoveCD)    
            else
                call TimerStart(d.t[whichslot],0.,false,function RemoveCD)    
            endif
        endif
    endfunction
    
    function GetRemainingCooldown takes unit whichunit, integer whichslot returns real
        return TimerGetRemaining(CD[whichunit].t[whichslot])
    endfunction
    
    function GetCooldown takes unit whichunit, integer whichslot returns real
        return CD[whichunit].dur[whichslot]
    endfunction
    
    function GetAbilityNameByIndex takes unit whichunit, integer whichslot returns string
        return GetObjectName(CD[whichunit].abil[whichslot])
    endfunction
    
    function GetAbilityByIndex takes unit whichunit, integer whichslot returns integer
        return CD[whichunit].abil[whichslot]
    endfunction
    
    function RunCooldown takes unit whichunit, integer abil returns nothing
        local integer i = 1
        set d = CD[whichunit]
        loop
            exitwhen i &gt; MAX_ABILITY
            if d.abil<i> == abil then
                call Cooldown(whichunit, i, d.dur<i>)
            endif
            set i = i + 1
        endloop
    endfunction
    
    function Ability2Index takes unit whichunit, integer abil_id returns integer
        local integer count = 1
        set d = CD[whichunit]
        loop
        exitwhen count &gt; MAX_ABILITY
            if CD[whichunit].abil[count] == abil_id then
                return count
            endif
            set count = count + 1
        endloop
        return 0
    endfunction
    
    function GetBaseCooldown takes unit whichunit, integer whichslot returns real
        return abili[GetAbilityByIndex(whichunit, whichslot)]
    endfunction
    
    function AddUses takes unit whichunit, integer whichslot, integer use returns nothing
        set d = CD[whichunit]
        set d.numberofuses[whichslot] = d.numberofuses[whichslot] + use
    endfunction
    
    function GetUses takes unit whichunit, integer whichslot returns integer
        set d = CD[whichunit]
        return d.numberofuses[whichslot]
    endfunction

function LearnAbility_Actions takes nothing returns nothing
    local integer abi = GetLearnedSkill()
    local integer i = index[abi]
    local real abil_cd = abili[abi]
    local integer fake
    
    
    debug call BJDebugMsg(I2S(i)+&quot; - &quot;+R2S(abil_cd))
    
    if GetUnitAbilityLevel(GetTriggerUnit(), abi) != 1 then
        set abil_cd = CD[GetTriggerUnit()].dur<i>
    endif
    
    if abil_cd != 0 then
        if i == 1 then
            set fake = &#039;A003&#039;
        elseif i == 2 then
            set fake = &#039;A000&#039;
        elseif i == 3 then
            set fake = &#039;A001&#039;
        elseif i == 4 then
            set fake = &#039;A002&#039;
        endif
        call UnitAddCooldown( GetTriggerUnit(), i, abi, fake, abil_cd )
    endif
    
endfunction

function AddCooldown_Actions takes nothing returns nothing
    local integer abi = GetSpellAbilityId()
    local integer i = index[abi]
    local real abil_cd = abili[abi] * MIN_MULT
    local real cd = GetCooldown( GetTriggerUnit(), i)
    local real newcd = 0
    
    if i != 5 then
        set newcd = NewCooldown(GetTriggerUnit(),i,cd)
        if newcd &lt; abil_cd then
            set newcd = abil_cd
        endif
    else
        set newcd = cd
    endif
    
    
    call Cooldown(GetTriggerUnit(), i, newcd)
    call AddUses(GetTriggerUnit(),i,1)
    call UnitResetCooldown(GetTriggerUnit())
endfunction

function AddCooldown_Conditions takes nothing returns boolean
    return IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true
endfunction

//! runtextmacro Globals( &quot;Runes&quot;, &quot;item Item&quot;, &quot;real X&quot;, &quot;real Y&quot; )

//! runtextmacro Callback( &quot;Runes&quot;, &quot;call CreateItem( GetItemTypeId(Item_Runes), X_Runes, Y_Runes)&quot; )

function Trig_Runes_Actions takes nothing returns nothing
    local integer itype = GetItemTypeId( GetManipulatedItem() )
    local integer atype
    
    if GetItemTypeId(GetManipulatedItem()) == &#039;I000&#039; then
        call ResetCooldownAll( GetTriggerUnit() )
        //! runtextmacro Timer( &quot;Runes&quot;,&quot;set Item_Runes = GetManipulatedItem()&quot;,&quot;set X_Runes = GetItemX(Item_Runes)&quot;,&quot;set Y_Runes = GetItemY(Item_Runes)&quot; )
    elseif GetItemTypeId(GetManipulatedItem()) == &#039;I001&#039; then
        call SetUnitManaPercentBJ(GetTriggerUnit(), 100)
        call SetUnitLifePercentBJ(GetTriggerUnit(), 100)
        //! runtextmacro Timer( &quot;Runes&quot;,&quot;set Item_Runes = GetManipulatedItem()&quot;,&quot;set X_Runes = GetItemX(Item_Runes)&quot;,&quot;set Y_Runes = GetItemY(Item_Runes)&quot; )
    elseif GetItemType( GetManipulatedItem()) == ITEM_TYPE_POWERUP then
        set atype = item_type[itype]
        if CD[GetTriggerUnit()].abil[index[atype]] != 0 then
            if GetLocalPlayer() == GetOwningPlayer( GetTriggerUnit() ) then
                call ClearTextMessages()
            endif
            call IssueImmediateOrder(GetTriggerUnit(), &quot;stop&quot;)
            call SetUnitAnimation( GetTriggerUnit(), &quot;stand&quot; )
            call DisplayTimedTextToPlayer(GetOwningPlayer(GetTriggerUnit()), 1,-1,5,&quot;|cffffcc00You can&#039;t learn a new ability!|r&quot;)
            //! runtextmacro Timer( &quot;Runes&quot;,&quot;set Item_Runes = GetManipulatedItem()&quot;,&quot;set X_Runes = GetItemX(Item_Runes)&quot;,&quot;set Y_Runes = GetItemY(Item_Runes)&quot; )
        else
            call UnitAddAbility(GetTriggerUnit(), atype)
            call UnitAddCooldown( GetTriggerUnit(), index[atype], atype, 0,abili[atype])
        endif
    endif
endfunction
//===========================================================================
//===========================================================================
//===========================================================================
function Cooldown_set_and_fire takes nothing returns nothing
    local trigger t1 = CreateTrigger(  )
    local trigger t2 = CreateTrigger(  )
    local trigger t3 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t3, EVENT_PLAYER_UNIT_PICKUP_ITEM )
    call TriggerAddAction( t3, function Trig_Runes_Actions )
    call TriggerRegisterAnyUnitEventBJ( t1, EVENT_PLAYER_HERO_SKILL )
    call TriggerAddAction( t1, function LearnAbility_Actions )
    call TriggerRegisterAnyUnitEventBJ( t2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( t2, function AddCooldown_Actions )
    call TriggerAddCondition( t2, Condition( function AddCooldown_Conditions ) )
    set t1 = null
    set t2 = null
    set t3 = null
    
    //Mountain King abilities
    set index[&#039;AHtb&#039;] = 1
    set abili[&#039;AHtb&#039;] = 5.
    set index[&#039;AHtc&#039;] = 2
    set abili[&#039;AHtc&#039;] = 10.
    set index[&#039;AHbh&#039;] = 3
    set abili[&#039;AHbh&#039;] = -1
    set index[&#039;AHav&#039;] = 4
    set abili[&#039;AHav&#039;] = 15.
    //Blood Mage abilities
    set index[&#039;AHfs&#039;] = 1
    set abili[&#039;AHfs&#039;] = 12.
    set index[&#039;AHbn&#039;] = 2
    set abili[&#039;AHbn&#039;] = 20.
    set index[&#039;AHdr&#039;] = 3
    set abili[&#039;AHdr&#039;] = 8.
    set index[&#039;AHpx&#039;] = 4
    set abili[&#039;AHpx&#039;] = 30.
    //Water Guardian abilties
    set index[&#039;A006&#039;] = 1
    set abili[&#039;A006&#039;] = 15
    set index[&#039;A005&#039;] = 2
    set abili[&#039;A005&#039;] = 14
    set index[&#039;A004&#039;] = 3
    set abili[&#039;A004&#039;] = -1
    set index[&#039;A008&#039;] = 4
    set abili[&#039;A008&#039;] = 20
    //
    //Scroll Abilities
    //================
    //Scroll of Strength
    set index[&#039;A009&#039;] = 5
    set abili[&#039;A009&#039;] = SCROLL_CD
    set item_type[&#039;I002&#039;] = &#039;A009&#039;
    //Scroll of Agility
    set index[&#039;A00A&#039;] = 5
    set abili[&#039;A00A&#039;] = SCROLL_CD
    set item_type[&#039;I003&#039;] = &#039;A00A&#039;
    //Scroll of Intelligence
    set index[&#039;A00B&#039;] = 5
    set abili[&#039;A00B&#039;] = SCROLL_CD
    set item_type[&#039;I004&#039;] = &#039;A00B&#039;
    //Not In Use Abilities
    //====================
    //Drain Spirit
    set index[&#039;A00E&#039;] = 1
    set abili[&#039;A00E&#039;] = 10
endfunction
endlibrary</i></i></i></i></i>
 

Nexor

...
Reaction score
74
The abilities get messed up. This system works the following:
-Learn ability
-cast ability -> go in cooldown, add fake ability to caster
-after cooldown -> change back to castable ability

But now when I cast the ability, the other player with the same unit will go into cooldown with the same ability :S:S
 

Nexor

...
Reaction score
74
Sorry for bumping too early, I really need this system to get working I promised it to my buddies :D:D
They'll kick me if I'm not ready with it, but I can't find the problem that occurs when two of the same unit-type cast a spell :S
 

Jesus4Lyf

Good Idea™
Reaction score
397
Your code is not really readable. You have functions named "Cooldown, AddCD, UnitAddCooldown, ResetCooldown, ResetCooldownAll, AddUses, AddCooldown_Actions" all of which could (judging just by the name) do nearly the same thing. We don't know what each function should do, so I don't like your chances of getting help.

I suggest you restructure your code. ;)
(As in, rewrite.)
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
//  Functions :
//
//  GetUnitAbilityCooldown(unit whichUnit, integer ability&#039;s id) -&gt; real
//  IsUnitAbilityCoolingDown(unit whichUnit, integer ability&#039;s id) -&gt; boolean
//  ResetUnitAbilityCooldown(unit whichUnit, integer ability&#039;s id)
//
//  Spells API :
//  set FakeAbility[which ability] = which fake ability (Automatically get registered in system.)
//  set AbilityCooldown[which ability][which level] = duration(real)
//
library CooldownSystem initializer Init requires AIDS

    globals
        private constant integer FAKE_ABIL = StringHash(&quot;Fake Ability&quot;)
        private constant integer FLAG = StringHash(&quot;Flag&quot;)
        private constant integer ID = StringHash(&quot;Data&quot;)
        private hashtable ht
    endglobals
    
    private struct AbilData
        private static thistype d
        timer t
        integer abil_id
        integer lv
        unit u
        
        static method create takes nothing returns thistype
            set thistype.d = thistype.allocate()
            if thistype.d.t == null then
                set thistype.d.t = CreateTimer()
                call SaveInteger(ht,GetHandleId(thistype.d.t),ID,thistype.d)
            endif
            return thistype.d
        endmethod
    endstruct
    
    private struct Cooldown extends array
        private static timer t = CreateTimer()
        private static thistype d
        private static integer abil_id
        private static integer lv
        private static AbilData abil
        
        static method resetcooldown takes unit whichUnit, integer whichAbil returns nothing
            set thistype.d = thistype[whichUnit]
            set thistype.abil = LoadInteger(ht,thistype.d,whichAbil)
            if thistype.abil != 0 then
                call UnitRemoveAbility(whichUnit,LoadInteger(ht,thistype.abil.abil_id,FAKE_ABIL))
                call UnitAddAbility(whichUnit,thistype.abil.abil_id)
                call SetUnitAbilityLevel(whichUnit,thistype.abil.abil_id,thistype.abil.lv)
                call RemoveSavedInteger(ht,thistype.d,thistype.abil.abil_id)
                call thistype.abil.destroy()
                call thistype.d.AIDS_removeLock()
            endif
        endmethod
        
        static method stopcooldown takes nothing returns nothing
            set thistype.abil = LoadInteger(ht,GetHandleId(GetExpiredTimer()),ID)
            call resetcooldown(thistype.abil.u,thistype.abil_id)
        endmethod
        
        static method startcooldown takes nothing returns nothing
            call UnitRemoveAbility(thistype.d.unit,thistype.abil_id)
            call UnitAddAbility(thistype.d.unit,LoadInteger(ht,abil_id,FAKE_ABIL))
            call TimerStart(thistype.abil.t,LoadReal(ht,thistype.abil_id,thistype.lv),false,function thistype.stopcooldown)
        endmethod
        
        static method fire takes nothing returns boolean
            set thistype.abil_id = GetSpellAbilityId()
            if LoadInteger(ht,thistype.abil_id,0) == 1 then
                set thistype.d = thistype[GetTriggerUnit()]
                set thistype.lv = GetUnitAbilityLevel(thistype.d.unit,thistype.abil_id)
                set thistype.abil = AbilData.create()
                set thistype.abil.abil_id = thistype.abil_id
                set thistype.abil.u = thistype.d.unit
                call SaveInteger(ht,thistype.d,thistype.abil_id,thistype.abil)
                call TimerStart(thistype.t,0.,false,function thistype.startcooldown)
                call thistype.d.AIDS_addLock()
            endif
            return false
        endmethod
        
        method AIDS_onDestroy takes nothing returns nothing
            call FlushChildHashtable(ht,this)
        endmethod
        //! runtextmacro AIDS()
    endstruct
    
    struct FakeAbility
        static method operator []= takes integer abil_id, integer fakeAbil returns nothing
            call SaveInteger(ht,abil_id,0,1)//flag it
            call SaveInteger(ht,abil_id,FAKE_ABIL,fakeAbil)
        endmethod
    endstruct
    
    struct AbilityCooldown
        method operator []= takes integer i, real duration returns nothing
            call SaveReal(ht,this,i,duration)
        endmethod
        static method operator [] takes integer i returns thistype
            return i
        endmethod
    endstruct
    
    function GetUnitAbilityCooldown takes unit whichUnit, integer whichAbil returns real
        return TimerGetRemaining(AbilData(LoadInteger(ht,Cooldown[whichUnit],whichAbil)).t)
    endfunction
    
    function IsUnitAbilityCoolingDown takes unit whichUnit, integer whichAbil returns boolean
        return HaveSavedInteger(ht,Cooldown[whichUnit],whichAbil)
    endfunction
    
    function ResetUnitAbilityCooldown takes unit whichUnit, integer whichAbil returns nothing
        call Cooldown.resetcooldown(whichUnit,whichAbil)
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger t
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t,Condition(function Cooldown.fire))
        
        set ht = InitHashtable()
    endfunction
endlibrary


Feel free to add your stuff inside, but don't mess it.
Hmm, this is more efficient and easy to use. After setting up the ability stuff in your spell init, the system will do it's job automatically for you. It also support practically unlimited ability cooldown for a unit. So, you can put spellbook on the unit, adding mass of abilities into it, casting it crazily... :p
 

Nexor

...
Reaction score
74
There were some errors in your code, two "thistype." are missing, but the real problem is that I want to change the cooldown of the ability unit-specific.

Like after some uses of Thunder Clap, Player Red's Mountain King can cast is much faster (less cooldown) as Player Blue's MK.

I don't see a function to set it to a unit.

@Jesus4Lyf:

Yeah I see what you meant :D
I just wanted to make my system usable first. I explain some of the functions what they shall do:
-call UnitResetCooldown: resets a unit's spell in the selected slot
-call UnitResetCooldownAll: resets all spell of a unit
-call UnitRestartCooldown: restarts the cooldown of a unit (the cooldown runs again without casting the spell)
-call UnitRestartCooldownAll: restarts all spells of a unit

I know that the names are a bit confusing because Reset and Restart are very similar to each other, but you get the idea I think
 

Nexor

...
Reaction score
74
Okay, I've got the problem but could not solve it.

When a unit learns a new skill the old one will get overwritten on every unit.
I can't repair it :S
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top