wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Warcraft III Modding > Developer's Corner > Triggers & Scripts
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 03-10-2007, 03:57 AM   #1
Tide-Arc Ephemera
Overdoses result in death
 
Tide-Arc Ephemera's Avatar
 
Join Date: Jan 2007
Posts: 2,365

Submissions (3)

Tide-Arc Ephemera is a jewel in the rough (206)Tide-Arc Ephemera is a jewel in the rough (206)Tide-Arc Ephemera is a jewel in the rough (206)

Default Memory Leaks

I've been having troubles trundling around this website ever since I rego'd, so... could anyone either...

Explain to me what a memory leak is, how it presents itself and what they do...
OR
Get me a link to something that has all the memory leak information expressed and ready to go.

I want to make a map generally leak free because I have this thing with having to perfect my maps... with what's in my reaches...
Tide-Arc Ephemera is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 03-10-2007, 04:44 AM   #2
botanic
User
 
botanic's Avatar
 
Join Date: Feb 2007
Posts: 551

Submissions (2)

botanic will become famous soon enough (41)botanic will become famous soon enough (41)

Send a message via AIM to botanic
Default

here ya go

http://www.wc3campaigns.net/showthre...ghlight=memory
botanic is offline   Reply With Quote
Old 03-10-2007, 05:09 AM   #3
Tide-Arc Ephemera
Overdoses result in death
 
Tide-Arc Ephemera's Avatar
 
Join Date: Jan 2007
Posts: 2,365

Submissions (3)

Tide-Arc Ephemera is a jewel in the rough (206)Tide-Arc Ephemera is a jewel in the rough (206)Tide-Arc Ephemera is a jewel in the rough (206)

Default

Thanks =D

+Rep
Tide-Arc Ephemera is offline   Reply With Quote
Old 03-10-2007, 06:17 AM   #4
Krysho
User
 
Krysho's Avatar
 
Join Date: Jan 2007
Posts: 53

Krysho will become famous soon enough (45)Krysho will become famous soon enough (45)

Default

A simple way to view it is that every type of variable that extends a handle (or extends an extension of a handle) can and will leak. If you know how to open up the common.j file, you can view every type of variable and see for yourself that basically every variable type is an extension of handle, and so most things can leak.
Quote:
type event extends handle // a reference to an event registration
type player extends handle // a single player reference
type widget extends handle // an interactive game object with life
type boolexpr extends handle
type conditionfunc extends boolexpr //extension of extension handle

The types of variables that don't leak include reals, integers, booleans, and strings (strings leaks once per unique string, but unavoidable).

The way I've come to view it for better understanding is that anything you create will work like a unit, pretty much. If you create a unit and just leave it there all game, it'll stay there, taking up space in memory. You can set a variable to equal this unit, and you can use this variable in different trigger actions to change the unit, but really, the variable is only a pointer. The unit's data is held off someplace and the variable only points to that space. If you change the variable to another unit, the original unit's data will still remain where it is unchanged... taking up space. To remove the unit, we have to use the Unit - Remove Unit action (or RemoveUnit() in JASS) to clear the memory of it.

