library Titanic initializer InitT
globals
private constant real DELAY = 0.03
private constant integer TA = 'A005'
private constant integer Ship = 'h001'
private constant integer Iceberg = 'h002'
private constant integer CastDummy = 'h003'
private constant integer SlowID = 'A002'
private constant real StartHeight = 700
private constant real HeightChange = 750*DELAY
private constant string Eff = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
private constant string KB_eff = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl"
private constant string TrailEff = "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl"
private constant real Base_KB = 250
private constant real KB_Inc = 50
private constant real KB_speed = 750*DELAY
private constant real KB_Dmg = 50
private constant real Ship_speed = 750*DELAY
private constant real KB_Dmg_Inc = 50
private constant real Base_Damage = 100
private constant real Damage_Inc = 100
private constant real AoE = 300
private constant integer EffectSpamRate = 6
private constant integer TrailEffRate = 3
private constant boolean KnockbackOnImpact = true
private constant location Zloc = Location(0,0)
private player TP
private real array TR
private unit array TU
private group KB_GROUP = CreateGroup()
private group GROUP = CreateGroup()
endglobals
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == TA
endfunction
private function GroupFilter takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(),TP) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL) == false) and (GetWidgetLife(GetFilterUnit()) > 0.405) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE)==false) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING)==false) and not IsUnitInGroup(GetFilterUnit(),KB_GROUP)
endfunction
private function RBL takes real x1,real y1,real x2, real y2 returns real
return Atan2(y2 - y1,x2 - x1)
endfunction
private function DBL takes real x1, real y1, real x2, real y2 returns real
return SquareRoot((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
endfunction
private function BuildEff takes integer num, real dist, string eff,real x, real y returns nothing
local integer i = 0
local real ia = 6.2831853/num
local real rad
loop
exitwhen i == num
set rad = ia * i
call DestroyEffect(AddSpecialEffect(eff,x+dist*Cos(rad),y+dist*Sin(rad)))
set i = i + 1
endloop
endfunction
private function GetDmg takes integer lvl returns real
return Base_Damage + (lvl - 1) * Damage_Inc
endfunction
private function GetKBDmg takes integer lvl returns real
return KB_Dmg + (lvl - 1) * KB_Dmg_Inc
endfunction
private function GetKBDist takes integer lvl returns real
return Base_KB + (lvl - 1) * KB_Inc
endfunction
private struct KB
unit u
unit t
real md
real cd
real s
real dmg
real rad
integer esr
string eff
static KB array index
static integer knock = 0
static timer knocker = CreateTimer()
static method Knockback takes nothing returns nothing
local KB kb
local real x
local real y
local integer i = 0
loop
exitwhen i >= KB.knock
set kb = KB.index[i]
if kb.cd < kb.md and GetWidgetLife(kb.t) > 0.405 then
set x = GetUnitX(kb.t) + kb.s * Cos(kb.rad)
set y = GetUnitY(kb.t) + kb.s * Sin(kb.rad)
set kb.cd = kb.cd + kb.s
call SetUnitX(kb.t,x)
call SetUnitY(kb.t,y)
if GetRandomInt(0,kb.esr) == kb.esr then
call DestroyEffect(AddSpecialEffectTarget(kb.eff,kb.t,"origin"))
endif
call UnitDamageTarget(kb.u,kb.t,kb.dmg,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
else
call GroupRemoveUnit(KB_GROUP,kb.t)
set kb.t = null
set kb.u = null
call kb.destroy()
set KB.knock = KB.knock - 1
set KB.index[i] = KB.index[KB.knock]
endif
set i = i + 1
endloop
if KB.knock == 0 then
call PauseTimer(KB.knocker)
endif
endmethod
static method GetKB takes unit c,unit t,real rad,real d,real s,real dmg,integer esr,string eff returns nothing
local KB kb = KB.allocate()
set kb.u = c
set kb.t = t
set kb.rad = rad
set kb.md = d
set kb.cd = 0
set kb.s = s
set kb.eff = eff
set kb.dmg = (dmg / d) * DELAY
if KB.knock == 0 then
call TimerStart(KB.knocker,DELAY,true, function KB.Knockback)
endif
set KB.index[KB.knock] = kb
set KB.knock = KB.knock + 1
call GroupAddUnit(KB_GROUP,t)
endmethod
endstruct
private function GroupAction takes nothing returns nothing
local unit eu = GetEnumUnit()
local real a = RBL(TR[1],TR[2],GetUnitX(eu),GetUnitY(eu))
local integer lvl = GetUnitAbilityLevel(TU[1],TA)
local real dmg = GetDmg(lvl)
local real kb_dist = GetKBDist(lvl)
local real kb_dmg = GetKBDmg(lvl)
local unit dummy = CreateUnit(TP,CastDummy,TR[1],TR[2],0)
local real rad = Atan2(GetUnitY(eu) - GetUnitY(TU[2]),GetUnitX(eu) - GetUnitX(TU[2]))
call IssueTargetOrder(dummy,"slow",eu)
call UnitApplyTimedLife(dummy,'B666',0.5)
call UnitDamageTarget(TU[1],eu,dmg,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call KB.GetKB(TU[1],eu,rad,kb_dist,KB_speed,kb_dmg,EffectSpamRate,KB_eff)
call GroupRemoveUnit(GROUP,eu)
set eu = null
set dummy = null
endfunction
private struct Titanic
unit c
unit tit
unit berg
real cd
real d
real h
real th
real s
real rad
static Titanic array ind
static integer sca = 0
static timer counter = CreateTimer()
static method Motion takes nothing returns nothing
local Titanic dat
local real x
local real y
local integer i = 0
local conditionfunc c = Condition(function GroupFilter)
loop
exitwhen i >= Titanic.sca
set dat = Titanic.ind[i]
if dat.h > dat.th then
set dat.h = dat.h - HeightChange
call SetUnitFlyHeight(dat.tit,dat.h,0)
else
if dat.cd < dat.d then
set x = GetUnitX(dat.tit) + dat.s * Cos(dat.rad)
set y = GetUnitY(dat.tit) + dat.s * Sin(dat.rad)
call DestroyEffect(AddSpecialEffect(TrailEff,x,y))
set dat.cd = dat.cd + dat.s
call SetUnitX(dat.tit,x)
call SetUnitY(dat.tit,y)
set TR[1] = GetUnitX(dat.tit)
set TR[2] = GetUnitY(dat.tit)
set TP = GetOwningPlayer(dat.c)
set TU[1] = dat.c
set TU[2] = dat.tit
call GroupEnumUnitsInRange(GROUP,TR[1],TR[2],100,c)
call ForGroup(GROUP,function GroupAction)
else
set TR[1] = GetUnitX(dat.berg)
set TR[2] = GetUnitY(dat.berg)
call BuildEff(6,100,Eff,TR[1],TR[2])
if KnockbackOnImpact == true then
set TP = GetOwningPlayer(dat.c)
set TU[1] = dat.c
set TU[2] = dat.tit
call GroupEnumUnitsInRange(GROUP,TR[1],TR[2],AoE,c)
call ForGroup(GROUP,function GroupAction)
endif
call KillUnit(dat.tit)
call KillUnit(dat.berg)
set dat.c = null
set dat.tit = null
set dat.berg = null
call dat.destroy()
set Titanic.sca = Titanic.sca - 1
set Titanic.ind[i] = Titanic.ind[Titanic.sca]
endif
endif
set i = i + 1
endloop
if Titanic.sca == 0 then
call PauseTimer(Titanic.counter)
call GroupClear(GROUP)
endif
set c = null
endmethod
static method Inject takes unit c,unit tit,unit berg,real rad,real d,real h,real s returns nothing
local Titanic dat = Titanic.allocate()
set dat.c = c
set dat.tit = tit
set dat.berg = berg
set dat.rad = rad
set dat.d = d
set dat.cd = 0
set dat.h = h
call MoveLocation(Zloc,GetUnitX(tit),GetUnitY(tit))
set dat.th = GetLocationZ(Zloc)
set dat.s = s
if Titanic.sca == 0 then
call TimerStart(Titanic.counter,DELAY,true, function Titanic.Motion)
endif
set Titanic.ind[Titanic.sca] = dat
set Titanic.sca = Titanic.sca + 1
endmethod
endstruct
private function Action takes nothing returns nothing
local unit C = GetTriggerUnit()
local real lx = GetSpellTargetX()
local real ly = GetSpellTargetY()
local real ux = GetUnitX(C)
local real uy = GetUnitY(C)
local real FP1 = RBL(lx,ly,ux,uy)
local real FP2 = RBL(ux,uy,lx,ly)
local unit berg = CreateUnit(GetOwningPlayer(C), Iceberg,lx,ly, FP1 * bj_RADTODEG)
local unit tit = CreateUnit(GetOwningPlayer(C), Ship,ux,uy, FP2 * bj_RADTODEG)
local real d = DBL(ux,uy,lx,ly)
local real speed = KB_speed
call BuildEff(6,100,Eff,lx,ly)
call SetUnitPathing(tit,false)
call UnitAddAbility(tit,'Arav')
call UnitRemoveAbility(tit,'Arav')
call SetUnitFlyHeight(tit,800,0)
call SetUnitFlyHeight (tit,1,1)
call Titanic.Inject(C,tit,berg,FP2,d,StartHeight,speed)
set C = null
set berg = null
set tit = null
endfunction
private function InitT takes nothing returns nothing
local trigger T = CreateTrigger()
local integer TI = 0
loop
exitwhen (TI >= bj_MAX_PLAYER_SLOTS)
call TriggerRegisterPlayerUnitEvent(T, Player(TI), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set TI = TI + 1
endloop
call TriggerAddAction(T,function Action)
call TriggerAddCondition(T,Condition(function Cond))
set T = null
endfunction
endlibrary