HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Specifying the unit that is neared...

02-27-2003, 11:36 AM#1
rwxr-xr-x
I've been trying to find a way to be able to reference the unit that one would come near when you use the Event Unit - A unit comes within <range> of <unit> but haven't been able to find a way. I was wondering if anybody may know if it's possible.

The reason I ask, is because I want to put all of my logic into a single trigger while having 12 events for when a unit comes within range of 12 different units. But as is, I find no way to determine what unit was "neared", for lack of a better term, when multiple events are used (at least without throwing in some logic to determine this, but I'm trying to avoid unecessary loops and if statements if possible).
02-27-2003, 03:39 PM#2
Aiursrage2k
A unit comes with in range of unit, to get the unit that is with in range, you would use Entering unit.
02-28-2003, 07:24 AM#3
rwxr-xr-x
No, I know how to get the unit that nears the unit. I'm trying to find a way to quickly get the unit that the triggering unit came near.

Here is hopefully a better example.

EVENTS
Unit - A unit comes within 100 of CustomUnit001 <gen>
Unit - A unit comes within 100 of CustomUnit002 <gen>
ACTIONS
<actions here>

Now, I have 2 events (though my real trigger would have 12), so any of them that is met will fire the trigger. The problem is, having more than one Unit within range event, I need a way to be able to identify what unit was neared (CustomUnit001 or CustomUnit002 in the above example).

As I said in my original post, I really don't want to have to iterate through a loop and test to deteremine what unit was neared by the triggering unit. May be what I have to do, I'm just trying to cut down on the amount of logic in the trigger.
02-28-2003, 08:00 AM#4
Guest
Hmm. You could create a loop that cycles through the possible options. You would need 2 variables, getunit[index] (unit array)and myunit (unit var). Where "A" is the total number of units you have events for... Example:

Set getunit[1] = CustomUnit001
Set getunit[2] = CustomUnit002

For each integer from 1 to # of units with events, if Distance Between (Position of triggering unit) and (Position of getunit[A]) <= (specify distance) then set myunit = getunit[A] else Do Nothing

This should make the variable "myunit" equal to the unit it came near. Couple of bug with this method. 1) The way the WC3 engine determines distance is wacky. I suggest adding 40 to distance value in the For Loop to compensate. 2) If both custom units are within range, it will return the higher number. You can overcome this by adding additional if/then statements to narrow your search further (ie, owner of triggering unit == owner of getunit[A] or whatever makes the most sense)

This would be far easier to accomplish in custom text, btw...

EDIT: LOL. After I wrote that I re-read your last post where you mentioned trying to avoid a loop. Oh well.... :)
02-28-2003, 08:19 AM#5
Guest
Also...out of curiosity...why don't you just set up 12 different triggers for each of the custom units? When each trigger executes, you will know the correct unit, right?

I know you can program in JASS (saw another thread). If your concerned about size, then just do it in custom text. Just define 11 udg_ trigger variables and create the triggers in the initialization function of the first custom trigger. I've do this quite often when I want to have similar triggers and use my custom functions for them.
02-28-2003, 08:35 AM#6
rwxr-xr-x
Yeah, your post about the loop was what I was going to do since I can't find a way to get what I want. :)

I currently have 24 triggers (2 associated for each player), and 1 controlling trigger that handles some things along with turning on the corresponding 2 triggers for the right player. In the first trigger, the only code that is unique is referencing the unit that something comes near, and a region for that player. In the second trigger, the only unique code is referencing array positions. Due to this, it only makes sense to reduce these.

The overall global scheme, however, is that I'm trying to make the triggers I'm writing as easy as possible for others to modify sicne I plan on releasing them to the community. I have a trigger that does nothing but setup variables, which is where anyone modifying the behavior of them would change things. The only downside is the unit that nears, they have to be there. Using Custom Text for these triggers would end up making things a little more difficult for those not familiar with JASS, since you can't use a variable in reference to the unit in the event.

Though, I thank you for the idea on creating triggers on the fly. This may just be the saving grace. Don't know why I didn't think of that. :D
02-28-2003, 03:26 PM#7
BoddoZerg
I don't think there IS a way to get the unit being "neared". Your best option is to create multiple triggers.

I remember having this problem before when I tried to set up one trigger that would handle units entering 20 different regions. I wanted to do something different based on which region was being entered. Unfortunately there is no reliable way to tell which region has been entered.

Simply searching an array for which region contains the unit doesn't work. Apparently, the "Unit Enters Region" event fires before the unit is fully in the region.

