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

[Lua] CooldownAdjust

CooldownAdjust is a cooldown stat which changes the cooldown of any ability used. But only during the spellcasting. Means it works with cooldown changes done outside of the spellcasting.
CooldownAdjust can differ between Normal, Item & Ultimate Spells and give different Cooldown Benefit/Drawback for them.

Built in sources of cooldown reduction: ItemCode, Buff/AbilityCode, Player-UnitCode, Unit-Specific.
Can exclude specific abilities to not use CooldownAdjust, Abilities with less default Cooldown, or define custom Rules in the CustomFilter function.

This is the Lua version of my jass version [JASS] - CooldownAdjust
Lua:
--[[
CooldownAdjust 1.12 (less Table) (No stacking-Groups)
By Tasyen

In this version Tables are only created at init, except by the user for ability sources which also happens probably only once per abilityCode.

CooldownAdjust extends / shortens cooldowns of any casted ability, based on the casters current cooldownAdjustmentValue.
The casters current cooldownAdjustmentValue is calced on Spellcasting, this still allows you to alter the cooldown of an ability outside of the spellcasting and it will be considered. And it removes the need of registering castable abilities.
This value then affects the cooldown only for a small moment, the spell casting.
Sources of cooldownAdjustment are Buffs / Abilities or ItemCodes.
Its also possible to give specific units or Units of one Type (Priest 'hmpr') of a player a base cooldownAdjustmentValue for a specific adjustType.
Any ability cast belongs to one adjustType there are 3. Item, Spell, Ultimate. A cooldownAdjustment-Source can affect some of them or all.
Cooldownadjustment supports 2 ways of interpretations of cooldownAdjustmentValue: SIMPLE_MODE (LoL like, before 2020) or armor Like (warcraft 3).
Abilities can be flaged to be unaffected by CooldownAdjust.

=======================
API
=======================
When not passing adjustType in any function call mentioning it, CooldownAdjust.TYPE_ANY is used.

function CooldownAdjust.CalcValue(unit [, integer adjustType]) returns real
	- returns the cooldownAdjustmentValue unit would have for spells of adjustType.

function CooldownAdjust.CalcMulti(real value) returns real
	converts cooldownAdjustmentValue in an multiplier respecting "CooldownAdjust.CAP_SHORTEN" and "CooldownAdjust.CAP_EXTEND" with the wanted converting type.

function CooldownAdjust.UnitSetValue(unit, real value [, integer adjustType])
	unit will have value as default CoolDownAdjustmentValue for adjustType.

function CooldownAdjust.UnitGetValue(unit [, integer adjustType]) returns real
	returns the units base adjustment value for exactly that adjustType. Does not consider abilities/buffs.

function CooldownAdjust.UnitAddValue(unit, real value [, integer adjustType])
	increases the currentValue by value.
	
function CooldownAdjust.UnitClear(unit)
	- removes the custom unit data

function CooldownAdjust.PlayerUnitsSetValue(player, integer unitCode, real value [, integer adjustType])
	units owned by player of unitCode have for adjustType value CooldownAdjustValue.
	Example: CooldownAdjust.PlayerUnitsSetValue(Player(0), 'Hpal', 100, CooldownAdjust.TYPE_ANY) -> paladins of player red will have 100 cooldown adjustvalue for any spellType.
	unitCode can be 0 to affect any UnitCode. Any UnitCode and UnitCode x sum up.

function CooldownAdjust.PlayerUnitsAddValue(player, integer unitCode, real value [, integer adjustType])
	adds value to the current value
	unitCode can be 0 to affect any UnitCode. Any UnitCode and UnitCode x sum up.

function this.PlayerUnitsGetValue(player, integer unitCode [, integer adjustType]) returns real
	returns the base adjustment value for units owned by player of GetUnitTypeId(unitCode) for exactly that adjustType.  Does not consider abilities/buffs.
	unitCode can be 0 to affect any UnitCode. Any UnitCode and UnitCode x sum up.


function CooldownAdjust.PlayerUnitsClear(player [, integer unitCode])
	clears saved data for a player for unitCode.
	unitCode is optional, when unitCode is not set all saved data for player is cleared

function CooldownAdjust.Register(integer abilityCode, real value [, integer adjustType, real valuePerLevel])
	- If an unit has abilityCode on SpellEffect it will be affected by this CooldownAdjust.
	- One ablityCode can have any amount of cooldownAdjustments
	- arguments after value can be skiped in a function call CooldownAdjust.Register('AHbz',20) resulting into:
		CooldownAdjust.TYPE_ANY, 0 per level, Free Stacking
	- value + valuePerLevel * abilityLevel (of the ability that gives cooldownadjustment) (buffs use level 1 currently).
		: + values reduces cooldown
		: - values extends cooldown
		: CooldownAdjust.RATIO defines how strong each value is.
		: CooldownAdjust.SIMPLE_MODE defines how the calced value is interpreted.

function CooldownAdjust.RegisterItem(integer itemCode, real value [, integer adjustType])
	-items of itemCode give value of adjustType when picked up and loses this value when droped.
	-Works for tomes.
	-One itemcode can have one value for each adjustType
	-Manipulates CooldownAdjust.UnitData

function CooldownAdjustApplyInventory(unit)
	-Runs this for any unit having items without having them pickedup (preplaced).

function CooldownAdjust.Exclude(integer abilityCode[, boolean flag])
	- CooldownAdjust ignores that casted ability
	- A ability can be allowed again with CooldownAdjust.Exclude('AHbz', false)
	- CooldownAdjust.Exclude('AHbz') same as CooldownAdjust.Exclude('AHbz', true)
	- also works with an UnitCode to exclude units of that unitCode.

=======================
Avoiding Cooldown Adjustment
=======================
There are multiple Options to avoid cooldownAdjustment in unwanted situations.

CooldownAdjust.Exclude, to filter out specific casted abilities 
"CooldownAdjust.THRESHOLD", Every spell with a default cooldown (the global one) below or equal to this definition will be ignored.
the definition function "CustomFilter", A function in which you have access to unit, usedItem (if there is one), and to the used Spell let it return false if you want the current spllcast untouched from CooldownAdjust.
Disable CooldownAdjust.TriggerSpellCast then this system stops doing its cd manipulation.

=======================
Definitions
=======================
--]]

