• 🏆 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!

[General] Detect number of units within range

Status
Not open for further replies.
Level 17
Joined
Jun 2, 2009
Messages
1,112
Hello everyone. My name is Volkan. I am the guy who creates maps for his friends. Age 36 and still i am active player. I am rarely requesting help when it comes to the World Editor.

Here is the scenario. You have an AI player which have 1 Hero. AI player and several units attacking enemy tower. When 5 of the units have died (1 ai hero and 2 units left) ai hero have to fall back. Somehow i cannot pass to action. Here is my last attempt. I have tried to simplify the code for the testing purpose.

Kac Kule ai Copy
Code:
Kac Kule ai Copy
    Events
        Unit - A unit Is attacked
    Conditions
        And - All (Conditions) are true
            Conditions
                (Attacking unit) Equal to Guard Tower 0013 <gen>
                ((Attacked unit) is A Hero) Equal to False
                (Number of units in (Units within 800.00 of (Position of Guard Tower 0013 <gen>) matching ((((Matching unit) belongs to an enemy of (Owner of (Attacking unit))) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((Number of units in (Units within 800.00 of (Position of (Attacking Unit)))) Less than or Equal to 2
    Actions
        Unit - Order ai1hero to Move To (Center of Region 001 <gen>)
        Unit - Order ai2hero to Move To (Center of Region 001 <gen>)
        Unit - Order ai3hero to Move To (Center of Region 001 <gen>)
        Unit - Order ai4hero to Move To (Center of Region 001 <gen>)
        Unit - Order ai5hero to Move To (Center of Region 001 <gen>)
        Game - Display to (All players) for 2.00 seconds the text: (Name of (Attacking unit))
        Game - Display to (All players) for 2.00 seconds the text: (Name of (Attacked unit))
        Game - Display to (All players) for 2.00 seconds the text: (Name of (Picked unit))

How can i make it work. Since yesterday i was spending 8 full hours and honestly i don't have any idea why i cannot make it. I will be happy if someone can help me about that. I want to make them retreat when attacking tower detects 2 or less units within it's range.
 
Level 17
Joined
Jun 2, 2009
Messages
1,112
Your third condition seems weird. It checks for units within range twice.
Also, there is a maximum length to a code line, maybe your condition is too long

Yes sadly i know but no more i have no idea how to deal with it. Somehow i need to check how many enemy units are within range of the tower. I feel tired now because it is my 4'th hour for this...
 
Level 17
Joined
Jun 2, 2009
Messages
1,112
  • (Number of units in (Units within 800.00 of (Position of Tower) matching ((((Matching unit) belongs to an enemy of (Owner of (Attacking unit)).) Equal to True) and (((Matching unit) is alive) Equal to True)).)) Less than or equal to 2
that should do i guess. It leaks, but it should work

Sadly no. This is why i was requested help. Still i cannot create trigger about that.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,457
I think you would want to do something like this. Might be a bit off though:
  • Events:
    • Unit - a unit is attacked
  • Conditions:
    • (Attacking unit) Equal to Guard Tower 0013 <gen>
    • ((Attacked unit) is A Hero) Equal to False
  • Actions:
    • Set Variable TempPoint = (Position of Guard Tower 0013 <gen>)
    • Set Variable TempGroup = Units within 800.00 of TempPoint matching ((((Matching unit) belongs to an enemy of (Owner of (Attacking unit))) Equal to True) and ((((Matching unit) is alive) Equal to True)
    • Custom script: call RemoveLocation (udg_TempPoint)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Number of units in TempGroup) Less than or equal to 2
      • Then - Actions
        • Set Variable TempPoint = (Center of Region 001 <gen>)
        • Unit - Order ai1hero to Move To TempPoint
        • Unit - Order ai2hero to Move To TempPoint
        • Unit - Order ai3hero to Move To TempPoint
        • Unit - Order ai4hero to Move To TempPoint
        • Unit - Order ai5hero to Move To TempPoint
        • Custom script: call RemoveLocation (udg_TempPoint)
      • Else - Actions
    • Custom script: call DestroyGroup (udg_TempGroup)
And it would be better to store those 5 ai heroes in a Unit Group so you can take advantage of "Pick every unit in Group":
  • Unit Group - Pick every unit in AiHeroes and do (Actions)
    • Loop - Actions
      • Unit - Order (Picked unit) to Move To TempPoint
 
Last edited:
Level 20
Joined
Feb 23, 2014
Messages
1,264
Okay, so... I think I get it.

Let's say you have a Paladin and 5 Footmen attacking a tower - you want the attacking party to retreat when there's only the Paladin and 2 or less Footmen remaining, is that it? If so, there is one important question to ask here: does the Paladin have to be alive for the retreat to happen? For instance, if the tower focuses and kills the hero first, should the Footmen still retreat when there's 2 or less of them left?

---

Anyway, there are a couple of problems here. For starters, the condition you posted is a mess... I'm sorry, but I really cannot understand the logic behind it. If I understood you incorrectly, please explain to me step by step what you want to happen, because I honestly don't have any other ideas.

Furthermore, one of your conditions states that the attacked unit cannot be a hero. This means that if the tower attacks the hero the whole time, the trigger will never fire, no matter how many Footmen there are in range. This can lead to a situation where your tower kills Footmen until there are only 2 left, but then starts attacking the hero, resulting in the attacking party not retreating despite meeting the intended retreat conditions, because the "attacked unit isn't a hero" condition not being met.

Moreover, the Hero also counts as a unit, so if you had a unit group with 1 hero and 2 regular units, counting them would return 3, not 2.

And some more general tips:

1. If you have a conditon block containing <condition1>, <condition2>, <condition3> etc. and you want it to pass when all conditions are true, you don't need to use an "And" block, because the condition block by itself is set to only pass if all conditions are true. The "And" block is useful in "condition trees", for instance - if you wanted to do something like this: "if <condition1> or (<condition2> and <condition3>)", i.e. either condition1 is true or both condition2 and condition3 are true.

2. You're not clearing leaks, which in this case is actually pretty huge - each time your version of the trigger fired it leaked 2 points and 2 unit groups just by checking the conditions with the potential for more if the conditions were met. And since that trigger will fire every time any unit is attacked ever, you're going to be generating hundreds if not thousands of leaks and it can eventually add up and cause issues.

3. It's preferrable to use (Triggering Unit), i.e. a unit that did or had something done to it that caused the trigger to fire, where possible and in the case of a trigger with an event "A unit is attacked", the unit that is being attacked is the (Triggering Unit), hence there's no point using (Attacked Unit).

---

If I understood you correctly, your trigger should look like this - assuming that the hero has to be alive:

  • Events
    • Unit - A unit Is attacked
  • Conditions
    • (Attacking unit) Equal to <Your Tower>
  • Actions
    • Set TempBoolean = False
    • Set TempPoint = (Position of <Your Tower>)
    • Set TempGroup = (Units within 800.00 of TempPoint matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of (Attacking unit))) Equal to True)))
    • Custom script: call RemoveLocation(udg_TempPoint)
    • Unit Group - Pick every unit in TempGroup and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • ((Picked unit) is A Hero) Equal to True
          • Then - Actions
            • Set TempBoolean = True
          • Else - Actions
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Number of units in TempGroup) Less than or equal to 3
        • TempBoolean Equal to True
      • Then - Actions
        • Set TempPoint = (Center of <Retreat Region>)
        • Unit Group - Pick every unit in TempGroup and do (Actions)
          • Loop - Actions
            • Unit - Order (Picked unit) to Move To TempPoint
        • Custom script: call RemoveLocation(udg_TempPoint)
      • Else - Actions
    • Custom script: call DestroyGroup(udg_TempGroup)
If you want any other scenario such as this trigger also working for 2+ heroes or the hero not having to be alive for the retreat to happen, let me know. That said, if I understood you correctly then this does exactly what you want, i.e. orders the attacking party to retreat if a) the hero is still alive and b) 2 or less regular units are alive.

