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

Cooldown Reduction [vJASS][LUA]

Cooldown Reduction v1.9
Intro
This library intension in to introduce to Warcraft an easy way to manipulate abilities cooldowns based on a cooldown reduction value that is unique for each unit.
How it Works?
When casting an ability, its "new" cooldown is calculated based on the amount of cooldown reduction of the casting unit. the formula for calculation is:
Cooldown = (Default Cooldown - Cooldown Offset) * [(1 - source1)*(1 - source2)*...] * (1 - Cooldown Reduction Flat)
The system also allow negative values for CDR, resulting in increased ability cooldown.
It does not accumulate because the abilities are registered automatically on the first cast, saving its base cooldown (Object Editor values) and always using this base value for calculation, so you can still edit the ability via the editor and the system takes care of the rest.
How to Import?
Simply copy the Cooldown Reduction folder over to your map, and start using the API functions.
Requirements
Cooldown Reduction requires RegisterPlayerUnitEvent and Unit Indexer . Credits to Magtheridon96 for RegisterPlayerUnitEvent and to Bribe for the Unit Indexer. It also requires patch 1.31+.

vJASS:
function GetUnitCooldownReduction takes unit u returns real
    -> Returns the amount of cdr a unit has (this bonuses stacks multiplicatively)
    -> 0.1 = 10%

function GetUnitCooldownReductionFlat takes unit u returns real
    -> Returns the amount of cdr flat a unit has (this bonuses stacks additively)
    -> 0.1 = 10%

function GetUnitCooldownOffset takes unit u returns real
    -> Returns the amount of cdr offset a unit has (this bonuses stacks additively)
    -> 3.0 = 3 seconds is taken from default cooldown before cdr calculation

function SetUnitCooldownReduction takes unit u, real value returns nothing
    -> Set the amount of cdr for a unit (stacks multiplicatively)

function SetUnitCooldownReductionFlat takes unit u, real value returns nothing
    -> Set the amount of cdr flat for a unit (stacks additively)

function SetUnitCooldownOffset takes unit u, real value returns nothing
    -> Set the amount of cdr offset for a unit (stacks additively)

function UnitAddCooldownReduction takes unit u, real value returns nothing
    -> Add to the amount of cdr of a unit. Accepts positive and negative values
    -> Adding a negative with the intent of removing a positive bonus will not work
    -> for that use/read UnitRemoveCooldownReduction().

function UnitAddCooldownReductionFlat takes unit u, real value returns nothing
    -> Add to the amount of cdr flat of a unit. Accepts positive and negative values

function UnitAddCooldownOffset takes unit u, real value returns nothing
    -> Add to the amount of cdr offset of a unit. Accepts positive and negative values

function UnitRemoveCooldownReduction takes unit u, real value returns nothing
    -> Use this function to remove a default cdr bonus from a unit. Additions of default cdr are paired,
    -> meaning that if you added 0.5 and are trying to remove 0.4, it will not work.

function CalculateAbilityCooldown takes unit u, integer id, integer level, real cooldown returns nothing
    -> Main funciton used to calculate ability coodown. It is used internaly by default and can
    -> be called by itself to set custom cooldowns that take advantage of cooldown reduction

function SimulateAbilityCooldown takes unit u, real cooldown returns real
    -> Given a unit and a custom cooldown value, this function will return the resultant
    -> cooldown after reductions.

function RegisterAbility takes unit u, integer id returns nothing
    -> Manually register an ability into the system.

function UnitAddCooldownReductionTimed takes unit u, real value, real duration returns nothing
    -> Add to the amount of cdr of a unit for a given duration. Accepts positive and negative values.
    -> It handles removing the bonus automatically

function UnitAddCooldownReductionFlatTimed takes unit u, real value, real duration returns nothing
    -> Add to the amount of cdr flat of a unit for a given period. Accepts positive and negative values.
    -> It handles removing the bonus automatically