(If you have any programming background, think on the very name "handle" ... sounds like something that'd "point" to data, and not hold it, yes?)

Well... a unit was only a demonstration, imagine if it were a point instead. Every time you do use something like "Center of Region X" or "Random Point in Region X" in your trigger actions, it creates a point (location) at the desired spot... this point is then used in the actions you want it in. However... the point is not removed at default, you have to do it yourself. Imagine if that point being there were as obvious as a unit being there - it's taking up space whether you notice it or not.

The same thing applies to unit groups (groups in JASS), floating text (texttags in JASS; though, you can set a timed life on this), player groups (forces in JASS), and many other things. Once they're created, they'll take up space if they're not removed.

Those are the types of leaks where you create something, a handle, in game - where it stays and takes up space. However, if you ever take up JASS, you'll soon learn of local variables. You'll need to know that these variables, while only being references usually, take up space too if they're handle types. To solve that problem, you need to nullify the variables when you're done with it (but NOT before destroying whatever the variable was referencing to first! - unless you have some other way of destroying the thing it references to)


And, on another note, you might sometimes encounter times where you won't need to "clean-up" leaks where you otherwise would.

Consider this situation:
Trigger:
Player 1 Unit Dies
Collapse Events
Unit - A unit owned by Player 1 (Red) Dies
Conditions
Collapse Actions
Game - Display to (All players) the text: A player owned by r...
Game - Display to Player Group - Player 1 (Red) the text: One of your units has died!
Game - Display to (Player group((Owner of (Triggering unit)))) the text: And I repeat, one of your units has died!
Three calls to display text to player groups. One displays to "All players," another to the player group "Player 1 (Red)", and another to the group of the player owning the triggering unit (assuming this was called after a unit did something). First of all, know that player groups will leak if you create one and don't remove it. So which of the above would leak, then? Convert it to JASS:
Collapse JASS:
function Trig_Player_1_Unit_Dies_Actions takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_007" )
    call DisplayTextToForce( bj_FORCE_PLAYER[0], "TRIGSTR_008" )
    call DisplayTextToForce( GetForceOfPlayer(GetOwningPlayer(GetTriggerUnit())), "TRIGSTR_009" )
endfunction

//trigger register events removed
So we can see that the first method calls a force that is returned by the JASS function "GetPlayersAll()," let's look at this function in JASS:
Collapse JASS:
function GetPlayersAll takes nothing returns force
    return bj_FORCE_ALL_PLAYERS
endfunction
It simply returns a variable... it doesn't create a force. So there it is, blizzard has some predefined variables, usually preceded by the "bj_" prefix. Since this player group has already been created, we don't need to remove it. In fact, if you remove this player group, further calls to "All players" won't work anymore... Unless you set the variable to equal a new player group that contains all players.

The case is the same for the second call, it uses a predefined variable that is set to be Player 1 (Red) (in the array, it's player-1, so 0 in the array to get player 1).

The last call to display text to a player, the owner of the triggering unit, is different, though. Look at the function "GetForceOfPlayer()" in JASS and you see this:
Collapse JASS:
function GetForceOfPlayer takes player whichPlayer returns force
    local force f = CreateForce()
    call ForceAddPlayer(f, whichPlayer)
    return f
endfunction
You can see that they create a new force, and add the player you want to it. This new force is set to a local variable (which, if I'm not mistaken, leaks since it's not nullified) and returns it for your use. Your message to the custom player group goes through, but the player group is never removed. This is a leak.

So we can do this to remove most of the leaks:
Trigger:
Player 1 Unit Dies
Collapse Events
Unit - A unit owned by Player 1 (Red) Dies
Conditions
Collapse Actions
Game - Display to (All players) the text: A player owned by r...
Game - Display to Player Group - Player 1 (Red) the text: One of your units h...
Set tempplayergroup = (Player group((Owner of (Triggering unit))))
Game - Display to tempplayergroup the text: And I repeat, one o...
Custom script: call DestroyForce(udg_tempplayergroup)
Or, if you want to skip the call to the function that creates a group altogether, you could do something like:
Trigger:
Player 1 Unit Dies
Collapse Events
Unit - A unit owned by Player 1 (Red) Dies
Conditions
Collapse Actions
Game - Display to (All players) the text: A player owned by r...
Game - Display to Player Group - Player 1 (Red) the text: One of your units h...
Custom script: set udg_tempplayergroup = bj_FORCE_PLAYER[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]
Game - Display to tempplayergroup the text: And I repeat, one o...
Using a custom script, you can directly set the temporary player group variable to equal the player in the array that you want. This saves some time, uses less function calls than the previous method; it also doesn't create a leak through the local variable not being nullified in the Blizzard function; and, another thing, you don't have to destroy the player group when you're done (it's predefined). Simple things like this can be discovered on your own in time.


You'll also want to be careful about not removing a specific handle, be it a point (location), unit, unit group, player group, or whatever... before you're done with it. And sure as hell make sure you don't change a temporary variable while it's being used.

For instance... you might be tempted to set a point variable to be the center of a region or the position of a unit, but have a wait before executing the trigger's actions. Well... the point will be created, the variable will be set to reference to it, but what happens if you use that variable again during the wait period? The variable will be set to a newly created point, and it will lose its reference to the old point. What happens to the old point, then? It's probably lost, taking up space, otherwise known as becoming a leak. What's more, your previous trigger probably failed to work properly. It might be hard to trace back to this problem happening if you're not looking for it.


One last note: If you set a variable to equal something predefined... for instance, like in the example above, "All players" (JASS: GetPlayersAll()), you will not want to Destroy or Remove ("clean-up") the actual handle's data, since it's not really a leak. (Deleting the handle data in this case will result in you not being able to use the "All players" predefined player group anymore) You will, however, want to nullify the variable if it's a local. If, for some reason, it becomes necessary to set a variable to equal another variable that's set to a handle (point/location, whatever), then you won't want to destroy the second variable after you're done with it until you're done with the point/location itself (both variables are set to the same point/location, therefore, destroying it from one variable will result in both variables not working).

Then there's the trivia: The most common leaks will probably be from unit groups and points, as others have probably said. Most people use those things quite often... "Pick every unit in Region X," or "Pick every unit in range of point X by 512.00" (hey, it leaks a unit group AND a point!) and so on. And... using stuff like Triggering Unit/Casting Unit in actions doesn't leak, despite returning a handle extension "unit". Why? Because it doesn't "create" the unit, the unit is already there, it's just returning the reference ("handle") to the unit. A unit will, of course, be a leak if you never get rid of it (corpses will eventually remove themselves, but they're taking up space while they're decaying).

Yada yada, I'm sure I can go on this topic for a long time. The tutorials I've read just don't seem to explain it all that well. Maybe you'll find something useful in this rambling.


2009 addendum regarding local variables:
Figured I'd update this post since I still received reputation for it over a year after the original post date. Most of this information is off the top of my head, from my recollection of reading random posts and overhearing random conversation; feel free to correct any glaring mistakes.

Upon the original writing of this post, I wasn't too clear on the exact reason for a local variable leak (and I skipped out on updating this for the longest time when I did find out). I'll clarify on local variables now.

Every object in memory corresponds to a certain class/type, and handle variables of the proper types only point to this object in memory. The handle variable itself, then, is simply an ID to reference a specific object; a handle is an integer, specifically. Each time a new object is introduced into wc3, an ID is assigned to the object (be it a point, unit, unit group, player force, text tag, or any other handle object).

When an object is removed from memory (via the Remove_ and Destroy_ functions), the ID associated with the object in question would normally not be in use anymore. Wc3 attempts to recycle these IDs to reuse them with further objects. However, it doesn't recycle the ID immediately upon clearing the object from memory - instead, it first checks if there are any handle variables referencing the object before recycling the ID. There is an internal counter for IDs in use, I believe. Apparently this counter fails to decrement if you do not null a local variable that references a handle (emphasis on local variable). That is, a local variable is only used for the block/scope in question before it is supposedly cleared (in your typical programming language). Wc3 apparently does not handle decrementing the counter for a handle ID automatically - you have to force this by nulling the handle variable.

Global variables apparently are not much cause for concern; although, I am not too sure on the reason why. I suppose it is typical to reuse global variables and thus decrement a handle ID naturally that way - or perhaps globals simply do not stall the recycling process when an object is cleared. Regardless, it seems to be the popular opinion that global variables do not need to be nulled.

On another note, if you'll remember, I've essentially stated that a local variable "leak" occurs when a handle ID is not recycled when it should be. There are some cases in which you don't want or need to recycle a handle ID, and thus, do not need to null a handle variable. This is the case if you have an object that is in the game permanently. Examples would be units permanently in the game, players (you don't recycle players during a game, yes?), and any other permanent things (recycled timers and so on). Probably the biggest concern for handle leaks would be in cases of massive object creation (for example, triggered spells / periodic unit creation / etc).

