scope Forward
globals
private constant real KNOCK_DISTANCE = 300
private constant real KNOCK_DURATION = 1.5
private real KNOCK_INVERVAL_DISTANCE = KNOCK_DISTANCE / KNOCK_DURATION * 0.03
endglobals
public struct KnockbackData
unit target
unit caster
real angle
real DistLeft
method destroy takes nothing returns nothing
set .target = null
set .caster = null
call .deallocate()
endmethod
static method Knock_Effects takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype D = GetTimerData(t)
if D.DistLeft > 0 then
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FlyingMachine\\FlyingMachineImpact.mdl", D.target, "chest"))
else
call ReleaseTimer(t)
endif
set t = null
endmethod
static method Timer_Actions takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype D = GetTimerData(t)
local real x
local real y
if D.DistLeft > 0 then
set x = GetUnitX(D.target) + KNOCK_INVERVAL_DISTANCE * Cos(D.angle)
set y = GetUnitY(D.target) + KNOCK_INVERVAL_DISTANCE * Sin(D.angle)
if not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
call SetUnitX(D.target, x)
call SetUnitY(D.target, y)
set D.DistLeft = D.DistLeft - KNOCK_INVERVAL_DISTANCE
else
call ReleaseTimer(t)
call PauseUnit(D.target, false)
call SetUnitPathing(D.target, true)
call D.destroy()
endif
else
call ReleaseTimer(t)
call PauseUnit(D.target, false)
call SetUnitPathing(D.target, true)
call D.destroy()
endif
set t = null
endmethod
static method Actions takes unit target, unit caster returns thistype
local thistype D = thistype.allocate()
local timer t = NewTimer()
local timer t2 = NewTimer()
local real extra
set D.target = target
set D.caster = caster
set D.DistLeft = KNOCK_DISTANCE
set D.angle = GetKnockbackAngle(GetUnitFacing(D.caster), (bj_RADTODEG * (Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))))
call PauseUnit(D.target, true)
call SetUnitPathing(D.target, false)
call SetTimerData(t, D)
call TimerStart(t, 0.03, true, function thistype.Timer_Actions)
call SetTimerData(t2, D)
call TimerStart(t2, 0.3, true, function thistype.Knock_Effects)
set t = null
set t2 = null
return D
endmethod
endstruct
public struct ForwardData
unit caster
unit target
real DistLeft
real angle
real xoffset
real yoffset
effect overhead
effect lefthand
effect righthand
group KnockedUnits = CreateGroup()
method destroy takes nothing returns nothing
set .caster = null
set .target = null
call DestroyEffect(.overhead)
call DestroyEffect(.lefthand)
call DestroyEffect(.righthand)
set .overhead = null
set .lefthand = null
set .righthand = null
call DestroyGroup(.KnockedUnits)
set .KnockedUnits = null
call .deallocate()
endmethod
static method Timer_Actions takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype D = GetTimerData(t)
local real x
local real y
local real xdist
local real ydist
local unit dummy
local unit u
if D.DistLeft > 128 then
set x = GetUnitX(D.caster) + D.xoffset
set y = GetUnitY(D.caster) + D.yoffset
call SetUnitX(D.caster, x)
call SetUnitY(D.caster, y)
set xdist = x - GetUnitX(D.target)
set ydist = y - GetUnitY(D.target)
set D.DistLeft = SquareRoot(xdist * xdist + ydist * ydist)
set D.angle = Atan2(GetUnitY(D.target) - y, GetUnitX(D.target) - x)
call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, 150, null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u == null
if not IsUnitInGroup(u, D.KnockedUnits) /*
*/and IsUnitEnemy(u, GetOwningPlayer(D.caster))/*
*/and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)/*
*/and not IsUnitType(u, UNIT_TYPE_DEAD)/*
*/and not IsUnit(u, D.target) then
call GroupAddUnit(D.KnockedUnits, u)
call KnockbackData.Actions(u, D.caster)
endif
call GroupRemoveUnit(bj_lastCreatedGroup, u)
endloop
else
call ReleaseTimer(t)
call SetUnitPathing(D.caster, true)
call PauseUnit(D.caster, false)
call SetUnitAnimation(D.caster, "stand")
call D.destroy()
set dummy = CreateUnit(GetOwningPlayer(D.caster), 'h001', x, y, 0)
call RemoveGuardPosition(dummy)
call UnitAddAbility(dummy, 'A000')
call IssueTargetOrder(dummy, "thunderbolt", D.target)
call UnitApplyTimedLife(dummy, 'BTLF', 1)
call DestroyEffect(D.overhead)
call DestroyEffect(D.lefthand)
call DestroyEffect(D.righthand)
call IssueTargetOrder(D.caster, "attack", D.target)
call SetUnitMoveSpeed(D.caster, GetUnitDefaultMoveSpeed(D.caster))
set dummy = null
endif
set t = null
endmethod
static method create takes nothing returns thistype
local thistype D = thistype.allocate()
local real xdist
local real ydist
local timer t = NewTimer()
local real movespeed
set D.caster = GetTriggerUnit()
set D.target = GetSpellTargetUnit()
set xdist = GetUnitX(D.caster) - GetUnitX(D.target)
set ydist = GetUnitY(D.caster) - GetUnitY(D.target)
set D.DistLeft = SquareRoot(xdist*xdist + ydist*ydist)
set movespeed = 50 * GetUnitAbilityLevel(D.caster, 'A001') + 15
call SetUnitMoveSpeedX(D.caster, GetUnitMoveSpeedX(D.caster) + movespeed)
call SetUnitPathing(D.caster, false)
call PauseUnit(D.caster, true)
call SetUnitAnimationByIndex(D.caster, 6)
set D.angle = Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster))
set D.xoffset = 10 * Cos(D.angle)
set D.yoffset = 10 * Sin(D.angle)
set D.overhead = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", D.caster, "overhead")
set D.lefthand = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", D.caster, "hand,left")
set D.righthand = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Bloodlust\\BloodlustTarget.mdl", D.caster, "hand,right")
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\BattleRoar\\RoarCaster.mdl", D.caster, "origin"))
call SetTimerData(t, D)
call TimerStart(t, 0.03, true, function thistype.Timer_Actions)
set t = null
return D
endmethod
static method Conditions takes nothing returns boolean
if GetSpellAbilityId() == 'A001' then
call thistype.create()
endif
return false
endmethod
static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function thistype.Conditions))
set t = null
endmethod
endstruct
endscope