do
	CooldownAdjust = {}
	local PercentChar = "\x25"
	local this = CooldownAdjust -- shortens the code
	local DEBUG = 2 -- display Messages on the screen (2) spellEvent data (1) Result and Selection

	local function CustomFilter(unit, spell, usedItem, isUltimativeSpell)
		return true
		--customizeable filter
		--return true to allow cooldownadjustment for this situation
		--return false to disallow cooldownadjustment for this situation
	end
	
-- constants for AdjustTypes

	this.TYPE_ANY = 0 -- Any spell casted
	this.TYPE_SPELL = 1 -- not item, nor ultimate
	this.TYPE_ITEM = 2 -- Spell used over an item
	this.TYPE_ULTIMATE = 3 -- Spells having requiered hero Level not 0 nor 1.
	-- Any is added to Spell, Item and Ultimate on casting.

	this.THRESHOLD = 0.5 -- Abilities with a default cooldown of this or less seconds, won't have their cooldown touched.
	this.RATIO = 0.01 -- How Strong is each point
	this.CAP_EXTEND = 5.0 -- Maximum cooldown Factor; for -udg_CooldownAdjustValue, 5.0 => Cooldown can be extended to 5.0 times as long
	this.CAP_SHORTEN = 0.20 -- Minimum cooldown Factor; for +udg_CooldownAdjustValue, 0.2 => Cooldown can be shortend to 20%
	this.SIMPLE_MODE = false -- (true) Lol like, (false) increases/decreases the possible amount of casts by Ratio in one default cooldown run.
