1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. The poll for our 11th Music Contest is up! Help us choose the most awesome cinematic tracks by casting a vote!
    Dismiss Notice
  3. Melee Mapping contest #3 - Poll is up! Vote for the best 4v4 melee maps!
    Dismiss Notice
  4. The 30th edition of the Modeling Contest is finally up! The Portable Buildings need your attention, so come along and have a blast!
    Dismiss Notice
  5. The Aftermath has been revealed for the 19th Terraining Contest! Be sure to check out the Results and see what came out of it.
    Dismiss Notice

Unit Within Range 1.5

Submitted by Tasyen
This bundle is marked as approved. It works and satisfies the submission rules.
This is an system which allows to detect when an unit comes in x range to another unit and gives access to range / entering / entered unit.
One can register multiple ranges onto 1 unit but each range can only be registered on each unit once at the same time.


How this script works?

You register an unit with an range.
Each time you do this, a Trigger will be created which will throw an event as soon an unit come within the registered range.
This Trigger allows to access registered Range and Unit.
The used trigger will be destroyed automatically, if the unit is removed / replaced / killed, when one wants that (default when using the GUI registering actions).
One now creates an Trigger which catches the WithinRangeEvent = 1.
Now use the variables described below.

How to install?

Make sure variables are auto generated
Copy the WithinRange Folder
Checkout the Demo folder you might use something from it.