Restating: you don't have to null a handle variable that points to a permanent object. Somewhere above I believe I said you should null a handle that references the "All players" group preset by Blizzard. In actuality, you probably wouldn't have to bother, really.

To summarize: the two common types of leaks you used to hear about were object leaks and handle reference (aka local variable) leaks.

Object leak - occurs when a stand-alone wc3 object is created in memory and kept in memory past its intended use.

A simple example would be a triggered spell creating dummy units to cast spells for visual effect. If you never remove the dummy units after they're done casting, they have then lasted past their intended use - thus, they are leaks. Wc3 unit objects give us a lot of support to clear memory of them, however, so a unit leak is easy to clear and generally should be unheard of.

Reference leak (local variable leak) - occurs when a handle ID is kept in memory as "in use" past its intended use (ie, after the object it references is destroyed); thus, more and more handle IDs are set in memory in a table somewhere, taking up space for no reason in particular.

An example of this would be if you were to create an object and set the object to a local handle variable. If you do not null the local handle variable before that particular script ends, the handle ID in question would be forever "in use" and never recycled.


Finally, I'll say that, despite this post being updated in 2009, I haven't added any of the issues that I have discovered relatively recently. Just reading around for a few minutes showed some new possibilities regarding leaks that I was not fully aware of (given I have not been an active mapper for ~4 years). The possibility of groups leaking when destroyed is one thing I've seen, for example.

