library Roflcopter initializer Init requires TimerUtils, II, SpellEffectEvent, Z
//Configurables and whatnot
globals
private constant integer SPELL_RAW = 'A000'
private constant string EXPLOSION_EFFECT = "Abilities\\Weapons\\CannonTowerMissile\\CannonTowerMissile.mdl"
private constant real HEIGHT = 350.0 //Roflcopter height
private constant real SPIN_PERIOD = 0.16 //Period between each propeller change
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
endglobals
private constant function DAMAGE takes unit caster,integer lvl returns real
return lvl * 50. //Damage dependency of level.
//You can also make damage depend on caster's stats by refering to unit variable 'caster'
endfunction
private constant function TRAVEL_LENGTH takes integer lvl returns real
return 1400. //How long does roflcopter fly
endfunction
private constant function BOMB_PERIOD takes integer lvl returns real
return 0.5 //How often will roflcopter throw bombs
endfunction
private constant function BOMB_AOE takes integer lvl returns real
return 200. //Area of effect for bomb explosion
endfunction
private constant function ROFLCOPTER_SPEED takes integer lvl returns real
return 7. //Movement speed or roflcopter
endfunction
private constant function BOMB_SPEED takes integer lvl returns real
return 7. //Fall speed of bombs
endfunction
private function FILTER takes unit caster,unit target,integer lvl returns boolean
//Filters which units will be damaged on explosion
return IsPlayerEnemy(GetOwningPlayer(caster),GetOwningPlayer(target)) /*
*/ and IsUnitType(target,UNIT_TYPE_GROUND) /*
*/ and not IsUnitType(target,UNIT_TYPE_DEAD)
endfunction
private function EFFECTS takes unit caster,unit target,real x,real y,real z,integer lvl returns nothing
//You can add here anything you want to happen on explosion given the above arguments
//For example, you can set damaged targets on fire with a spell casted by dummy or something
endfunction
//Don't change stuff below
//===================================================================
globals
private constant string R1 = "ROFL:ROFL:LOL\n ^\n ---------------\\ L\n / [ ] ===== O\n / / L\n [_________/\n I I\n \\-----------------"
private constant string R2 = " LOL:ROFL:ROFL\n ^\n ---------------\\\n / [ ] ===== LOL\n / /\n [_________/\n I I\n \\-----------------"
private constant string R3 = " ROFL:ROFL:LOL\n ^\n /---------------\nLOL ===== [ ] \\\n \\ \\\n \\_________]\n I I\n -----------------/"
private constant string R4 = " LOL:ROFL:ROFL\n ^\n L /---------------\n O ===== [ ] \\\n L \\ \\\n \\_________]\n I I\n -----------------/"
private constant real DEVIATION = 100.0
endglobals
private keyword roflcopter
private struct instance
integer n
unit u
real bs
real rs
real d
real a
integer lv
method add takes nothing returns nothing
set .n = .n + 1
endmethod
method sub takes nothing returns nothing
set .n = .n - 1
if .n == 0 then
call .destroy()
endif
endmethod
static method create takes unit u,real x,real y returns thistype
local thistype this = thistype.allocate()
local integer l = GetUnitAbilityLevel(u,SPELL_RAW)
set .u = u
set .bs = BOMB_SPEED(l)
set .rs = ROFLCOPTER_SPEED(l)
set .d = DAMAGE(u,l)
set .a = BOMB_AOE(l)
set .lv = l
call roflcopter.create(this,x,y,TRAVEL_LENGTH(l),BOMB_PERIOD(l))
return this
endmethod
endstruct
private keyword bomb
private struct roflcopter
texttag t = CreateTextTag()
instance i
real x
real y
real l
real a
timer bp
timer sp
integer p
method execute takes nothing returns nothing
set .x = .x + .i.rs * Cos(.a)
set .y = .y + .i.rs * Sin(.a)
call SetTextTagPos(.t,.x - DEVIATION,.y,HEIGHT)
set .l = .l - .i.rs
if .l <= 0 then
call .destroy()
endif
endmethod
implement II
static method bombdrop takes nothing returns nothing
local thistype this = thistype(GetTimerData(GetExpiredTimer()))
call bomb.create(.i,.x,.y,HEIGHT)
endmethod
static method spin takes nothing returns nothing
local thistype this = thistype(GetTimerData(GetExpiredTimer()))
if .p == 1 then
call SetTextTagText(.t,R2,0.023)
set .p = 2
elseif .p == 2 then
call SetTextTagText(.t,R1,0.023)
set .p = 1
elseif .p == 3 then
call SetTextTagText(.t,R4,0.023)
set .p = 4
else
call SetTextTagText(.t,R3,0.023)
set .p = 3
endif
endmethod
static method create takes instance i,real x,real y,real l,real p returns thistype
local thistype this = thistype.allocate()
local real a = Atan2(y - GetUnitY(i.u),x - GetUnitX(i.u))
if a < 0 then
set a = 2 * bj_PI + a
endif
set .i = i
set .l = l
set .a = a + bj_PI / 2
set .bp = NewTimer()
call TimerStart(.bp,p,true,function thistype.bombdrop)
call SetTimerData(.bp,this)
set .sp = NewTimer()
call TimerStart(.sp,SPIN_PERIOD,true,function thistype.spin)
call SetTimerData(.sp,this)
call SetTextTagPermanent(.t,false)
call SetTextTagVisibility(.t,true)
set .x = x + l / 2 * Cos(a - bj_PI / 2) - DEVIATION
set .y = y + TRAVEL_LENGTH(i) / 2 * Sin(a - bj_PI / 2)
call SetTextTagPos(.t,.x,.y,HEIGHT)
if a < bj_PI then
set .p = 1
call SetTextTagText(.t,R1,0.023)
else
set .p = 3
call SetTextTagText(.t,R3,0.023)
endif
call .start()
call .i.add()
return this
endmethod
method destroy takes nothing returns nothing
call DestroyTextTag(.t)
call ReleaseTimer(.bp)
call ReleaseTimer(.sp)
call .end()
call .i.sub()
call .deallocate()
endmethod
endstruct
private struct bomb
static thistype This
static group g = CreateGroup()
texttag t = CreateTextTag()
instance i
real x
real y
real h
method execute takes nothing returns nothing
set .h = .h - .i.bs
call SetTextTagPos(.t,.x,.y,.h)
if .h <= 3.00 then
call .destroy()
endif
endmethod
implement II
static method create takes instance i,real x,real y,real h returns thistype
local thistype this = thistype.allocate()
set .i = i
set .x = x
set .y = y
set .h = h
call SetTextTagPermanent(.t,false)
call SetTextTagVisibility(.t,true)
call SetTextTagPos(.t,x,y,h)
call SetTextTagText(.t,"*",0.04)
call .start()
call .i.add()
return this
endmethod
static method explosion takes nothing returns boolean
local thistype this = .This
local unit u = GetFilterUnit()
local real x
local real y
local real z
local real z2
if FILTER(.i.u,u,.i.lv) then
set x = GetUnitX(u) - .x
set y = GetUnitY(u) - .y
set z2 = GetZ(.x,.y) + .h
set z = GetUnitZ(u) - z2
if x*x+y*y+z*z <= .i.a*.i.a then
call UnitDamageTarget(.i.u,u,.i.d,false,false,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
call EFFECTS(.i.u,u,.x,.y,z2,.i.lv)
endif
endif
set u = null
return false
endmethod
method destroy takes nothing returns nothing
call DestroyTextTag(.t)
call DestroyEffect(AddSpecialEffect(EXPLOSION_EFFECT,.x,.y))
set .This = this
call GroupEnumUnitsInRange(.g,.x,.y,.i.a,Filter(function thistype.explosion))
call .end()
call .i.sub()
call .deallocate()
endmethod
endstruct
private function Cast takes nothing returns nothing
call instance.create(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
endfunction
private function Init takes nothing returns nothing
call RegisterSpellEffectEvent(SPELL_RAW, function Cast)
endfunction
endlibrary