| 03-09-2010, 11:25 AM | #1 |
I am doing a very advanced filter system right now. You can connect the different filter types with ands / ors and have a very high functionality, without making anything to complicated. Some of its features:
JASS:library CustomFilterExamples initializer all requires CustomFilter, CFLib, CFEnum //: ------------------------------------------------------------------------ //: Lets do some basic stuff at first. private function e1 takes nothing returns nothing //: Create a new group local group g = CreateGroup() //: and lets use the alive filter call FILTER_UNIT_ALIVE.apply() //: and now lets enumerate units into the group. call GroupEnumUnitsInRange(g, 0., 0., 512., UNIT_FILTER) //: Lets do a little check if we picked any unit call BJDebugMsg("We picked " + I2S(CountUnitsInGroup(g)) + " units!") endfunction //: ------------------------------------------------------------------------ //: Lets do something more advanced. We pick all units that are non-heroes //: and print them. private function e2_Print takes nothing returns nothing //: Notice how we can access to the global variable //: FILTER_UNIT at any place! call BJDebugMsg(GetUnitName(FILTER_UNIT)) endfunction private function e2 takes nothing returns nothing local group g = CreateGroup() call FILTER_UNIT_NOT_HERO.apply() //: We actually need to link the enum with function //: Do this AFTER applying the filter! call setOnUnitEnum(e2_Print) call GroupEnumUnitsInRange(g, 0., 0., 512., UNIT_FILTER) endfunction //: ------------------------------------------------------------------------ //: Lets do some advanced filtering this time. //: Who wants all units to be filtered, everytime? //: To face it, we want only 10 units that are not undead. private function e3 takes nothing returns nothing local group g = CreateGroup() //: Notice how we can connect filters inside each other! local LimitedFilter lf = LimitedFilter.create(FILTER_UNIT_NOT_UNDEAD, 10) call lf.apply() call GroupEnumUnitsInRange(g, 0., 0., 512., UNIT_FILTER) call lf.destroy() //: Lets do a little check if we picked any unit call BJDebugMsg("We picked " + I2S(CountUnitsInGroup(g)) + " units!") endfunction //: ------------------------------------------------------------------------ //: We still haven't concatigated conditions yet. //: This time, we want to have an unit that is either dead or alive and //: not an hero private function e4 takes nothing returns nothing local group g = CreateGroup() //: Notice how we can connect this two filters //: with an AND connector. local AndFilter ad = AndFilter.create(FILTER_UNIT_ALIVE, FILTER_UNIT_HERO, false) //: Notice how we can now connect 2 filters //: of different types with this or filter local OrFilter of = OrFilter.create(FILTER_UNIT_DEAD, ad) call of.apply() call GroupEnumUnitsInRange(g, 0., 0., 512., UNIT_FILTER) call of.destroy() call ad.destroy() //: Lets do a little check if we picked any unit call BJDebugMsg("We picked " + I2S(CountUnitsInGroup(g)) + " units!") endfunction //: ------------------------------------------------------------------------ //: Now we want to do something more advanced. //: This time we want to have a filter for all units of a spell. //: The filter is for disentigrate from Diablo III, so we use the CFEnum //: library to get new, great enumeration functions. //: For this spell we want to have alive units only, that are enemies. globals private constant real DISINTEGRATE_RANGE = 128. endglobals private struct e5struct private unit caster = null private real x1 = 0. private real y1 = 0. private real x2 = 0. private real y2 = 0. private method dmg takes nothing returns nothing local real lastHp = GetUnitState(FILTER_UNIT, UNIT_STATE_LIFE) local real newHp = lastHp - 25. call SetUnitState(FILTER_UNIT, newHp) endmethod //: This is the method that is run every few ms. private method e5 takes nothing returns nothing local group g = CreateGroup() //: Create a new allyfilter local AllyFilter af = AllyFilter.create(GetOwningPlayer(.caster), false) //: Create a new andfilter and connect it with ally and alivefilter local AndFilter andf = AndFilter.create(af, FILTER_UNIT_ALIVE, false) call andf.apply() //: Notice how we again connect enumeration with method calls. call setOnUnitEnum(.dmg) //: Function of the CFLib call EnumUnitsInRangeOfLine(g, .x1, .y1, .x2, .y2, DISINTEGRATE_RANGE) call andf.destroy() call af.destroy() endmethod endstruct //: ------------------------------------------------------------------------ //: Lets use our own condition functions. private function e6_Print takes nothing returns nothing //: Notice how we can access to the global variable //: FILTER_UNIT at any place! call BJDebugMsg(GetUnitName(FILTER_UNIT)) endfunction private function e6_Cond takes nothing returns boolean return GetUnitState(FILTER_UNIT, UNIT_STATE_LIFE) >= 100. endfunction private function e6 takes nothing returns nothing local group g = CreateGroup() //: Lets filter all units (TRUE_FILTER) that match our condition local CondFilter cf = UnitCondFilter.create(TRUE_FILTER, e6_Cond, false) call cf.apply() //: Notice how we again connect enumeration with method calls. call setOnUnitEnum(e6_Print) call GroupEnumUnitsInRange(g, 0., 0., 512., UNIT_FILTER) call cf.destroy() //: Thats it. Was is that hard? endfunction //: ------------------------------------------------------------------------ //: Now you know about a lot of functionality of this system. //: Thanks for downloading and using. //: ------------------------------------------------------------------------ private function all takes nothing returns nothing call e1() //call e2() //call e3() //call e4() //call e5struct.create().e5() //call e6() endfunction endlibrary CF_UP_v.0.0.1.w3x Edit: Sorry for removing the library, I am currently completely remaking it! |
| 03-09-2010, 05:16 PM | #2 |
The idea is pretty nice. It would be nice to have a standardized script that allows similar target-checking fields (and functionality) as WarCraft III's object editor provides. |
| 03-09-2010, 06:30 PM | #3 | |
Updated first post with an early wip. Please check it. Edit: Some advantages: Quote:
Edit2: The testmap now enumerates 2 random living units by player 1 and kills them! :D have fun! (One will stay alive) |
| 03-10-2010, 01:11 AM | #4 |
Does this support 3+ filters? =D (Have 3 different filters for an enumeration) |
| 03-10-2010, 04:03 AM | #5 |
Does this run a boolexpr for each filter, or are they all combined into one? |
| 03-10-2010, 08:13 AM | #6 | ||
Quote:
(You can also connect and, or, nand and nor filters with another one! So unlimited tree of filters possible!) Example (This uses 2 unittype filters and one limit filter): JASS:// Enumerate alive units that are non-heroes please! local AndFilter af = AndFilter.create(FILTER_UNIT_ALIVE, FILTER_UNIT_NOT_HERO, false) // Don't exceed the limit of 2. local LimitedFilter lf = LimitedFilter.create(af, 2) call lf.apply() //Do enumeration lf.destroy() af.destroy() Quote:
Edit: I have decided to make an enumeration utils for this. So this will soon have for example Line Enumeration functions. Thanks for the input. |
| 03-10-2010, 12:24 PM | #7 |
I really don't see how this is better than just writing your own custom filter functions. |
| 03-10-2010, 12:38 PM | #8 | |
Quote:
Also I updated examples. Now you can easily remake disintegrate with new enumeration functions. Also, this does only need 4 boolexpr vars, no matter how many Enums and filters you have. |
| 03-10-2010, 11:28 PM | #9 | |||||||||
I still don't see how this is better than just writing your own custom filter functions. Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
|
| 03-11-2010, 12:07 AM | #10 | |
Quote:
Nope, you'll hit an OP limit at some point or another. This system BYPASSES that, that's just how good it is. |
| 03-11-2010, 01:01 AM | #11 |
Systems who's sole purpose is soft coding on the level of this library are the devil. Libraries are supposed to make writing code easier, or cleaner, or faster, or better. When you generalize a solution, you are attempting to expand the domain of problems that it solves; Which is all well and good. Of course, systems like this are an example of taking it too far, to the point of the inner platform effect. You end up with a less functional clone of the platform the library was designed with, while maintaining a similar, or worse level of end-user complexity. In JASS, there is also the concern of execution speed, as it's a really slow language. Truly, it is libraries like this that need to be burned in a lake of boiling liquid sulfur, not put in to general use. As an aside, let me point to another inner-platform we are all familiar with: The trigger editing GUI. Remember that next time you think about coding an all-encompassing soft-coding system. The concept of DRY (Don't Repeat Yourself) is a good one at it's core. Try to minimize repetition to ease development and maintenance. However, when you attempt to abstract to the point of a general solution, you're trying too hard. One's attempts at reducing repetition should be focused on specific instances of repetition, and trying to consolidate them. Attempting to consolidate 20 different things all in to one, without assessing if they should actually be consolidated, inevitably leads to the aforementioned inner-platform effect. |
| 03-11-2010, 01:35 AM | #12 |
Every word in EF's post is gold. People here should start doing more WC3 maps & mods instead of systems "for the lulz", expecting to have the luck of catching a programming need. I'll save this post because it's really useful. |
| 03-11-2010, 07:36 AM | #13 | ||||||||||||||||||
|
| 03-11-2010, 09:47 AM | #14 | |||||||||||||||||
|
| 03-29-2010, 08:10 AM | #15 |
If you checked the examples, how can you still say that this system is bad? It's fast, efficient and has a lot of new functionality. It even provides new features that makes life easier. |