In any case, consider this post outdated. I imagine you'd only be reading this if you somehow came in upon a search or a link, anyway.

Last edited by Krysho : 01-05-2009 at 02:35 PM.
Krysho is offline   Reply With Quote
Old 03-10-2007, 07:26 AM   #5
Toink
User
 
Join Date: Oct 2006
Posts: 1,086

Submissions (3)

Toink is on a distinguished road (17)

Send a message via Yahoo to Toink
Default

In short, local variables declared in a function are only used ONCE in that function, if that function is called again it will declare NEW locals but does NOT replace the locals used before. The older locals are simply stored in a 'space' which takes up memory. Btw, globals do not leak.
Toink is offline   Reply With Quote
Old 03-10-2007, 07:34 AM   #6
Krysho
User
 
Krysho's Avatar
 
Join Date: Jan 2007
Posts: 53

Krysho will become famous soon enough (45)Krysho will become famous soon enough (45)

Default

Globals in general will not leak because the general idea is that you will re-use them and reset them to new references (as far as I know, anyway - feel free to correct). If you're never going to use a certain global again, you might as well nullify it. (For instance, when deleting an initialization trigger or some such, set gg_trg_trigger = null) Though it shouldn't be a big deal... with locals, you can be declaring new variables over and over again thousands upon thousands of times; I suppose it's more of your tastes when dealing with globals.

Last edited by Krysho : 03-10-2007 at 07:35 AM.
Krysho is offline   Reply With Quote
Old 03-10-2007, 08:45 PM   #7
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

A handle (the 'root' type for things like locations, items, units, ext ext) is a pointer. it is the X over the buried tresure, where the tresure is actual data. Without the X, the tresure still exists. Moving the X will not do anything to the tresure. (like setting the variable "MyUnit" to a diffrent unit. the old unit it was assigned to still exists. it didnt magically disapear)

A memory leak is where you leave buried tresure without an X, so it serves no purpose but to take up space. (WC3 has shite in the way of garbage collection) Moving the X to point at diffrent tresure will still leave the old tresure there. So you must dig up the tresure and get rid of it. (destroy everything based off handel when it has outlives its usefullness)

Now, you dont have to destroy a unit or item or the like, because it still has a purpose. it can still be orderd by human players, killed normally, and involved in other triggers. you dont call 'remove unit' after every trigger that deals with a unit, do you? The things you have to really worry about are locations and the like. things that will still exist if you dont destroy them explicity, but serve no purpose after they have been used.

