HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Need help with Variables + Removing Leaks

06-17-2008, 02:16 PM#1
Kyrbi0
Ok, so I got this neat "Leak Checker" program, which not only scans and marks leaks, but also suggests a fix for each one. (For those interested, it can be downloaded here). Anyway, I had a couple questions.

Click image for larger version

Name:	Wc3C Post ~ Leak Fixing2.JPG
Views:	23
Size:	63.7 KB
ID:	34935
1. It tells me (for example, Location leaks) to set the point to a variable (MyLoc), reference the variable instead of the point, then remove the location. 'K. But since I have, like, 20 different triggers (mostly for spells) that could all be firing off at once and using "MyLoc", wouldn't I need a different "MyLoc" (like "MyLocSpell1", "MyLocSpell2", etc) for each spell??

Click image for larger version

Name:	Wc3C Post ~ Leak Fixing1.JPG
Views:	8
Size:	66.2 KB
ID:	34934
2. For Unit Group leaks, it offers help, but it doesn't specify where to place the code (same for all the other types of Leaks). I mean, I understand to set the unit group to a variable before the actual "Pick Every Unit" code. But does the "removeunitgroup" code go after everything inside the loop, or after the loop outside the loop? (Hope that makes sense).

3. Finally, (and I may be confusing this with Local Variables), I remember reading somewhere that you have to null the variable, then remove it. What's that all about?



Thanks in advance for help. :P
06-17-2008, 03:21 PM#2
darkwulfv
Ugh, GUI leaks. Spawn of the devil, I swear.

You better know some lite JASS, 'cause you'll need it.

To make a global variable a local variable:
Make a global location, call it "TempPoint"
The FIRST action in your trigger:
"Custom Script:" In that custom script, put "local location udg_TempPoint"

Now use TempPoint like you normally would. Setting it, etc. (You can only do this for one variable per trigger) TempPoint is now "local" and won't mess up with other triggers using it.

At the end of your trigger, use custom script again. Put in: "call RemoveLocation(udg_TempPoint)"
Right after it, put one more Custom Script: "set udg_TempPoint = null"


About Part 2:

Set the global variable to whatever at the beginning of your script. Now, use it like normal. At the very end of your script, put in custom script: "call DestroyGroup(udg_WhateverYouNamedTheVariable)"

Part 3:
That's incorrect. In fact, that CAUSES a leak. You remove, then you null. If you null, then try to remove, the game loses reference of that object and it is stuck forever, hence a leak (except for units when they die, and things of that nature)

PS: I would learn JASS. All this leak-cleaning stuff gets a lot easier to manage, trust me.
PSS: I'm hoping you know this, but don't put the " " in the custom script, or else it will cause lots and lots of errors.
06-17-2008, 04:14 PM#3
Themerion
Quote:
Originally Posted by kyrbi0
It tells me (for example, Location leaks) to set the point to a variable (MyLoc), reference the variable instead of the point, then remove the location. 'K. But since I have, like, 20 different triggers (mostly for spells) that could all be firing off at once and using "MyLoc", wouldn't I need a different "MyLoc" (like "MyLocSpell1", "MyLocSpell2", etc) for each spell??

They cannot fire off all at once. Unless you use Wait or Run Trigger the trigger will run from beginning to end without other triggers running.

Regarding groups:
Trigger:
Actions
Set MyGroup = (Units owned by Player 1 (Red) of type Footman)
Collapse Unit Group - Pick every unit in MyGroup and do (Actions)
Collapse Loop - Actions
Animation - Change (Picked unit)'s size to (100.00%, 100.00%, 200.00%) of its original size
Custom script: call DestroyGroup(udg_MyGroup)

Another option is to tell Warcraft you want the group destroyed. Run the Custom Script before you pick all units, and the group will be destroyed automatically.
Trigger:
Actions
Custom Script: set bj_wantDestroyGroup = true
Collapse Unit Group - Pick every unit in (Units owned by Player 1 (Red) of type Footman) and do (Actions)
Collapse Loop - Actions
Animation - Change (Picked unit)'s size to (100.00%, 100.00%, 200.00%) of its original size
06-17-2008, 09:30 PM#4
Kyrbi0
Wow, thanks for all the help; +Rep, of course. Now let's see...