function UnitAddCooldownOffsetTimed takes unit u, real value, real duration returns nothing
    -> Add to the amount of cdr offset of a unit for a given period. Accepts positive and negative values.
    -> It handles removing the bonus automatically

function GetUnitAbilityCooldownEx takes unit u, integer abilityId, integer level returns string
    -> Returns the calculated cooldown for an ability as a string

function GetUnitCooldownReductionEx takes unit u returns string
    -> Returns the amount of cdr a unit has as a string factored by 100
    -> example of return: 10.50 -> 0.105 internally.

function GetUnitCooldownReductionFlatEx takes unit u returns string
    -> Returns the amount of cdr flat a unit has as a string factored by 100
    -> example of return: 10.50 -> 0.105 internally.

function GetUnitCooldownOffsetEx takes unit u returns string
    -> Returns the amount of cdr offset a unit has as a string

function GetAbilityTable takes nothing returns hashtable
    -> Returns the table that holds the units default cooldown reduction values.
    -> Use with caution! you might break stuff
Lua:
function GetUnitCooldownReduction(unit)
    -> Returns the amount of cdr a unit has (this bonuses stacks multiplicatively)
    -> 0.1 = 10%

function GetUnitCooldownReductionFlat(unit)
    -> Returns the amount of cdr flat a unit has (this bonuses stacks additively)
    -> 0.1 = 10%

function GetUnitCooldownOffset(unit)
    -> Returns the amount of cdr offset a unit has (this bonuses stacks additively)
    -> 3.0 = 3 seconds is taken from default cooldown before cdr calculation

function SetUnitCooldownReduction(unit, real)
    -> Set the amount of cdr for a unit (stacks multiplicatively)

function SetUnitCooldownReductionFlat(unit, real)
    -> Set the amount of cdr flat for a unit (stacks additively)

function SetUnitCooldownOffset(unit, real)
    -> Set the amount of cdr offset for a unit (stacks additively)

function UnitAddCooldownReduction(unit, real)
    -> use this function to pass a custom cooldown as parameter taht will
    -> advantage of this system

function UnitAddCooldownReductionFlat(unit, real)
    -> Add to the amount of cdr of a unit. Accepts positive and negative values
    -> Adding a negative with the intent of removing a positive bonus will not work
    -> for that use/read UnitRemoveCooldownReduction().

function UnitAddCooldownOffset(unit, real)
    -> Add to the amount of cdr flat of a unit. Accepts positive and negative values

function UnitRemoveCooldownReduction(unit, real)
    -> Use this function to remove a default cdr bonus from a unit. Additions of default cdr are paired,
    -> meaning that if you added 0.5 and are trying to remove 0.4, it will not work.

function CalculateAbilityCooldown(unit, ability, level, cooldown)
    -> Main funciton used to calculate ability coodown. It is used internaly by default and can
    -> be called by itself to set custom cooldowns that take advantage of cooldown reduction

function SimulateAbilityCooldown(unit, cooldown)
    -> Given a unit and a custom cooldown value, this function will return the resultant
    -> cooldown after reductions.

function RegisterAbility(unit, ability)
    -> Manually register an ability into the system.

function UnitAddCooldownReductionTimed(unit, value, duration)
    -> Add to the amount of cdr of a unit for a given duration. Accepts positive and negative values.
    -> It handles removing the bonus automatically

function UnitAddCooldownReductionFlatTimed(unit, value, duration)
    -> Add to the amount of cdr flat of a unit for a given period. Accepts positive and negative values.
    -> It handles removing the bonus automatically

function UnitAddCooldownOffsetTimed(unit, value, duration)
    -> Add to the amount of cdr offset of a unit for a given period. Accepts positive and negative values.
    -> It handles removing the bonus automatically

function GetUnitCooldownReductionEx(unit)
    -> Returns the amount of cdr a unit has as a string factored by 100
    -> example of return: 10.50 -> 0.105 internally.

function GetUnitCooldownReductionFlatEx(unit)
    -> Returns the amount of cdr flat a unit has as a string factored by 100
    -> example of return: 10.50 -> 0.105 internally.