--[[
=======================
SIMPLE_MODE (true)
	Each point affects the value by CooldownAdjust.RATIO percent.

Example:
the buff of Brillianz-Aura shall reduces Cooldowns by 10%.

ratio = 0.01 inside CooldownAdjust.RATIO
then we use register the Brillianz-Aura-Buff as source of CooldownAdjust with "CooldownAdjust.Register" ( integer abilityCode, real value [, integer adjustType])
->
CooldownAdjust.Register('BHab', 10)

with this line: any unit having the buff 'BHab' will gain 10 CooldownAdjustValue. Each point interpretated as 1% cooldown reduction. the 0 means affect any spell.
so the unit would now have 10% CooldownReduction.

if one would want to have 20%, one just doubles it.
CooldownAdjust.Register('BHab', 20)

=======================
SIMPLE_MODE (fasle)
In this mode each point increases the casts per default cooldown by ratio (when one could cast instantly). For the user it looks like first points give alot of %, while later points give less.
While it is absurd to have 300% in SIMPLE_MODE(true), it is sane in this mode. In this mode such value would mean that you can cast the spell 3 additonal times in the time you could cast it normaly once.

When having 100s cd with 50 value in (Ratio 0.01) you can cast your spell 0.5 additonal times in that 100s. Result into 1,5 casts in 100s. 100s/1.5 = 66.6s
negative side increases for each point the cooldown by ratio. -20 = 120% cooldown -100 = 200% cooldown

If one would want to calc the % one could do it with that equation.
	value = ( 1 / CooldownAdjust.RATIO ) / ( 1 /wanted Reduction - 1)

Example: ratio = 0.01, wanted % = 20

	value = 100 / (1/0.2 - 1)
	-> 100 / (5 - 1) = 100/4 = 25
25 cooldownAdjustmentValue would reduce cooldown by 20%.

=======================
negative cooldownadjustment is always linear

with ratio 0.01
each -1 cooldownAdjustmentValue extends cooldown by 1%, so -100 would double the cooldown, -200 would tripple it.
this is only the case if the total cooldownAdjustmentValue goes below 0.
if an unit has + and - and they they first add each other.
	-20 and 45 -> 25 (shorten by ~20%)

============
Globals
============
--]]

	this.ResetCount = 0
	this.ResetUnit = {} -- data that is reseted when this.Timer expires
	this.ResetSpell = {} -- ^^
	this.ResetLevel = {} -- ^^
	this.ResetValue = {} -- ^^
	this.AbilitySources = { -- [AdjustType][AbilityCode] that way sources not mattering can be ignored and one does not have to check for correct Type.
		[this.TYPE_ANY] = {},
		[this.TYPE_SPELL] = {},
		[this.TYPE_ITEM] = {},
		[this.TYPE_ULTIMATE] = {}
	} -- What abilities give cooldownAdjustmentValues
	this.ItemData = { -- [AdjustType][ItemCode]
        [this.TYPE_ANY] = __jarray(0),
		[this.TYPE_SPELL] = __jarray(0),
		[this.TYPE_ITEM] = __jarray(0),
		[this.TYPE_ULTIMATE] = __jarray(0)
    } -- What items give cooldownAdjustmentValues
	this.DataExclude = {} -- Which Spells do not trigger CooldownAdjust
	this.UnitData = { -- [AdjustType][unit] that way no tables for units have to be created and there is a base Value.
		[this.TYPE_ANY] = __jarray(0),
		[this.TYPE_SPELL] = __jarray(0),
		[this.TYPE_ITEM] = __jarray(0),
		[this.TYPE_ULTIMATE] = __jarray(0)
	}
    this.PlayerUnitData = {} -- custom base cooldownAdjustmentValues for unitCode owned by a player
	-- this.PlayerUnitData[Player][AdjustType][unitCode]
	-- unitCode can be 0 which is used by any unitCpde additonal to the own field.
	for playerIndex = 0, bj_MAX_PLAYER_SLOTS - 1, 1 do
		-- prepare player tables
		this.PlayerUnitData[Player(playerIndex)] = {
            [this.TYPE_ANY] = __jarray(0),
            [this.TYPE_SPELL] = __jarray(0),
            [this.TYPE_ITEM] = __jarray(0),
            [this.TYPE_ULTIMATE] = __jarray(0)
        }
	end