I don't know whether this is true for the Unit gets within range of Unit event, but I wouldn't bet on a "Distance Between Units" trigger being able to detect anything.
02-28-2003, 04:19 PM#8
rwxr-xr-x
I did try with a test trigger specifying all 12 events, and then running through a loop to find out what unit was neared, and it doesn't work all the time. I think some of this may even be due to the fact that a hero could just be inside the 50 range, but walk back outside of it by the time the loop gets to him. Or worse, 2 heros near at the same time, causing even more confusion.

Unfortunately, I also tried a test in creating a trigger on the fly, and that won't work either because I can't use a variable when defining a unit on the board for the Unit within range event. ARGH!

I've decided to keep things as they are. Everything works, and isn't that big of a deal. Oh well :bgrun:
02-28-2003, 04:41 PM#9
Aiursrage2k
Revision2.1 (to not stretch the page width)
Too add a unit simply create a unit as normal, then call TriggerExecute( gg_trg_AddRangeCheck ). It requires three user generated variables: interger max, unit array u, trigger array a1.

Code:
function indexWhich  takes nothing returns integer
  local integer i = 0
  local integer rc = 0
  loop
    exitwhen i > udg_max
    if(GetTriggeringTrigger() == udg_a1[i]) then
      set rc = i
      set i = udg_max
    endif
    set i = i + 1
   endloop
   return rc
endfunction

function uiR  takes nothing returns nothing
  local integer index 
  local string ut
  set index = indexWhich()
  set ut = UnitId2StringBJ(GetUnitTypeId(udg_u[index]))
  //The unit thats it close to is udg_u[index]
  call DisplayTextToForce( GetPlayersAll(), "index: " + I2S(index))
  call DisplayTextToForce(GetPlayersAll(), "unittype: " + ut)
endfunction


function AddUnit takes nothing returns nothing
    local integer m
    set m = udg_max
    set udg_u[m] = GetLastCreatedUnit()
    set udg_a1[m] = CreateTrigger(  )
    call TriggerRegisterUnitInRangeSimple( udg_a1[m], 256, udg_u[m] )
    call TriggerAddAction( udg_a1[m], function uiR )
    set udg_max = m + 1  
endfunction

function InitTrig_AddRangeCheck takes nothing returns nothing
  set gg_trg_AddRangeCheck = CreateTrigger(  )
  call TriggerAddAction( gg_trg_AddRangeCheck, function AddUnit )
endfunction
02-28-2003, 06:09 PM#10
BoddoZerg
Quote:
Originally posted by rwxr-xr-x
I did try with a test trigger specifying all 12 events, and then running through a loop to find out what unit was neared, and it doesn't work all the time.


This happens because the trigger fires while the entering unit is "on the edge" of the region it's entering. ("Region" includes both gg_rects and "Comes Within Range" events) Based on precision or some other internal issue, sometimes a unit that fires an "Enters Region" trigger will work with "Unit is within Region", but other times it won't.
02-28-2003, 06:37 PM#11
Guest
Quote:
This happens because the trigger fires while the entering unit is "on the edge" of the region it's entering.

Hmm. Maybe if you have really little regions (like 4x4)....
02-28-2003, 07:04 PM#12
rwxr-xr-x
My test for a unit in range is 50. It's this small because I need to create the effect of entering a portal. If you're curious as to what I'm using this for, check the link in my sig. I just released v1.2 of my Diablo Town Portal triggers.

I'm in the process of modifying them though to use some of the ideas that Aiursrage2k posted. Should help to reduce the amount of code considerably.
02-28-2003, 08:50 PM#13
PitzerMike
You could try it with a unit group and a filter, this would need no global variables:

function GetNearedUnit takes nothing returns boolean
if GetUnitTypeId(GetFilterUnit()) == 'nC01' or GetUnitTypeId(GetFilterUnit()) == 'nC01' then //... for all the possible unit types, the neared unit could be
return true
endif
return false
endfunction

function Your_Trigger_Actions takes nothing returns nothing
local filterfunc YourFilter = Filter(function GetNearedUnit)
local group NearedGroup = CreateGroup()
local unit Neared
call GroupEnumUnitsInRange(NearedGroup,GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),60,YourFilte r) // radius is 60 so nothing can go wrong (if the neared units are too close to each other you will have to use 50)
set Neared = FirstOfGroup(NearedGroup)
//..........Do whatever you want with the Neared unit..............
endfunction

This will only work if the neared units are far enough from each other so the ranges won't overlap
Specifying the unit that is neared... - Wc3C.net