function GetUnitCooldownOffsetEx(unit)
    -> Returns the amount of cdr offset a unit has as a string

function GetAbilityTable()
    -> Returns the hashtable that holds the units default cooldown reduction values.
    -> Use with caution! you might break stuff

(v1.0)
  • Submission
(v1.1)
  • Redesign the system.
  • 3 types of cooldown manipulation
    • Default cooldown reduction now stacks multiplicatively
    • Flat cooldown reduction stacks additively
    • Offset cooldown stacks additively
(v1.2)
  • Added a new functionality CalculateAbilityCooldown() (See API) used by the default method of calculating a new cooldown and also used to manualy set an ability cooldown that will take advantage of the system.
(v1.3)
  • Splitted CooldownReduction into 2 Libraries: CooldownReduction and CooldownReductionUtils
  • Fixed a bug when removing the last default buff of a unit.
  • Fixed a minor leak
  • Code Cleaning
(v1.4)
  • Fixed a bug for the Flat and Offset types
(v1.5)
  • BIG UPDATE: System redesigned to be more efficient, not calculating the cooldowns on every cast for every ability but only when a unit has its cooldown reduction parameters altered.
  • function GetUnitAbilityCooldown() removed in v1.5. Users can now use the native BlzGetUnitAbilityCooldown() normally.
  • function RegisterAbility() removed, since it's pointless 1.5
  • Added a Legacy section in the code for versions 1.4 and lower
(v1.6)
  • CooldownReduction now uses Table Library instead of a fixed size array to list the registered abilities. This allows for a more dynamic and less limited system.
(v1.7)
  • System ported to LUA.
(v1.8)
  • Fixed a bug where abilities were not being registered.
  • Code optimizations for the vJASS version (now requires Alloc)
  • The system now registers abilities when casting and when learning
  • New function
    JASS:
    function RegisterAbility takes unit u, integer id returns nothing
    (see API)
  • New function
    JASS:
    function SimulateAbilityCooldown takes unit u, real cooldown returns real
    (See API)
(v1.9)
  • Fixed a minor bug when registering units.
  • Added a unit filter configuration function so the user can filter out units that she/he don't want to be registered by the system
Contents

Cooldown Reduction (Map)

Cooldown Reduction (Map)

Level 13
Joined
Jul 15, 2007
Messages
763
There are a few issues with this:
  • Doesn't seem to support abilities with their own dynamic cooldowns, e.g. if an ability's cooldown is dependent on the caster's mana at cast for example, the CDR from this system is not applied. There's no advice given by this resource on how to handle these situations (if it can handle it at all).
  • It's a lot of code for something that can be made in GUI with a hashtable. What advantages does this have?
  • I personally use BlzGetAbilityCooldown in mine (and then abilities with dynamic cooldowns are processed individually). Out of interest is there a reason you did not want to use this?
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Would be cool if this supports cooldown offset in addition to cooldown factor:
cooldown = (<base cooldown> - <cooldown_reduction_offset>)*(1 - <cooldown_reduction_factor>)

EDIT:
Btw, when doing for example:
JASS:
call UnitAddCooldownReduction(u, 0.5)
call UnitAddCooldownReduction(u, 0.5)
It should stack the added reductions multiplicatively, not additively. This would be the intuitive interpretation of the API from a user perspective. Looking above, you could argue that the user intends for the unit to have 100% cooldown reduction there, but imagine for example that the two calls above^ are called by two different systems using the same API, each system expects that it would reduce 50% from what is currently the cooldown of spells of that unit.
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
Doesn't seem to support abilities with their own dynamic cooldowns, e.g. if an ability's cooldown is dependent on the caster's mana at cast for example, the CDR from this system is not applied. There's no advice given by this resource on how to handle these situations (if it can handle it at all).

