• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Limiting unit groups

Status
Not open for further replies.
Level 19
Joined
Jan 22, 2011
Messages
3,968
I want a unit group to only contain 1 unit (the first unit the trigger can find that matches the conditions that unit has to have in order to be part of the group). Sounds complicated? let me explain.
I have a spell that searches for the closest enemy hero and deals damage to it. It doesn't matter how far he is, but he must be the closests to the caster. In order to do so I used a group using range (because I am assuming that if I use region it just picks all units in that region at once, and not just only one by one).
I set the group as a variable so I can delete it later using custom scripts to avoid leaks. But I don't know how to make the group only contain one unit. Any ideas? All help will be appreciated.
Sincerely, Paillan
 
Level 12
Joined
Jan 2, 2016
Messages
973
If you have a unit variable "Temp_Unit", and your Group is "Temp_Group" your code will look like:
  • -------- some stuff ---------
  • Custom script: set udg_Temp_Unit = FirstOfGroup(udg_Temp_Group)
  • Unit Group - Remove all units from Temp_Group
  • Unit Group - Add Unit Temp_Unit to Temp_Group
  • Unit - //do stuff you want to Temp_Unit
  • -------- more stuff ---------
After this, your unit group will contain only this one unit, and you wouldn't need FirstOfGroup anymore, unless you re-set the unit group.
 
A group which contains only 1 unit is basicly not needed.
A unit variable does better.

You only need a group to iterate though units in range. (you should maybe set a maximum range)
And you compare the distance from picked unit to your caster.
If the distance is shorter you save it in a variable, and also save the unit in a variable.
if the distance is higher than the current distance variable then you simply ignore.

After the unit group loop you should have two variables that you can use.
A unit (clostest unt) variable and a real (distance) variable.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
There is a jass function called FirstOfGroup() which, as the name suggest selects the first unit that was added into the group.

last* unit that was added to the group... if only it was the first, FoG would be so much better -_-
The name FirstOfGroup simply refers to the first in the list of the group.

But as IcemanBo explained, you still have to check which unit is the closest.

So simply said: (trigger)
- Set closestUnit = No unit.
- Set closestRange = (inf)
- Loop
---- Set range is distance between picked unit and caster
---- If range is lower than closestRange
------- Set closestRange = range
------- Set closestUnit = picked unit

Picked unit will be the closest unit of the group...
However, I already know who that will be... the caster himself, cause he is the closest to himself :D
You should make a condition before the range check if the unit is actually allowed to be the one you search for... in this case, a check if the picked unit is an enemy and is a hero.

However, it is not really good to pick all units in the entire map (cause this spell is global) and check for only... 6, 7, 8 heroes?
Instead, you should keep a list of all heroes in the game (can be a group as well).
Looping through that group and doing the same checks for the range will be better because you will still check if it is an enemy hero, but you will not do that check for all normal units.
 
Level 19
Joined
Jan 22, 2011
Messages
3,968
last* unit that was added to the group... if only it was the first, FoG would be so much better -_-
The name FirstOfGroup simply refers to the first in the list of the group.

But as IcemanBo explained, you still have to check which unit is the closest.

So simply said: (trigger)
- Set closestUnit = No unit.
- Set closestRange = (inf)
- Loop
---- Set range is distance between picked unit and caster
---- If range is lower than closestRange
------- Set closestRange = range
------- Set closestUnit = picked unit

Picked unit will be the closest unit of the group...
However, I already know who that will be... the caster himself, cause he is the closest to himself :D
You should make a condition before the range check if the unit is actually allowed to be the one you search for... in this case, a check if the picked unit is an enemy and is a hero.

However, it is not really good to pick all units in the entire map (cause this spell is global) and check for only... 6, 7, 8 heroes?
Instead, you should keep a list of all heroes in the game (can be a group as well).
Looping through that group and doing the same checks for the range will be better because you will still check if it is an enemy hero, but you will not do that check for all normal units.

so first of group does not work... It's no problem, I can pick unit's that are only heroes, I already have the matching condition, and of course it ignores the caster.
I will try to make use of the range system, thank you.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
FirstOfGroup() is simply a function that returns the last added unit... I assume it can be useful for some stuff, but the only thing I use it for is FirstOfGroup iterations.
It is just a nicer and more efficient way to loop through a unit group.

However, you dont want to pick the last added unit, you want to pick a unit that is the closest to a specific unit... so you have to at least check every unit that is a candidate for that.

"I already have the matching condition"
You mean one inside "Pick all units in map matching ..."?
In that case, no, you still pick ALL units, then check each one individually if they follow that matching condition.
So that is still not what I meant.
But if you have a list of all the heroes, then it is simple indeed.

@Chaosy,
You still check a million times... if you at least have a million units :D
And in that way, you still do not know if your unit is actually the unit you want.
There may be a unit that comes after you set the integer to 1, that is closer than the unit you already have.
 
Status
Not open for further replies.
Top