- Joined
- Feb 11, 2011
- Messages
- 1,860
I have a spell that gives a chance to block damage done. Then, if the attacker is non-hero, it returns the damage amount (with the use of a missile). However, this missile sometimes bugs. It randomly gets 'attached' to the target's head and then gets destroyed a few seconds later. What's wrong?
Notes:
- I am giving it a 100% chance to fire for testing purposes.
- I know this is a very crude damage-blocking spell, but that doesn't matter. The focus is the missile bug.
- Any optimizations welcome!
JASS:
scope HeavyDefences initializer onInit
globals
private constant integer SPELL_ID = 'A004'
private constant integer MISSILE_ID = 'h00H'
private constant real MISSILE_SPEED = 1000 * 0.03
endglobals
public struct Missile
unit caster = null
unit missile = null
unit target = null
real angle = 0
real damage = 0
real distance = 0
method destroy takes nothing returns nothing
set .missile = null
set .target = null
set .caster = null
call .deallocate()
endmethod
private static method Timer_Actions takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
local real dx = GetUnitX(.missile) - GetUnitX(.target)
local real dy = GetUnitY(.missile) - GetUnitY(.target)
local real x
local real y
set .distance = dx * dx + dy * dy
if .distance > (2 * MISSILE_SPEED) and not IsUnitType(.target, UNIT_TYPE_DEAD) then
set .angle = bj_RADTODEG * (Atan2(GetUnitY(.target) - GetUnitY(.missile), GetUnitX(.target) - GetUnitX(.missile)))
set x = GetUnitX(.missile) + MISSILE_SPEED * Cos(bj_DEGTORAD * .angle)
set y = GetUnitY(.missile) + MISSILE_SPEED * Sin(bj_DEGTORAD * .angle)
call SetUnitX(.missile, x)
call SetUnitY(.missile, y)
call SetUnitFacing(.missile, .angle)
elseif IsUnitType(.target, UNIT_TYPE_DEAD) then
call RemoveUnit(.missile)
call ReleaseTimer(t)
call .destroy()
endif
if .distance <= (2 * MISSILE_SPEED) then
call UnitDamageTarget(.caster, .target, .damage, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
call RemoveUnit(.missile)
call ReleaseTimer(t)
call .destroy()
endif
set t = null
endmethod
public static method Create takes unit target, unit source, real damage returns thistype
local thistype this = thistype.allocate()
local timer t = NewTimerEx(this)
local real x = GetUnitX(source)
local real y = GetUnitY(source)
set .target = target
set .caster = source
set .damage = damage
set .angle = bj_RADTODEG * (Atan2(GetUnitY(.target) - y, GetUnitX(.target) - x))
set .missile = CreateUnit(Player(0), MISSILE_ID, x, y, .angle)
call TimerStart(t, 0.03, true, function thistype.Timer_Actions)
set t = null
set target = null
set source = null
return this
endmethod
endstruct
private function Actions takes nothing returns nothing
local unit attacker = Damage.source
local unit damaged = GetTriggerUnit()
local unit dummy
if GetUnitAbilityLevel(damaged, SPELL_ID) > 0 and GetRandomInt(1, 1) <= (4 * GetUnitAbilityLevel(damaged, SPELL_ID) + 2) then
call SetWidgetLife(damaged, GetWidgetLife(damaged) + R2I(Damage.amount))
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\Defend\\DefendCaster.mdl", damaged, "origin"))
if not IsUnitType(attacker, UNIT_TYPE_HERO) then
call Missile.Create(attacker, damaged, Damage.amount)
endif
endif
set attacker = null
set damaged = null
endfunction
private function onInit takes nothing returns nothing
call RegisterDamageById(function Actions, DAMAGE_ID_MELEE)
call RegisterDamageById(function Actions, DAMAGE_ID_RANGED)
endfunction
endscope
- I am giving it a 100% chance to fire for testing purposes.
- I know this is a very crude damage-blocking spell, but that doesn't matter. The focus is the missile bug.
- Any optimizations welcome!