I'm working on a version where an ability object will be passed as a parameter instead of its id, so doing what you mentioned will be a breeze. For your example, you will only need to call RegisterDefaultCooldown(abiltiy) right after you change the ability cooldown based on mana to make the system work as intended.

It's a lot of code for something that can be made in GUI with a hashtable. What advantages does this have?

It's not a lot of code, the JASS API takes almost as much lines as the core system itself. The advantages, well JASS over GUI for starter, hence performance. Dynamic indexing for timed bonus and using only one timer. The ability to use it integrated with Spell description modification. there's more, but not going to write a book here.

I personally use BlzGetAbilityCooldown in mine (and then abilities with dynamic cooldowns are processed individually). Out of interest is there a reason you did not want to use this?

When using SetAbilityRealLevelField to change the cooldown you will be changing it permanently, so if at some point you need to revert it and you are not using any kind of data structure to save its default values than you wont be able to go back, that's why I created it. Also, to still allow the user to play around with the editor fields. In the new upcoming version, dynamic cooldowns will still be able to take advantage of cdr if you re-register the ability after the cooldown change.

Would be cool if this supports cooldown offset in addition to cooldown factor:
cooldown = (<base cooldown> - <cooldown_reduction_offset>)*(1 - <cooldown_reduction_factor>)

EDIT:
Btw, when doing for example:
JASS:
call UnitAddCooldownReduction(u, 0.5)
call UnitAddCooldownReduction(u, 0.5)
It should stack the added reductions multiplicatively, not additively. This would be the intuitive interpretation of the API from a user perspective. Looking above, you could argue that the user intends for the unit to have 100% cooldown reduction there, but imagine for example that the two calls above^ are called by two different systems using the same API, each system expects that it would reduce 50% from what is currently the cooldown of spells of that unit.

I'm implementing all the features you required, but by stacking multiplicatively, handling negative bonuses might not be possible.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
but by stacking multiplicatively, handling negative bonuses might not be possible.
You multiply the reciprocal instead if the input is negative Lol no :p

Another thing to consider.. It is important to make systems compatible with existing map/system codes, requiring minimal changes, to make it essentially plug-and-play if possible. And I can definitely see that it is possible to do it here. Which means, it should work correctly with existing jass natives like BlzGetUnitAbilityCooldown()

This will definitely help those users who are displaying cooldown info in the abilities in their map and also other systems without having to change each native call with a custom one.

The way to deal with this is to not set the new ability cooldown only on every cast, but it should update the cooldowns of the abilities a unit has on every call UnitAddCooldownReduction() and other similar call. You can maybe more easily achieve this by integrating this useful snippet List Unit Abilities into yours.
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
Sorry I got confused there, the formula should have been
CD = (CD_Base - CDR_Offset) * [(1 - CDR_Factor1)*(1 - CDR_Factor2)...*(1 - CDR_FactorN)]
It works regardless of sign

Ok. Also i tested the List unit abilities snippet, and found a few problems.
  • Huge lag that the system causes when loading abilities.
  • It fails to detect abilities with raw codes that begin with letters greater than S
  • It lists a lot of useless abilities for this system, like Inventory, Move, Attack, which will add a lot of comparisons and degrade performance.
In all honesty, doing a simple ctrl + shift + f and deleting 3 letters do not seem to be such a burden, considering the possibility that the system might work for some abilities and not for others.
Let me know what you think.
 
Level 20
Joined
May 16, 2012
Messages
635
I haven't reviewed the resource, so I don't know its importantce. But for listing abilities, @Ricola3D put effort into it and made an improved version of listing withunder all possible abilities. [System][vJASS] List World Editor Object IDs

Basically the use for it would be to allow users to keep using BlzGetUnitAbilityCooldown instead of replacing it with a GetUnitAbilityCooldown that this system provides. The native function will still work, but with a one call delay after cooldown reduction is modified for an unit. Again, really seems to me like a minor modification.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Ok. Also i tested the List unit abilities snippet, and found a few problems.
  • Huge lag that the system causes when loading abilities.
  • It fails to detect abilities with raw codes that begin with letters greater than S
  • It lists a lot of useless abilities for this system, like Inventory, Move, Attack, which will add a lot of comparisons and degrade performance.