This can be seen 'better' by using the return bug and H2I. A handel can be converted to an integer, and stored in something like a game cache. The handels data, like a unit, still exists, but you have stored a pointer to it in the game cache.

Now, lets hope Furys first-post of the morning is more coherent then he thinks it is...
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-10-2007, 10:02 PM   #8
Pyrogasm
Lackadaisically Absent.
 
Pyrogasm's Avatar


Respected User
 
Join Date: Sep 2006
Posts: 4,523

Submissions (9)

Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)

Hero Contest - Fourth place

Send a message via ICQ to Pyrogasm Send a message via AIM to Pyrogasm Send a message via MSN to Pyrogasm Send a message via Yahoo to Pyrogasm
Default

Nice work, Krysho. Rep'd!
__________________
Quote:
Originally posted by Rising_Dusk
Your spells are mostly ignored because they are not very cool so we aren't very excited to review/approve them, but you are incredibly persistent and won't give us an excuse to graveyard it. That is generally what results in a resource being ignored for a long time.

The Spell Request Thread Done for, unless someone else wants to revive it...
It lasted a damn long time.

Please; Ask for Help Appropriately














Quote:
Originally posted by Kyrbi0
Huh. Almost makes me wish I had a girlfriend, to take advantage of today (wait, no, that's not what I meant... I mean, take advantage of the fact that it is international women's day... gah, never mind).
Quote:
Originally posted by Pyrogasm
Rome may not have been built in a day, but the Romans sure as hell didn't say "look at this great city we built guys!" when they had nothing more than a bit of stone and some cottages.
Pyrogasm is offline   Reply With Quote
Old 04-04-2007, 03:20 AM   #9
Zwan
User
 
Join Date: Apr 2003
Posts: 321

Submissions (1)

Zwan is on a distinguished road (12)

Default

Got a question for Krysho. I was recently told one of my methods is actually causing a leak, and after digging around I cant quite find the answer I need so I thought I'd run it by you.

When using a commonly re-used variable (unit group in this case), I have been using 'Unit group - add unit group" to add all units to the temp group and clearing (remove all) when done. Would doing this be creating a leak?

My understanding was that since I am not creating the group as a local variable using "set variable" that I was not creating a leak. It was also mentioned that doing this is slower than set/destroy, I assume because the game has to search for the reference.

Here is a snippet of a trigger using this method as an example;

Trigger:
Set Aether_Caster = (Casting unit)
Set Aether_Start = (Position of Aether_Caster)
Unit Group - Add all units of (Units within 512.00 of Aether_Start) to Aether_Targets
Collapse Unit Group - Pick every unit in Aether_Targets and do (Actions)
Collapse Loop - Actions
Set Aether_Dummy = (Create a unit for (Owner of Aether_Caster) of type Aether_Snap_Dummy at ((X of (Picked unit)),(Y of (Picked unit))) facing (Facing of Aether_Caster) degrees)
Unit - Add a 0.50 second Generic expiration timer to Aether_Dummy
Unit - Order Aether_Dummy to Human Blood Mage - Banish (Picked unit)
Unit Group - Remove all units from Aether_Targets
Point - Remove Aether_Start


At any rate, I dont wanna go around making false statements if this method is flawed.
Zwan is offline   Reply With Quote
Old 04-04-2007, 03:29 AM   #10
Pyrogasm
Lackadaisically Absent.
 
Pyrogasm's Avatar


Respected User
 
Join Date: Sep 2006
Posts: 4,523

Submissions (9)

Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)Pyrogasm is a splendid one to behold (638)

Hero Contest - Fourth place

Send a message via ICQ to Pyrogasm Send a message via AIM to Pyrogasm Send a message via MSN to Pyrogasm Send a message via Yahoo to Pyrogasm
Default

No, Zwan, that is perfectly acceptable.

