scope BounceScope initializer Init
globals
/* BType is a value that shows how many times can ball make another balls, for example:
Start ball has BType = 4, so he will do balls: 1 - 3 - 9 - 27, (four times), every new balls will have BType - 1*/
private integer SpellId = 'A000'
private string SpellEffect = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" // spell effect if BType will more then 0
private string SpellEffectOnDeath = "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl" // spell effect when BType == 0
private real DistancePerBallType = 300 // as more this value then more will be move distance of new balls
private real DamageMultiply = 40 // this value multiply on BType value (damage value)
private real FlyHeightPerBallType = 40 // this value changes balls fly height per BType (100 + BType * this value)
//////Timer period//////
private real TimerTick = 0.03 // timer period
//////////////////////
endglobals
struct Bounce
private static timer t = CreateTimer()
private static integer m[]
private static integer MUI = -1
unit a
unit ball
real angle
real d
real dmg
real x
real y
real speed
real count
real time
real distancePlus
integer BType
private method StopAction takes integer j returns nothing
set m[j] = m[MUI]
set MUI = MUI - 1
if MUI == -1 then
call PauseTimer(t)
endif
endmethod
private static method Bounce_Loop takes nothing returns nothing
local thistype this
local integer i = 0
local real dx
local real dy
local real height
local group g
local unit F
local real checkX
local real checkY
loop
exitwhen i > MUI
set this = m[i]
set checkX = GetUnitX(ball) + speed * Cos(angle)
set checkY = GetUnitY(ball) + speed * Sin(angle)
if GetRectMinX(bj_mapInitialPlayableArea) <= checkX and checkX <= GetRectMaxX(bj_mapInitialPlayableArea) and GetRectMinY(bj_mapInitialPlayableArea) <= checkY and checkY <= GetRectMaxY(bj_mapInitialPlayableArea)
set count = count + TimerTick
call SetUnitX(ball, checkX)
call SetUnitY(ball, checkY)
set dx = x - GetUnitX(ball)
set dy = y - GetUnitY(ball)
set height = (4 * (100 + FlyHeightPerBallType * BType) / d) * (d - SquareRoot(dx * dx + dy * dy)) * (SquareRoot(dx * dx + dy * dy) / d)
call SetUnitFlyHeight(ball, height, 0)
if count >= time then
set g = CreateGroup()
call GroupEnumUnitsInRange(g, GetUnitX(ball), GetUnitY(ball), 80 + (30 * BType), null)
set BType = BType - 1
loop
set F = FirstOfGroup(g)
exitwhen F == null
if IsUnitEnemy(F, GetOwningPlayer(a)) and not IsUnitType(F, UNIT_TYPE_DEAD) then
call UnitDamageTarget(a, F, dmg, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_DIVINE, null)
endif
call GroupRemoveUnit(g, F)
set F = FirstOfGroup(g)
endloop
call DestroyGroup(g)
if BType != 0 then
call DestroyEffect(AddSpecialEffect(SpellEffect, GetUnitX(ball), GetUnitY(ball)))
call SetUnitFlyHeight(ball, 0, 0)
set d = distancePlus + (BType * 60)
set dmg = DamageMultiply * BType
set count = 0
call SetUnitScale(ball, BType / 1.5, BType / 1.5, BType / 1.5)
set x = GetUnitX(ball) + d * Cos(angle)
set y = GetUnitY(ball) + d * Sin(angle)
set time = (0.4 + BType * 0.1)
set speed = d / time * TimerTick
call Bounce_Start(a, angle + (30 * bj_DEGTORAD), BType, GetUnitX(ball), GetUnitY(ball), distancePlus, false)
call Bounce_Start(a, angle - (30 * bj_DEGTORAD), BType, GetUnitX(ball), GetUnitY(ball), distancePlus, false)
else
call DestroyEffect(AddSpecialEffect(SpellEffectOnDeath, GetUnitX(ball), GetUnitY(ball)))
RemoveUnit(ball)
set ball = null
set a = null
call StopAction(i)
call destroy()
endif
endif
else
call DestroyEffect(AddSpecialEffect(SpellEffectOnDeath, GetUnitX(ball), GetUnitY(ball)))
RemoveUnit(ball)
set ball = null
set a = null
call StopAction(i)
call destroy()
endif
set i = i + 1
endloop
endmethod
public static method Bounce_Start takes unit Caster, real NewAngle, integer NewBType, real NewX, real NewY, real NewDPlus, boolean IsSpell returns nothing
local thistype this = thistype.create()
local real dx
local real dy
set MUI = MUI + 1
set m[MUI] = this
set a = Caster
set BType = NewBType
set angle = NewAngle
set distancePlus = NewDPlus
set d = distancePlus + (BType * 60)
set dmg = DamageMultiply * BType
set count = 0
set ball = CreateUnit(GetOwningPlayer(a), 'h000', NewX, NewY, angle)
set dx = GetSpellTargetX() - GetUnitX(ball)
set dy = GetSpellTargetY() - GetUnitY(ball)
call UnitAddAbility(ball, 'Arav')
call UnitRemoveAbility(ball, 'Arav')
call SetUnitScale(ball, NewBType / 1.5, NewBType / 1.5, NewBType / 1.5)
if not IsSpell then
set x = GetUnitX(ball) + d * Cos(angle)
set y = GetUnitY(ball) + d * Sin(angle)
else
set d = SquareRoot(dx * dx + dy * dy)
set distancePlus = DistancePerBallType / (300 / d)
set x = GetUnitX(ball) + d * Cos(angle)
set y = GetUnitY(ball) + d * Sin(angle)
endif
set time = 0.4 + BType * 0.1
set speed = d / time * TimerTick
if MUI == 0 then
call TimerStart(t, TimerTick, true, function thistype.Bounce_Loop)
endif
endmethod
endstruct
private function Spell_Start_Cond takes nothing returns boolean
local unit a
local real angle
if GetSpellAbilityId() == SpellId then
set a = GetSpellAbilityUnit()
set angle = Atan2(GetSpellTargetY() - GetUnitY(a), GetSpellTargetX() - GetUnitX(a))
call Bounce.Bounce_Start(a, angle, 4, GetUnitX(a), GetUnitY(a), 0, true)
set a = null
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger Cast = CreateTrigger( )
local integer index = 0
loop
call TriggerRegisterPlayerUnitEvent(Cast, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set index = index + 1
exitwhen index == 16
endloop
call TriggerAddCondition(Cast, Condition(function Spell_Start_Cond))
set Cast = null
endfunction
endscope