In all honesty, doing a simple ctrl + shift + f and deleting 3 letters do not seem to be such a burden, considering the possibility that the system might work for some abilities and not for others.
Let me know what you think.
Hmm, if it has such drawbacks, I think you can just stick to your original idea. I was just pushing it because the concept of this being a plug-and-play system is really cool. But yea, I think it better to stick with your previous method unless a more reasonable solution is found =).
 
Level 3
Joined
Apr 7, 2020
Messages
32
I'm quite a noob at JASS but I have a few questions in regards to this system. First off thanks a lot for this I've been looking for a way to do cooldown reductions across the game.

First question: Is there a way to avoid this called function of CDR from running on Caster dummies. Second: Does it matter? Would I save performance even if I did?
 
Level 20
Joined
May 16, 2012
Messages
635
I'm quite a noob at JASS but I have a few questions in regards to this system. First off thanks a lot for this I've been looking for a way to do cooldown reductions across the game.

First question: Is there a way to avoid this called function of CDR from running on Caster dummies. Second: Does it matter? Would I save performance even if I did?

1, 2 & 3 - It's possible but I would say it's not relevant, since in normal conditions, abilities have few levels. I would say that it will only be a problem if you have an ability with 1000 levels and you are casting it very, very frequently, but other than that, I would not worry about performance. The system works but registering abilities on cast, so when a unit cast an ability for the first time, the system will take that casted ability from that unit, loop through all it's levels and save in a table the cooldowns for each level. Subsequent casts for that unit of that ability are loaded, which is pretty fast. For dummy units, who usually have their abilities added to them when they are created, the system will do this every time they cast an ability, but again, basically no impact on performance on normal conditions.
 
Level 3
Joined
Apr 7, 2020
Messages
32
That's what I thought, I just had to make sure! Thanks again. I was just in the process of making a cooldown reduction system myself literally this morning and I spotted this. Saved me a lot of time! :cool:2
 
Doing a routine code inspection on the Cooldown Reduction System:
  • The following code appears to have a number of redundancy in lines:

    JASS:
    //Removes are paired with additions. If trying to remove a value that was not
    //added first, than it should fail.
    //Since its a multiplication, the order of operations do not alter the result,
    //so to save performance, when removing a bonus, the last bonus registered is
    // moved to the position of the bonus that was just removed and the loop breks.
    static method Remove takes unit u, real amount returns nothing
        // Auxilliary Code
        if amount != 0 then
            loop
                if aux == amount then
                    // To be Refactored
                    if i == BonusCount[idx] - 1 then
                        call RemoveSavedReal(Ability_Table, id, i)
                    else
                        set aux = LoadReal(Ability_Table, id, BonusCount[idx] - 1) 
                        call SaveReal(Ability_Table, id, i, aux)
                        call RemoveSavedReal(Ability_Table, id, BonusCount[idx] - 1)
                    endif
                // Auxilliary Code

    The code can be refactored to reduce the number of lines and still do the same thing:
    JASS:
    if i != BonusCount[idx] - 1 then
        set aux = LoadReal(Ability_Table, id, BonusCount[idx] - 1) 
        call SaveReal(Ability_Table, id, i, aux)
    endif
    call RemoveSavedReal(Ability_Table, id, i)

  • Moreover, in the function, the first condition can be rewritten to act as a break-point
    From,
    JASS:
    static method Remove takes unit u, real amount returns nothing
        // Auxilliary Code
        // To be Refactored
        if amount != 0 then

    To,
    JASS:
    static method Remove takes unit u, real amount returns nothing
        // Auxilliary Code
        // To be Refactored
        if not (amount != 0) then
            return
        endif
        loop
            // Auxilliary Code

  • In static method GetNewCooldown, the local abil variable is not nullified before
    the return statement.

  • Exposing the hashtable Ability_Table to users may run the risk of unwanted
    behavior due to the potential of overwriting vital ability data in ways that
    the system might not anticipate.
