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

[System] Cooldown

Status
Not open for further replies.
I have been searching for this resource and I guess noone ever made this kind of system.

Today, I created a Custom Cooldown System which, of course, applies custom cooldown to your ability.
Ability applied with custom cooldown will be disabled for n seconds and will be replaced by a passive ability that serves as an indicator that the spell is on cooldown.

Here is the code:

JASS:
library Cooldown
    globals
        private constant real TIMEOUT = 0.031250000
        
        private integer array CD_IDS
    endglobals

    private module Initializer
        private static method onInit takes nothing returns nothing
            call init()
        endmethod
    endmodule
    
    
    struct Cooldown extends array
        private static integer array r
        private static integer ic = 0
        
        private real cooldown
        private integer source_abil
        private integer cd_abil
        private player owner
        private unit u
        
        private thistype n
        private thistype p
        private static integer c = 0
        
        private static constant timer t = CreateTimer()
        
        private static method allocate takes nothing returns thistype
            local thistype this = r[0]
            
            if this == 0 then
                set ic = ic + 1
                return ic
            endif
            set r[0] = r[this]
            return this
        endmethod
        
        private method deallocate takes nothing returns nothing
            set r[this] = r[0]
            set r[0] = this
        endmethod
        
        private static method periodic takes nothing returns nothing
            local thistype this = thistype(0).n
            loop
                exitwhen this == 0
                if cooldown >= TIMEOUT then
                    set cooldown = cooldown - TIMEOUT
                else

                    call UnitRemoveAbility(u, cd_abil)
                    call SetPlayerAbilityAvailable(owner, source_abil, true)
                    
                    set cooldown = 0
                    set u = null
                    set owner = null
                    set source_abil = 0
                    set cd_abil = 0
                    
                    set p.n = n
                    set n.p = p
                    call deallocate()
                    
                    set c = c -1
                    if c == 0 then
                        call PauseTimer(t)
                    endif
                endif
                set this = n
            endloop
        endmethod
        
        static method startEx takes player tempp, unit tempu, integer src_abil, real cd, integer cd_ability returns thistype
            local thistype this = allocate()
            
            call SetPlayerAbilityAvailable(tempp, src_abil, false)
            
            call UnitAddAbility(tempu, cd_ability)
            
            set owner = tempp
            set u = tempu
            set source_abil = src_abil
            set cooldown = cd
            set cd_abil = cd_ability
            
            set n = 0
            set p = thistype(0).n
            set p.n = this
            set thistype(0).p = this
            
            set c = c + 1
            if c == 1 then
                call TimerStart(t, TIMEOUT, true, function thistype.periodic)
            endif
            return this
        endmethod
        
        static method start takes player tempp, unit tempu, integer src_abil, real cd, integer x, integer y returns thistype
            return startEx(tempp, tempu, src_abil, cd, CD_IDS[x*3 + y])
        endmethod
        
        method operator value= takes real cd returns nothing
            set cooldown = cd
        endmethod
        
        method operator value takes nothing returns real
            return cooldown
        endmethod
        
        private static method init takes nothing returns nothing
            set CD_IDS[0] = 'cd00'
            set CD_IDS[1] = 'cd01'
            set CD_IDS[2] = 'cd02'
            set CD_IDS[3] = 'cd10'
            set CD_IDS[4] = 'cd11'
            set CD_IDS[5] = 'cd12'
            set CD_IDS[6] = 'cd20'
            set CD_IDS[7] = 'cd21'
            set CD_IDS[8] = 'cd22'
            set CD_IDS[9] = 'cd30'
            set CD_IDS[10] = 'cd31'
            set CD_IDS[11] = 'cd32'
        endmethod
        
        implement Initializer
    endstruct

endlibrary

and some test:
  • Untitled Trigger 001
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
      • (Ability being cast) Equal to Thunder Clap
    • Actions
      • Custom script: local unit u = GetTriggerUnit()
      • Custom script: local real cd = GetRandomReal(0., 4.)
      • Custom script: call Cooldown.start(GetOwningPlayer(u), u, 'A000', cd, 1, 2)
      • Custom script: call DisplayTextToPlayer(GetLocalPlayer(), 0, 0,"Cooldown : " + R2S(cd))
      • Custom script: set u = null

I haven't tested the system yet with Channeling spells and Autocasts(I assume that autocasts are not supported)

I would like some feedbacks and suggestions about how can I improve this system.

Thank you :D
 

Attachments

  • Cooldown v1.0.w3x
    18.8 KB · Views: 143
Level 12
Joined
Mar 13, 2012
Messages
1,121
1. The missing cooldown indicator. People hate when a spell is in cooldown and they can not see for how long.
2. You're using SetPlayerAbilityAvailable which is fine for your own map but not good for a system, as it disables the ability for all units of that player.
 
1. The missing cooldown indicator. People hate when a spell is in cooldown and they can not see for how long.
2. You're using SetPlayerAbilityAvailable which is fine for your own map but not good for a system, as it disables the ability for all units of that player.

You know it is impossible to manipulate or create an indicator for this. Also i forgot to say thag this syatem is MPI because using UnitAdd/Remove Ability for heroes can have a poasibility to bug
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
You know it is impossible to manipulate or create an indicator for this. Also i forgot to say thag this syatem is MPI because using UnitAdd/Remove Ability for heroes can have a poasibility to bug