--- EDIT:

So I think I actually misundestood - you don't want the whole attacking party to retreat, but just the hero, right? In that case the trigger would look like this:

  • Events
    • Unit - A unit Is attacked
  • Conditions
    • (Attacking unit) Equal to <Your Tower>
  • Actions
    • Set TempPoint = (Position of <Your Tower>)
    • Set TempGroup = (Units within 800.00 of TempPoint matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of (Attacking unit))) Equal to True)))
    • Custom script: call RemoveLocation(udg_TempPoint)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • (Number of units in TempGroup) Less than or equal to 3
      • Then - Actions
        • Set TempPoint = (Center of <Retreat Region>)
        • Unit Group - Pick every unit in TempGroup and do (Actions)
          • Loop - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • ((Picked unit) is A Hero) Equal to True
              • Then - Actions
                • Unit - Order (Picked unit) to Move To TempPoint
              • Else - Actions
        • Custom script: call RemoveLocation(udg_TempPoint)
      • Else - Actions
    • Custom script: call DestroyGroup(udg_TempGroup)
Disclaimer: this will only tell the attacking hero to retreat - you used many hero variables, but also said that you want the "AI hero to fall back" (implying a single hero), so it made more sense for me to go for something like this. If that was a mistake and you need help modifying the trigger, let me know.
 
Last edited:
Level 17
Joined
Jun 2, 2009
Messages
1,112
I think you would want to do something like this. Might be a bit off though:

