- Joined
- Jul 18, 2010
- Messages
- 2,377
CooldownAdjust allows to extend shorten cooldowns by giving abilities/Buffs a cooldownAdjustmentValue. The caster's current cooldownAdjustmentValue is calced on Spellcasting. This value then affects the cooldown only for an small moment, the spell casting. Cooldown adjustment value uses an simlear fomular as armorReduction.
I used this cooldown adjustment value instead of direct % values to avoid reaching big % adjustments to fast, when stacking up multiple sources.
ChangeLog:
I used this cooldown adjustment value instead of direct % values to avoid reaching big % adjustments to fast, when stacking up multiple sources.
JASS:
//CooldownAdjust 1.04c
//By Tasyen
// CooldownAdjust extends / shortens cooldowns of any casted ability, based on casters current cooldownAdjustmentValue.
// The casters current cooldownAdjustmentValue is calced on Spellcasting.
// This value then affects the cooldown only for an small moment, the spell casting.
// Cooldownadjustment supports 2 ways of interpretations of cooldownAdjustmentValue: Linear (LoL Like) or armor Like.
// Sources of cooldownAdjustment are Buffs / Abilities which are saved in array form.
// One can bind Sources to groups to use only the best current available of the group.
// It's also possible for a cooldownAdjustment-Source to affect only itemSpells or normalSpells or both.
//=======================
// Variables of CooldownAdjust
// udg_CdAdjustAbility: If an unit has this ability on SpellEffect it will be affected by this CdAdjust.
// udg_CdAdjustBuff: like udg_CdAdjustAbility but Buff (GUI Friendly allow both), Bugg (Buff allways return 1 as Level).
// udg_CdAdjustType: affect itemSpells or/and normal spells
// 0 = affect both; 1 affect normal spells; 2 = affect itemSpells
// udg_CdAdjustGroup: a group is a number, all sources with the same number will be considered as one group.
// : only the highest absolute cooldownValue of each group is used. (-30 overpowers 28 and changes the groups value from 28 CooldownReduction to 30 CooldownExtension)
// : sources with group = 0 will stack freely.
// : I personaly use an abilityId like 'A000' the one first beeing added to that group which is treated as represent of that group.
// udg_CdAdjustValue: the basePower of this CdAdjustment
// udg_CdAdjustValuePerLevel: Increases the adjustValue for each Level of this source owned by the caster (Level 1 is affected by this) (Buff Level is not recognized)
// A + value reduces cooldown
// A - value extends cooldown
// the power of each point of udg_CdAdjustValue is influenced by the definition "function CooldownAdjustRatio".
// supports 2 types of interpretation, linear and armor like. One can define which one is used inside the definition "function CooldownUseValueLinear".
// used Indexes are 1 to udg_CdAdjustLast
//=======================
// Linear Scaling
// Each point affects the value with the same weight.
// Example:
// the buff of Brillianz-Aura reduces Cooldowns by 10%.
// we use ratio = 0.01 check "function CooldownAdjustRatio"
// then we use register the Brillianz-Aura-Buff as source of CooldownAdjust with "function CdAdjustRegister" takes integer abilityId, real value, integer adjustType returns nothing
// ->
// call CdAdjustRegister('BHab', 10, 0)
// with this line: any caster having the buff 'BHab' will gain 10 CooldownAdjustValue. Each point interpretated as 1% cooldown reduction. the 0 means affect item and normal spells.
// so the caster would now have 10% CooldownReduction.
// if one would want to have 20%, one just takes the double.
// call CdAdjustRegister('BHab', 20, 0)
//=======================
// Armor Like
// The first points give alot of %, while later points give less %.
// Cause of that it can be quite complicated to calc the wanted amount of CdAdjust, which also is done from point zero.
// How to calc a % cooldown reduction?
// use this equation to calculate the +CdAdjustValue.
// value = ( 1 / CooldownAdjustRatio() ) / ( 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%.
// Let's test the tripple, how much one needs for 60%?
// 100 / (1/4/5 -1)
// 100 / (5/4 - 1)
// 100 / (3/4) = 400 / 3 = 133 + 1/3
// you see to reach 60% Reduction one would need 133.33 Value which is kinda is more than 5.3 times of the value needed for 20% reduction.
//=======================
// 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 - they first add each other.
// -20 and 45 -> 25 (shorten by ~20%)
//=======================
// Avoid Cooldown Adjustment
// There are multiple Options to avoid cooldownAdjustment in unwanted situations.
// First there is the "udg_CdAdjustExlcudes" Ability-List, this List can contain all Spells you want to be unaffected by CooldownAdjust.
// Second there is the definition function "CooldownAdjustThreshold", Every spell with a default cooldown (the global one) below or equal to this definition will be ignored.
// Third there is the definition function "CooldownAdjustFilter", A function in which you have access to caster, usedItem (if there is one), and to the used Spell let it return false if you want the current spllcast untouched from CooldownAdjust.
// CdAdjustExlcudes: a List of castable abilities not beeing affected by CooldownAdjust, spells with a default (inside the global value) cooldown equal or less to CooldownAdjustThreshold() are ignored on default.
// used Indexes are 1 to CdAdjustExlcudesLast
//=======================
//Variables to do the 0 Timer skip over the cooldown start. Don't Touch them.
//udg_CdAdjust__Unit - Unit array
//udg_CdAdjust__Spell - integer array
//udg_CdAdjust__Add - real array
//udg_CdAdjust__Last - integer
//udg_CdAdjust__Timer - timer
//=======================
//API
//=======================
// function CooldownAdjust_GetValue takes unit caster, item usedItem returns real
// - returns the cooldownAdjustmentValue caster would have, use usedItem == null if none is used.
// function CooldownAdjust_CalcMulti takes real value returns real
// converts cooldownAdjustmentValue in an multiplier respecting "CooldownAdjustCapShorten" and "CooldownAdjustCapExtend"
//1 Line setters
// function CdAdjustRegisterSuper takes integer abilityId, real value, real valuePerLevel, integer adjustType, integer stackingGroup returns nothing
// - when an unit has abilityId it gains CooldownAdjustValue: value + valuePerLevel * abilityLevel (buffs allways use level 1).
// - if the adjustType is 0 it affects all spells, with 2 spells from items, with 1 unit spells
// - only the best of one stackingGroup is used, if an unit has multiple sources of cooldown adjustments of the same group. stackingGroup = 0 for free stacking.
// function CdAdjustRegister takes integer abilityId, real value, integer adjustType returns nothing
// -wrapper, no stackingGroup, only 1 level
// function CdAdjustExclude takes integer abilityId returns nothing
// - exclude that ability beeing affected from CooldownAdjust
//=======================
//Definitions
//=======================
constant function CooldownAdjustThreshold takes nothing returns real
return 0.5 //Abilities with a default cooldown of this or less seconds, won't have their cooldown touched.
endfunction
constant function CooldownAdjustRatio takes nothing returns real
return 0.01 //How Strong is each point
endfunction
constant function CooldownAdjustCapExtend takes nothing returns real
return 3.0 //Maximum cooldown Multi; used by - udg_CdAdjustValue, 3.0 => Cooldown can be extended to 3 times as long
endfunction
constant function CooldownAdjustCapShorten takes nothing returns real
return 0.60 //Minimum cooldown Multi; used by + udg_CdAdjustValue, 0.6 => Cooldown can be shortend to 60%
endfunction
constant function CooldownUseValueLinear takes nothing returns boolean
return false
// true = each point reduces cooldown by CooldownAdjustRatio()%
// false = armor like, the first ones give much % the later ones give less %.
endfunction
function CooldownAdjustFilter takes unit caster, integer spell, item usedItem returns boolean
return true
//customizeable filter
//return true to allow cooldownadjustment for this situation
//return false to disallow cooldownadjustment for this situation
endfunction
//============
//Code
//=======================
function LogBasedRising takes real value, real power, real ratio returns real
if power >= 0 then
set power = (power * ratio) / (power * ratio + 1 )
return value - value * power
else
set power = - power
return value + value * power * ratio //negative power is linear
endif
endfunction
function CooldownAdjust_CDReset takes nothing returns nothing
local integer level
local real cd
loop //Revert the cooldown change done for all casters in the list
exitwhen udg_CdAdjust__Last == 0
set level = GetUnitAbilityLevel(udg_CdAdjust__Unit[udg_CdAdjust__Last], udg_CdAdjust__Spell[udg_CdAdjust__Last]) - 1
set cd = BlzGetUnitAbilityCooldown(udg_CdAdjust__Unit[udg_CdAdjust__Last], udg_CdAdjust__Spell[udg_CdAdjust__Last], level)
call BlzSetUnitAbilityCooldown(udg_CdAdjust__Unit[udg_CdAdjust__Last], udg_CdAdjust__Spell[udg_CdAdjust__Last], level, cd - udg_CdAdjust__Add[udg_CdAdjust__Last])
set udg_CdAdjust__Last = udg_CdAdjust__Last - 1
endloop
endfunction
function CooldownAdjust_CalcMulti takes real value returns real
if value != 0 then //Is there a value?
//Change this part if you want another Value interpretation
if CooldownUseValueLinear() then
set value = 1.0 - value * CooldownAdjustRatio() //Linear
else
set value = LogBasedRising(1, value, CooldownAdjustRatio()) // Armor Like
endif
if value > CooldownAdjustCapExtend() then // Extension Cap
return CooldownAdjustCapExtend()
elseif value < CooldownAdjustCapShorten() then // Reduction Cap
return CooldownAdjustCapShorten()
else //Normal Value
return value
endif
else //No Adjustment
return 1.0
endif
endfunction
function CooldownAdjust_GetValue takes unit caster, boolean itemSpell returns real
local integer buffIndex = udg_CdAdjustLast
local integer array buffGroupsUsed
local integer buffGroupsUsedLast = 0
local integer newGroupChecker = 0
local integer level
local real array buffGroupsUsedMax
local real result = 0
local real currentValue
local boolean newGroup
loop //Loop all possible Cooldown Reductions
exitwhen buffIndex == 0
// Has this Cooldown Reduction, also does this affect Items or this is no itemSpell?
//Accept buff or ability (GUI Friendly)!!
set level = IMaxBJ(GetUnitAbilityLevel(caster, udg_CdAdjustBuff[buffIndex]), GetUnitAbilityLevel(caster, udg_CdAdjustAbility[buffIndex]))
if level != 0 and ( (udg_CdAdjustType[buffIndex] == 0) or ( udg_CdAdjustType[buffIndex] == 1 and not itemSpell) or (udg_CdAdjustType[buffIndex] == 2 and itemSpell) ) then
set currentValue = udg_CdAdjustValue[buffIndex] + udg_CdAdjustValuePerLevel[buffIndex] * level
if udg_CdAdjustGroup[buffIndex] != 0 then //uses Stacking Groups?
set newGroup = true
set newGroupChecker = buffGroupsUsedLast
loop //Test for beeing a new Cooldown Reduction Group
exitwhen newGroupChecker == 0
if buffGroupsUsed[newGroupChecker] == udg_CdAdjustGroup[buffIndex] then //same group?
if RAbsBJ(buffGroupsUsedMax[newGroupChecker]) < RAbsBJ(currentValue) then //only the absolute strongest of one group is used. -100 will overpower, 99 completly
set buffGroupsUsedMax[newGroupChecker] = currentValue
endif
set newGroup = false
exitwhen true //each Group is used only once.
endif
set newGroupChecker = newGroupChecker - 1
endloop
if newGroup then //New Group -> add it to the list
set buffGroupsUsedLast = buffGroupsUsedLast + 1
set buffGroupsUsedMax[buffGroupsUsedLast] = currentValue
set buffGroupsUsed[buffGroupsUsedLast] = udg_CdAdjustGroup[buffIndex]
endif
else // free stacking
set result = result + currentValue
endif
endif
set buffIndex = buffIndex - 1
endloop
loop //calc in the bests of all found CooldownGroups
exitwhen buffGroupsUsedLast == 0
set result = result + buffGroupsUsedMax[buffGroupsUsedLast]
set buffGroupsUsedLast = buffGroupsUsedLast - 1
endloop
return result
endfunction
function CooldownAdjust_OnEffect takes nothing returns nothing
local unit caster = GetTriggerUnit()
local integer spell = GetSpellAbilityId()
local integer spellOrder = GetUnitCurrentOrder(caster)
local integer level = GetUnitAbilityLevel(caster, spell) - 1
local real cd = BlzGetUnitAbilityCooldown(caster, spell, level)
local boolean itemSpell = ( spellOrder >= 852008 and spellOrder <= 852013)
local real cooldownAdjustmentValue
local integer excludeList = udg_CdAdjustExlcudesLast
local item usedItem
if itemSpell then
set usedItem = UnitItemInSlot(caster, spellOrder - 852008)
else
set usedItem = null
endif
if BlzGetAbilityCooldown(spell,level) > CooldownAdjustThreshold() and CooldownAdjustFilter(caster, spell, usedItem) then //Does this ability pass the cooldown Threshold, and the customizeable Filter?
loop
exitwhen excludeList == 0
if spell == udg_CdAdjustExlcudes[excludeList] then //Excluded spell?
set caster = null
return
endif
set excludeList = excludeList - 1
endloop
set cooldownAdjustmentValue = CooldownAdjust_GetValue(caster, usedItem !=null )
if cooldownAdjustmentValue != 0 then
set cd = BlzGetUnitAbilityCooldown(caster, spell, level)
set udg_CdAdjust__Last = udg_CdAdjust__Last + 1
set udg_CdAdjust__Unit[udg_CdAdjust__Last] = caster
set udg_CdAdjust__Spell[udg_CdAdjust__Last] = spell
set udg_CdAdjust__Add[udg_CdAdjust__Last] = cd * CooldownAdjust_CalcMulti(cooldownAdjustmentValue) - cd
call BlzSetUnitAbilityCooldown(caster, spell, level, cd + udg_CdAdjust__Add[udg_CdAdjust__Last])
call TimerStart(udg_CdAdjust__Timer, 0.01, false, function CooldownAdjust_CDReset)
endif
endif
set caster = null
set usedItem = null
endfunction
function CdAdjustRegisterSuper takes integer abilityId, real value, real valuePerLevel, integer adjustType, integer stackingGroup returns nothing
set udg_CdAdjustLast = udg_CdAdjustLast + 1
set udg_CdAdjustAbility[udg_CdAdjustLast] = abilityId
set udg_CdAdjustValue[udg_CdAdjustLast] = value
set udg_CdAdjustValuePerLevel[udg_CdAdjustLast] = valuePerLevel
set udg_CdAdjustType[udg_CdAdjustLast] = adjustType
set udg_CdAdjustGroup[udg_CdAdjustLast] = stackingGroup
endfunction
function CdAdjustRegister takes integer abilityId, real value, integer adjustType returns nothing
call CdAdjustRegisterSuper(abilityId, value, 0, adjustType, 0)
endfunction
function CdAdjustExclude takes integer abilityId returns nothing
set udg_CdAdjustExlcudesLast = udg_CdAdjustExlcudesLast + 1
set udg_CdAdjustExlcudes[udg_CdAdjustExlcudesLast] = abilityId
endfunction
function CdAdjustFilterMorphs takes nothing returns boolean
//Warcraft 3 1.30.1, Morphings spells crash when chaing cooldown of such spells(thanks Jampion)
local integer unitOrder = GetUnitCurrentOrder(GetTriggerUnit())
call BJDebugMsg(OrderId2String(unitOrder))
if unitOrder == OrderId("burrow") or unitOrder == OrderId("unburrow") or unitOrder == OrderId("sphinxform") or unitOrder == OrderId("unsphinxform") or unitOrder == OrderId("bearform") or unitOrder == OrderId("unbearform") or unitOrder == OrderId("ravenform") or unitOrder == OrderId("unravenform") or unitOrder == OrderId("root") or unitOrder == OrderId("unroot") or unitOrder == OrderId("etherealform") or unitOrder == OrderId("unetherealform") or unitOrder == OrderId("corporealform") or unitOrder == OrderId("uncorporealform") or unitOrder == OrderId("submerge") or unitOrder == OrderId("unsubmerge") or unitOrder == OrderId("robogoblin") or unitOrder == OrderId("unrobogoblin") or unitOrder == OrderId("metamorphosis") or unitOrder == OrderId("stoneform") or unitOrder == OrderId("unstoneform") or unitOrder == OrderId("chemicalrage") or unitOrder == OrderId("elementalfury") then
// call BJDebugMsg("Filter")
return false
endif
//Warcraft 3 1.30.1, Also necrotic spells crash
//instant = raisedead autocast
if unitOrder == OrderId("raisedead") or unitOrder == OrderId("instant")or unitOrder == OrderId("vengeance") or unitOrder == OrderId("vengeanceinstant") or unitOrder == OrderId("carrionscarabs") or unitOrder == OrderId("carrionscarabsinstant") then
// call BJDebugMsg("Filter")
return false
endif
//Some orders with unmetamorph
if unitOrder == OrderId("smart") or unitOrder == OrderId("attack") then
// call BJDebugMsg("Filter")
return false
endif
return true
endfunction
//=======================
function InitTrig_CooldownAdjust takes nothing returns nothing
local integer index = 0
set gg_trg_CooldownAdjust = CreateTrigger()
call TriggerAddAction(gg_trg_CooldownAdjust, function CooldownAdjust_OnEffect)
//call TriggerAddCondition(gg_trg_CooldownAdjust, Condition(function CdAdjustFilterMorphs))
loop
call TriggerRegisterPlayerUnitEvent(gg_trg_CooldownAdjust, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
endfunction
ChangeLog:
1.04c Fixed Ability Cooldown reading/setting for V1.31+, Disable the Morph Filter
1.04a&b
Added missing Filters: elementalfury, chemicalrage, stoneform, raise skeletons, some metamoph cases
1.04Fixed a null
timer 0.01 -> 0.0
GetValue(unit, item) -> GetValue(unit, boolean)
Filters out any spell using an morphing order.
1.03timer 0.01 -> 0.0
GetValue(unit, item) -> GetValue(unit, boolean)
Filters out any spell using an morphing order.
Revamped the Register Functions to 2 in number.
Allows now Linear Scaling.
Improved Docu.
1.02Allows now Linear Scaling.
Improved Docu.
The groupstacking ifs do now fit the cooldownValue.
Added a customizeable filterfunction CooldownAdjustFilter. inside Definitions
Splitted CalcMult into 2 functions GetValue and CalcMulti
CooldownAdjust_GetValue now has acces to the usedItem, but currently does nothing with it.
Added text explaning negative cooldownadjustmentValue.
Renamed the Caps and Min Cooldown Threshold.
Added a customizeable filterfunction CooldownAdjustFilter. inside Definitions
Splitted CalcMult into 2 functions GetValue and CalcMulti
CooldownAdjust_GetValue now has acces to the usedItem, but currently does nothing with it.
Added text explaning negative cooldownadjustmentValue.
Renamed the Caps and Min Cooldown Threshold.
Attachments
Last edited: