function chainCast takes unit attacker, unit target, integer damage, boolean canCrit, integer bounces, integer minBounceForRebounce, integer bounceWait, string abilityOrder, integer buffcode, real damageReduction, real aoe returns nothing
local unit dummycaster
local integer dtype = lastDmgType
local integer coeff = lastCoeff
local integer currentBounce = 1
local unit temp = attacker
local location loc = GetUnitLoc(temp)
local location locTarget = GetUnitLoc(target)
local group unitGroup
local player pl = GetOwningPlayer(attacker)
loop
call BJDebugMsg("in chain loop")
// cast a spell that gives a buff but does no dmg
set dummycaster = CreateUnitAtLoc(pl, 'Hpal', loc, AngleBetweenPoints(loc, locTarget))
call UnitAddAbility(dummycaster, 'A001')
call IssueTargetOrder(dummycaster, abilityOrder, target)
call UnitApplyTimedLife(dummycaster, 'BTLF', 1)
loop
exitwhen (GetUnitAbilityLevel(target, buffcode) > 0)
call TriggerSleepAction(.29)
endloop
call BJDebugMsg("made it through the loop")
call damageUnit(attacker, target, damage, ATTACK_TYPE_HERO, dtype, coeff, canCrit)
set temp = target
// get unit group
call RemoveLocation(loc)
set loc = GetUnitLoc(temp)
call BJDebugMsg("new loc")
call GroupEnumUnitsInRangeOfLoc(unitGroup, loc, aoe, Filter(function enemyFilter))
call BJDebugMsg("unit group created")
set damage = R2I(damage * damageReduction)
exitwhen currentBounce == bounces
// find new target
set target = GroupPickRandomUnit(unitGroup)
call RemoveLocation(locTarget)
set locTarget = GetUnitLoc(target)
set currentBounce = currentBounce + 1
// wait between bounces
if (bounceWait > 0) then
call TriggerSleepAction(bounceWait)
endif
endloop
call RemoveLocation(loc)
set locTarget = null
set loc = null
set attacker = null
set target = null
endfunction
function enemyFilter takes nothing returns boolean
local unit u = GetFilterUnit()
return (IsUnitEnemy(u, GetOwningPlayer(u)) and (GetUnitState(u, UNIT_STATE_LIFE) > 0))
endfunction
(IsUnitEnemy(u, GetOwningPlayer(u)) and (GetUnitState(u, UNIT_STATE_LIFE) > 0))
Two things.
1. (GetUnitState(u, UNIT_STATE_LIFE) > 0) use 0.405 to be more accurate.
2. IsUnitEnemy(u, GetOwningPlayer(u)) What, you are having personal dilemmas - are you an enemy of yourself?
library ChainSystem requires DamageSys
globals
player chainCast_castingPlayer
endglobals
struct chaindata
integer bounces
integer minBounceForRebounce
integer buffcode
real bounceWait
real damageReduction
real aoe
string abilityOrder
endstruct
function enemyFilter takes nothing returns boolean
local unit u = GetFilterUnit()
local boolean bool
call BJDebugMsg("In Filter")
set bool = (IsUnitEnemy(u, chainCast_castingPlayer) and (GetUnitState(u, UNIT_STATE_LIFE) > .405))
if (bool) then
call BJDebugMsg("True")
else
call BJDebugMsg("False")
endif
set u = null
return bool
endfunction
function chainCast takes damagedata dmgdata, chaindata chainData returns nothing
local unit dummycaster
local integer currentBounce = 1
local unit temp = dmgdata.attacker
local location loc = GetUnitLoc(temp)
local location locTarget = GetUnitLoc(dmgdata.target)
local group unitGroup
local player plyr = GetOwningPlayer(dmgdata.attacker)
loop
call BJDebugMsg("in chain loop")
// cast a spell that gives a buff but does no dmg
set dummycaster = CreateUnitAtLoc(plyr, 'Hpal', loc, AngleBetweenPoints(loc, locTarget))
call UnitAddAbility(dummycaster, 'A001')
call IssueTargetOrder(dummycaster, chainData.abilityOrder, dmgdata.target)
call UnitApplyTimedLife(dummycaster, 'BTLF', 1)
loop
exitwhen (GetUnitAbilityLevel(dmgdata.target, chainData.buffcode) > 0)
call TriggerSleepAction(.29)
endloop
call BJDebugMsg("made it through the loop")
call damageUnit(dmgdata)
set temp = dmgdata.target
// get unit group
call RemoveLocation(loc)
set loc = GetUnitLoc(temp)
call BJDebugMsg("new loc")
set chainCast_castingPlayer = GetOwningPlayer(dmgdata.attacker)
call GroupEnumUnitsInRangeOfLoc(unitGroup, loc, chainData.aoe, Filter(function enemyFilter))
call BJDebugMsg("unit group created")
set dmgdata.damage = R2I(dmgdata.damage * chainData.damageReduction)
exitwhen currentBounce == chainData.bounces
// find new target
set dmgdata.target = GroupPickRandomUnit(unitGroup)
call RemoveLocation(locTarget)
set locTarget = GetUnitLoc(dmgdata.target)
set currentBounce = currentBounce + 1
// wait between bounces
if (chainData.bounceWait > 0) then
call TriggerSleepAction(chainData.bounceWait)
endif
endloop
call RemoveLocation(loc)
call chainData.destroy()
call dmgdata.destroy()
set locTarget = null
set loc = null
endfunction
endlibrary
Its for the newly dead. Just as soon as you kill a unit, its health goes down to something like 0.405 (I can't remember the exact number, and I don't htink that was it) as it begins to decay. From there, it goes to 0.404, 0.403, 0.402, 0.401, and then 0.Out of curiosity, why 0.405?
loop
exitwhen (GetUnitAbilityLevel(dmgdata.target, chainData.buffcode) > 0)
call TriggerSleepAction(.29)
endloop
Actually, when a unit's life hits .405 or below, it dies and its health is set to 0.Its for the newly dead. Just as soon as you kill a unit, its health goes down to something like 0.405 (I can't remember the exact number, and I don't htink that was it) as it begins to decay. From there, it goes to 0.404, 0.403, 0.402, 0.401, and then 0.
So... its just to exclude the newly-dead.