Variable Description
WithinRangeEvent The thrown Event:
+1 = entered range;
-1 = Autoderegister on killed/removed/replaced
WithinRangeUnit The registered unit to which an unit is nearing
WithinRangeEnteringUnit The unit entering the range
WithinRangeRange The registered range of the current Event
WithinRangeUsers A Group containing all units using Range detection generated by this system.
WithinRangeWanted_Filter Used when evoking UnitWithinRange, a Filter can only access the entering Unit with Triggering Unit
A Filter allows you to prevent unwanted Event Throws.
resetValue = no Filter
WithinRangeWanted_Trigger This Trigger will be executed, when an unit enters (it checks conditions)
resetValue = no Trigger
WithinRangeWanted_Event defines the event thrown, when an uniter enters.
(0 won't throw an event)
resetValue = "constant function UnitWithinRangeDefaultEvent", default 1.0
WithinRangeWanted_Keep when set the Wanted_ variables won't reset when evoking UnitWithinRange


Code (vJASS):

   function RegisterUnitWithinRangeEvent takes unit u, real range, code filter, real eventValue returns boolean
       - more simple usage of super: no trigger, destroyFilterWhenDone=true, cleanOnKilled = true
   function RegisterUnitWithinRangeTrigger takes unit u, real range, code filter, trigger execution returns boolean
       - more simple usage of super: no Event Thrown, destroyFilterWhenDone=true, cleanOnKilled = true
   function RegisterUnitWithinRangeSuper takes unit u, real range, boolean cleanOnKilled, boolexpr filter, trigger execution, real eventValue, boolean destroyFilterWhenDone returns boolean
       - inside the filter you can only access the entering Unit with GetTriggerUnit()
       - Start the detection for this Unit with this range
       - can not register twice the same range (main number 800.0 and 800.1 are now allowed) onto 1 unit.
       - cleanOnKilled will generate an trigger which will execute DeRegisterUnitWithinRangeUnit as soon the unit dies.
       - cleanOnKilled creates 1 Trigger for each Unit registered.
   function RegisterUnitWithinRangeEx takes unit u, real range, boolean cleanOnKilled, boolexpr filter returns boolean
       -backwards comptatible, wrapper for super
   function RegisterUnitWithinRange takes unit u, real range, boolean cleanOnKilled returns boolean
       -backwards comptatible, wrapper for super

   function DeRegisterUnitWithinRange takes unit u, real range returns boolean
       Destroys the range detection with this specific Range and Unit.

   function DeRegisterUnitWithinRangeUnit takes unit u returns boolean
       Destroys all Triggers used by the unit from UnitWithinRange.
 




This System can be used without writing Jass.
  • Register
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • -------- Autoregister on start --------
      • Set WithinRangeRange = x //0 or below is not allowed
      • Set WithinRangeUnit = your Unit
      • -------- Optional --------
      • Set WithinRangeWanted_Filter = ((Max. Mana of (Triggering unit)) greater as 0.00) //You can only access the entering unit with Triggering Unit, The Filter will prevent unwanted event Throws.
      • Set WithinRangeWanted_Event = y //0 won't throw an event.
      • Set WithinRangeWanted_Trigger = your Trigger
      • Set WithinRangeWanted_Keep = False/True //Wanted_ variables will reset each time you evoke WithinRange; Except when setting "Wanted_keep" = true.
      • Trigger - Run WithinRange <gen> (ignoring conditions)

  • DeRegister
    • Events
    • Conditions
    • Actions
      • Set WithinRangeRange = x //with 0 you remove all ranges from this unit
      • Set WithinRangeUnit = your unit
      • Trigger - Run WithinRange__DeRegister (ignoring conditions)


Credits

Dr Super Good





Version Changes
1.5 One can now choose the EventValue thrown, or to not throw an event.
One can now choose a trigger beeing executed (includs checking conditions) when a unit enters
GUI can now use the Filters.
Destroys the given Filters, as soon the triggers is deregistered, except you evoked "function RegisterUnitWithinRangeSuper" directly and choosed otherwise.

1.4 Hashes triggers <-> unit now with registered Range

-> better remove/registering
-> one can not register 2 ranges with the same main number (onto the same unit) anymore (800.2 & 800.1)

Now one can setup an BoolExpr Filter, to prevent unwanted events (not supported in GUI)
moved the GUI Wrappers into the main Code.
1.3d auto clean now at <= 0.405
1.3c Removes now the last TriggerHandle when reindexing.
1.3b Removes now TriggerHandle from the table when removeing single Ranges.
replaced an unneeded table read with an local variable
1.3a removed outcommented code
Added gui wrapper Triggers for "Deregister x" and "Deregister all"
This Triggers are in the optional wrapper folder
Previews
Contents

RegisterUnitWithinRange 1.5 (Map)

Reviews
IcemanBo
I'm not sure I mentioned it, but changes seem to be made. Can you change: call TriggerRegisterUnitStateEvent(trig, u, UNIT_STATE_LIFE, LESS_THAN, 0.4) to call TriggerRegisterUnitStateEvent(trig, u, UNIT_STATE_LIFE, LESS_THAN_OR_EQUAL, 0.405 Anyways,...
  1. Daffa the Mage

    Daffa the Mage

    Map Moderator

    Joined:
    Jan 30, 2013
    Messages:
    7,294
    Resources:
    22
    Packs:
    1
    Maps:
    8
    Spells:
    12
    Tutorials:
    1
    Resources:
    22
    Nice, about time we got more of the useful events.
     
  2. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    241
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    Unfortunately this system fails to detect units that are revived while inside a range. So you will need detect ressurection (unit indexer) and move the unit somewhere and then move it back to it's position. But it does detect units that are created (enter playable map area).

    Anyway, this is a useful, simple system that is very modular. Would be nice if you made a GUI api for it, too, since dynamic triggers are out of reach of GUI.
     
  3. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    976
    Resources:
    10
    Tools:
    2
    Maps:
    2
    Spells:
    5
    Tutorials:
    1
    Resources:
    10
    In my testings units revived with resurrection / Revie-hero - trigger action, both were detected again.
    what revive you used?

    Yes dynamic triggers are, but the triggers needed for this systems are generated by the system itself when registering an unit.

    You mean i should give all of this 3 Jass API functions an GUI wrapper?
    I can do that.​
     
  4. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    241
    Resources:
    3
    Spells:
    2
    Tutorials:
    1
    Resources:
    3
    They were? I was pretty sure that's not how it worked, but Blizzard might've changed it with the recent patches :S I ran into this problem when I was making my Aura System.
    I only assumed from the code, I'll check it out in-game then xD

    Yeah, I mean, they can be used with GUI now, but people would need to use custom scripts. It would be nice to have a GUI way to do it, like:
    Global Variable: Unit
    Global Variable: Range
    Run trigger: Register Unit

    So basically a GUI wrapper trigger that takes the global variables as "parameters". You know the drill ^_^
     
  5. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    976
    Resources:
    10
    Tools:
    2
    Maps:
    2
    Spells:
    5
    Tutorials:
    1
    Resources:
    10
    Updated v1.3a.
     
  6. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,846
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    call TriggerRegisterUnitStateEvent(trig, u, UNIT_STATE_LIFE, LESS_THAN, 0.5)

    why not directly using a death event ? it's more accurate and straight forward for death
    call TriggerRegisterUnitEvent(trig, u, EVENT_UNIT_DEATH )


    Code (vJASS):

                    set trig =  LoadTriggerHandle(udg_WithinRangeHash, unitId, size)
                    call SaveTriggerHandle(udg_WithinRangeHash,unitId,LoopA, trig )

    ^The trigger handle should be removed from hashtable. Same here:
    call DestroyUnitWhithinTrigger(LoadTriggerHandle(udg_WithinRangeHash,unitId,-1))


    Code (vJASS):

                //if the last trigger was removed, remove it from users.
                if LoadInteger(udg_WithinRangeHash,unitId,0) == 0 then

    (can be) ->
    Code (vJASS):

                //if the last trigger was removed, remove it from users.
                if size == 1 then


    The work you do with tracking TriggerActions is correct, but not required. A trigger's action will be properly destroyed when a trigger got destroyed, too.

    It has a bit potential to do a bit less coding if you decide to create one trigger which will fire for any unit death, and there checks are done for potential trigger-decoupling, and to fire events -- instead of caring for unit specific triggers and their size counter. Neither is right, or wrong, but it maybe can simplify it a bit.

    The documentation is missing the
    -1
    event.

    Might it be useful to provide "A unit leaves range of unit" functionality? Like when a unit is in range of a unit, and then gets out of range at some time, hmm..
     
  7. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    976
    Resources:
    10
    Tools:
    2
    Maps:
    2
    Spells:
    5
    Tutorials:
    1
    Resources:
    10
    I use lifestate changer state to catch Remove & Replace & Killed. The death Event would only catch killed.
    Guess will use 0.4 then.

    Sometime ago I read some post on hive which said the opposite :|, that's why i did that.
    In dat table ConditionalTriggerExecute vs TriggerEvaluate.
    Hmm, sounds like i should use conditions instead of actions, fine.

    That is a good idea.
    Hmm, it would need an timer -> ask for an further feature: intervallic events while in range.

    Ah i see thanks.

    You mean i should use this ones?
    Code (vJASS):

    call RemoveSavedHandle(udg_WithinRangeHash, unitId, LoopA)
    call RemoveSavedHandle(udg_WithinRangeHash, unitId, -1)
     
     
    Last edited: Sep 27, 2017
  8. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,846
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I write later, but just wanted to say quickly that I'm not sure anymore that a "leaving event" is a good idea.
     
  9. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,692
    Resources:
    0
    Resources:
    0
    The script attaches data to the unit using the range, the current setup of linear searching (O(n) worst-case IIRC) might cause the thread to exceed the thread limit op (I'm not sure?). Maybe you could generate hashkeys using
    StringHash(RealToInt typecast)
    and directly access a targeted range to speed the search a bit?

    My jass is rusty so I'm sorry in advance if I missed stuff or was wrong.
     
  10. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,846
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    [continued ...]

    For leaving event we would periodicly enumerate and keep track of all in-range units, to recognize when they're out of range.
    And the philisophy for most use cases is probably different; I can't think of a scenario where:
    1. trigger registration + requirement of data structure to hold units
    -- is better than:
    2. a) direct distance check between 2 specified units
    or
    2. b) using a temp group enumeration directly

    1. seems always like a workaround, less efficient, and less performant. Not sure there is a useful case in jass for this, which has more pros than cons. (maybe you know one)

    Okay, legit answer. Hm.. but I'm not really happy with this, too. It's also somehow less accurate. But not very sure you should use a periodic check for it/or require deinex event "just" for this.

    Good you don't believe every bullshit you read, thanks. You're correct of course. Seems I had something with periodic check in mind or just wrote shit.

    Yeh, because the entries are only flushed when a unit is completly unregistered at the moment, though it should also remove single entries when a single registration is unregistered.

    It's not wrong, I think it's a smart thinking. But dunno if a unit is registered so often practically that typecast + hashload + stringhash will be very superior for most cases. I guess both is okay here.
     
    Last edited: Oct 15, 2017
  11. chobibo

    chobibo

    Joined:
    Sep 24, 2005
    Messages:
    2,692
    Resources:
    0
    Resources:
    0
    I was wrong when I typed
    RealToInt
    . I really meant
    RealToString
    . Sorry hehe :D
     
  12. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    5,846
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I'm not sure I mentioned it, but changes seem to be made.

    Can you change:
    call TriggerRegisterUnitStateEvent(trig, u, UNIT_STATE_LIFE, LESS_THAN, 0.4)

    to
    call TriggerRegisterUnitStateEvent(trig, u, UNIT_STATE_LIFE, LESS_THAN_OR_EQUAL, 0.405


    Anyways, we can approve it already. It's useful. : )
     
  13. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    976
    Resources:
    10
    Tools:
    2
    Maps:
    2
    Spells:
    5
    Tutorials:
    1
    Resources:
    10
    Autoclean now at "LESS_THAN_OR_EQUAL, 0.405".
     
  14. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    976
    Resources:
    10
    Tools:
    2
    Maps:
    2
    Spells:
    5
    Tutorials:
    1
    Resources:
    10
    Updated to V1.4
     
  15. Devalut

    Devalut

    Joined:
    Feb 9, 2009
    Messages:
    440
    Resources:
    0
    Resources:
    0
    Is it possible to detect specifically dead units?
     
  16. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    976
    Resources:
    10
    Tools:
    2
    Maps:
    2
    Spells:
    5
    Tutorials:
    1
    Resources:
    10
    No, this System uses the warcraft 3 built in "unit comes in range event", which excludes dead units on default.

    Edit: But I could upload an alternative version based on timers allowing such a behaviour.
     
    Last edited: Feb 3, 2018
  17. Devalut

    Devalut

    Joined:
    Feb 9, 2009
    Messages:
    440
    Resources:
    0
    Resources:
    0
    I will make no demands, but I would be interested none the less!