By that method, you never create a new group out of Aether_Targets.

However, this line does leak a group:
Trigger:
Unit Group - Add all units of (Units within 512.00 of Aether_Start) to Aether_Targets

So, you're still going to need 1 temporary group to add everything to, which is essentially more work because you have to destroy/de-leakify that group anyway.
__________________
Quote:
Originally posted by Rising_Dusk
Your spells are mostly ignored because they are not very cool so we aren't very excited to review/approve them, but you are incredibly persistent and won't give us an excuse to graveyard it. That is generally what results in a resource being ignored for a long time.

The Spell Request Thread Done for, unless someone else wants to revive it...
It lasted a damn long time.

Please; Ask for Help Appropriately














Quote:
Originally posted by Kyrbi0
Huh. Almost makes me wish I had a girlfriend, to take advantage of today (wait, no, that's not what I meant... I mean, take advantage of the fact that it is international women's day... gah, never mind).
Quote:
Originally posted by Pyrogasm
Rome may not have been built in a day, but the Romans sure as hell didn't say "look at this great city we built guys!" when they had nothing more than a bit of stone and some cottages.
Pyrogasm is offline   Reply With Quote
Old 04-04-2007, 09:09 AM   #11
Anitarf
Procrastination Incarnate


Development Director
 
Join Date: Feb 2004
Posts: 8,190

Submissions (19)

Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)Anitarf has a brilliant future (903)

2008 Spell olympics - Fire - SilverApproved Map: Old School Alliance TacticsHero Contest #2 - 3rd PlaceSpell making session 2 winner

Default

Yeah, the problem here is that (Units within 512.00 of Aether_Start) itself creates a group. In JASS, this translates to GetUnitsInRangeOfLocAll(), which calls GetUnitsInRangeOfLocMatching(). This function creates a group, then adds units to it with the GroupEnumUnitsInRangeOfLoc() function. So, if you wanted to add units in range of a location to a group without creating new groups, this is what you would use, in your example, it would look like this:

Custom script: call GroupEnumUnitsInRangeOfLoc(udg_Aether_Targets, udg_Aether_Start, 512, null)

Of course, if you go that far, there's no reason for you to use GUI stuff like locations anymore. In JASS, most things can be done faster by using coordinates. There's more data to be passed around (two coordiantes except of one location) but there's no more need to create/destroy handles (locations).

GroupEnumUnitsInRange(udg_Aether_Targets, GetUnitX(udg_Aether_Caster), GetUnitY(udg_Aether_Caster), 512, null)
__________________
Anitarf is offline   Reply With Quote
Old 04-04-2007, 02:31 PM   #12
MaD[Lion]
MaD Da ViNci
 
MaD[Lion]'s Avatar


Respected User
 
Join Date: Apr 2003
Posts: 1,699

Submissions (10)

MaD[Lion] is a jewel in the rough (225)MaD[Lion] is a jewel in the rough (225)MaD[Lion] is a jewel in the rough (225)MaD[Lion] is a jewel in the rough (225)

Default

I think we need to inject Infrane's divine explaination of memory leak, it explained me everything by just looking! yes looking.
Attached Images
File Type: jpg memory leak.JPG (133.6 KB, 171 views)
__________________
Current Projects:
MaDOS (outdated)System for object movements & effects - NEW VERSION IS UNDER W.I.P
Cinematic SystemSystem for making better cinematics and with fancy effects
Timing SystemTiming system that simulates the usage of PolledWait just with 0.01 accuracy
MaD[Lion] is offline   Reply With Quote
Old 04-04-2007, 07:29 PM   #13
Zwan
User
 
Join Date: Apr 2003
Posts: 321

Submissions (1)

Zwan is on a distinguished road (12)

Default

Good stuff, thanks a lot guys.

I was a bit too pre-occupied with dodging creating a group out of aether_targets and I was overlooking the obvious on my units in range action.

I really should have caught that, but Im glad I asked about it.
Zwan is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 04:06 PM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services