During testing, the system ran with little to no issues; cooldown reduction not resetting back to normal when an item is removed. A demonstration of the bug is shown below.

 
Level 20
Joined
May 16, 2012
Messages
635
Doing a routine code inspection on the Cooldown Reduction System:
  • The following code appears to have a number of redundancy in lines:

    JASS:
    //Removes are paired with additions. If trying to remove a value that was not
    //added first, than it should fail.
    //Since its a multiplication, the order of operations do not alter the result,
    //so to save performance, when removing a bonus, the last bonus registered is
    // moved to the position of the bonus that was just removed and the loop breks.
    static method Remove takes unit u, real amount returns nothing
        // Auxilliary Code
        if amount != 0 then
            loop
                if aux == amount then
                    // To be Refactored
                    if i == BonusCount[idx] - 1 then
                        call RemoveSavedReal(Ability_Table, id, i)
                    else
                        set aux = LoadReal(Ability_Table, id, BonusCount[idx] - 1) 
                        call SaveReal(Ability_Table, id, i, aux)
                        call RemoveSavedReal(Ability_Table, id, BonusCount[idx] - 1)
                    endif
                // Auxilliary Code

    The code can be refactored to reduce the number of lines and still do the same thing:
    JASS:
    if i != BonusCount[idx] - 1 then
        set aux = LoadReal(Ability_Table, id, BonusCount[idx] - 1) 
        call SaveReal(Ability_Table, id, i, aux)
    endif
    call RemoveSavedReal(Ability_Table, id, i)

  • Moreover, in the function, the first condition can be rewritten to act as a break-point
    From,
    JASS:
    static method Remove takes unit u, real amount returns nothing
        // Auxilliary Code
        // To be Refactored
        if amount != 0 then

    To,
    JASS:
    static method Remove takes unit u, real amount returns nothing
        // Auxilliary Code
        // To be Refactored
        if not (amount != 0) then
            return
        endif
        loop
            // Auxilliary Code

  • In static method GetNewCooldown, the local abil variable is not nullified before
    the return statement.

  • Exposing the hashtable Ability_Table to users may run the risk of unwanted
    behavior due to the potential of overwriting vital ability data in ways that
    the system might not anticipate.
During testing, the system ran with little to no issues; cooldown reduction not resetting back to normal when an item is removed. A demonstration of the bug is shown below.


I'll look into it. Thanks for the reply.
 
Level 20
Joined
May 16, 2012
Messages
635
The code can be refactored to reduce the number of lines and still do the same thing:

Actually the correct refactor is:
JASS:
call RemoveSavedReal(Ability_Table, id, i)
if i != BonusCount[idx] - 1 then
    set aux = LoadReal(Ability_Table, id, BonusCount[idx] - 1)
    call SaveReal(Ability_Table, id, i, aux)
    call RemoveSavedReal(Ability_Table, id, BonusCount[idx] - 1)
endif

the way you put it, values will be shifted to the right and fail to remove middles, but thx anyway.

In static method GetNewCooldown, the local abil variable is not nullified before
the return statement.

Fixed.

Exposing the hashtable Ability_Table to users may run the risk of unwanted
behavior due to the potential of overwriting vital ability data in ways that
the system might not anticipate.

I've put a warning ahha and moved it to the Utils Lib. I mainly added it so i could display the bonuses in the test map, but someone might find a use to it.

During testing, the system ran with little to no issues; cooldown reduction not resetting back to normal when an item is removed. A demonstration of the bug is shown below.

Fixed.

I split the Lib in 2, cuz i know you will ask for it :p.
 
I split the Lib in 2, cuz i know you will ask for it

iu

There is also a logical mistake on my part in the suggested refactorization of the code. It should have been:
call RemoveSavedReal(Ability_Table, id, BonusCount[idx] - 1)