First of all, thank you for your interest. Yes you understand correctly. I have a moba map since 2003 and i have decided to create AI for it. Here is the current looking of my trigger. Region 099 is the area that ai should fall back if there are very few creeps around them. But the funny part is, during the my first test my hero was forcing to go back the Region 099

  • Kac Kule ai Copy
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Attacking unit) Equal to Soul Tower Level 2 0035 <gen>
    • Actions
      • Set TempPoint = (Position of Soul Tower Level 2 0035 <gen>)
      • Set TempGroup = (Units within 800.00 of TempPoint matching ((((Matching unit) belongs to an enemy of (Owner of (Attacking unit))) Equal to True) and (((Matching unit) is alive) Equal to True)))
      • Custom script: call RemoveLocation (udg_TempPoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in TempGroup) Less than or equal to 3
        • Then - Actions
          • Set TempPoint = (Center of Region 099 <gen>)
          • Unit Group - Pick every unit in TempGroup and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A Hero) Equal to True
                • Then - Actions
                  • Unit - Order (Picked unit) to Move To (Center of Region 099 <gen>)
                • Else - Actions
          • Custom script: call RemoveLocation (udg_TempPoint)
        • Else - Actions
      • Custom script: call DestroyGroup (udg_TempGroup)
Yes, i believe it will gonna work. Now here it comes the worst part. I have to detect is ai running back or not. If yes, auto attack trigger should not work for them. And additionally i need to tell the AI attack with waves always etc etc. You have my thanks. Still i haven't tried it yet but i believe it will gonna work. IF i cannot solve my issues, i will gonna update the post. Thank you again my friend.
 
Level 17
Joined
Jun 2, 2009
Messages
1,112
And here it comes my "vital" question. Creating AI is far difficult than i thought.
How can i check Level of HeroRota ability for TempGroup? Before proceed to the next region, i need to tell them where they are (point value of tempgroup units, ability level of tempgroup units etc etc)

  • DevilAttackTop2Test
    • Events
      • Unit - A unit enters DUstKule2 <gen>
    • Conditions
      • (Unit-type of (Entering unit)) Equal to Footman
    • Actions
      • Set TempPoint = (Position of Guard Tower 0025 <gen>)
      • Set TempGroup = (Units within 500.00 of TempPoint matching ((((Matching unit) belongs to an ally of (Owner of (Entering unit))) Equal to True) and ((((Matching unit) is A Hero) Equal to True) and (((Percentage life of (Matching unit)) Greater than or equal to 30.00) and (((O
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of HeroRota for (Triggering unit)) Equal to 1
        • Then - Actions
          • Unit Group - Order TempGroup to Attack-Move To (Center of DUstKule2 <gen>)
          • Custom script: call RemoveLocation (udg_TempPoint)
          • Custom script: call DestroyGroup (udg_TempGroup)
        • Else - Actions
It is not a problem for this mid lane trigger. Because AI can attack directly center of the enemy hearquarters. It is straigth.

  • DevilAttackMid1
    • Events
      • Unit - A unit enters DOrtaKule3 <gen>
    • Conditions
      • (Unit-type of (Entering unit)) Equal to Footman
    • Actions
      • Set TempPoint = (Position of Guard Tower 0014 <gen>)
      • Set TempGroup = (Units within 500.00 of TempPoint matching ((((Matching unit) belongs to an ally of (Owner of (Entering unit))) Equal to True) and ((((Matching unit) is A Hero) Equal to True) and (((Percentage life of (Matching unit)) Greater than or equal to 30.00) and (((O
      • Unit Group - Order TempGroup to Attack-Move To (Position of Town Hall 0037 <gen>)
      • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call DestroyGroup (udg_TempGroup)
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,457
You mean something like this?
  • Actions
    • Unit Group - Pick every unit in TempGroup and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Level of HeroRota for (Picked unit)) Equal to 1
            • (Point-value of (Picked unit)) Equal to 100
          • Then - Actions
            • -------- do stuff --------
          • Else - Actions
Also, your first trigger (DevilAttackTop2Test) is incorrect, you want to Remove TempPoint and Destroy TempGroup below the If Then Else, not inside of it. Otherwise, if this condition isn't true:
  • (Level of HeroRota for (Triggering unit)) Equal to 1
Then the Point and Unit Group never get removed and will leak.

This also leaks a Point:
  • Unit Group - Order TempGroup to Attack-Move To (Center of DUstKule2 <gen>)
You need to set a Point variable equal to (Center of DUstKule2 <gen>) and reference that instead.

You leak in the second trigger as well:
  • Unit Group - Order TempGroup to Attack-Move To (Position of Town Hall 0037 <gen>)
Anytime you're referencing some place (center of, position of, etc) and not using the TempPoint method (Set TempPoint, Use TempPoint, Remove TempPoint) then you're creating a leak.
 
Last edited:
Status
Not open for further replies.
Top