- Joined
- Feb 11, 2011
- Messages
- 1,860
I am making a spell for my map which is as follows:
The part that I am having trouble with is getting nearby units to get knocked back while charging. The distance is inaccurate and it is laggy while units are being knocked back. Here is the code:
What am I doing wrong? Thanks.
ForwardActive: The hero charges forward to the targeted unit. Any enemy that he comes into contact with during the charge takes damage and is knocked back 120 distance. The hero gains bonus armour and movement speed during the charge.
JASS:
scope Forward
globals
private constant real KNOCK_DISTANCE = 120
private constant real KNOCK_DURATION = 1
endglobals
public struct KnockbackData
unit target
unit caster
real angle
real DistLeft = KNOCK_DISTANCE
method destroy takes nothing returns nothing
set .target = null
set .caster = 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 x2
local real y2
local real distance = KNOCK_DISTANCE / KNOCK_DURATION * 0.03
if D.DistLeft > 0 then
set x = GetUnitX(D.target)
set y = GetUnitY(D.target)
set x2 = x + distance * Cos(D.angle * bj_DEGTORAD)
set y2 = y + distance * Sin(D.angle * bj_DEGTORAD)
if not IsTerrainPathable(x2, y2, PATHING_TYPE_WALKABILITY) then
call SetUnitX(D.target, x2)
call SetUnitY(D.target, y2)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\FlyingMachine\\FlyingMachineImpact.mdl", D.target, "chest"))
set D.DistLeft = D.DistLeft - 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()
set D.target = target
set D.caster = caster
set D.angle = 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)
set t = null
return D
endmethod
endstruct
public struct ForwardData
unit caster
unit target
real DistLeft
real angle
effect overhead
effect lefthand
effect righthand
group KnockedUnits
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 x2
local real y2
local real xdist
local real ydist
local unit dummy
local unit u
set x = GetUnitX(D.caster)
set y = GetUnitY(D.caster)
if D.DistLeft > 128 then
set x2 = x + 10 * Cos(D.angle * bj_DEGTORAD)
set y2 = y + 10 * Sin(D.angle * bj_DEGTORAD)
call SetUnitX(D.caster, x2)
call SetUnitY(D.caster, y2)
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 D.angle = bj_RADTODEG * (Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))
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 KnockbackData.Actions(u, D.caster)
call GroupAddUnit(D.KnockedUnits, u)
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.deallocate()
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)
endif
set dummy = null
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()
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))
call SetUnitPathing(D.caster, false)
call PauseUnit(D.caster, true)
call SetUnitAnimationByIndex(D.caster, 6)
set D.angle = bj_RADTODEG * (Atan2(GetUnitY(D.target) - GetUnitY(D.caster), GetUnitX(D.target) - GetUnitX(D.caster)))
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