@Darkwulf: Ah, ok, that makes sense. I've known of locals for a while, but now it makes sense; you can use the same variable because it's "local" to the trigger in which it's used.
However, you said I can only "localize" and stuff one variable per trigger, am I right? That may be a problem, where I need to summon sfx + reference locations...

And also thanks about the order; I wasn't sure it needed to be nulled at all; I'd just heard one way or the other. Cool.

P.S. Yeah, I know... I learned quick/visual basic programming in high school, so I have some background... But I'm less than a year away from leaving, and it seems like a big ordeal, very different and still hard to read... Meh.
P.P.S. What do you take me for, a incontinent juvenile?!... :P, just kidding. Normal precautions, of course.

@Themerion: Thanks for the visual. However, I've heard of using that "Custom Script: set bj_wantDestroyGroup = true" before; then somebody mentioned that it didn't work properly, or that it needed to be repeated for each action-line in the Unit Group thingy... Am I making sense?
My apologies if it seems like I be doubtin' your wisdom, mon.
06-17-2008, 09:42 PM#5
Themerion
Quote:
Originally Posted by Kyrbi0
I've heard of using that "Custom Script: set bj_wantDestroyGroup = true" before; then somebody mentioned that it didn't work properly, or that it needed to be repeated for each action-line in the Unit Group thingy... Am I making sense?

I'm not very familiar with the bj_wantDestroy method, it's possible that there are issues with it which I am ignorant of. I myself stick to the first version (set variable), but I noticed that the "Unit Group - Pick All Units..." function looks like this:

Collapse Unit Group - Pick All Units...:
function ForGroupBJ takes group whichGroup, code callback returns nothing
    // If the user wants the group destroyed, remember that fact and clear
    // the flag, in case it is used again in the callback.
    local boolean wantDestroy = bj_wantDestroyGroup
    set bj_wantDestroyGroup = false

    call ForGroup(whichGroup, callback)

    // If the user wants the group destroyed, do so now.
    if (wantDestroy) then
        call DestroyGroup(whichGroup)
    endif
endfunction

