| 01-11-2009, 10:37 AM | #1 |
When I was writing code with GroupEnumUnitsXXX natives, I found out that they require a valid group parameter. Creating temporary group every time whenever I needed to enum units was definitely messy. Otherwise, I had to use globals block to define a single private dummy group for each library. So I came up with the idea of writing a library that contains every element needed. This library greatly simplifies process to enum units. You don't have to worry about anything about groups. It also eliminates the need of creating a filter every time (or defining a global for it). Using it is extremely easy. All you need is a callback function that matches the signature. You can see it in the example below. Example Code:function MyCallback takes unit u returns nothing call BJDebugMsg(GetUnitName(u)) // print name endfunction // straightforward call EnumUnitsOfPlayer(GetTriggerPlayer(), MyCallback) Very simple, isn't it? There are two styles: .execute and .evaluate. The only difference is one line of code, but you should be aware of the differences: .execute style allows waits inside callbacks, while .evaluate style runs faster but doesn't allow waits inside callbacks. Library Code (.execute):library EnumUtils initializer init // .execute style // uses .execute for callback // safe to use waits, but a bit slower than .evaluate public function interface callback takes unit enumUnit returns nothing globals private group g private boolexpr filterEnumUnits private callback enum_cb endglobals function EnumUnitsInRange takes real x, real y, real radius, callback cb returns nothing set enum_cb = cb call GroupEnumUnitsInRange(g, x, y, radius, filterEnumUnits) endfunction function EnumUnitsInRect takes rect r, callback cb returns nothing set enum_cb = cb call GroupEnumUnitsInRect(g, r, filterEnumUnits) endfunction function EnumUnitsOfPlayer takes player whichPlayer, callback cb returns nothing set enum_cb = cb call GroupEnumUnitsOfPlayer(g, whichPlayer, filterEnumUnits) endfunction private function EnumerateUnits takes nothing returns boolean call enum_cb.execute(GetFilterUnit()) return false endfunction private function init takes nothing returns nothing set g = CreateGroup() set filterEnumUnits = Filter(function EnumerateUnits) endfunction endlibrary Library Code (.evaluate):library EnumUtils initializer init // .evaluate style // uses .evaluate for callback // you can't use waits, but a bit faster than .execute public function interface callback takes unit enumUnit returns nothing globals private group g private boolexpr filterEnumUnits private callback enum_cb endglobals function EnumUnitsInRange takes real x, real y, real radius, callback cb returns nothing set enum_cb = cb call GroupEnumUnitsInRange(g, x, y, radius, filterEnumUnits) endfunction function EnumUnitsInRect takes rect r, callback cb returns nothing set enum_cb = cb call GroupEnumUnitsInRect(g, r, filterEnumUnits) endfunction function EnumUnitsOfPlayer takes player whichPlayer, callback cb returns nothing set enum_cb = cb call GroupEnumUnitsOfPlayer(g, whichPlayer, filterEnumUnits) endfunction private function EnumerateUnits takes nothing returns boolean call enum_cb.evaluate(GetFilterUnit()) return false endfunction private function init takes nothing returns nothing set g = CreateGroup() set filterEnumUnits = Filter(function EnumerateUnits) endfunction endlibrary |
| 01-11-2009, 11:15 AM | #2 |
BJ Style? I dont see any clean up functions. Looks like units stay in group forever. |
| 01-11-2009, 11:23 AM | #3 | |
Quote:
They don't. Actually, they aren't even added to the group. Filter function EnumerateUnits always returns false no matter what the unit is, and units are added when filter function returns true. |
| 01-11-2009, 01:25 PM | #4 |
Not bad actually. The only problem is that it performs worse than doing the enums yourself. But this should simplify code for cases where you only need one small enum in rare times so that performance is not worth the code bloat. |
| 01-11-2009, 01:57 PM | #5 | |
Quote:
Just a question of curiosity. Would it be faster than BJ functions? |
| 01-11-2009, 02:07 PM | #6 |
It would probably be slower when there are a lot of units. |
| 01-11-2009, 03:14 PM | #7 | |
Quote:
Hmm... How much performance improvement do you expect if the code is changed to ".evaluate" instead of ".execute"? |
| 01-11-2009, 03:43 PM | #8 |
You use .execute? Well, the answer is 3x faster but it will still be slower than BJ functions when you have plenty of units. Actually, .execute is very useful since it will allow you to have waits, so that's more of a reason to use these functions. Perhaps have versions for .evaluate and .execute? |
| 01-11-2009, 03:56 PM | #9 | |
Quote:
That seems to be a good idea. |
| 01-11-2009, 04:56 PM | #10 |
Please do not make your functions public, but instead make them neither public nor private. The SCOPEPREFIX_ overhead makes this very painful to use. |
| 01-11-2009, 05:06 PM | #11 | |
Quote:
Okay, fixed. BTW I thought keeping function names themselves shorter would be enough, but it seemed a bit long when I saw it again. |
| 01-11-2009, 05:09 PM | #12 |
Awesome, this is very useful now. Good job. |
| 01-11-2009, 05:22 PM | #13 |
Does anyone know whether ForceEnumPlayers works without a genuine force? I just thought I could add something like EnumPlayersInForce. |