As far as test maps go, the reported bug was fixed (and no longer applies to newer versions of the Cooldown Reduction System). The cooldown reduction algorithm checks out, so I don't see a major reason for this not to be Approved.
 
I'm curious why you don't base your system on BlzStartUnitAbilityCooldown. If you call BlzStartUnitAbilityCooldown and the ability is already cooling down on the chosen unit the value you specify overwrites the remaining cooldown. e.g. If you just had a bloodmage cast phoenix and call BlzStartUnitAbilityCooldown(udg_test_unit,'AHpx',10.0) the remaining cooldown will be set to 10 seconds.

edit: I take that back, what I proposed doesn't work with "starts the effect of an ability"

edit2: It works if you use some sort of a delay with a starts the effect of an ability event.

edit3: I hadn't fully tested it before I brought this up hence the edits. I think your way is better.
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
I'm curious why you don't base your system on BlzStartUnitAbilityCooldown. If you call BlzStartUnitAbilityCooldown and the ability is already cooling down on the chosen unit the value you specify overwrites the remaining cooldown. e.g. If you just had a bloodmage cast phoenix and call BlzStartUnitAbilityCooldown(udg_test_unit,'AHpx',10.0) the remaining cooldown will be set to 10 seconds.

edit: I take that back, what I proposed doesn't work with "starts the effect of an ability"

edit2: It works if you use some sort of a delay with a starts the effect of an ability event.

edit3: I hadn't fully tested it before I brought this up hence the edits. I think your way is better.

ahahahhahaha.

@MyPad i'm sorry man, but i'm cooking a version of this system that will be fully automatic and more efficient, following the idea that @AGD gave a few post up. It will not calculate "new" cooldowns on every ability cast for every unit, but will do so when the cooldown reductions are manipulated for that unit in specific, so much better. I'll keep a section with the legacy code but I'm making it so it's compatible backwards as well, apart from a function to get the "new" cooldown, since the way I'm doing it the users will be able to use the BlzGetUnitAbilityCooldown() native.
 
Have you considered making a similar library for ability cast range? I made a test library based on your algorithm already but I won't release it since all I did was rename a few things and change the ability real level field to cast range. However this was using the previous version's code so I'd love to see a new cast range library based on your new algorithm.

edit: Sorry about the double post. I figured it was ok since there was an update to this resource since my last post.
 
Level 20
Joined
May 16, 2012
Messages
635
Have you considered making a similar library for ability cast range? I made a test library based on your algorithm already but I won't release it since all I did was rename a few things and change the ability real level field to cast range. However this was using the previous version's code so I'd love to see a new cast range library based on your new algorithm.

edit: Sorry about the double post. I figured it was ok since there was an update to this resource since my last post.

I'll look into it. Thx!

Edit: I think I'll build an Ability Object API to allow users to take control of any common field, like cast range, mana cost, area of effect, casting time, duration, etc...
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
I don't know if it's only me but I can't seem to open or even find the map on 1.31 patch. Is it reforged only now? :(

It's not Reforged only, it's 1.31+ only, so it might be just you. But anyway, this system do not requires any object data to work, so you can just copy the code and the requirements from the Trigger Preview and copy them into your map.
 
