- Joined
- May 4, 2007
- Messages
- 2,260
scope LightningInvocation initializer Init
globals
private constant integer AID = 'A000' //ability ID
private constant integer HBID = 'A003' //hero book ID
private constant integer HAID = 'A001' //hero aura ID
private constant integer MBID = 'A00B'//melee book ID
private constant integer MAID = 'A005'//melee aura ID
private constant integer RBID = 'A00A' //ranged book ID
private constant integer RAID = 'A006' //ranged aura ID
private constant integer THID = 'A002' //dummy unit's thunder ability ID
private constant integer DUMID = 'h000' //rawcode for dummy unit
private constant string DUMORDER = "thunderclap" //the order the dummy unit must get to invoke thunder
private constant real DUMLIFE = 2.0 //the LifeTime of the dummy unit
private constant real MINRANGE = 100.00 //The minimal range
private constant real MAXRANGE = 900.00 //The maximum range the spell will afect
private constant real HEIGHT = 1000.0 //the height of the field where it will be rain and wind
private constant real WIDTH = 900.0 //the width of the field where it will be rain and wind
private constant integer WIND = 'WNcw' //rawcode for the weathereffect of wind
private constant integer RAIN = 'RAhr' //rawcode for the weather effect of rain
endglobals
private struct Mystruct
unit caster = GetTriggerUnit()
timer repeator = CreateTimer()
timer picker = CreateTimer()
timer remover = CreateTimer()
group buffer = CreateGroup()
trigger end = CreateTrigger()
triggeraction endAction
triggercondition endCondition
weathereffect rain
weathereffect wind
endstruct
//==========================================================================
private function End_Conds takes nothing returns boolean
return GetSpellAbilityId() == AID
endfunction
//==========================================================================
private function End_Acts takes nothing returns nothing
//catches the trigger and runs this function
local Mystruct data = GetTriggerStructB(GetTriggeringTrigger())
local unit targ
//stops the rain and the wind
call EnableWeatherEffect( data.wind, false )
call EnableWeatherEffect( data.rain, false )
call RemoveWeatherEffect( data.wind)
call RemoveWeatherEffect( data.rain)
//Cleans all units from data.buffer and destroys it
loop
set targ = FirstOfGroup(data.buffer)
exitwhen(targ == null)
call UnitRemoveAbility(targ, RBID)
call UnitRemoveAbility(targ, MBID)
call UnitRemoveAbility(targ, HBID)
call GroupRemoveUnit(data.buffer, targ)
endloop
call DestroyGroup(data.buffer)
//removes the created trigger in the Code_acts function
call TriggerRemoveCondition(data.end,data.endCondition)
call TriggerRemoveAction(data.end,data.endAction)
call DestroyTrigger(data.end)
call ClearTriggerStructB(data.end)
//stops the repeator timer and ends the spell once and for all
call PauseTimer(data.repeator)
call DestroyTimer(data.repeator)
call PauseTimer(data.picker)
call DestroyTimer(data.picker)
call PauseTimer(data.remover)
call DestroyTimer(data.remover)
call ClearTimerStructA(data.repeator)
call ClearTimerStructB(data.picker)
call ClearTimerStructC(data.remover)
endfunction
//==========================================================================
// Read this tutorial to understand why this function exists and what it does:
// [url]http://www.wc3campaigns.net/showthread.php?t=83337[/url]
private function CopyGroup takes group g returns group
set bj_groupAddGroupDest = CreateGroup()
call ForGroup(g, function GroupAddGroupEnum)
return bj_groupAddGroupDest
endfunction
//==========================================================================
private function Remover takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructC(GetExpiredTimer())
local unit targ
local group aux = CopyGroup(data.buffer)
//here I check all units in data.buffer to see if they are inside range
loop
set targ = FirstOfGroup(aux)
exitwhen(targ == null)
if (IsUnitInRange(data.caster, targ, 900) == false) then
call GroupRemoveUnit(data.buffer, targ)
call UnitRemoveAbility(targ, HBID)
call UnitRemoveAbility(targ, RBID)
call UnitRemoveAbility(targ, MBID)
endif
call GroupRemoveUnit(aux,targ)
endloop
call DestroyGroup(aux)
set aux = null
endfunction
//==========================================================================
private function Picker takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructB(GetExpiredTimer())
local group g = CreateGroup()
local unit targ
local player p = GetOwningPlayer(data.caster)
local integer level = GetUnitAbilityLevel(data.caster, AID)
//here i select friendly units, give them new ability, and add them to data.buffer
call GroupEnumUnitsInRange( g, GetUnitX( data.caster ), GetUnitY( data.caster ), 900, Filter(null))
loop
set targ = FirstOfGroup( g )
exitwhen (targ == null)
if IsUnitAlly(targ, p) then
if IsUnitType(targ, UNIT_TYPE_HERO) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405 ) and ((targ == data.caster)== false) then
//spell book for hero atatckers
call UnitAddAbility(targ, HBID) //add book
call SetUnitAbilityLevel(targ, HBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,HAID, level)//sets lv of Ability to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), HBID, false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_MELEE_ATTACKER) and (IsUnitType(targ, UNIT_TYPE_HERO) == false) and (IsUnitType(targ, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405) then
//spell book for melee atatcker units
call UnitAddAbility(targ, MBID) //add book
call SetUnitAbilityLevel(targ, MBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,MAID, level)//sets lv of Melee to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), MBID, false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_RANGED_ATTACKER) and (IsUnitType(targ, UNIT_TYPE_HERO) == false) and (IsUnitType(targ, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405) then
//spell book for ranged atatckers
call UnitAddAbility(targ, RBID) //add book
call SetUnitAbilityLevel(targ, RBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,RAID, level)//sets lv of ranged to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), RBID, false )
call GroupAddUnit(data.buffer, targ)
endif
endif
call GroupRemoveUnit(g,targ)
endloop
call DestroyGroup(g)
set g = null
endfunction
//==========================================================================
private function InvokeThunder takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructA(GetExpiredTimer())
//This uses polar projection. Formula: Center + r * trigfunction(angle teta);
//where Center is the center coordinate X or Y
//r is the distance (in the case rabdom between 300 and 600)
//trigfunction is Sin if using Y and Cos if using X
//angle teta is the angle formed between r and the axis (in this case random, can be all circle)
local real randomX
local real randomY
local unit dummy
local integer exit = GetUnitAbilityLevel(data.caster, AID)
local integer counter = 0
loop
exitwhen(counter >= exit)
set randomX = GetUnitX(data.caster) + GetRandomReal(MINRANGE, MAXRANGE) * Cos(GetRandomReal(0.0, 360.0) * bj_DEGTORAD)
set randomY = GetUnitY(data.caster) + GetRandomReal(MINRANGE, MAXRANGE) * Sin(GetRandomReal(0.0, 360.0) * bj_DEGTORAD)
set dummy = CreateUnit(GetOwningPlayer(data.caster), DUMID, randomX, randomY, 0)
call UnitAddAbility(dummy, THID)
call IssueImmediateOrder( dummy, DUMORDER )
call UnitApplyTimedLife(dummy, 'BTLF', DUMLIFE)
set counter = counter + 1
endloop
set dummy = null
endfunction
//==========================================================================
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID
endfunction
//==========================================================================
private function Actions takes nothing returns nothing
local Mystruct data = Mystruct.create()
//variables for the rain and wind
local real x = GetUnitX(data.caster)
local real y = GetUnitY(data.caster)
//creates the weather effects and makes them visible
set data.wind = AddWeatherEffect(Rect( x - WIDTH * 0.5, y - HEIGHT * 0.5, x + WIDTH * 0.5, y + HEIGHT * 0.5 ), WIND)
set data.rain = AddWeatherEffect(Rect( x - WIDTH * 0.5, y - HEIGHT * 0.5, x + WIDTH * 0.5, y + HEIGHT * 0.5 ), RAIN)
call EnableWeatherEffect( data.wind, true )
call EnableWeatherEffect( data.rain, true )
//starts the effect of the spell, thunders start falling from sky
call SetTimerStructA(data.repeator, data)
call TimerStart(data.repeator, 3 / GetUnitAbilityLevel(data.caster, AID), true, function InvokeThunder)
//creates the timer that picks units arround the hero to give them abilities
call SetTimerStructB(data.picker, data)
call TimerStart(data.picker, 1, true, function Picker)
//This timer checks every 0.8 secs if a unit is outside range, to remove the buffs
call SetTimerStructC(data.remover, data)
call TimerStart(data.remover, 0.8, true, function Remover)
//creates the trigger that will end the spell when the hero stops channeling
call SetTriggerStructB(data.end, data)
call TriggerRegisterAnyUnitEventBJ( data.end, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
set data.endCondition = TriggerAddCondition( data.end, Condition( function End_Conds ) )
set data.endAction = TriggerAddAction( data.end, function End_Acts )
endfunction
//===========================================================================
private function Init takes nothing returns nothing
set gg_trg_Lightning_Invocation = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Lightning_Invocation, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
call TriggerAddCondition( gg_trg_Lightning_Invocation, Condition( function Conditions ) )
call TriggerAddAction( gg_trg_Lightning_Invocation, function Actions )
endfunction
endscope
Your map is almost certainly leaking handle indices substantially at some point.
I will look into it later.
But when I tested it today I did not manage to recreate the bug.
But came to another one.
I start Lightning Invocation level 3.
Everything works well.
Before it is over, I start it again.
Level 3 Buff stays there, but a level 1 buff appears for a short duration. Then it goes away and level 3 buff acts normally.
P.s. It is certain that those messages appear because some Function that uses H2I or something similar(U2I etc; doesn't really matter) works only with indexes lower than something.
Note that Unit Indexes for example are Always bigger than n and systems that are not meant to be used with units will not work with indexes bigger than that n. But other stuffs indexes are lower than that n(like timers, triggers and dialogs)
library DataSystem // Must be same with trigger name
// Touching the other parts causes you to bleed to death
// %80 made by grim001
private function True takes nothing returns boolean
return true
endfunction
function H2I takes handle h returns integer
return h
return 0
endfunction
globals
sound lastCreatedSound
real MapMaxX
real MapMaxY
real MapMinX
real MapMinY
group ForTheAll = CreateGroup()
filterfunc nullfilter
private integer array channelcounter1
private integer array channelcounter2
private integer array channelcounter3
private boolean array channeling1
private boolean array channeling2
private boolean array channeling3
endglobals
//! textmacro StoreRegister takes S,otype
scope store$S$
globals
private $otype$ array $S$1
private $otype$ array $S$2
private $otype$ array $S$3
endglobals
function Set$S$ takes handle h, integer v returns nothing
local integer i = H2I(h) - 0x100000
if (i < 8191) then
set $S$1[i] = v
elseif (i < 16382) then
set $S$2[i - 8191] = v
elseif (i < 24573) then
set $S$3[i - 16382] = v
else
call BJDebugMsg("Data System Error: Handle index too high")
endif
endfunction
function Get$S$ takes handle h returns $otype$
local integer i = H2I(h) - 0x100000
if (i < 8191) then
return $S$1[i]
elseif (i < 16382) then
return $S$2[i - 8191]
elseif (i >= 24573) then
call BJDebugMsg("Data System Error: Handle index too high")
endif
return $S$3[i - 16382]
endfunction
endscope
//! endtextmacro
//! runtextmacro StoreRegister("Data","integer")
function StartChanneling takes unit u returns integer
local integer i = H2I(u) - 0x100000
if (i < 8191) then
if channelcounter1[i] > 500 then
set channelcounter1[i] = 0
endif
set channelcounter1[i] = channelcounter1[i]+1
set channeling1[i] = true
return channelcounter1[i]
elseif (i < 16382) then
if channelcounter2[i-8191] > 500 then
set channelcounter2[i-8191] = 0
endif
set channelcounter2[i-8191] = channelcounter2[i-8191]+1
set channeling2[i-8191] = true
return channelcounter2[i-8191]
elseif (i < 24573) then
if channelcounter3[i-16382] > 500 then
set channelcounter3[i-16382] = 0
endif
set channelcounter3[i-16382] = channelcounter3[i-16382]+1
set channeling3[i-16382] = true
return channelcounter3[i]
else
call BJDebugMsg("Data System Error: Handle index too high")
return 0
endif
endfunction
function IfChanneling takes unit u,integer a returns boolean
local integer i = H2I(u) - 0x100000
if (i < 8191) then
return channeling1[i] and channelcounter1[i] == a
elseif (i < 16382) then
return channeling2[i-8191] and channelcounter2[i-8191] == a
elseif (i >= 24573) then
call BJDebugMsg("Data System Error: Handle index too high")
endif
return channeling3[i-16382] and channelcounter3[i-16382] == a
endfunction
private function ChannelBreak takes nothing returns nothing
local integer i = H2I(GetTriggerUnit()) - 0x100000
if (i < 8191) then
set channeling1[i] = false
elseif (i < 16382) then
set channeling2[i-8191] = false
elseif (i < 24573) then
set channeling3[i-16382] = false
else
call BJDebugMsg("Data System Error: Handle index too high")
endif
endfunction
public function InitTrig takes nothing returns nothing
local trigger trig = CreateTrigger()
local integer i = 0
loop
exitwhen i == 16
call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_DEATH,null)
call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_SPELL_FINISH,null)
call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_SPELL_ENDCAST,null)
set i = i+1
endloop
set i = 0
call TriggerAddAction(trig,function ChannelBreak)
set trig = null
set nullfilter = Filter(function True)
set MapMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
set MapMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
set MapMinX = GetRectMinX(bj_mapInitialPlayableArea)
set MapMinY = GetRectMinY(bj_mapInitialPlayableArea)
endfunction
function PreloadSoundLabel takes string label returns nothing
local sound snd= CreateSoundFromLabel(label,false,false,true,0,0)
call SetSoundVolume(snd,0)
call StartSound(snd)
call KillSoundWhenDone(snd)
set snd = null
endfunction
endlibrary
library SoundVarSet
globals
string SystemSoundLabel
endglobals
endlibrary
//! textmacro RegisterSound takes S
scope $S$SoundScope
globals
private sound array s1
private sound array s2
private sound array s3
endglobals
function Play$S$ takes real x,real y,real z returns nothing
local integer i = 0
local boolean found = false
loop
exitwhen s1[i] == null
if (GetSoundIsLoading(s1[i]) or GetSoundIsPlaying(s1[i])) == false then
call SetSoundPosition(s1[i],x,y,z)
call StartSound(s1[i])
set found = true
exitwhen true
endif
if i == 8000 then
loop
exitwhen s2[i] == null
if (GetSoundIsLoading(s2[i]) or GetSoundIsPlaying(s2[i])) == false then
call SetSoundPosition(s2[i],x,y,z)
call StartSound(s2[i])
set found = true
exitwhen true
endif
set i = i+1
endloop
else
set i = i+1
endif
endloop
if not found then
if i < 8000 then
set s1[i] = CreateSoundFromLabel(SystemSoundLabel,false,true,false,0,0)
call SetSoundPosition(s1[i],x,y,z)
call StartSound(s1[i])
else
set s2[i] = CreateSoundFromLabel(SystemSoundLabel,false,true,false,0,0)
call SetSoundPosition(s2[i],x,y,z)
call StartSound(s2[i])
endif
endif
endfunction
endscope
//! endtextmacro
You never destroy any Mystructs in this code. Even though you destroy all of their handles the ids of those wont get recycled because the structs wont get recycled, since if the structs won't get recycled (i.e. destroyed) their members will still point to the handles forever and thus reserve their ids.
Solution is just to destroy the 'data' variable in End_Acts, and make sure you dont leave structs undestroyed elsewhere either.
This is about leaking or the problem ?
private function End_Acts takes nothing returns nothing
//catches the trigger and runs this function
local Mystruct data = GetTriggerStructB(GetTriggeringTrigger())
local unit targ
//stops the rain and the wind
call EnableWeatherEffect( data.wind, false )
call EnableWeatherEffect( data.rain, false )
call RemoveWeatherEffect( data.wind)
call RemoveWeatherEffect( data.rain)
//Cleans all units from data.buffer and destroys it
loop
set targ = FirstOfGroup(data.buffer)
exitwhen(targ == null)
call UnitRemoveAbility(targ, RBID)
call UnitRemoveAbility(targ, MBID)
call UnitRemoveAbility(targ, HBID)
call GroupRemoveUnit(data.buffer, targ)
endloop
call DestroyGroup(data.buffer)
//removes the created trigger in the Code_acts function
call TriggerRemoveCondition(data.end,data.endCondition)
call TriggerRemoveAction(data.end,data.endAction)
call DestroyTrigger(data.end)
call ClearTriggerStructB(data.end)
//stops the repeator timer and ends the spell once and for all
call PauseTimer(data.repeator)
call DestroyTimer(data.repeator)
call PauseTimer(data.picker)
call DestroyTimer(data.picker)
call PauseTimer(data.remover)
call DestroyTimer(data.remover)
call ClearTimerStructA(data.repeator)
call ClearTimerStructB(data.picker)
call ClearTimerStructC(data.remover)
//LINE ADDED HERE !! IS THIS CORRECT ?? IS THIS THE ONLY LINE I HAVE TO ADD TO
//SOLVE ALL MY PROBLEMS ??? DON'T I HAVE TO DO THIS IN OTHER FUNCTIONS ?
//IS IT IN THE CORRECT POSITION ??
call data.destroy()
endfunction
Disciple of life said I only have to do it once =S Man am I confused ... Desiciple we need our hero again!!! show up man !I ain't sure but
you have to null the local Mystruct variables(structs) in every function you use them.
Yeah, I can't give DiscipleOfLife rep neither.
scope LightningInvocation initializer Init
globals
private constant integer AID = 'A05B' //ability ID
private constant integer HBID = 'A056' //hero book ID
private constant integer HAID = 'A051' //hero aura ID
private constant integer MBID = 'A057'//melee book ID
private constant integer MAID = 'A053'//melee aura ID
private constant integer RBID = 'A058' //ranged book ID
private constant integer RAID = 'A054' //ranged aura ID
private constant integer MCBID = 'A05A'//mechanical book
private constant integer MCAID = 'A059'//maechanical aura
private constant integer THID = 'A055' //dummy unit's thunder ability ID
private constant integer DUMID = 'h01H' //rawcode for dummy unit
private constant string DUMORDER = "thunderclap" //the order the dummy unit must get to invoke thunder
private constant real DUMLIFE = 2.0 //the LifeTime of the dummy unit
private constant real MINRANGE = 100.00 //The minimal range
private constant real MAXRANGE = 900.00 //The maximum range the spell will afect
private constant real HEIGHT = 1000.0 //the height of the field where it will be rain and wind
private constant real WIDTH = 900.0 //the width of the field where it will be rain and wind
private constant integer WIND = 'WNcw' //rawcode for the weathereffect of wind
private constant integer RAIN = 'RAhr' //rawcode for the weather effect of rain
private constant integer THNUM = 3 //number of thunders called per cicle
private constant real CICLE = 1 //number of seconds we wait until we call thunders again
endglobals
private struct Mystruct
unit caster = GetTriggerUnit()
timer repeator = CreateTimer()
timer picker = CreateTimer()
timer remover = CreateTimer()
group buffer = CreateGroup()
trigger end = CreateTrigger()
triggeraction endAction
triggercondition endCondition
weathereffect rain
weathereffect wind
endstruct
//==========================================================================
private function End_Conds takes nothing returns boolean
return GetSpellAbilityId() == AID
endfunction
//==========================================================================
private function End_Acts takes nothing returns nothing
//catches the trigger and runs this function
local Mystruct data = GetTriggerStructB(GetTriggeringTrigger())
local unit targ
//stops the rain and the wind
call EnableWeatherEffect( data.wind, false )
call EnableWeatherEffect( data.rain, false )
call RemoveWeatherEffect( data.wind)
call RemoveWeatherEffect( data.rain)
//Cleans all units from data.buffer and destroys it
loop
set targ = FirstOfGroup(data.buffer)
exitwhen(targ == null)
call GroupRemoveUnit(data.buffer, targ)
call UnitRemoveAbility(targ, HBID)
call UnitRemoveAbility(targ, RBID)
call UnitRemoveAbility(targ, MBID)
call UnitRemoveAbility(targ, MCBID)
call GroupRemoveUnit(data.buffer, targ)
endloop
call DestroyGroup(data.buffer)
//removes the created trigger in the Code_acts function
call TriggerRemoveCondition(data.end,data.endCondition)
call TriggerRemoveAction(data.end,data.endAction)
call DestroyTrigger(data.end)
call ClearTriggerStructB(data.end)
//stops the repeator timer and ends the spell once and for all
call PauseTimer(data.repeator)
call DestroyTimer(data.repeator)
call PauseTimer(data.picker)
call DestroyTimer(data.picker)
call PauseTimer(data.remover)
call DestroyTimer(data.remover)
call ClearTimerStructA(data.repeator)
call ClearTimerStructB(data.picker)
call ClearTimerStructC(data.remover)
call data.destroy()
endfunction
//==========================================================================
private function Remover takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructC(GetExpiredTimer())
local unit targ
local group aux = CopyGroup(data.buffer)
//here I check all units in data.buffer to see if they are inside range
loop
set targ = FirstOfGroup(aux)
exitwhen(targ == null)
if (IsUnitInRange(data.caster, targ, 900) == false) then
call GroupRemoveUnit(data.buffer, targ)
call UnitRemoveAbility(targ, HBID)
call UnitRemoveAbility(targ, RBID)
call UnitRemoveAbility(targ, MBID)
call UnitRemoveAbility(targ, MCBID)
endif
call GroupRemoveUnit(aux,targ)
endloop
call DestroyGroup(aux)
set aux = null
endfunction
//==========================================================================
private function Picker takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructB(GetExpiredTimer())
local group g = CreateGroup()
local unit targ
local player p = GetOwningPlayer(data.caster)
local integer level = GetUnitAbilityLevel(data.caster, AID)
//here i select friendly units, give them new ability, and add them to data.buffer
call GroupEnumUnitsInRange( g, GetUnitX( data.caster ), GetUnitY( data.caster ), 900, Filter(null))
loop
set targ = FirstOfGroup( g )
exitwhen (targ == null)
if IsUnitAlly(targ, p) then
if IsUnitType(targ, UNIT_TYPE_HERO) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405 ) and ((targ == data.caster)== false) then
//spell book for hero atatckers
call UnitAddAbility(targ, HBID) //add book
call SetUnitAbilityLevel(targ, HBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,HAID, level)//sets lv of Ability to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), HBID, false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_MELEE_ATTACKER) and (IsUnitType(targ, UNIT_TYPE_HERO) == false) and (IsUnitType(targ, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405) then
//spell book for melee atatcker units
call UnitAddAbility(targ, MBID) //add book
call SetUnitAbilityLevel(targ, MBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,MAID, level)//sets lv of Melee to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), MBID, false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_RANGED_ATTACKER) and (IsUnitType(targ, UNIT_TYPE_HERO) == false) and (IsUnitType(targ, UNIT_TYPE_MECHANICAL) == false) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405) then
//spell book for ranged atatckers
call UnitAddAbility(targ, RBID) //add book
call SetUnitAbilityLevel(targ, RBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,RAID, level)//sets lv of ranged to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ), RBID, false )
call GroupAddUnit(data.buffer, targ)
elseif IsUnitType(targ, UNIT_TYPE_MECHANICAL) and (GetUnitState(targ, UNIT_STATE_LIFE) > 0.405 ) and (IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false) then
//spell book for mechanical atatckers
call UnitAddAbility(targ, MCBID) //add book
call SetUnitAbilityLevel(targ, MCBID, level) // set lv of book to the level of the current hero ability
call SetUnitAbilityLevel(targ,MCAID, level)//sets lv of ranged to the level of the current hero ability
call SetPlayerAbilityAvailable( GetOwningPlayer(targ),MCBID, false )
call GroupAddUnit(data.buffer, targ)
endif
endif
call GroupRemoveUnit(g,targ)
endloop
call DestroyGroup(g)
set g = null
endfunction
//==========================================================================
private function InvokeThunder takes nothing returns nothing
//catches the expired timer and runs this function
local Mystruct data = GetTimerStructA(GetExpiredTimer())
//This uses polar projection. Formula: Center + r * trigfunction(angle teta);
//where Center is the center coordinate X or Y
//r is the distance (in the case rabdom between 300 and 600)
//trigfunction is Sin if using Y and Cos if using X
//angle teta is the angle formed between r and the axis (in this case random, can be all circle)
local real randomX
local real randomY
local unit dummy
local integer exit = THNUM
local integer counter = 0
loop
exitwhen(counter >= exit)
set randomX = GetUnitX(data.caster) + GetRandomReal(MINRANGE, MAXRANGE) * Cos(GetRandomReal(0.0, 360.0) * bj_DEGTORAD)
set randomY = GetUnitY(data.caster) + GetRandomReal(MINRANGE, MAXRANGE) * Sin(GetRandomReal(0.0, 360.0) * bj_DEGTORAD)
set dummy = CreateUnit(GetOwningPlayer(data.caster), DUMID, randomX, randomY, 0)
call UnitAddAbility(dummy, THID)
call IssueImmediateOrder( dummy, DUMORDER )
call UnitApplyTimedLife(dummy, 'BTLF', DUMLIFE)
set counter = counter + 1
endloop
set dummy = null
endfunction
//==========================================================================
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID
endfunction
//==========================================================================
private function Actions takes nothing returns nothing
local Mystruct data = Mystruct.create()
//variables for the rain and wind
local real x = GetUnitX(data.caster)
local real y = GetUnitY(data.caster)
//creates the weather effects and makes them visible
set data.wind = AddWeatherEffect(Rect( x - WIDTH * 0.5, y - HEIGHT * 0.5, x + WIDTH * 0.5, y + HEIGHT * 0.5 ), WIND)
set data.rain = AddWeatherEffect(Rect( x - WIDTH * 0.5, y - HEIGHT * 0.5, x + WIDTH * 0.5, y + HEIGHT * 0.5 ), RAIN)
call EnableWeatherEffect( data.wind, true )
call EnableWeatherEffect( data.rain, true )
//starts the effect of the spell, thunders start falling from sky
call SetTimerStructA(data.repeator, data)
call TimerStart(data.repeator, 2.0, true, function InvokeThunder)
//creates the timer that picks units arround the hero to give them abilities
call SetTimerStructB(data.picker, data)
call TimerStart(data.picker, CICLE, true, function Picker)
//This timer checks every 0.8 secs if a unit is outside range, to remove the buffs
call SetTimerStructC(data.remover, data)
call TimerStart(data.remover, 2.0, true, function Remover)
//creates the trigger that will end the spell when the hero stops channeling
call SetTriggerStructB(data.end, data)
call TriggerRegisterAnyUnitEventBJ( data.end, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
set data.endCondition = TriggerAddCondition( data.end, Condition( function End_Conds ) )
set data.endAction = TriggerAddAction( data.end, function End_Acts )
endfunction
//===========================================================================
private function Init takes nothing returns nothing
set gg_trg_Lightning_Invocation = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Lightning_Invocation, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
call TriggerAddCondition( gg_trg_Lightning_Invocation, Condition( function Conditions ) )
call TriggerAddAction( gg_trg_Lightning_Invocation, function Actions )
endfunction
endscope
I still have the problem ='(
Are you guys sure this trigger is fixed?? Is there a chance that the problem is from other triggers as well ?
You could just install safety into the system using game cache (which it should have anyway). To fix the underlying problem, make sure you null handle variables at the end of functions.
.... Sorry to disappoint you, but the code I posted, uses nearly 0 BJ's ... It's only BJ is the trigger event .. and i really doubt that is much of a problem ...
Ciebron, can i use your spell on my map?
There's really no point to getting rid of TriggerRegisterAnyUnitEventBJ, unless you have several calls to it in the same initializer, and even then it's not a big deal.You can get rid of that too
So now you are ok to using a BJ
About Atan2BJ you were not, and it is far more harmless(or so to speak) than TriggerRegisterAnyUnitEventBJ
function TriggerRegisterAnyUnitEventBJ takes trigger trig, playerunitevent whichEvent returns nothing
local integer index
set index = 0
loop
call TriggerRegisterPlayerUnitEvent(trig, Player(index), whichEvent, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
endfunction
function Atan2BJ takes real y, real x returns real
return Atan2(y, x) * bj_RADTODEG
endfunction
Constants are not faster.
However, Vex's Optimizer inlines them (except, to my knowledge, some like Boolexprs which it would be stupid to inline)
I'm not sure if it checks for non-constants that are never set except in their declaration, but I doubt it, since it would be stupid to.
I wouldn't be surprised if it becomes solely vJass doing all of the obfuscating and optimizing after a while, since there's no reason not to.but vJASS is starting to auto-inline (or is that the optimizer?).