--============
--Code
--============
	local function convert2Number(value)
		if type(value) == "string" then value = FourCC(value) end
		return value
	end

	function NonSimpleRising(amount, ratio)
		if amount == 0 then
			return 1
		elseif amount > 0 then
			amount =  (amount * ratio) / (amount * ratio + 1 )
			return 1 - 1 * amount
		else
			amount = - amount
			return 1 + 1 * amount * ratio	-- negative power is linear
		end
	end

	function this.CalcMulti(value)
		if value ~= 0 then --Is there a value?
			-- Change this part if you want another Value interpretation
			if this.SIMPLE_MODE then
				value = 1.0 - value * this.RATIO -- Simple Rising
			else	
				value = NonSimpleRising(value, this.RATIO) -- Armor Like
			end
			return math.max(this.CAP_SHORTEN, math.min(value, this.CAP_EXTEND))
		else  -- No Adjustment
			return 1.0
		end	
	end

	function this.CalcValue(unit, adjustType)
		local result = 0
		adjustType = adjustType or this.TYPE_ANY
		-- unit specific bonus
		result = this.UnitGetValue(unit, this.TYPE_ANY) 
		if adjustType ~= this.TYPE_ANY then
			result = result +  this.UnitGetValue(unit, adjustType)
		end

		-- player unitTypeId bonus
		local unitOwner = GetOwningPlayer(unit)
		local unitTypeId = GetUnitTypeId(unit)
		result = result + this.PlayerUnitsGetValue(unitOwner, unitTypeId, this.TYPE_ANY)  
		if adjustType ~= this.TYPE_ANY then
			result = result + this.PlayerUnitsGetValue(unitOwner, unitTypeId, adjustType)
		end

		-- player unspecific bonus
		result = result + this.PlayerUnitsGetValue(unitOwner, 0, this.TYPE_ANY)  
		if adjustType ~= this.TYPE_ANY then
			result = result + this.PlayerUnitsGetValue(unitOwner, 0, adjustType)
		end
		
		-- buff and ability bonus
		for k, dataObject in ipairs(this.AbilitySources[adjustType])
		do	
			local ability = BlzGetUnitAbility(unit, dataObject.Ability)
			-- have ability?
			if ability then
				local level = GetUnitAbilityLevel(unit, dataObject.Ability)
				local currentValue = dataObject.Value + dataObject.ValuePerLevel * level
				result = result + currentValue
			end
        end
        if adjustType ~= this.TYPE_ANY then
			for k, dataObject in ipairs(this.AbilitySources[this.TYPE_ANY])
            do	
                local ability = BlzGetUnitAbility(unit, dataObject.Ability)
                -- have ability?
                if ability then
                    local level = GetUnitAbilityLevel(unit, dataObject.Ability)
                    local currentValue = dataObject.Value + dataObject.ValuePerLevel * level
                    result = result + currentValue
                end
            end
        end
        
		return result
	end
	
    function this.Register(abilityCode, value, adjustType, valuePerLevel)
		local newObject = {}
		newObject.Ability = convert2Number(abilityCode)
		newObject.Value = value
		newObject.ValuePerLevel = valuePerLevel or 0
        --newObject.AdjustType = adjustType or this.TYPE_ANY
		table.insert(this.AbilitySources[adjustType or this.TYPE_ANY], newObject)
	end

	function this.UnitSetValue(unit, value, adjustType)
		this.UnitData[adjustType or this.TYPE_ANY][unit] = value
	end

	function this.UnitGetValue(unit, adjustType)
		return this.UnitData[adjustType or this.TYPE_ANY][unit]
	end

	function this.UnitClear(unit)
		this.UnitData[this.TYPE_ANY][unit] = nil
		this.UnitData[this.TYPE_SPELL][unit] = nil
		this.UnitData[this.TYPE_ITEM][unit] = nil
		this.UnitData[this.TYPE_ULTIMATE][unit] = nil
	end

	function this.UnitAddValue(unit, value, adjustType)
		adjustType = adjustType or this.TYPE_ANY
		this.UnitSetValue(unit, this.UnitGetValue(unit, adjustType) + value, adjustType)
	end

	function this.PlayerUnitsSetValue(player, unitCode, value, adjustType)
		unitCode = convert2Number(unitCode)
		this.PlayerUnitData[player][adjustType or this.TYPE_ANY][unitCode] = value
	end

	function this.PlayerUnitsGetValue(player, unitCode, adjustType)
		unitCode = convert2Number(unitCode)
		return this.PlayerUnitData[player][adjustType or this.TYPE_ANY][unitCode]
	end
	function this.PlayerUnitsAddValue(player, unitCode, value, adjustType)
		unitCode = convert2Number(unitCode)
		adjustType = adjustType or this.TYPE_ANY
		this.PlayerUnitsSetValue(player, unitCode, this.PlayerUnitsGetValue(player, unitCode, adjustType) + value, adjustType)
	end

	function this.PlayerUnitsClear(player, unitCode)		
		-- when unitCode is set remove a specific field
		if unitCode then
			unitCode = convert2Number(unitCode)
            this.PlayerUnitData[player][this.TYPE_ANY][unitCode] = nil
            this.PlayerUnitData[player][this.TYPE_SPELL][unitCode] = nil
            this.PlayerUnitData[player][this.TYPE_ITEM][unitCode] = nil
            this.PlayerUnitData[player][this.TYPE_ULTIMATE][unitCode] = nil
        else
            this.PlayerUnitData[player][this.TYPE_ANY] = __jarray(0)
            this.PlayerUnitData[player][this.TYPE_SPELL] = __jarray(0)
            this.PlayerUnitData[player][this.TYPE_ITEM] = __jarray(0)
            this.PlayerUnitData[player][this.TYPE_ULTIMATE] = __jarray(0)
		end
	end

    function this.RegisterItem(itemCode, value, adjustType)
        itemCode = convert2Number(itemCode)
        this.ItemData[adjustType or this.TYPE_ANY][itemCode] = value
        this.ItemData[itemCode] = true -- this item manipulates cooldown
	end

	function this.Exclude(abilityCode, flag)
		if flag == nil or flag == true then
			this.DataExclude[convert2Number(abilityCode)] = true
		else
			this.DataExclude[convert2Number(abilityCode)] = nil
		end
	end

	local function TimerResetAction()
		local cd
		for i = 1, this.ResetCount do
			cd = BlzGetUnitAbilityCooldown(this.ResetUnit[i], this.ResetSpell[i], this.ResetLevel[i])
			BlzSetUnitAbilityCooldown(this.ResetUnit[i], this.ResetSpell[i], this.ResetLevel[i], cd - this.ResetValue[i])
			this.ResetUnit[i] = nil
		end
		this.ResetCount = 0
	end

	local function InitTriggers()
		local function CreateTriggerEx(action)
			local trigger = CreateTrigger()
			TriggerAddAction(trigger, action)
			return trigger
		end
		this.Timer = CreateTimer() -- used to reach the after spell effect event
		this.TriggerSpellCast = CreateTriggerEx(function() -- handle the executon on spelleffect-event
			local spell = GetSpellAbilityId()

			-- exclude this spellCode or UnitCode? Yes -> skip it.
			if this.DataExclude[spell] or this.DataExclude[GetUnitTypeId(GetTriggerUnit())] then return end

			local unit = GetTriggerUnit()
			local spellOrder = GetUnitCurrentOrder(unit)
			local level = GetUnitAbilityLevel(unit, spell) - 1
			local spellReqLevel = BlzGetAbilityIntegerField(GetSpellAbility(), ABILITY_IF_REQUIRED_LEVEL)			

			-- channel spells also could be considered ultimate when the flag is set regardless of required Level, but unsure if that is wanted.
			--local isUltimativeSpell = (spellReqLevel ~= 0 and spellReqLevel ~= 1) or (BlzBitAnd(BlzGetAbilityIntegerLevelField(GetSpellAbility(), ABILITY_ILF_OPTIONS, level), 8) > 0)
			local isUltimativeSpell = (spellReqLevel ~= 0 and spellReqLevel ~= 1)

			-- check for order to know if used over item. But one also could check the flag though the Flag would not ensure the ability is inside an item.
			local itemSpell = ( spellOrder >= 852008 and spellOrder <= 852013)
			--local itemSpell = BlzGetAbilityBooleanField(GetSpellAbility(), ABILITY_BF_ITEM_ABILITY)

			-- I don't use that but it might be something.
			--local isHeroSpell = BlzGetAbilityBooleanField(GetSpellAbility(), ABILITY_BF_HERO_ABILITY)
	
			if DEBUG and DEBUG >= 2 then print(GetUnitName(unit), GetObjectName(spell), "SpellOrder: "..tostring(spellOrder).."/"..OrderId2StringBJ(spellOrder), "ItemSpell: "..tostring(itemSpell), "Ultimate: "..tostring(isUltimativeSpell)) end
	
			local usedItem
			if itemSpell then
				usedItem = UnitItemInSlot(unit, spellOrder - 852008)
			else
				usedItem = nil
			end
			if BlzGetAbilityCooldown(spell,level) > this.THRESHOLD and CustomFilter(unit, spell, usedItem, isUltimativeSpell) then	-- Does this ability pass the cooldown Threshold, and the customizeable Filter?
				local cooldownAdjustmentValue
				if usedItem ~= nil then
					cooldownAdjustmentValue = this.CalcValue(unit, this.TYPE_ITEM)
				elseif isUltimativeSpell then
					cooldownAdjustmentValue = this.CalcValue(unit, this.TYPE_ULTIMATE)
				else
					cooldownAdjustmentValue = this.CalcValue(unit, this.TYPE_SPELL)
				end
	
				if cooldownAdjustmentValue ~= 0 then
					local cd = BlzGetUnitAbilityCooldown(unit, spell, level)
					local baseCooldown = cd
					this.ResetCount = this.ResetCount + 1
					local index = this.ResetCount
					this.ResetUnit[index] = unit
					this.ResetSpell[index] = spell
					this.ResetLevel[index] = level
					this.ResetValue[index] =  cd * this.CalcMulti(cooldownAdjustmentValue) - cd
										
					BlzSetUnitAbilityCooldown(unit, spell, level , cd + this.ResetValue[index])
					TimerStart(this.Timer, 0.00, false, TimerResetAction)
					if DEBUG and DEBUG >= 1 then
						print (string.format( PercentChar.. ".2f", baseCooldown).." -> ".. string.format( PercentChar.. ".2f",BlzGetUnitAbilityCooldown(unit, spell, level)))
					end
				end				
			end
		end)
		 
		this.TriggerItem = CreateTriggerEx(function()
			local itemCode = GetItemTypeId(GetManipulatedItem())
			if this.ItemData[itemCode] then
				local unit = GetTriggerUnit()
				local add = 1
				if GetHandleId(GetTriggerEventId()) == GetHandleId(EVENT_PLAYER_UNIT_DROP_ITEM) then
					-- tomes bonuses are not lost when droping, Life == 0 is item dead/removed
					if IsItemIdPowerup(itemCode) and GetWidgetLife(GetManipulatedItem()) == 0 then return end
					add = -1
				end
                this.UnitAddValue(unit, add * this.ItemData[this.TYPE_ANY][itemCode], this.TYPE_ANY)
                this.UnitAddValue(unit, add * this.ItemData[this.TYPE_SPELL][itemCode], this.TYPE_SPELL)
                this.UnitAddValue(unit, add * this.ItemData[this.TYPE_ITEM][itemCode], this.TYPE_ITEM)
                this.UnitAddValue(unit, add * this.ItemData[this.TYPE_ULTIMATE][itemCode], this.TYPE_ULTIMATE)
			end
		end)
		if DEBUG and DEBUG >=1 then this.TriggerSelect = CreateTriggerEx(function()
				local unit = GetTriggerUnit()
				-- any does not make much sense to display, because it is included in the specific ones.
				--local any = this.CalcValue(unit, this.TYPE_ANY)
				local spell = this.CalcValue(unit, this.TYPE_SPELL)
				local item = this.CalcValue(unit, this.TYPE_ITEM)
				local ulti = this.CalcValue(unit, this.TYPE_ULTIMATE)
				

				print(GetUnitName(unit), GetHeroProperName(unit))
				--print("Any: ".. string.format( PercentChar.. ".1f", this.CalcMulti(any)*100) .. PercentChar.. " (".. string.format( PercentChar.. ".1f", any) .. ")")
				print("Spell: ".. string.format( PercentChar.. ".1f", this.CalcMulti(spell)*100) .. PercentChar.. " (".. string.format( PercentChar.. ".1f", spell) .. ")")
				print("Item: ".. string.format( PercentChar.. ".1f", this.CalcMulti(item)*100) .. PercentChar.. " (".. string.format( PercentChar.. ".1f", item) .. ")")
				print("Ultimate: ".. string.format( PercentChar.. ".1f", this.CalcMulti(ulti)*100) .. PercentChar.. " (".. string.format( PercentChar.. ".1f", ulti) .. ")")
			end)
			TriggerRegisterAnyUnitEventBJ(this.TriggerSelect, EVENT_PLAYER_UNIT_SELECTED)
		end
		for playerIndex = 0, bj_MAX_PLAYER_SLOTS - 1, 1 do
			TriggerRegisterPlayerUnitEvent(this.TriggerSpellCast, Player(playerIndex), EVENT_PLAYER_UNIT_SPELL_EFFECT, nil)
			TriggerRegisterPlayerUnitEvent(this.TriggerItem, Player(playerIndex), EVENT_PLAYER_UNIT_PICKUP_ITEM, nil)
			TriggerRegisterPlayerUnitEvent(this.TriggerItem, Player(playerIndex), EVENT_PLAYER_UNIT_DROP_ITEM, nil)
		end
	end


	if OnInit then -- Total Initialization v5.2.0.1 by Bribe
		OnInit.trig(InitTriggers)
	else -- without
		local real = InitBlizzard
		function InitBlizzard()
			real()
			InitTriggers()
		end
	end
