scope DiabolicSpecialHoundMaster
globals
constant real CHAIN_MAX_DISTANCE = 550.0
constant real CHAIN_BREAK_DISTANCE = 625.0
constant group diabolicSpecialHoundMastersLookingToChain = CreateGroup()
endglobals
public keyword DiabolicSpecialHoundMaster_LookForChainTargetsFor
private struct Chain
private static timer t = CreateTimer()
private static thistype array chains
static group chainedUnits = CreateGroup()
private unit master
private unit target
private lightning vfx
public static method IsUnitChained takes unit target returns boolean
return chains[GetUnitUserData(target)].target == target
endmethod
method destroy takes nothing returns nothing
//clean up everything
call GroupRemoveUnit(chainedUnits, target)
set chains[GetUnitUserData(target)] = 0
set master = null
set target = null
call DestroyLightning(vfx)
set vfx = null
call deallocate()
endmethod
method update takes nothing returns nothing
local real mx = GetUnitX(master)
local real my = GetUnitY(master)
local real mz = BlzGetUnitZ(master)
local real tx = GetUnitX(target)
local real ty = GetUnitY(target)
local real tz = BlzGetUnitZ(target)
local real dx = tx - mx
local real dy = ty - my
local real distance = SquareRoot(dx * dx + dy * dy)
local real angle
//call BJDebugMsg("Updateing Chain to " + GetUnitName(target))
if UnitAlive(master) and UnitAlive(target) then
call MoveLightningEx(vfx, true, mx, my, mz + 60, tx, ty, tz + 60)
if distance > CHAIN_MAX_DISTANCE then
//call BJDebugMsg("OUTSIDE MAX RANGE, target=" + GetUnitName(target))
if distance > CHAIN_BREAK_DISTANCE and GetUnitTypeId(target) != HOUND_MASTER_WOLF_UNIT then
call DiabolicSpecialHoundMaster_LookForChainTargetsFor.evaluate(master)
call destroy()
else
set angle = Atan2(dy, dx)
call SetUnitX(target, mx + CHAIN_MAX_DISTANCE * Cos(angle))
call SetUnitY(target, my + CHAIN_MAX_DISTANCE * Sin(angle))
endif
//set udg_Knockback2DUnit = target
//set udg_Knockback2DAngle = bj_RADTODEG * Atan2(dy, dx)
//set udg_Knockback2DDistance = (distance - 500)
//set udg_Knockback2DTime = 0.10 + udg_Knockback2DDistance / 650.0
//set udg_Knockback2DCollision = 8.0
//set udg_Knockback2DFX = ""
//set udg_Knockback2DUnbiasedCollision = true
//call TriggerExecute(gg_trg_Knockback_2D)
endif
else
call destroy()
endif
endmethod
static method updateAll takes nothing returns nothing
local group tempGroup
local unit u
local integer numberOfChains = BlzGroupGetSize(chainedUnits)
//call BJDebugMsg("Chains Updating: Count=" + I2S(numberOfChains))
if numberOfChains == 0 then
//call BJDebugMsg("No chained units still exists, pausing...")
call PauseTimer(t)
return
endif
set tempGroup = CreateGroup()
call BlzGroupAddGroupFast(chainedUnits, tempGroup)
loop
set u = FirstOfGroup(tempGroup)
exitwhen u == null
call chains[GetUnitUserData(u)].update()
call GroupRemoveUnit(tempGroup, u)
endloop
call DestroyGroup(tempGroup)
set tempGroup = null
endmethod
public static method ChainUnit takes unit master, unit target returns nothing
local thistype this = thistype.allocate()
set .master = master
set .target = target
set .vfx = AddLightningEx("WHCA", true, GetUnitX(master), GetUnitY(master), BlzGetUnitZ(master) + 60, GetUnitX(target), GetUnitY(target), BlzGetUnitZ(target) + 60)
call SetLightningColor(.vfx, 0.25, 0.25, 0.25, 1.0) //Gray, solid, chain
if BlzGroupGetSize(chainedUnits) == 0 then
call TimerStart(t, 1. / 50., true, function thistype.updateAll)
endif
call GroupAddUnit(chainedUnits, target)
set chains[GetUnitUserData(target)] = this
endmethod
endstruct
function DiabolicSpecialChainUnit takes unit master, unit target returns nothing
//call BJDebugMsg(GetUnitName(master) + " chaining " + GetUnitName(target))
call Chain.ChainUnit(master, target)
endfunction
function DiabolicSpecialsHoundMasterLookForTargets_SpecificUnit takes unit master returns nothing
local real x = GetUnitX(master)
local real y = GetUnitY(master)
local group tempGroup = CreateGroup()
local unit u
local player owner = GetOwningPlayer(master)
call GroupEnumUnitsInRange(tempGroup, x, y, CHAIN_MAX_DISTANCE - 125.0, null)
loop
set u = FirstOfGroup(tempGroup)
exitwhen u == null
if IsUnitType(u, UNIT_TYPE_HERO) and not IsUnitAlly(u, owner) and not Chain.IsUnitChained(u) then
call DiabolicSpecialChainUnit(master, u)
call GroupRemoveUnit(diabolicSpecialHoundMastersLookingToChain, master)
set u = null
exitwhen true
endif
call GroupRemoveUnit(tempGroup, u)
endloop
call DestroyGroup(tempGroup)
set owner = null
set tempGroup = null
endfunction
function DiabolicSpecialsHoundMasterLookForTargets takes nothing returns nothing
local group tempGroup
local unit u
if BlzGroupGetSize(diabolicSpecialHoundMastersLookingToChain) == 0 then
call ReleaseTimer(GetExpiredTimer())
else
set tempGroup = CreateGroup()
call BlzGroupAddGroupFast(diabolicSpecialHoundMastersLookingToChain, tempGroup)
loop
set u = FirstOfGroup(tempGroup)
exitwhen u == null
if UnitAlive(u) then
call DiabolicSpecialsHoundMasterLookForTargets_SpecificUnit(u)
else
call GroupRemoveUnit(diabolicSpecialHoundMastersLookingToChain, u)
endif
call GroupRemoveUnit(tempGroup, u)
endloop
call DestroyGroup(tempGroup)
set tempGroup = null
endif
endfunction
public function DiabolicSpecialHoundMaster_LookForChainTargetsFor takes unit master returns nothing
if BlzGroupGetSize(diabolicSpecialHoundMastersLookingToChain) == 0 then
call TimerStart(NewTimer(), 0.67, true, function DiabolicSpecialsHoundMasterLookForTargets)
endif
call GroupAddUnit(diabolicSpecialHoundMastersLookingToChain, master)
endfunction
function DiabolicSpecialHoundMaster_CreateHound takes unit master returns nothing
local unit hound = CreateUnit(GetOwningPlayer(master), HOUND_MASTER_WOLF_UNIT, GetUnitX(master) + GetRandomReal(-100, 100), GetUnitY(master) + GetRandomReal(-100, 100), 0)
//Math: https://www.wolframalpha.com/input/?i=x+%3D+1%2C10%2C20%2C30%2C40+for+%28120+%2B+7.5+*+%281+%2B+x+*+0.04%29+*+x%29
call BlzSetUnitMaxHP(hound, R2I(120 + 7.5 * (1 + udg_current_wave_nr * 0.04) * udg_current_wave_nr))
call BlzSetUnitArmor(hound, 25 + 1.75 * udg_current_wave_nr)
call BlzSetUnitBaseDamage(hound, R2I(14 + 1.75 * (1 + udg_current_wave_nr * 0.04) * udg_current_wave_nr), 0)
call SetUnitState(hound, UNIT_STATE_LIFE, MaxHp(hound))
call DiabolicSpecialChainUnit(master, hound)
call IssuePointOrderLoc( hound, "attack", udg_center_player_spawn_point )
set hound = null
endfunction
endscope