I've ran into this big issue with my spell, Magic Javelin. I have it set up using vJass and have evaded using a timer (due to lack of knowledge and internet to look it up) and finally have the chance to look up timers. However, it appears that although the conditions are met, the actions are not ran at all.
I have added debug messages in each of the functions that I find might interfere, and even commented out the temporary trigger to see if the actions would run. I haven't ran into this issue before with my other triggers and have no idea why it doesn't work.
Here is the spell
If you're wondering about the condition being after the actions, I have set it there to see if I could run the actions function through the conditions. Still, no luck. It's strange because not even the debug message is displayed for the actions, even when the conditions run true and I run actions through the conditions functions itself to bypass the trigger's call to the actions.
What could be wrong? I've tried to write it as cleanly as possible so it's easier to read. I feel there is an issue with the actions function itself, but it's still a mystery why it wouldn't run at all.
PS: Please bear with the lack of decomposition and structs. This spell is still in its primitive stages.
I have added debug messages in each of the functions that I find might interfere, and even commented out the temporary trigger to see if the actions would run. I haven't ran into this issue before with my other triggers and have no idea why it doesn't work.
Here is the spell
JASS:
scope MagicJavelin initializer Init
//*********************************************************************************************************************\\
//***********************************************config****************************************************************\\
//*********************************************************************************************************************\\
globals
private constant real INTERVAL = 0.03625 //Time between ticks
private constant integer SPELL_ID = 'A002' //Object data
private constant integer DUMMY_ID = 'h001'
private constant real INITIAL_DISTANCE = 150 //Range data/hit sensitivity
private constant real HIT_RADIUS = 15 // !Do not exceed INITIAL_DISTANCE!
private constant real DAMAGE = 50 //Initial damage
private constant real DAMAGE_PER_LEVEL = 75 //Additional damage per level
private constant real DAMAGE_PER_SECOND = 100 //Initial damage per second travelled
private constant real DAMAGE_PER_LVLSEC = 150 //Additional damage per second travelled per level
private constant real INITIAL_SPEED = 700 //Initial travel speed
private constant real SPEED_CLIMB = 250 //Amount of travel between ticks
private constant real SPEED_DIVISOR = 100 //How much speed is divided by. Set to 100 for higher precision.
endglobals
//Switches/Toggleables
globals
private constant boolean FRIENDLY_FIRE = true //Determines if it hits allies
endglobals
//Formulae
private function SpeedCalc takes nothing returns real
return INITIAL_SPEED / SPEED_DIVISOR
endfunction
private function ClimbCalc takes integer nTicks returns real
return (SPEED_CLIMB / SPEED_DIVISOR) * nTicks
endfunction
private function DamageCalc takes integer level, integer nTicks returns real
//Step 1: Find initial damage.
local real Damage = DAMAGE + (DAMAGE_PER_LEVEL * (level - 1))
//Step 2: Calculate Damage Per Second
local real DPS = DAMAGE_PER_SECOND + (DAMAGE_PER_LVLSEC * (level - 1))
//Step 3: Convert to Damage Per Tick
set DPS = DPS / INTERVAL
//Step 4: Calculate final damage based on time travelled.
return Damage + (DPS * nTicks)
endfunction
//*********************************************************************************************************************\\
//*******************************************End of config*************************************************************\\
//*********************************************************************************************************************\\
globals
private unit Caster
private unit Dummy
private player PlayerID
private real Angle
private integer Ticks = 0
private group UnitHit
private trigger ticker
endglobals
private function SetGlobals takes nothing returns nothing
local location ls
local location lc
call BJDebugMsg("Globals set")
set Caster = GetSpellAbilityUnit()
set PlayerID = GetOwningPlayer(Caster)
set lc = GetUnitLoc(Caster)
set ls = GetSpellTargetLoc()
set Angle = AngleBetweenPoints(lc, ls)
call RemoveLocation(ls)
call RemoveLocation(lc)
endfunction
//*********************************************************************************************************************\\
//***********************************conditional data******************************************************************\\
//*********************************************************************************************************************\\
//*********************************************************************************************************************\\
//*********************************************************************************************************************\\
//*********************************************************************************************************************\\
private function GroupConds takes nothing returns boolean
if(FRIENDLY_FIRE) then
return (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)) == false and (IsUnitAliveBJ(GetFilterUnit()) == true)
endif
return (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)) == false and (IsUnitAliveBJ(GetFilterUnit()) == true and not(IsUnitAlly( GetFilterUnit(), PlayerID )))
endfunction
private function GroupActions takes nothing returns nothing
call UnitDamageTargetBJ( Caster, GetEnumUnit(), DamageCalc(GetHeroLevel(Caster), Ticks), ATTACK_TYPE_PIERCE, DAMAGE_TYPE_NORMAL )
call RemoveUnit( Dummy )
call BJDebugMsg("UNIT HIT")
set UnitHit = null
call DestroyGroup( UnitHit )
call DestroyTrigger( ticker )
endfunction
private function Tick takes nothing returns nothing
local location dummyLoc = GetUnitLoc(Dummy)
set Ticks = Ticks + 1
call BJDebugMsg("Tick Tock")
call SetUnitPositionLoc( Dummy, PolarProjectionBJ(dummyLoc, ClimbCalc(Ticks), Angle) )
set UnitHit = GetUnitsInRangeOfLocMatching(HIT_RADIUS, dummyLoc, Condition(function GroupConds))
call RemoveLocation(dummyLoc)
call ForGroupBJ( UnitHit, function GroupActions )
set UnitHit = null
call DestroyGroup(UnitHit)
endfunction
//*********************************************************************************************************************\\
//**************************************************core***************************************************************\\
//*********************************************************************************************************************\\
private function StartTicking takes nothing returns nothing
call BJDebugMsg("Ticker started")
set ticker = CreateTrigger()
call TriggerRegisterTimerEventPeriodic( ticker, INTERVAL )
call TriggerAddAction( ticker, function Tick )
endfunction
private function Actions takes nothing returns nothing
local location casterLoc = GetUnitLoc(Caster)
local location castLoc = GetSpellTargetLoc()
call BJDebugMsg("Actions initialized")
call SetGlobals()
call CreateUnitAtLoc( PlayerID, DUMMY_ID, PolarProjectionBJ(casterLoc, INITIAL_DISTANCE, Angle), Angle )
set Dummy = GetLastCreatedUnit()
call BJDebugMsg(R2S(GetLocationX(casterLoc)) + "__" + R2S(GetLocationY(casterLoc)))
call BJDebugMsg(R2S(GetLocationX(castLoc)) + "__" + R2S(GetLocationY(castLoc)))
call StartTicking()
endfunction
private function Conditions takes nothing returns boolean
local boolean b = GetSpellAbilityId() == SPELL_ID
if(b) then
call BJDebugMsg("true")
else
call BJDebugMsg("False")
endif
return b
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function Conditions ) )
call TriggerAddAction( t, function Actions )
call BJDebugMsg("Trigger Created")
endfunction
endscope
If you're wondering about the condition being after the actions, I have set it there to see if I could run the actions function through the conditions. Still, no luck. It's strange because not even the debug message is displayed for the actions, even when the conditions run true and I run actions through the conditions functions itself to bypass the trigger's call to the actions.
What could be wrong? I've tried to write it as cleanly as possible so it's easier to read. I feel there is an issue with the actions function itself, but it's still a mystery why it wouldn't run at all.
PS: Please bear with the lack of decomposition and structs. This spell is still in its primitive stages.