scope WaterCage
globals
constant real WATER_CAGE_BASE_RANGE = 250
constant real WATER_CAGE_LEVEL_RANGE = 25
constant real WATER_CAGE_BASE_DURATION = 10.00
constant real WATER_CAGE_LEVEL_DURATION = 2.00
constant integer WATER_CAGE_ABILITY_ID = 'aw01'
constant integer PATHING_BLOCKER_BOTH = 'YTfb'
constant integer WATER_CAGE_CENTER_DUMMY = 'n000'
constant integer SPELL_IMMUNITY_ABILITY = 'aw02'
constant string MANA_DRAIN_LIGHTNING = "DRAM"
integer array GlobalCageStruct[128]
integer array GlobalPreventDamageStruct[8192]
unit array InvulnerableUnits[8192]
real array InvulnerableDamage[8192]
real CageLocationX
real CageLocationY
real CageMaxRange
endglobals
private function H2I takes handle H returns integer
return H
return 0
endfunction
struct CageStruct
unit CagedCaster
unit CageCenterDummy
group CagedGroup
integer CageLevel
real CenterX
real CenterY
real Range
trigger NoNewUnits
player array AllowedPlayers[16]
destructable array CageBlocker[32]
real array CornerX[32]
real array CornerY[32]
lightning array Horizontal1[32]
lightning array Horizontal2[32]
lightning array Horizontal3[32]
lightning array Vertical[32]
static method create takes unit whichUnit, integer whatLevel returns CageStruct
local CageStruct Cage = CageStruct.allocate()
set Cage.CagedCaster = whichUnit
set Cage.CenterX = GetUnitX(whichUnit)
set Cage.CenterY = GetUnitY(whichUnit)
set Cage.CageLevel = whatLevel
set Cage.Range = WATER_CAGE_BASE_RANGE+WATER_CAGE_LEVEL_RANGE*whatLevel
return Cage
endmethod
method onDestroy takes nothing returns nothing
local integer a = 0
set .CagedCaster = null
call DestroyGroup(.CagedGroup)
set .CagedGroup = null
loop
if .NoNewUnits != null then
call ReleaseTriggerSpecialData(.NoNewUnits)
call DestroyTrigger(.NoNewUnits)
set .NoNewUnits = null
endif
if .CageBlocker[a] != null then
call RemoveDestructable(.CageBlocker[a])
set .CageBlocker[a] = null
endif
if .Horizontal1[a] != null then
call DestroyLightning(.Horizontal1[a])
set .Horizontal1[a] = null
endif
if .Horizontal2[a] != null then
call DestroyLightning(.Horizontal2[a])
set .Horizontal2[a] = null
endif
if .Horizontal3[a] != null then
call DestroyLightning(.Horizontal3[a])
set .Horizontal3[a] = null
endif
if .Vertical[a] != null then
call DestroyLightning(.Vertical[a])
set .Vertical[a] = null
endif
set a = a+1
exitwhen a == 32
endloop
endmethod
static method TooFar takes nothing returns boolean
return GetDistanceXY(GetUnitX(GetFilterUnit()), GetUnitY(GetFilterUnit()), CageLocationX, CageLocationY) > CageMaxRange
endmethod
static method NotADummy takes nothing returns boolean
return GetUnitAbilityLevel(GetFilterUnit(), 'aloc') == 0
endmethod
method PushAndPull takes nothing returns nothing
local group TemporaryGroup = CreateGroup()
local unit ToBeMoved
local real Angle
set CageLocationX = .CenterX
set CageLocationY = .CenterY
set CageMaxRange = .Range
set .CagedGroup = CreateGroup()
call GroupEnumUnitsInRange(TemporaryGroup, .CenterX, .CenterY, .Range+200, Filter(function CageStruct.TooFar))
loop
set ToBeMoved = FirstOfGroup(TemporaryGroup)
exitwhen ToBeMoved == null
set Angle = AngleBetweenPointsXY(.CenterX, .CenterY, GetUnitX(ToBeMoved), GetUnitY(ToBeMoved))
call SetUnitX(ToBeMoved, .CenterX+Cos(Angle)*200)
call SetUnitY(ToBeMoved, .CenterY+Sin(Angle)*200)
call GroupRemoveUnit(TemporaryGroup, ToBeMoved)
set ToBeMoved = null
endloop
call GroupEnumUnitsInRange(TemporaryGroup, .CenterX, .CenterY, .Range, Filter(function CageStruct.NotADummy))
loop
set ToBeMoved = FirstOfGroup(TemporaryGroup)
exitwhen ToBeMoved == null
call SetUnitX(ToBeMoved, .CenterX)
call SetUnitY(ToBeMoved, .CenterY)
call GroupAddUnit(.CagedGroup, ToBeMoved)
call GroupRemoveUnit(TemporaryGroup, ToBeMoved)
set ToBeMoved = null
endloop
call DestroyGroup(TemporaryGroup)
set TemporaryGroup = null
endmethod
static method IsUnitBannedFromCage takes nothing returns boolean
local integer this = GetTriggerSpecialData(GetTriggeringTrigger())
local integer i = 0
local player p = GetOwningPlayer(GetTriggerUnit())
loop
if .AllowedPlayers[i] == p then
return false
endif
exitwhen i == 16
set i = i+1
endloop
set p = null
return true
endmethod
static method BanUnitFromCage takes nothing returns nothing
local integer this = GetTriggerSpecialData(GetTriggeringTrigger())
local real angle = AngleBetweenPointsXY(.CenterX, .CenterY, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
call SetUnitX(GetTriggerUnit(), .CenterX+Cos(angle)*(.Range+150))
call SetUnitY(GetTriggerUnit(), .CenterY+Sin(angle)*(.Range+150))
endmethod
private static method DestroyCage takes nothing returns nothing
local integer this = GetTimerData(GetExpiredTimer())
call ReleaseTimer(GetExpiredTimer())
call .destroy()
endmethod
private static method CreateCage4 takes nothing returns nothing
local integer this = GetTimerData(GetExpiredTimer())
local integer index = 0
local real angle = 0
local real distance = .Range-300
local real currentX
local real currentY
call ReleaseTimer(GetExpiredTimer())
loop
set angle = angle+0.195
set currentX = .CenterX+Cos(angle)*.Range
set currentY = .CenterY+Sin(angle)*.Range
set .Vertical[index] = AddLightningEx("DRAM", true, currentX, currentY, 0, currentX, currentY, 450)
set index = index+1
exitwhen angle >= 6.20
endloop
endmethod
private static method CreateCage3 takes nothing returns nothing
local integer this = GetTimerData(GetExpiredTimer())
local integer index = 0
local real angle = 0
local real lastX = .CenterX+Cos(angle)*.Range
local real lastY = .CenterY+Sin(angle)*.Range
local real currentX
local real currentY
local timer Temp
call ReleaseTimer(GetExpiredTimer())
loop
set angle = angle+0.195
set currentX = .CenterX+Cos(angle)*.Range
set currentY = .CenterY+Sin(angle)*.Range
set .Horizontal3[index] = AddLightningEx("DRAM", true, lastX, lastY, 375, currentX, currentY, 375)
set lastX = currentX
set lastY = currentY
set index = index+1
exitwhen angle >= 6.20
endloop
set Temp = NewTimer()
call SetTimerData(Temp, this)
call TimerStart(Temp, 0.7, false, function CageStruct.CreateCage4)
set Temp = null
endmethod
private static method CreateCage2 takes nothing returns nothing
local integer this = GetTimerData(GetExpiredTimer())
local integer index = 0
local real angle = 0
local real lastX = .CenterX+Cos(angle)*.Range
local real lastY = .CenterY+Sin(angle)*.Range
local real currentX
local real currentY
local timer Temp
call ReleaseTimer(GetExpiredTimer())
loop
set angle = angle+0.195
set currentX = .CenterX+Cos(angle)*.Range
set currentY = .CenterY+Sin(angle)*.Range
set .Horizontal2[index] = AddLightningEx("DRAM", true, lastX, lastY, 225, currentX, currentY, 225)
set lastX = currentX
set lastY = currentY
set index = index+1
exitwhen angle >= 6.20
endloop
set Temp = NewTimer()
call SetTimerData(Temp, this)
call TimerStart(Temp, 0.7, false, function CageStruct.CreateCage3)
set Temp = null
endmethod
method CreateCage takes nothing returns nothing
local real angle = 0
local real lastX = .CenterX+Cos(angle)*.Range
local real lastY = .CenterY+Sin(angle)*.Range
local integer index = 0
local real currentX
local real currentY
local timer Temp
loop
set angle = angle+0.195
set currentX = .CenterX+Cos(angle)*.Range
set currentY = .CenterY+Sin(angle)*.Range
set .CageBlocker[index] = CreateDestructable(PATHING_BLOCKER_BOTH, currentX, currentY, 0, 1, 1)
set .Horizontal1[index] = AddLightningEx("DRAM", true, lastX, lastY, 75, currentX, currentY, 75)
set lastX = currentX
set lastY = currentY
set index = index+1
exitwhen angle >= 6.20
endloop
set .CageCenterDummy = CreateUnit(GetOwningPlayer(.CagedCaster), WATER_CAGE_CENTER_DUMMY, .CenterX, .CenterY, 0)
set .NoNewUnits = CreateTrigger()
call SetTriggerSpecialData(.NoNewUnits, this)
call TriggerRegisterUnitInRange(.NoNewUnits, .CageCenterDummy, .Range+100, null)
call TriggerAddCondition(.NoNewUnits, Condition(function CageStruct.IsUnitBannedFromCage))
call TriggerAddAction(.NoNewUnits, function CageStruct.BanUnitFromCage)
set Temp = NewTimer()
call SetTimerData(Temp, this)
call TimerStart(Temp, 0.7, false, function CageStruct.CreateCage2)
set Temp = NewTimer()
call SetTimerData(Temp, this)
call TimerStart(Temp, WATER_CAGE_BASE_DURATION+WATER_CAGE_LEVEL_DURATION*.CageLevel, false, function CageStruct.DestroyCage)
set Temp = null
endmethod
private static method CanUnitAttack takes nothing returns boolean
local integer this = GetTriggerSpecialData(GetTriggeringTrigger())
return GetDistanceXY(.CenterX, .CenterY, GetUnitX(GetEventDamageSource()), GetUnitY(GetEventDamageSource())) > .Range
endmethod
private static method UnitRemoveInvulnerable takes nothing returns nothing
local integer index = GetTimerData(GetExpiredTimer())
call ReleaseTimer(GetExpiredTimer())
call SetUnitState(InvulnerableUnits[index], UNIT_STATE_LIFE, GetUnitState(InvulnerableUnits[index], UNIT_STATE_LIFE)+InvulnerableDamage[index])
call UnitRemoveAbility(InvulnerableUnits[index], SPELL_IMMUNITY_ABILITY)
set InvulnerableUnits[index] = null
endmethod
private static method UnitMakeInvulnerable takes nothing returns nothing
local integer index
local real CurrentLife
local real MaxLife
local real EventDamage
local timer Temp
local unit Target
if GetTriggerEventId() == EVENT_UNIT_DAMAGED then
set Target = GetTriggerUnit()
set CurrentLife = GetUnitState(Target, UNIT_STATE_LIFE)
set MaxLife = GetUnitState(Target, UNIT_STATE_MAX_LIFE)
set EventDamage = GetEventDamage()
loop
set index = GetRandomInt(0, 8190)
exitwhen InvulnerableUnits[index] == null
endloop
if CurrentLife > 0.405 then
if EventDamage < MaxLife-CurrentLife then
call SetUnitState(Target, UNIT_STATE_LIFE, CurrentLife+EventDamage)
else
if EventDamage < CurrentLife then
set InvulnerableDamage[index] = EventDamage
else
call SetUnitState(Target, UNIT_STATE_LIFE, MaxLife)
set InvulnerableDamage[index] = EventDamage+CurrentLife-MaxLife
endif
set InvulnerableUnits[index] = Target
endif
endif
call UnitAddAbility(Target, SPELL_IMMUNITY_ABILITY)
set Temp = NewTimer()
call SetTimerData(Temp, index)
call TimerStart(Temp, 0.00, false, function CageStruct.UnitRemoveInvulnerable)
set Temp = null
else
call ReleaseTriggerSpecialData(GetTriggeringTrigger())
call DisableTrigger(GetTriggeringTrigger())
endif
endmethod
method StartInvulnerability takes nothing returns nothing
local trigger t
local unit u
local group temporary = CreateGroup()
loop
set u = FirstOfGroup(.CagedGroup)
exitwhen u == null
set t = CreateTrigger()
call SetTriggerSpecialData(t, this)
call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_DAMAGED)
call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_DECAY)
call TriggerAddCondition(t, Condition(function CageStruct.CanUnitAttack))
call TriggerAddAction(t, function CageStruct.UnitMakeInvulnerable)
call GroupAddUnit(temporary, u)
call GroupRemoveUnit(.CagedGroup, u)
set u = null
endloop
loop
set u = FirstOfGroup(temporary)
exitwhen u == null
call GroupAddUnit(.CagedGroup, u)
call GroupRemoveUnit(temporary, u)
set u = null
endloop
call DestroyGroup(temporary)
set t = null
endmethod
endstruct
function Trig_Water_Cage_Conditions takes nothing returns boolean
return GetSpellAbilityId() == WATER_CAGE_ABILITY_ID
endfunction
function Trig_Water_Cage_Actions takes nothing returns nothing
local CageStruct Cage = CageStruct.create(GetTriggerUnit(), GetUnitAbilityLevel(GetTriggerUnit(),WATER_CAGE_ABILITY_ID))
call Cage.PushAndPull()
call Cage.CreateCage()
call Cage.StartInvulnerability()
endfunction
//===========================================================================
function InitTrig_Water_Cage takes nothing returns nothing
set gg_trg_Water_Cage = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Water_Cage, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Water_Cage, Condition( function Trig_Water_Cage_Conditions ) )
call TriggerAddAction( gg_trg_Water_Cage, function Trig_Water_Cage_Actions )
endfunction
endscope