end

Example:
Lua:
--Kaels owned by Player red have 100 cooldownvalue for normal spells (not items not ultimate)
CooldownAdjust.PlayerUnitsSetValue(Player(0), "Hkal", 100, 1)
--This unit gets 25 cooldownvalue for any ability
--CooldownAdjust.UnitAddValue(gg_unit_unec_0016, 25)

CooldownAdjust.RegisterItem('rwiz', 100/9)
CooldownAdjust.RegisterItem('ckng', 5, 1)
CooldownAdjust.RegisterItem('bgst', -100)
CooldownAdjust.RegisterItem('I000', 1)
CooldownAdjust.RegisterItem('I000', 1, 1) --gives also 1 point for normal spells resulting in 2 for it

CooldownAdjust.RegisterItem('rst1', 25)
CooldownAdjust.RegisterItem('rag1', 25)
CooldownAdjust.RegisterItem('rin1', 40)
-- +100 bonus for items
CooldownAdjust.RegisterItem('lgdh', 100, 2)
-- + 20 for spells
CooldownAdjust.RegisterItem('rde4', 20, 1)

--this is a ability/buff source they are recalced on every spellcast, making them the more expensive sources
--adds 25 to spell and reduces items by 25
CooldownAdjust.Register('B000', 25, 1)
CooldownAdjust.Register('B000', -25, 2)
 
Last edited:
Top