Level 13
Joined
Mar 21, 2014
Messages
893
No, it means 1.31 and above, inclusive.
Hmm, that's interesting. I have the patch 1.31 and my WE can't seem to open the file (it throws level info data missing or invalid error) and the same goes to my wc3 (I can't find the map in the folder). I downloaded it 2 times; to make sure the download isn't corrupted, still it throws the error. My patch version is 1.31.1.12164, so I suppose it meet the requirement, right?
 
Level 20
Joined
May 16, 2012
Messages
635
Hmm, that's interesting. I have the patch 1.31 and my WE can't seem to open the file (it throws level info data missing or invalid error) and the same goes to my wc3 (I can't find the map in the folder). I downloaded it 2 times; to make sure the download isn't corrupted, still it throws the error. My patch version is 1.31.1.12164, so I suppose it meet the requirement, right?

Probably one of the recent patches messed up the maps compiled in their version to be opened for older versions of the editor, but the code should compile just fine for you, just copy them over and test it.
 
I think it's a good idea to have a "Ability learned" event too that registers abilities as they're learned.
I have a lot of dynamic ability-texts that write out actual values for a lot of things, (now including cooldowns!), but they must cast once before it's correct. I don't like it.

Additionally, I really like the new League of Legends way, I.E. Spell Haste (% more casts if you cast it directly when off-cooldown), that is, 100 Haste -> 50% CDR, 200 Haste -> 66.66% CDR, 300 haste -> 75% CDR), but I have put it on top of this system using the flat amount myself, so it's no problem.

Edit: I believe there is a bug in vJass edition in Abilities#update, the j-variable must be set to 0 between i-loops, or all abilities aren't correctly updated.

Edit: Confirmed bug: Have at least 2 abilities. Register first (by casting while having cooldown reduction). Level it to "rank 2". Register 2nd ability, keep it at rank 1. Now 2nd ability won't be effected by cooldown reduction due to the above mentioned reason. If you have more abilities, they will not be effected either, unless they are higher level than any previous registered ability.
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
I think it's a good idea to have a "Ability learned" event too that registers abilities as they're learned.
I have a lot of dynamic ability-texts that write out actual values for a lot of things, (now including cooldowns!), but they must cast once before it's correct. I don't like it.

Additionally, I really like the new League of Legends way, I.E. Spell Haste (% more casts if you cast it directly when off-cooldown), that is, 100 Haste -> 50% CDR, 200 Haste -> 66.66% CDR, 300 haste -> 75% CDR), but I have put it on top of this system using the flat amount myself, so it's no problem.

Edit: I believe there is a bug in vJass edition in Abilities#update, the j-variable must be set to 0 between i-loops, or all abilities aren't correctly updated.

Edit: Confirmed bug: Have at least 2 abilities. Register first (by casting while having cooldown reduction). Level it to "rank 2". Register 2nd ability, keep it at rank 1. Now 2nd ability won't be effected by cooldown reduction due to the above mentioned reason. If you have more abilities, they will not be effected either, unless they are higher level than any previous registered ability.
All fixed in the version 1.8, except for the league of legends method of calculating cdr, because that`s just tweaks you can do yourself. See the Changelog.
 

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,864
Would be nice to have the API posted between comment section at top of script in lua.
It is in CooldownReductionUtils, so it should also be in CooldownReduction.
The same logic applies on your other systems, not every library in your Lua version this happens.
There's also very few libraries of VJASS version that don't have this.
Nonetheless, the system is epic.
 
Level 8
Joined
Aug 5, 2014
Messages
190
Is there somewhere legacy version for 1.31? Because the one that in legacy download option doesnt fit for 1.31 and already uses natives from 1.32.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
i there a version for 1.31?
The comment before yours asked the same question:
Is there somewhere legacy version for 1.31? Because the one that in legacy download option doesnt fit for 1.31 and already uses natives from 1.32.
I think it's safe to assume that's a no. Also, if it's true that this uses natives from 1.32 then you're pretty much out of luck. (Time to update?)
 
Level 5
Joined
Nov 3, 2018
Messages
73
The comment before yours asked the same question:

I think it's safe to assume that's a no. Also, if it's true that this uses natives from 1.32 then you're pretty much out of luck. (Time to update?)
the only reason that keeps me from updating getting the reforged treatment i know you can get classic graphics but that's not my reason not to update
i had to follow a guide here to get my game back from reforged to TFT
so far i managed to found a couple 1.31 .1.32 and 1.33 systems which they were not for my version but seem to work pretty neat for me

so that's why i'm hunting down old versions , my old starcraft map breaks down a lot once i go into reforged and its way too much work to leave it behind


tldr: got my map with years of work that i dont want to lose to reforged (since it does not work there and everything breaks)
 
Top