- Reaction score
- 91
I have a spell that spawns a big amount of missiles that curve (zig-zag) forward for some time. If they hit a unit that is able to deflect missiles (with some spell or something like that), the missiles should be destroyed and a new one gets created that should be like a "deflected" one - it has to go in the opposite direction and do the same stuff as the first ones. Basically, a recreation of a missile struct but with a different owner.
There has to be something wrong in the OnDamage function:
It should calculate the angle correctly, though it seems that it always returns a value that will make them go right.
JASS:
scope ArcaneMissiles initializer Init
globals
public constant integer AID_RAW = 039;A000039;
private constant integer UID_RAW = 039;h002039;
private constant integer UID_SFX = 039;h003039;
private constant real PERIOD = 0.03125
private constant real PERIOD2 = PERIOD * 3
private constant string SFX_ONE = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
private constant string SFX_TWO = "Abilities\\Spells\\Items\\OrbCorruption\\OrbCorruption.mdl"
endglobals
// Self-explanatory stuff.
private function SPEED takes unit cast returns real
return 35.
endfunction
private function DURATION takes unit cast returns real
return 0.85
endfunction
private function MANA_BURN takes unit cast, integer lvl returns real
return 10. * lvl
endfunction
private function DAMAGE takes unit cast, integer lvl returns real
return 15. * lvl
endfunction
globals
private HandleTable ht
endglobals
private struct Data
unit cast
unit missile
timer tim
real angle
boolean flip = false
integer somewait
integer ticks
real deduction
real value
integer lvl
trigger trig
private static method Callback takes nothing returns nothing
local Data d = ht[GetExpiredTimer()]
local real x
local real y
local real face
// Flip should stand for direction... True for right and false for left.
if d.flip == true then
set face = (GetUnitFacing(d.missile) + d.value) * bj_DEGTORAD
else
set face = (GetUnitFacing(d.missile) - d.value) * bj_DEGTORAD
endif
set x = GetUnitX(d.missile) + (SPEED(d.cast) - d.deduction) * Cos(face)
set y = GetUnitY(d.missile) + (SPEED(d.cast) - d.deduction) * Sin(face)
call SetUnitX(d.missile, x)
call SetUnitY(d.missile, y)
call SetUnitFacing(d.missile, face * bj_RADTODEG)
set d.somewait = d.somewait - 1
if d.somewait <= 0 then
// Flip, so the missile can curve to the opposite direction.
set d.somewait = GetRandomInt(1, 14)
set d.flip = not d.flip
endif
// Missile should end.
set d.ticks = d.ticks - 1
if d.ticks <= 0 then
call d.destroy()
endif
endmethod
private static method OnDamage takes nothing returns boolean
local Data d = ht[GetTriggeringTrigger()]
local unit targ = GetTriggerUnit()
local location loc
if IsUnitEnemy(targ, GetOwningPlayer(d.cast)) and IsUnitType(targ, UNIT_TYPE_DEAD) == false then
// Can the unit deflect?
if IS_DEFLECTING[GetUnitId(targ)] == false then
call UnitDamageTarget(d.cast, targ, DAMAGE(d.cast, d.lvl), true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
call SetUnitState(targ, UNIT_STATE_MANA, GetUnitState(targ, UNIT_STATE_MANA) - MANA_BURN(d.cast, d.lvl))
call DestroyEffect(AddSpecialEffectTarget(SFX_ONE, targ, "overhead"))
call DestroyEffect(AddSpecialEffectTarget(SFX_ONE, targ, "chest"))
call DestroyEffect(AddSpecialEffectTarget(SFX_ONE, targ, "origin"))
else
// If yes, then ... spawn a new missile for the deflecting unit.
// It should work fine, but it always makes them go right!
set loc = GetUnitLoc(targ)
call Data.create(targ, loc)
call RemoveLocation(loc)
set loc = null
endif
call d.destroy()
endif
set targ = null
return false
endmethod
static method create takes unit cast, location loc returns Data
local Data d = Data.allocate()
local real x = GetUnitX(cast)
local real y = GetUnitY(cast)
local real lx = GetLocationX(loc)
local real ly = GetLocationY(loc)
set d.cast = cast
set d.angle = bj_RADTODEG * Atan2(ly - y, lx - x)
set d.missile = CreateUnit(GetOwningPlayer(d.cast), UID_RAW, x, y, d.angle)
set d.lvl = GetUnitAbilityLevel(d.cast, AID_RAW)
set d.deduction = GetRandomReal(0., 8.)
set d.value = GetRandomReal(4.155, 8.12)
call SetUnitX(d.missile, x)
call SetUnitY(d.missile, y)
// My indexing stuff...
set IS_SOME_DUMMY[GetUnitId(d.missile)] = true
if GetRandomInt(0, 1) == 0 then
set d.flip = true
// Some randomness on creation- whether to start from left or right.
endif
set d.somewait = GetRandomInt(1, 7) //
set d.ticks = R2I(DURATION(d.cast) / PERIOD)
set d.tim = NewTimer()
set d.trig = CreateTrigger()
call TriggerRegisterUnitInRange(d.trig, d.missile, 100., BOOLEXPR_TRUE)
call TriggerAddCondition(d.trig, Condition(function Data.OnDamage))
set ht[d.trig] = d
set ht[d.tim] = d
call TimerStart(d.tim, PERIOD, true, function Data.Callback)
return d
endmethod
method onDestroy takes nothing returns nothing
call ht.flush(.tim)
call ReleaseTimer(.tim)
call TriggerClearConditions(.trig)
call DisableTrigger(.trig)
call DestroyTrigger(.trig)
call KillUnit(.missile)
endmethod
endstruct
private struct Temp
unit cast
location loc
timer tim
integer ticks = 11
private static method Callback takes nothing returns nothing
local Temp d = ht[GetExpiredTimer()]
call Data.create(d.cast, d.loc) // Create missiles periodically,
// instead of instantly, for better
// visual effect.
set d.ticks = d.ticks - 1
if d.ticks <= 0 then
call d.destroy()
endif
endmethod
static method create takes unit cast returns Temp
local Temp d = Temp.allocate()
set d.cast = cast
set d.loc = GetSpellTargetLoc()
set d.tim = NewTimer()
set ht[d.tim] = d
call TimerStart(d.tim, PERIOD2, true, function Temp.Callback)
return d
endmethod
method onDestroy takes nothing returns nothing
call ht.flush(.tim)
call ReleaseTimer(.tim)
call RemoveLocation(.loc)
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_RAW
endfunction
private function Actions takes nothing returns nothing
call Temp.create(GetTriggerUnit())
endfunction
private function Init takes nothing returns nothing
call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function Conditions, function Actions)
set ht = HandleTable.create()
endfunction
endscope
There has to be something wrong in the OnDamage function:
JASS:
set loc = GetUnitLoc(targ)
call Data.create(targ, loc)
call RemoveLocation(loc)
set loc = null
endif
It should calculate the angle correctly, though it seems that it always returns a value that will make them go right.