How to make a visible cooldown indicator? - Spell shield.
Also, it is possible to disable an ability for one unit at a time by using engineering upgrade to replace it with a disabled one.
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
Also, can you elaborate more about the spell shield?
By adding a spell shield and letting a dummy cast a spell on the unit you can trigger it. Voila cooldown indicator. Some work to integrate it in a system though.

I would advise you not to use engineering upgrade and just remove/add the ability. Never saw a real bug with it and for engineering upgrade you get problems with non-hero units and you need one for every ability.
 
By adding a spell shield and letting a dummy cast a spell on the unit you can trigger it. Voila cooldown indicator. Some work to integrate it in a system though.

I would advise you not to use engineering upgrade and just remove/add the ability. Never saw a real bug with it and for engineering upgrade you get problems with non-hero units and you need one for every ability.

Then how would you customize the value of cooldown :v
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
With spell shield?

Well the easy version is to make a spell shield abilty with many levels with different cooldowns and setting the level according to the cooldown of the casted ability.

The hard version is to create a spell shield duplicate of every abilty having the same icon and cooldown as the ability.
 
With spell shield?

Well the easy version is to make a spell shield abilty with many levels with different cooldowns and setting the level according to the cooldown of the casted ability.

The hard version is to create a spell shield duplicate of every abilty having the same icon and cooldown as the ability.

You know this won't work. If, for example, I have an ability with a cooldown of 3.14 seconds and was reduced by 20%(which is 3.14-0.528), how can the spell shield create a cooldown indicator this precise?

The job of this system is much like League of Legends' system, which allows you to reduce cooldowns of abilities by percentage, permanently or temporarily
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
Only 1 ability needs to have many levels. You can set the levels according to what you need. Then you make 1 engineering upgrade per ability to switch it with the one that has many levels. When the cooldown has been applied, you switch it back. This can be done so fast that the user doesn't even notice the change.
Since you only have 1 ability that's truly taxing, then you have quite a lot of freedom with the levels. You can use a logarithmic scale if you want uniform accuracy.

You can't make it as precise as LoL, but it's unnecessary and you can get pretty close.
 
Only 1 ability needs to have many levels. You can set the levels according to what you need. Then you make 1 engineering upgrade per ability to switch it with the one that has many levels. When the cooldown has been applied, you switch it back. This can be done so fast that the user doesn't even notice the change.
Since you only have 1 ability that's truly taxing, then you have quite a lot of freedom with the levels. You can use a logarithmic scale if you want uniform accuracy.

You can't make it as precise as LoL, but it's unnecessary and you can get pretty close.

Then you make 1 engineering upgrade per ability to switch it with the one that has many levels

Then you make 1 engineering upgrade per ability

per ability

That doesn't sound quite portable to me :O


Well, about the indicator thing, that can somehow disappoint the players :V and also the map makers because their gonna import so many abilities for my system to work. Im making the system as light as possible
 
Wow, I didn't know the spell shield thing. You learn something new every day...

Btw, there is also a way to "restart" an existing cooldown indicator or stop it by using the engineering upgrade.

Basicly, when a spell is on cooldown, you can apply engineering upgrade to change the ability to whatever cooldown you want. The difference in cooldown time will be applied to the already cooling ability; the cooldown indicator, however, will start from zero again.

This means that when a spell has a 10 second cooldown and 4 seconds of said cooldown are already over and you change it to a spell with a 7 second cooldown; the cooldown indicator will restart from zero again, but will only take 3 seconds to complete.

It's a neat little trick that can be applied to create custom cooldowns.
 
Also, I think this should come in two flavour versions:

1) version 1 uses ability disable to hide the original ability (MPI, but not MUI)
2) version 2 uses ability removal and readding to hide the original ability (MUI)

So, why is this important? Basicly, version 2 has the drawback over version 1 that it removes the ability completely, making it complicated to track if said unit has the ability or not, when it is currently on cooldown.
Disabled abilities will return true for a potential GetUnitAbilityLevel > 0 check, which is important for compatibility with other spellcasting systems.

So let the user decide which flavour to use here. Depending on the type of game and systems used, it might be a big advantage to go only MPI if you don't need MUI.
 
Also, I think this should come in two flavour versions:

1) version 1 uses ability disable to hide the original ability (MPI, but not MUI)
2) version 2 uses ability removal and readding to hide the original ability (MUI)

So, why is this important? Basicly, version 2 has the drawback over version 1 that it removes the ability completely, making it complicated to track if said unit has the ability or not, when it is currently on cooldown.
Disabled abilities will return true for a potential GetUnitAbilityLevel > 0 check, which is important for compatibility with other spellcasting systems.

So let the user decide which flavour to use here. Depending on the type of game and systems used, it might be a big advantage to go only MPI if you don't need MUI.

well I'll go then with the MPI one
 
Level 12
Joined
Mar 13, 2012
Messages
1,121
Is there a way to refresh a cooldown from an item ability?
Except from refreshing all cooldowns on the unit no, there are only ugly workarounds known, like removing the item and adding another one which looks similar with a different cooldown group.
 
Status
Not open for further replies.
Top