JASS:
library DamageReduction uses DamageEvent, Table
/*
Made by: edo494
Version: 1.1
Requires:
DamageEvent - [url]http://www.hiveworkshop.com/forums/jass-resources-412/system-physical-damage-detection-228456/[/url]
Table(Bribe) - [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url]
This library allows you to manipuate damage received by
any unit on the map depending on the unit type, the
unit, its abilities, item types of wearing items as well
as items weared by the unit.
This library manipulates the damage of all 3 types(Physical,
Spell and Code).
Primary reason of existance of this resource is because of the
problem that people use Runed Bracers for spell damage reduction,
even tho the DDS will not work if they do so.
Disadvantage of this resource is that every reduction
is scaled additively, which means that if unit
has 10% + 15% reduction, it will have 25% total
reduction.
If reduction reaches >100%, it is automatically adjusted to
100% meaning that you will always take 0 damage as long as you
have it on you
API:
NOTE!!! Abilities do not work unless you call one of the following:
function UnitRegisterAbility takes unit u, integer abil returns nothing
function UnitTypeRegisterAbility takes integer uType, integer abil returns nothing
function UnitAddAbilityEx takes unit whichUnit, integer abilId returns boolean
More about those function below Struct API
NOTE!!! Methods set are called reset, because set is reserved keyword and cannot be
a name for method
Legend: integer a - always refers to amplifyType, the type we want
the function to modify
Example: Reduction.SPELL, Reduction.CODE
real pRd - always refers to percentual reduction
Example: 0.16(which represents 16%)
integer ut - always refers to unit type, that we
want to modify values for
unit u - always refers to unit we want to modify
values for
integer it - always refers to item type we want
to modify values for
item i - always refers to item we want to modify
values for
integer ab - always refers to ability(via rawcode)
that we want to modify values for
integer lv - always refers to the level of ability
we are modifying
globals:
Visit configuration block below this documentation
struct Reduction extends array
static integer PHYSICAL = REDUCTION_PHYSICAL
static integer SPELL = REDUCTION_SPELL
static integer CODE = REDUCTION_CODE
- those 3 integers define the reduction types
you are applying
//--- UNIT TYPE REDUCTIONS API ---//
static Reduction.UnitType.reset takes takes integer ut, integer a, real pRd returns nothing
- sets the reduction for UnitType "ut" of type "a" to "pRd"
static Reduction.UnitType.add takes integer ut, integer a, real pRd returns nothing
- adds/increases the reduction for UnitType "ut" of type "a" to "pRd"
static Reduction.UnitType.substract takes integer ut, integer a, real pRd returns nothing
- substracts/decreases the reduction for UnitType "ut" of type "a" to "pRd"
- equivalent to call: Reduction.UnitType.add(ut, a, -pRd)
static Reduction.UnitType.get takes integer ut, integer a returns real
- returns the amount of reduction for UnitType "ut" of type "a"
//--- UNIT REDUCTION API ---//
static Reduction.Unit.reset takes takes unit u, integer a, real pRd returns nothing
- sets the reduction for unit "u" of type "a" to "pRd"
static Reduction.Unit.add takes unit u, integer a, real pRd returns nothing
- adds/increases the reduction for unit "u" of type "a" to "pRd"
static Reduction.Unit.substract takes unit u, integer a, real pRd returns nothing
- substracts/decreases the reduction for unit "u" of type "a" to "pRd"
- equivalent to call: Reduction.Unit.add(ut, a, -pRd)
static Reduction.Unit.get takes unit u, integer a returns real
- returns the reduction for unit "u" of type "a"
//--- ITEM TYPE REDUCTION API ---//
static Reduction.ItemType.reset takes takes integer it, integer a, real pRd returns nothing
- sets the reduction for item type "it" of type "a" to "pRd"
static Reduction.ItemType.add takes integer it, integer a, real pRd returns nothing
- adds/increases the reduction for item type "it" of type "a" to "pRd"
static Reduction.ItemType.substract takes integer it, integer a, real pRd returns nothing
- substracts/decreases the reduction for item type "it" of type "a" to "pRd"
- equivalent to call: Reduction.ItemType.add(it, a, -pRd)
static Reduction.ItemType.get takes integer it, integer a returns real
- returns the reduction for item type "it" of type "a"
//--- ITEM REDUCTION API ---//
static Reduction.Item.reset takes takes item i, integer a, real pRd returns nothing
- sets the reduction for item "i" of type "a" to "pRd"
static Reduction.Item.add takes item i, integer a, real pRd returns nothing
- adds/increases the reduction for item "i" of type "a" to "pRd"
static Reduction.Item.substract takes item i, integer a, real pRd returns nothing
- substracts/decreases the reduction for item "i" of type "a" to "pRd"
- equivalent to call: Reduction.Item.add(ut, a, -pRd)
static Reduction.Item.get takes item i, integer a returns real
- returns the reduction for item "i" of type "a"
//--- ON CAST REDUCTION API ---//
static Reduction.OnCast.setTime takes integer ab, integer lv, real howLong returns nothing
Sets a time for given ability on given level for how long the bonus should be applied.
static Reduction.OnCast.getTime takes integer ab, integer lv returns real
Returns for how long will given ability on given level apply its reduction for.
static Reduction.OnCast.useMultiLevel takes integer ab, boolean use returns nothing
Marks whether the ability uses multiple level bonuses or not.
If it does, it will use each individual level for ability as differnet.
If doesnt, it will always apply level == 1 to the effect(time, amount).
static Reduction.OnCast.usesMultiLevel takes integer ab returns boolean
Returns whether ability uses multiple level bonuses or not.
static Reduction.OnCast.reset takes integer ab, integer lv, integer a, real pRd returns nothing
Equivalent to: substract(get(...)) followed by add(...)
static Reduction.OnCast.add takes integer ab, integer lv, integer a, real pRd returns nothing
Increases Reduction for given ability when it is cast of given type("a") by pRd.
static Reduction.OnCast.substract takes integer ab, integer lv, integer a, real pRd returns nothing
Reduces Reduction for given ability when it is cast of given type("a") by pRd.
static Reduction.OnCast.get takes integer ab, integer lv, integer a returns real
Returns how much reduction of given type will be applied when ability is cast with given level.
//--- ABILITY REDUCTION API ---//
static Reduction.Ability.useMultiLevel takes integer ab, boolean use returns nothing
- sets whether given ability uses multi level bonuses or not
- if true is passed, each level for ability "ab" will have different
reduction values(for all types)
static Reduction.Ability.usesMultiLevel takes integer ab returns boolean
- gets whether the ability "ab" uses multi level bonuses or not
static Reduction.Ability.reset takes integer ab, integer lv, integer a, real pRd returns nothing
- sets the reduction for ability "ab" of type "a" to "pRd" for given level "lv"
- if ability doesnt use mutli level bonuses, returns the same value for any "lv" passed
static Reduction.Ability.add takes integer ab, integer lv, integer a, real pRd returns nothing
- adds/increases the reduction for ability "ab" of type "a" to "pRd" for given level "lv"
- if ability doesnt use mutli level bonuses, returns the same value for any "lv" passed
static Reduction.Ability.substract takes integer ab, integer lv, integer a, real pRd returns nothing
- substracts/reduces the reduction for ability "ab" of type "a" to "pRd" for given level "lv"
- if ability doesnt use mutli level bonuses, returns the same value for any "lv" passed
- equivalent to call: Reduction.Ability.add(ab, lv, a, -pRd)
static Reduction.Ability.get takes integer ab, integer lv, integer a returns real
- gets the reduction for ability "ab" of type "a" for given level "lv"
- if ability doesnt use mutli level bonuses, returns the same value for any "lv" passed
Functional API
function UnitRegisterAbility takes unit u, integer abil returns nothing
- registers ability with rawcode "abil" into unit "u"
- Reduction from this ability will only be considered if the unit
has this ability
function UnitUnregisterAbility takes unit u, integer abil returns nothing
- unregisters ability with rawcode "abil" from unit "u"
- Reduction from this ability will no longer be accounted when unit "u"
- takes damage even if he has this ability learened
function UnitTypeRegisterAbility takes integer uType, integer abil returns nothing
- registers ability with rawcode "abil" for unit type "uType"
- whenever unit of type "uType" takes damage, and has this ability
(>0 level in it), the Reduction will be applied to the damage
function UnitTypeUnregisterAbility takes integer uType, integer abil returns nothing
- unregisters ability with rawcode "abil" for unit type "uType"
function UnitAddAbilityEx takes unit whichUnit, integer abilId returns boolean
- first adds ability "abilId" into unit "whichUnit"
- if it was added successfully, it also calls
UnitRegisterAbility(whichUnit, abilId)
- returns the return value of UnitAddAbility
function UnitRemoveAbilityEx takes unit whichUnit, integer abilId returns boolean
- first removes "abilId" from "whichUnit"
- if it was successful, it also calls
UnitUnregisterAbility(whichUnit, abilId)
- returns the return value of UnitRemoveAbility
NOTE: - Yes, I know the names are very potentionally
conflicting, Im up for better name suggestions
- Keep in mind that the functions should have
considerably short name
*/
/***********************************/
/******** Configuration ********/
/***********************************/
globals
//when you remove all abilities from list of one unit, it will
//automatically recycle given instance
//also applies to unit-type specific list
private constant boolean DESTROY_EMPTY_STRUCTS = false
//if you want the list of registered unit abilities inside the list
//to be in strict order(so they are always in the order of insertation), make it true
private constant boolean UNIT_ABIL_LIST_STRICT_ORDER = false
//set this to true if you dont want the list of unit's abilities
//to contain duplicates
private constant boolean LIST_SECURE_DOUBLE_ADD = false
//if this is set, every time unit takes damage the
//output the damage before and after modification
//as well as the modification factor
private constant boolean DEBUG_PRINT_ON_HIT_DMG = false
//how often should onCast values be updated(if you take inverse of this value
//you will find out how many times per second will this system update onCast time)
private constant real TICK_TIME = 1.0/8
//how many different REDUCTION_XXX there are
private constant integer DAMAGE_TYPES = 3
endglobals
/***************************************/
/******** End Configuration ********/
/***************************************/
globals
//first value must be 0, and they should increment by 1
constant integer REDUCTION_PHYSICAL = 0
constant integer REDUCTION_SPELL = 1
constant integer REDUCTION_CODE = 2
endglobals
globals
private Table amplifiedPhys
private Table amplifiedMag
private Table amplifiedCode
//to dispatch in O(1) the types without if block
private Table array ampDispatch
private Table abilDatIndicies
private Table unitListIndicies
endglobals
private struct OnCastDat
unit caster
Table amounts
real time
static thistype head
thistype next
thistype prev
static method create takes unit caster returns thistype
local thistype this = allocate()
set this.caster = caster
set amounts = Table.create()
set this.next = head.next
set this.prev = head
set head.next = this
return this
endmethod
method destroy takes nothing returns nothing
call amounts.destroy()
set this.next.prev = this.prev
set this.prev.next = this.next
set this.prev = 0
set this.next = 0
call deallocate()
endmethod
static method allocated takes nothing returns boolean
return head.next != 0
endmethod
private static method onInit takes nothing returns nothing
set head = create(null)
endmethod
endstruct
private struct AbilDat
TableArray levels
boolean multiLevel
//for onCast
Table overallTime
//end for onCast
static method create takes nothing returns thistype
local thistype this = allocate()
set overallTime = Table.create()
set levels = TableArray[DAMAGE_TYPES]
set multiLevel = true
return this
endmethod
method dispatch takes integer i returns Table
return levels[i]
endmethod
method destroy takes nothing returns nothing
call levels.destroy()
call overallTime.destroy()
endmethod
endstruct
private struct UnitAbilList
private Table list
private unit stored
static method create takes unit toStore returns thistype
local thistype this = allocate()
set list = Table.create()
set list[0] = 0
set stored = toStore
return this
endmethod
method size takes nothing returns integer
return list[0]
endmethod
static if DEBUG_MODE then
private method isInside takes integer abilId returns boolean
return list[abilId] != 0
endmethod
elseif LIST_SECURE_DOUBLE_ADD then
private method isInside takes integer abilId returns boolean
return list[abilId] != 0
endmethod
endif
method add takes integer abilId returns nothing
//cSize now points one beyond the last element
local integer cSize = list[0] + 1
static if DEBUG_MODE then
if isInside(abilId) then
return
endif
elseif LIST_SERCURE_DOUBLE_ADD then
if isInside(abilId) then
return
endif
endif
set list[0] = cSize
set list[cSize] = abilId
//make it point to itself for O(1) removal
set list[abilId] = cSize
endmethod
method sumOfBonus takes integer modifType returns real
local AbilDat aDat = 0
local integer curr = 1
local integer cSize = list[0]
local integer abilLvl = 0
local integer abilId = 0
local real result = 0
loop
set abilId = list[curr]
set aDat = abilDatIndicies[abilId]
if aDat != 0 then
set abilLvl = GetUnitAbilityLevel(stored, abilId)
if not aDat.multiLevel and abilLvl != 0 then
set abilLvl = 1
endif
set result = result + aDat.dispatch(modifType).real[abilLvl]
endif
exitwhen curr >= cSize
set curr = curr + 1
endloop
return result
endmethod
method sumOfBonusEx takes unit forUnit, integer modifType returns real
local unit u = stored
local real r = 0
if stored == forUnit then
return sumOfBonus(modifType)
endif
set stored = forUnit
set r = sumOfBonus(modifType)
set stored = u
return r
endmethod
private method popBack takes nothing returns nothing
//get the size
local integer cSize = list[0]
//shrink it by one
set list[0] = cSize - 1
//make the pointer inside list[abilId] point to nothing
set list[list[cSize]] = 0
//make the last element store no ability
set list[cSize] = 0
endmethod
static if UNIT_ABIL_LIST_STRICT_ORDER then
private method removeStrict takes integer size, integer pos returns nothing
//pos is the current position, size is the size of the list
local integer iter = pos
local integer abilId = list[pos]
//loop over [pos, end]
loop
exitwhen iter == size
set list[iter] = list[iter + 1]
endloop
//make the current ability point to nothing
set list[abilId] = 0
//pop from back, cause that ability is inside twice now
call popBack()
endmethod
endif
method remove takes integer abilId returns nothing
local integer pos = list[abilId]
//points into the last element of the list
local integer cSize = list[0]
//if it isnt inside the list
//or the list is empty
if pos == 0 or cSize == 0 then
return
endif
//if strict order
static if UNIT_ABIL_LIST_STRICT_ORDER then
call removeStrict(cSize, pos)
else
//move whatever you want
//if it isnt the last element
if pos != cSize then
//replace ours with last
set list[pos] = list[cSize]
endif
//make the ability pointer point to nothing
set list[abilId] = 0
//pop last element
//call to popBack will shrink the size automatically
//it will also remove the pointer of list[abilId] = position
call popBack()
endif
endmethod
method destroy takes nothing returns nothing
call list.destroy()
endmethod
endstruct
//for Reduction.UnitType.XXX syntax
private struct UnitTypeImpl extends array
static method reset takes integer unitType, integer amplifType, real percentReduction returns nothing
set ampDispatch[amplifType].real[unitType] = percentReduction
endmethod
static method add takes integer unitType, integer amplifType, real percentReduction returns nothing
local real cA = ampDispatch[amplifType].real[unitType] + percentReduction
set ampDispatch[amplifType].real[unitType] = cA
endmethod
static method substract takes integer unitType, integer amplifType, real percentReduction returns nothing
call add(unitType, amplifType, -percentReduction)
endmethod
static method get takes integer unitType, integer amplifType returns real
return ampDispatch[amplifType].real[unitType]
endmethod
endstruct
//for Reduction.Unit.XXX syntax
private struct UnitImpl extends array
static method reset takes unit u, integer amplifType, real percentReduction returns nothing
set ampDispatch[amplifType].real[GetHandleId(u)] = percentReduction
endmethod
static method add takes unit u, integer amplifType, real percentReduction returns nothing
local integer hId = GetHandleId(u)
local real cA = ampDispatch[amplifType].real[hId] + percentReduction
set ampDispatch[amplifType].real[hId] = cA
endmethod
static method substract takes unit u, integer amplifType, real percentReduction returns nothing
call add(u, amplifType, -percentReduction)
endmethod
static method get takes unit u, integer amplifType returns real
return ampDispatch[amplifType].real[GetHandleId(u)]
endmethod
endstruct
//for Reduction.ItemType.XXX syntax
private struct ItemTypeImpl extends array
static method reset takes integer itemType, integer amplifType, real percentReduction returns nothing
set ampDispatch[amplifType].real[itemType] = percentReduction
endmethod
static method add takes integer itemType, integer amplifType, real percentReduction returns nothing
local real cA = ampDispatch[amplifType].real[itemType] + percentReduction
set ampDispatch[amplifType].real[itemType] = cA
endmethod
static method substract takes integer itemType, integer amplifType, real percentReduction returns nothing
call add(itemType, amplifType, -percentReduction)
endmethod
static method get takes integer itemType, integer amplifType returns real
return ampDispatch[amplifType].real[itemType]
endmethod
endstruct
//for Reduction.Item.XXX syntax
private struct ItemImpl extends array
static method reset takes item it, integer amplifType, real percentReduction returns nothing
set ampDispatch[amplifType].real[GetHandleId(it)] = percentReduction
endmethod
static method add takes item it, integer amplifType, real percentReduction returns nothing
local integer hId = GetHandleId(it)
local real cA = ampDispatch[amplifType].real[hId] + percentReduction
set ampDispatch[amplifType].real[hId] = cA
endmethod
static method substract takes item it, integer amplifType, real percentReduction returns nothing
call add(it, amplifType, -percentReduction)
endmethod
static method get takes item it, integer amplifType returns real
return ampDispatch[amplifType].real[GetHandleId(it)]
endmethod
endstruct
//for Reduction.OnCast.XX
private struct OnCastImpl extends array
static method setTime takes integer abil, integer level, real howLong returns nothing
local AbilDat dat = abilDatIndicies[-abil]
if level == 0 then
set level = 1
endif
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[-abil] = dat
endif
if not dat.multiLevel then
set level = 1
endif
set dat.overallTime.real[level] = howLong
endmethod
static method getTime takes integer abil, integer level returns real
local AbilDat dat = abilDatIndicies[-abil]
return dat.overallTime.real[level]
endmethod
static method useMultiLevel takes integer abil, boolean use returns nothing
local AbilDat dat = abilDatIndicies[-abil]
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[-abil] = dat
endif
set dat.multiLevel = use
endmethod
static method usesMultiLevel takes integer abil returns boolean
local AbilDat dat = abilDatIndicies[-abil]
return dat != 0 and dat.multiLevel
endmethod
static method reset takes integer abil, integer level, integer amplifType, real percentReduction returns nothing
local AbilDat dat = abilDatIndicies[-abil]
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[-abil] = dat
endif
if not dat.multiLevel then
set level = 1
endif
set dat.dispatch(amplifType).real[level] = percentReduction
endmethod
static method add takes integer abil, integer level, integer amplifType, real percentReduction returns nothing
local AbilDat dat = abilDatIndicies[-abil]
local real cA = 0
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[-abil] = dat
endif
if not dat.multiLevel then
set level = 1
endif
set cA = dat.dispatch(amplifType).real[level] + percentReduction
set dat.dispatch(amplifType).real[level] = cA
endmethod
static method substract takes integer abil, integer level, integer amplifType, real percentReduction returns nothing
call add(abil, level, amplifType, -percentReduction)
endmethod
static method get takes integer abil, integer level, integer amplifType returns real
local AbilDat dat = abilDatIndicies[-abil]
if dat == 0 then
return 0.
endif
if not dat.multiLevel then
set level = 1
endif
return dat.dispatch(amplifType).real[level]
endmethod
endstruct
//for Reduction.Ability.XXX syntax
private struct AbilityImpl extends array
static method useMultiLevel takes integer abil, boolean use returns nothing
local AbilDat dat = abilDatIndicies[abil]
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[abil] = dat
endif
set dat.multiLevel = use
endmethod
static method usesMultiLevel takes integer abil returns boolean
local AbilDat dat = abilDatIndicies[abil]
return dat != 0 and dat.multiLevel
endmethod
static method reset takes integer abil, integer level, integer amplifType, real percentReduction returns nothing
local AbilDat dat = abilDatIndicies[abil]
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[abil] = dat
endif
if not dat.multiLevel then
set level = 1
endif
set dat.dispatch(amplifType).real[level] = percentReduction
endmethod
static method add takes integer abil, integer level, integer amplifType, real percentReduction returns nothing
local AbilDat dat = abilDatIndicies[abil]
local real cA = 0
if dat == 0 then
set dat = AbilDat.create()
set abilDatIndicies[abil] = dat
endif
if not dat.multiLevel then
set level = 1
endif
set cA = dat.dispatch(amplifType).real[level] + percentReduction
set dat.dispatch(amplifType).real[level] = cA
endmethod
static method substract takes integer abil, integer level, integer amplifType, real percentReduction returns nothing
call add(abil, level, amplifType, -percentReduction)
endmethod
static method get takes integer abil, integer level, integer amplifType returns real
local AbilDat dat = abilDatIndicies[abil]
if dat == 0 then
return 0.
endif
if not dat.multiLevel then
set level = 1
endif
return dat.dispatch(amplifType).real[level]
endmethod
endstruct
/********************************/
/******** Struct API ********/
/********************************/
struct Reduction extends array
readonly static integer PHYSICAL = REDUCTION_PHYSICAL
readonly static integer SPELL = REDUCTION_SPELL
readonly static integer CODE = REDUCTION_CODE
readonly static AbilityImpl Ability = 1
readonly static UnitImpl Unit = 1
readonly static UnitTypeImpl UnitType = 1
readonly static ItemImpl Item = 1
readonly static ItemTypeImpl ItemType = 1
readonly static OnCastImpl OnCast = 1
endstruct
function UnitRegisterAbility takes unit u, integer abil returns nothing
local integer hId = GetHandleId(u)
local UnitAbilList list = unitListIndicies[hId]
if list == 0 then
set list = UnitAbilList.create(u)
set unitListIndicies[hId] = list
endif
call list.add(abil)
endfunction
function UnitUnregisterAbility takes unit u, integer abil returns nothing
local integer hId = GetHandleId(u)
local UnitAbilList list = unitListIndicies[hId]
if list != 0 then
call list.remove(abil)
static if DESTROY_EMPTY_STRUCTS then
if list.size() == 0 then
set unitListIndicies[hId] = 0
call list.destroy()
endif
endif
endif
endfunction
function UnitTypeRegisterAbility takes integer uType, integer abil returns nothing
local UnitAbilList list = unitListIndicies[uType]
if list == 0 then
set list = UnitAbilList.create(null)
set unitListIndicies[uType] = list
endif
call list.add(abil)
endfunction
function UnitTypeUnregisterAbility takes integer uType, integer abil returns nothing
local UnitAbilList list = unitListIndicies[uType]
if list != 0 then
call list.remove(abil)
static if DESTROY_EMPTY_STRUCTS then
if list.size() == 0 then
set unitListIndicies[uType] = 0
call list.destroy()
endif
endif
endif
endfunction
function UnitAddAbilityEx takes unit whichUnit, integer abilId returns boolean
local boolean b = UnitAddAbility(whichUnit, abilId)
if b then
call UnitRegisterAbility(whichUnit, abilId)
endif
return b
endfunction
function UnitRemoveAbilityEx takes unit whichUnit, integer abilId returns boolean
local boolean b = UnitRemoveAbility(whichUnit, abilId)
if b then
call UnitUnregisterAbility(whichUnit, abilId)
endif
return b
endfunction
private function accumulateForItems takes unit ofUnit, integer ofType returns real
local item it = null
local integer itType = 0
local integer looper = 0
local integer max = bj_MAX_INVENTORY
local real r = 0
loop
exitwhen max == looper
set it = UnitItemInSlot(ofUnit, looper)
set itType = GetItemTypeId(it)
set r = r + Reduction.Item.get(it, ofType)
set r = r + Reduction.ItemType.get(itType, ofType)
set looper = looper + 1
endloop
set it = null
return r
endfunction
private function dmgHandler takes nothing returns nothing
local real reductionPh = 0
local real reductionSp = 0
local real reductionCo = 0
local unit u = PDDS.target
local integer uId = GetHandleId(u)
local integer dmgType = PDDS.damageType
local UnitAbilList uList = unitListIndicies[uId]
local real redFull = 0
local UnitAbilList uTypeList = unitListIndicies[GetUnitTypeId(u)]
local real amount = PDDS.amount
static if DEBUG_PRINT_ON_HIT_DMG then
local string dOutput = "Before: " + R2S(amount)
endif
if uList != 0 then
set redFull = redFull + uList.sumOfBonus(dmgType)
endif
if uTypeList != 0 then
set redFull = redFull + uTypeList.sumOfBonusEx(u, dmgType)
endif
set redFull = redFull + Reduction.UnitType.get(GetUnitTypeId(u), dmgType)
set redFull = redFull + Reduction.Unit.get(u, dmgType)
set redFull = redFull + accumulateForItems(u, dmgType)
if redFull > 1 then
set amount = 0
else
set amount = amount * (1 - redFull)
endif
static if DEBUG_PRINT_ON_HIT_DMG then
set dOutput = dOutput + " After: " + R2S(amount) + " factor: " + R2S(redFull)
call BJDebugMsg(dOutput)
endif
set PDDS.amount = amount
set u = null
endfunction
globals
private timer CastLooper = CreateTimer()
endglobals
private function CopyAbilToCastInstance takes OnCastDat cDat,/*
*/AbilDat aDat, integer abilLvl returns OnCastDat
local integer looper = 1
local integer mLooper = 0
if not aDat.multiLevel then
set abilLvl = 1
endif
loop
set cDat.amounts.real[mLooper] = aDat.dispatch(mLooper).real[abilLvl]
exitwhen mLooper == DAMAGE_TYPES - 1
set mLooper = mLooper + 1
endloop
set cDat.time = aDat.overallTime.real[abilLvl]
return cDat
endfunction
private function onCastLooper takes nothing returns nothing
local OnCastDat looper = OnCastDat.head
local boolean alloc = OnCastDat.allocated()
local integer looperT = 0
loop
set looper.time = looper.time - TICK_TIME
if (looper.time <= 0.) then
//go through all possible reductions
loop
call Reduction.Unit.substract(looper.caster, looperT, looper.amounts.real[looperT])
exitwhen looperT == DAMAGE_TYPES - 1
set looperT = looperT + 1
endloop
call looper.destroy()
endif
exitwhen looper == 0
set looper = OnCastDat.head.next
endloop
if alloc and not OnCastDat.allocated() then
call PauseTimer(CastLooper)
endif
endfunction
private function onCastHandler takes nothing returns boolean
local unit caster = GetTriggerUnit()
local integer abil = GetSpellAbilityId()
local AbilDat dat = abilDatIndicies[-abil]
local boolean was = OnCastDat.allocated()
local integer abilityLevel = GetUnitAbilityLevel(caster, abil)
local OnCastDat onCDat = 0
if dat == 0 then
return false
endif
set onCDat = CopyAbilToCastInstance(OnCastDat.create(caster), dat, abilityLevel)
if OnCastDat.allocated() and not was then
call TimerStart(CastLooper, TICK_TIME, true, function onCastLooper)
endif
//use as loop now
set abil = 0
//loop through all possible reductions
loop
call Reduction.Unit.add(caster, abil, onCDat.amounts.real[abil])
exitwhen abil == DAMAGE_TYPES - 1
set abil = abil + 1
endloop
set caster = null
return false
endfunction
private module m
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call AddDamageHandler(function dmgHandler)
set amplifiedPhys = Table.create()
set amplifiedMag = Table.create()
set amplifiedCode = Table.create()
set ampDispatch[0] = amplifiedPhys
set ampDispatch[1] = amplifiedMag
set ampDispatch[2] = amplifiedCode
set abilDatIndicies = Table.create()
set unitListIndicies = Table.create()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Filter(function onCastHandler))
set t = null
endmethod
endmodule
private struct s extends array
implement m
endstruct
endlibrary
Example:
JASS:
scope s initializer init
private function f takes nothing returns nothing
//destroy timer, preventing leaks
call DestroyTimer(GetExpiredTimer())
//decrease damage reduction of Physical damage for
//Boots of speed by 16.6%
call Reduction.ItemType.substract('bspd', Reduction.PHYSICAL, 0.166)
endfunction
private function init takes nothing returns nothing
//create footman for enemy player
local unit u = CreateUnit(Player(1), 'hfoo', 0, 0, 0)
//create paladin for us
local unit h = CreateUnit(Player(0), 'Hmkg', 0, -380, 0)
//set damage reduction of spell damage for all footmans on map
//to -0.15
call Reduction.UnitType.add(GetUnitTypeId(u), Reduction.SPELL, -0.15)
//set damage reduction of spell damage for specific footman
//we created to -0.15
call Reduction.Unit.add(u, Reduction.SPELL, -0.15)
//in here, footman will take 30% more damage from spells
//say to the system that Mountain King is using Storm Bolt
call UnitTypeRegisterAbility('Hmkg', 'AHtb')
//Set Multiple level bonus for Storm Bolt to false
//Basically this means that every level of Storm Bolt
//uses the same bonuses
call Reduction.Ability.useMultiLevel('AHtb', false)
//after that set physical damage reduction for Storm Bolt
//at level 0(doesnt matter because of false in useMultiLevel)
//to 36.7% reduced damage
call Reduction.Ability.add('AHtb', 0, Reduction.PHYSICAL, 0.367)
//At this point, as long as any Mountain King has
//Storm Bolt learned(level is >0), he will receive
//the reduction
//set reduction for Boots of Speed of type Physical to 16.6%
call Reduction.ItemType.add('bspd', Reduction.PHYSICAL, 0.166)
//at this point, if any unit that receives damage is carrying
//Boots of Speed, he will receive the reduction
//start timer to remove reduction from Boots of Speed
call TimerStart(CreateTimer(), 5., false, function f)
//give the spawned hero Boots of Speed
call UnitAddItemById(h, 'bspd')
//set time of day to 12 pm, so we can see nice and far
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 12)
endfunction
endscope
- added OnCast
- fixed PDDS incompatibility
- fixed UnitAbilDat.isInside returns nothing despite returning boolean
- modified dispatch method inside AbilDat, so that it does simple array subscript now(on TableArray, should still be faster than possibly 3 if block evaluations)
- added new configurable: TICK_TIME
- Removed functions from API(code would be unmanageably big + I would have to update 2 interfaces every time)
- Code now supports arbitrary number of Reduction types, besides the hardcoded 3 ones, but it has strong requirement: All damage types must be set to incrementing value starting at 0. There is afaik no support for this currently in LFH's DDS, so may not be really usable, but it is there.
-
library DamageAmplifier
->library DamageReduction
- Initial Release on Hive
- Full API Rework
Attachments
Last edited: