• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] OMG help!

Status
Not open for further replies.
Guys you gotta help me! When i use one of my spells, if there are many units nearby my caster there is a chance i get this message:

error.jpg

I use ABC system... is that the reason of this ??
Can some1 indicate me some solutions plz =S
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Yeap, post it.
I remember reading something about indexes being to high in the description of a system.
But now that i recall it might not be this ABC ;)
 
MMMmm, it is not an infinite loop, everything is under perfect control....
Anyway, I post a map with a version of it.
Makes no sense since the version i am using is lighter =S

This is the code with the Atan2 problem as well, but it doesn't affect Lightning Invocation (the spell being used).
Hope it helps !!

Is it because i use too much memory ?? Like Using timer until C ??

off-topic: OMG !! 999 posts and 111 rep points !! =P
 

Attachments

  • Lightning Theme Flame_Phoenix.w3x
    48.7 KB · Views: 41
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
For now I was unable to come to that bug.
But there is a buff removal bug.
Haven't tested a lot, but the units (ranged melee and heroes) somehow got the buff level 1 permanently. When casted the spell again (at higher level) the buff for level 3 appeared but the buff for level one was permanent.
Maybe leveling the skill after starting to channel than casting it again before channeling is finished.
You should use a ability stop event.
 
Well, i came to a similar bug yesterday ... but i have no apparent reason for that to happen ... anyway, i did some intensive testing yesterday, i think the problem doesn't lie on ABC neither that spell, but on a system called "Data System" made by grim00.
I can post the system here.
Anyway, i will try to change the ability to use only two clocks instead of tree.
About the bug, i make no idea why it happens .... If you look with attention you see my units don't get any buff... they get an aura inside a spell book, so there can be an icon describing the level and ability.

However i must know, am I finishng the spell correctly ? can you guys tell me if there is any leaks or bugs left in End_Actions ? Do i have to clean up something ?
I can also post the data system if you guys need =S

The code is really easy to understand, here i post the heart trigger:
JASS:
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

POST 1000 !!!! =p
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
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)
 
Your map is almost certainly leaking handle indices substantially at some point.

OMG !? where ?? is it on this code ?
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)

Well, that is not a bug spiwn. You see, because those are buff type auras, it means that when I add an aura to an unit, it will be default level 1. Than even if i set it to level 3 immediately, there is a period i must wait until level 1 buff disappears, which takes about 2-3 seconds. This is a bug from Blizzard about their auras, and because i am using them, there is little i can do to fix it. Unfortunately for me an aura doesn't disappear instantly like a spell buff.
But because my map already uses ALL buffs, i have no choice but to use auras :S

Anyway, here is what i think may be causing the problem: a DataSystem made by grim00 and changed by Need_O2.
JASS:
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

There is also this SoundSystem made by Need_O2, but i don't think this is the problem
JASS:
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
 
Level 9
Joined
Mar 25, 2005
Messages
252
You never destroy any Mystructs in the LightningInvocation's 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.
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
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 ?
 
AHhhh, damn I knew i was forgetting something !! This is terrible news, if you are right, than all my codes using ABC LEAK !! OMG

JASS:
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

I've added a line. Please tell me if i need to do more stuff to correct any this huge problem of mine plz =S
You guys will surely get +rep =)

EDIT
damn i can't give you guys rep, I have to "spread it" first ... anyway, you guys will get credit ! =)
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
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.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
You only have to destroy the struct once.
But nulling all the pointers that point to it is something different.
 
JASS:
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 ?
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Atm I think that the systems work fine.
The problem is incorrect usage.
But haven't really studied the code of your spell nor the system too much up to now.
 
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.

Well, that is the problem ... because those are imported spells which i didn't creates, there is little i can do to null them, because i don't know where to null them and how to do so.
Thus my only reasonable option is to remove that system, among with spells using it =S
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
So now you are ok to using a BJ :D
About Atan2BJ you were not, and it is far more harmless(or so to speak) than TriggerRegisterAnyUnitEventBJ ;)
 
Level 11
Joined
Apr 6, 2008
Messages
760
So now you are ok to using a BJ :D
About Atan2BJ you were not, and it is far more harmless(or so to speak) than TriggerRegisterAnyUnitEventBJ ;)

JASS:
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

JASS:
function Atan2BJ takes real y, real x returns real
    return Atan2(y, x) * bj_RADTODEG
endfunction

enuff said....
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
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.

Again 100% correct.
The optimizer started to inline constants when Vexorian introduced the JESP standart, so that when you implement a spell that is JESP and u optimize your map it is not slowed by calling the constant functions/variables.
 
Level 14
Joined
Nov 20, 2005
Messages
1,156
Constant functions and globals compile to exactly the same byte code, or at least so sayeth the Lord, I believe, and thus it must be so.

Constant functions are faster in the sense that Vex's optimizer inlines them, but vJASS is starting to auto-inline (or is that the optimizer?).
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Well maybe it's features will be included in JNGP.
So you just click the Vexorian Optimizer menu in the main window and blah ...
 
Status
Not open for further replies.
Top