- Joined
- Jul 26, 2008
- Messages
- 1,009
Alright I have a skill called Rush. Basically the caster "Rushes" towards a point and upon hitting an enemy he stops and deals AoE damage.
Problem is if he gets caught on something he just sort of sits there til the timer runs out.
What I want is a way to detect if he's stuck on an object and force him to stop and finish the spell. I had it where it checked if he was still in range of his last coordinates but that just caused issues.
Here it is. It uses Knockback, XEDamage and GroupUtils:
Problem is if he gets caught on something he just sort of sits there til the timer runs out.
What I want is a way to detect if he's stuck on an object and force him to stop and finish the spell. I had it where it checked if he was still in range of his last coordinates but that just caused issues.
Here it is. It uses Knockback, XEDamage and GroupUtils:
JASS:
scope Rush initializer InitTrig_Rush
globals
private constant integer SPELLID = 'Rush'
private constant real tick = 0.034
private unit TEMP
endglobals
private struct Data extends xedamage
unit c
unit t
real x
real y
real dur
static method GroupDamage takes nothing returns boolean
local xedamage d= xedamage.create()
local real a = bj_RADTODEG*Atan2( GetUnitY(GetFilterUnit()) - GetUnitY(TEMP), GetUnitX(GetFilterUnit()) - GetUnitX(TEMP) )
local integer lvl = GetUnitAbilityLevel(TEMP, SPELLID)
set d.dtype = DAMAGE_TYPE_NORMAL
set d.atype = ATTACK_TYPE_MELEE
call d.damageTarget(TEMP,GetFilterUnit(), SpellStat(TEMP,true)*(0.5+0.2*lvl) + 25+25*lvl)
if IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(TEMP)) and not(IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)) and not( IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD ))then
call KnockbackTarget(TEMP, GetFilterUnit(), a, 250., 700., false, true, false, GetAbilityEffectById(SPELLID, EFFECT_TYPE_MISSILE, 0))
endif
call d.destroy()
return false
endmethod
static method GroupEm takes nothing returns boolean
local xedamage d= xedamage.create()
local real a = bj_RADTODEG*Atan2( GetUnitY(GetFilterUnit()) - GetUnitY(TEMP), GetUnitX(GetFilterUnit()) - GetUnitX(TEMP) )
local integer lvl = GetUnitAbilityLevel(TEMP, SPELLID)
if IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(TEMP)) and not(IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)) and not( IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD ))then
set d.dtype = DAMAGE_TYPE_NORMAL
set d.atype = ATTACK_TYPE_MELEE
call d.damageTarget(TEMP,GetFilterUnit(), SpellStat(TEMP,true)*(0.5+0.2*lvl) + 25+25*lvl)
call KnockbackTarget(TEMP, GetFilterUnit(), a, 250., 700., false, true, false, GetAbilityEffectById(SPELLID, EFFECT_TYPE_MISSILE, 0))
endif
call d.destroy()
return false
endmethod
static method Timer takes nothing returns nothing
local timer tim = GetExpiredTimer()
local Data D = Data(GetTimerData(tim))
local integer lvl = GetUnitAbilityLevel(D.c, SPELLID)
local real angle = Atan2(D.y - GetUnitY(D.c), D.x - GetUnitX(D.c))
local real x = GetUnitX(D.c) + 20 * Cos(angle)
local real y = GetUnitY(D.c) + 20 * Sin(angle)
local real dist = SquareRoot((GetUnitX(D.c)-D.x) * (GetUnitX(D.c)-D.x) + (GetUnitY(D.c)-D.y) * (GetUnitY(D.c)-D.y))
local group g = NewGroup()
if IsTerrainWalkable(x,y) and not(IsUnitType(D.c, UNIT_TYPE_DEAD)) then
call SetUnitPosition(D.c, x, y)
call SetUnitFacing(D.c, angle * bj_RADTODEG)
set TEMP = D.c
if dist < 19 or D.dur > 3 then
call GroupEnumUnitsInArea(g, x, y, 160, Filter(function Data.GroupDamage))
call DestroyEffect(AddSpecialEffectTarget(GetAbilityEffectById(SPELLID, EFFECT_TYPE_MISSILE, 1), D.c, "origin"))
call D.destroy()
call ReleaseTimer(tim)
else
call GroupEnumUnitsInArea(g, x, y, 60, Filter(function Data.GroupEm))
endif
else
call GroupEnumUnitsInArea(g, x, y, 160, Filter(function Data.GroupDamage))
call DestroyEffect(AddSpecialEffectTarget(GetAbilityEffectById(SPELLID, EFFECT_TYPE_MISSILE, 1), D.c, "origin"))
call D.destroy()
call ReleaseTimer(tim)
endif
call ReleaseGroup(g)
set D.dur = D.dur + tick
endmethod
static method create takes unit c, real x, real y returns Data
local timer tim = NewTimer()
local Data D = Data.allocate()
local integer lvl = GetUnitAbilityLevel(c, SPELLID)
set D.c = c
set D.x = x
set D.y = y
set D.dur = 0
call SetTimerData(tim,D)
call TimerStart(tim, tick, true, function Data.Timer)
return D
endmethod
static method Conditions takes nothing returns boolean
if GetSpellAbilityId() == SPELLID then
call Data.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
endif
return true
endmethod
endstruct
//===========================================================================
public function InitTrig_Rush takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, function Data.Conditions )
call XE_PreloadAbility(SPELLID)
endfunction
endscope