So I assumed it would work too.
06-17-2008, 09:52 PM#6
darkwulfv
Yes, the set bj_wantdestroygroup method is usable. I would actually encourage using it MOST of the time (sometimes you want to save a group, but if it's just for a temporary group, set it to true. The function automatically sets it back to false for you)
06-17-2008, 09:54 PM#7
Kyrbi0
Hey, I'm just spouting baseless, rumor-mongering remarks; I'm gonna wait until someone "higher-up" the JASS food-chain tells me otherwise. Until then, I'll probably just stick with the 'localized' unit-group variables-thingy.

EDIT: Woops, posted a few seconds too late. Ok then, that's cool; makes work easier for me :P.
Again, thanks for the help.

(Oh yeah, and what if I need to use more than one type of local variables, like sfx and location?)
06-17-2008, 09:57 PM#8
darkwulfv
Quote:
(Oh yeah, and what if I need to use more than one type of local variables, like sfx and location?)
I wouldn't worry about the SFX. Sometimes (not all the time), you can use "Destroy Special Effect" and then when it asks which effect to destroy, just make it create one. Beware, though, this will ONLY work if the effect has a death animation, and the death animation is many times different than the effect you want.

Otherwise, a temporary global works fine for special effects. I don't think you need to worry about localizing it. Just make sure you destroy it at the end so it doesn't leak.
06-17-2008, 10:11 PM#9
Themerion
You only need to localize a variable when you're using Waits in the trigger. Scripts and triggers run in one piece, so you can use temporary global variables as long as there's no wait in between.

Quote:
Originally Posted by Wolfie is right
...a temporary global works fine...

Sometimes you want a wait though. Blizzard use this approach for Special Effects in Extreme Candy Wars:

Set SpecialFX=LastCreatedEffect().
Run Trigger:
Trigger:
Special Effect Destruction
Events
Conditions
Collapse Actions
Custom script: local effect tempEffect
Custom script: set tempEffect = udg_SpecialFX
Wait 7.00 game-time seconds
Custom script: set udg_SpecialFX = tempEffect
Special Effect - Destroy SpecialFX

(See? Even Blizzard use temporary globals! (here to pass data between triggers))
06-17-2008, 10:15 PM#10
Kyrbi0
Ok, cool.

(Hey, wait a minute, you posted within 10 minutes of your other post... Am I the only one with the "600 second wait" between posts??)

(darn, 307 seconds to go...)
(now 44...)


Curse you, forum-based wait command! Thwarted again!
Hmm... that can't be. I don't usually need Waits, but it seems like there was something else I needed locals for.



P.S. I'll probably just edit this post again and again instead of reposting; takes too long.
06-17-2008, 11:45 PM#11
darkwulfv
The 600 second wait is mandatory for new members for a while. Everyone had to go through with it. It wears off soon, don't worry.

And locals are useful for cleaning things like locations, groups, etc. Plus, it's a good reassurance even if you aren't using waits, just for the safety of it.

Beware, though. Global -> Local conversion do NOT work with Pick Every Unit In Group or If/Then/Else (maybe even loops, not sure), due to the GUI's stupidity of making new functions for those when they really aren't needed. I think you can re-declare the local inside the block, but I'm not 100% sure.
06-23-2008, 07:28 PM#12
Kyrbi0
Quote:
Set SpecialFX=LastCreatedEffect().
Run Trigger:

Trigger:
Trigger:
Collapse Special Effect Destruction
Events
Conditions
Collapse
Actions
Custom script: local effect tempEffect
Custom script: set tempEffect = udg_SpecialFX
Wait 7.00 game-time seconds
Custom script: set udg_SpecialFX = tempEffect
Special Effect - Destroy SpecialFX

I'm sorry, I don't really get the usage of this. Is this an entirely separate trigger? Do I need to set my created special effects to a variable, as you indicated above the trigger-code? And where do I put all the in (since I'm using a "For Integer A" loop thing). For reference, here's mine:

Trigger:
Final Finale xx Remove Effects
Collapse Events
Unit - A unit Stops casting an ability
Unit - A unit Finishes casting an ability
Collapse Conditions
(Ability being cast) Equal to Voodoo Maledict
Collapse Actions
Custom script: local location udg_TempPoint
Unit - Remove Voodoo Shield from (Casting unit)
Collapse Unit Group - Pick every unit in (Units of type 1: Sun-Trap) and do (Actions)
Collapse Loop - Actions
Unit - Kill (Picked unit)
Collapse Unit Group - Pick every unit in (Units of type 2: Mega-Wave) and do (Actions)
Collapse Loop - Actions
Unit - Kill (Picked unit)
Unit - Kill (Target unit of ability being cast)
Set TempPoint = (Position of (Target unit of ability being cast))
Collapse For each (Integer A) from 1 to 5, do (Actions)
Collapse Loop - Actions
Special Effect - Create a special effect at TempPoint using Abilities\Spells\Human\Resurrect\ResurrectTarget.mdl
Wait 0.05 game-time seconds
Special Effect - Destroy (Last created special effect)
Custom script: call RemoveLocation(udg_TempPoint)
Custom script: set udg_TempPoint = null
06-23-2008, 08:09 PM#13
Themerion
Quote:
Originally Posted by Kyrbi0
I'm sorry, I don't really get the usage of this. Is this an entirely separate trigger? Do I need to set my created special effects to a variable, as you indicated above the trigger-code?

The usage of it is that you can clean up your special effect leaks. Yes, it is a separate trigger. Yes, you need to set the effects to a variable after creation.

As I stated in the other post you shouldn't use waits in a for loop.

Since you don't want the entire effect to be played, I suggest you put the time before destruction in a variable as well:

Trigger:
Special Effect Destruction
Events
Conditions
Collapse Actions
Custom script: local effect tempEffect
Custom script: set tempEffect = udg_SpecialFX
Wait (TempReal) game-time seconds
Custom script: set udg_SpecialFX = tempEffect
Special Effect - Destroy SpecialFX

When you run the trigger Special Effect Destruction, it will store your effect in the trigger. It will then wait TempReal seconds and finally destroy the effect.

Trigger:
Special Effect - Create a special effect at TempPoint using Abilities\Spells\Human\Resurrect\ResurrectTarget.mdl
Set SpecialFX = (Last Created Special Effect)
Set TempReal = 0.05
Trigger - Run (Special Effect Destruction)

100% safe and leak-free.
06-23-2008, 08:45 PM#14
Kyrbi0
Ah, ok. Thanks for clearing that up.