scope SpinBash initializer Init
// Spin Bash by The_Witcher
// The Blademaster spins the target around,
// damaging all enemies in range.
// After some time he releases his target, throwing it away.
globals
// the rawcode of your ability(press CTRL + D in object editor)
private constant integer SpellID = 'A000'
// the interval of the timer (increase if laggy)
private constant real interval = 0.01
// the distance between the target and the caster when
// spinnig around
private constant real SpinDistance = 150
// the curve is a constant used by the parabola forumla
private constant real Curve = 1.5
// this is the range in where units have to be around the target
// to get damaged
private constant real DamageRange = 80
endglobals
private function GetRotateTime takes integer lvl returns real
local real lowest = IMaxBJ(4-lvl,0)
local real highest = lowest + 2
return GetRandomReal(lowest,highest) // on lvl 1 between 4 and 6 seconds
endfunction
private function GetThrowDistance takes integer lvl returns real
return 200.*lvl //100 on lvl 1, 200 on lvl 2,...
endfunction
private function GetRotateSpeed takes integer lvl returns real
return 4.*lvl // +4 degree every interval
endfunction
private function GetSpinDamage takes integer lvl returns real
return 30.*lvl // every unit hit by the spinning/thrown unit takes this damage (here 30/60/90)
endfunction
private function GetTargetDamage takes integer lvl returns real
return 40.*lvl // the damage the target takes (here 40/80/120)
endfunction
//-----------Don't modify anything below this line---------
private struct data
unit u
unit v
real a
real d
real s
real maxd
integer lvl
integer mode = 1
real dmg1
real dmg2
group DamageOnceGroup
endstruct
globals
private data array DATAS
private integer total = 0
private timer tim = CreateTimer()
private group g = CreateGroup()
private item ite
private player TempPlayer
private data TempDat
endglobals
private function IsCoordPathable takes real x, real y returns boolean
local real xx
local real yy
call SetItemVisible(ite,true)
call SetItemPosition(ite,x,y)
set xx = GetItemX( ite ) - x
set yy = GetItemY( ite ) - y
call SetItemVisible(ite,false)
if xx < 1 and xx > -1 and yy < 1 and yy > -1 then
return true
endif
return false
endfunction
private function JumpParabola takes real dist, real maxdist, real curve returns real
local real t = (dist * 2) / maxdist - 1
return (- t * t + 1) * (maxdist / curve)
endfunction
private function EnemiesOnly takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(),TempPlayer) and not (IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) or GetUnitTypeId(GetFilterUnit()) == 0 )
endfunction
private function Damage takes nothing returns nothing
if not IsUnitInGroup(GetEnumUnit(),TempDat.DamageOnceGroup) then
call UnitDamageTarget(TempDat.u,GetEnumUnit(),TempDat.dmg1,true,false,ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
call GroupAddUnit(TempDat.DamageOnceGroup,GetEnumUnit())
endif
endfunction
private function execute takes nothing returns nothing
local data dat
local integer i = 0
local real x
local real y
local unit u
loop
exitwhen i >= total
set dat = DATAS[i]
if dat.mode == 1 then
// Spinning around
set x = GetUnitX(dat.u) + SpinDistance * Cos(dat.a*bj_DEGTORAD)
set y = GetUnitY(dat.u) + SpinDistance * Sin(dat.a*bj_DEGTORAD)
call SetUnitX(dat.v,x)
call SetUnitY(dat.v,y)
call SetUnitFacing(dat.v,dat.a-180)
set dat.a = dat.a + dat.s
set dat.d = dat.d - interval
set TempPlayer = GetOwningPlayer(dat.u)
call GroupEnumUnitsInRange(g,GetUnitX(dat.v),GetUnitY(dat.v), DamageRange,Condition(function EnemiesOnly))
call GroupRemoveUnit(g,dat.v)
set TempDat = dat
call ForGroup(g, function Damage)
call GroupClear(g)
if dat.a > 360 then
set dat.a = dat.a - 360
call GroupClear(dat.DamageOnceGroup)
endif
if dat.d <= 0 then
set dat.d = 0
set dat.maxd = GetThrowDistance(dat.lvl)
set dat.mode = 2
call PauseUnit(dat.u,false)
call SetUnitAnimation(dat.u,"stand")
call GroupClear(dat.DamageOnceGroup)
endif
else
// throw
set x = GetUnitX(dat.v) + dat.s * Cos(dat.a*bj_DEGTORAD)
set y = GetUnitY(dat.v) + dat.s * Sin(dat.a*bj_DEGTORAD)
if IsCoordPathable(x,y) then
call SetUnitX(dat.v,x)
call SetUnitY(dat.v,y)
call GroupEnumUnitsInRange(g,GetUnitX(dat.v),GetUnitY(dat.v), DamageRange,Condition(function EnemiesOnly))
call GroupRemoveUnit(g,dat.v)
set TempDat = dat
call ForGroup(g, function Damage)
call GroupClear(g)
endif
set dat.d = dat.d + dat.s
if dat.mode == 3 then
call SetUnitFlyHeight(dat.v,JumpParabola(dat.d,dat.maxd,Curve),0)
else
call SetUnitFlyHeight(dat.v,JumpParabola(dat.d,dat.maxd,Curve*3),0)
endif
if dat.d >= dat.maxd and dat.mode == 2 then
set dat.d = 0
set dat.maxd = GetThrowDistance(dat.lvl) / 3
set dat.mode = 3
call GroupClear(dat.DamageOnceGroup)
call UnitDamageTarget(dat.u,dat.v,dat.dmg2,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
elseif dat.d >= dat.maxd and dat.mode == 3 then
call SetUnitFlyHeight(dat.v,0,0)
call PauseUnit(dat.v,false)
call SetUnitTimeScale(dat.v,1)
call DestroyGroup(dat.DamageOnceGroup)
set total = total - 1
set DATAS[i] = DATAS[total]
call dat.destroy()
set i = i - 1
endif
endif
set i = i + 1
endloop
if total == 0 then
call PauseTimer(tim)
endif
endfunction
private function start takes nothing returns boolean
local data dat
if GetSpellAbilityId() == SpellID then
set dat = data.create()
set dat.u = GetTriggerUnit()
set dat.v = GetSpellTargetUnit()
set dat.a = bj_RADTODEG * Atan2(GetUnitY(dat.v) - GetUnitY(dat.u), GetUnitX(dat.v) - GetUnitX(dat.u))
set dat.lvl = GetUnitAbilityLevel(dat.u,SpellID)
set dat.d = GetRotateTime(dat.lvl)
set dat.s = GetRotateSpeed(dat.lvl)
set dat.dmg1 = GetSpinDamage(dat.lvl)
set dat.dmg2 = GetTargetDamage(dat.lvl)
set dat.DamageOnceGroup = CreateGroup()
call IssueImmediateOrder(dat.u,"stop")
call PauseUnit(dat.u,true)
call PauseUnit(dat.v,true)
call SetUnitTimeScale(dat.v,0)
call SetUnitAnimation(dat.u,"spin")
call UnitAddAbility(dat.v,'Amrf')
call UnitRemoveAbility(dat.v,'Amrf')
set DATAS[total] = dat
set total = total + 1
if total == 1 then
call TimerStart(tim,interval,true, function execute)
endif
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerAddCondition(t,Condition(function start))
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
set ite = CreateItem('wolg',0,0)
call SetItemVisible(ite,false)
call SetItemInvulnerable( ite, true)
endfunction
endscope