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

[Trigger] issue order attack unit's get stuck

Status
Not open for further replies.
Level 12
Joined
Nov 3, 2013
Messages
989
Why isn't this working? The units get stuck repeadely issuing "attack target" order, but that should only happen if there's a unit with less HP. And obviously there can't be more than one unit with the least. (There can be a tie, but that just means the first one picked becomes the attack target.)
  • attack nearby lowest health
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Owner of (Attacking unit)) Not equal to (Triggering player)
    • Actions
      • Set tempUnit = (Triggering unit)
      • Set tempPoint = (Position of (Attacking unit))
      • Set tempReal = (Life of tempUnit)
      • Unit Group - Pick every unit in (Units within 85.00 of tempPoint matching (((Matching unit) belongs to an enemy of (Owner of (Attacking unit))) Equal to True)) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Life of (Picked unit)) Less than tempReal
            • Then - Actions
              • Set tempUnit = (Picked unit)
              • Set tempReal = (Life of tempUnit)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_tempPoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering unit) Not equal to tempUnit
        • Then - Actions
          • Unit - Order (Attacking unit) to Attack tempUnit
        • Else - Actions
I just wanted units to focus on units with lower health, without running across half the map first (like the AI)...
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
"(Triggering unit) Not equal to tempUnit"
replace triggering unit with tempUnit

If I'm correct, it's because a unit group creates a new function, thus triggering unit wont work since you're in a new function.
(don't bother to understand if you don't know jass)

edit: wops you can't do that. You'll have to use two variables, one for picked unit and one for triggering unit. The triggering unit needs to be saved above the unit group.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
The new function still operates during the event's execution.
(Triggering unit), (Attacking unit) and (Triggering player) should still work fine.

Your best shot is to test the code in different scenarios and use debug messages.
One message can be just after the issue order action telling you (name of attacking unit) + " is now attacking " + (name of tempUnit)

Useful testscenarios can be a 1vs1 fight of units. (if there are no other units, will it work?)
Or 1vs3 attempting to attack a unit with higher health.

(You might also want to change the health thingy into percentage of health... but that is just something else.)
 
Level 12
Joined
Nov 3, 2013
Messages
989
"(Triggering unit) Not equal to tempUnit"
replace triggering unit with tempUnit

If I'm correct, it's because a unit group creates a new function, thus triggering unit wont work since you're in a new function.
(don't bother to understand if you don't know jass)

edit: wops you can't do that. You'll have to use two variables, one for picked unit and one for triggering unit. The triggering unit needs to be saved above the unit group.

Doesn't that only apply while in the other function? I mean I don't ever use GetTriggerUnit() inside the actual group enumeration.

I'll still give it a try though.

The new function still operates during the event's execution.
(Triggering unit), (Attacking unit) and (Triggering player) should still work fine.

Your best shot is to test the code in different scenarios and use debug messages.
One message can be just after the issue order action telling you (name of attacking unit) + " is now attacking " + (name of tempUnit)

Useful testscenarios can be a 1vs1 fight of units. (if there are no other units, will it work?)
Or 1vs3 attempting to attack a unit with higher health.

(You might also want to change the health thingy into percentage of health... but that is just something else.)

Yeah, I'll do that if chaosy's suggestion doesn't fix it.

Maybe the lowest EHP (taking armor, spell resistance, and buffs into account.) maybe, but not %hp. If a unit has less % hp but higher max hp it will most likely live longer.

Perhaps something like taking into account what other units are attacking would also be good, but then we're talking about something akin to an actual useful system rather than 5 minutes of GUI triggers.
 
Level 12
Joined
Nov 3, 2013
Messages
989
I see.
Then my guess is that you got a infinite loop because ordering a unit to attack with triggers will trigger the event.

I'm not completely sure if ordering to attack the same unit you're already attacking will interrupt the order or not but it's worth testing.

But that's the thing, I only order to attack if (triggering unit) not equal to tempUnit

Basically nothing should happen at all if the original target turns out to be the "new" target as well. (that's why I made the OP)

But we'll see, I haven't made the changes yet.

edit: I made the extra variable and now it's even weirder. The units will walk up to each other, stare each other in the eye for a second or two, and then they begin attacking each other as normal.

wtf...
 
Level 12
Joined
Nov 3, 2013
Messages
989
here. And thanks in advance.:grin:

p.s. It's just some crappy map I'm trying things on.

edit: and this is how the current trigger looks like by the way:

  • attack nearby lowest health
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Owner of (Attacking unit)) Not equal to (Triggering player)
    • Actions
      • Trigger - Turn off (This trigger)
      • Set tempUnit = (Triggering unit)
      • Set tempUnit2 = (Attacking unit)
      • Set tempPoint = (Position of tempUnit2)
      • Set tempReal = (Life of tempUnit)
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 100.00 of tempPoint matching (((Matching unit) belongs to an enemy of (Owner of tempUnit2)) Equal to True)) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Life of (Picked unit)) Less than tempReal
            • Then - Actions
              • Set tempUnit3 = (Picked unit)
              • Set tempReal = (Life of tempUnit3)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_tempPoint)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • tempUnit Not equal to tempUnit3
        • Then - Actions
          • Unit - Order tempUnit2 to Attack tempUnit
        • Else - Actions
      • Trigger - Turn on (This trigger)
Still haven't put in any messages :p
 

Attachments

  • Footy vs Sentry.w3x
    26.9 KB · Views: 29
Level 12
Joined
Nov 3, 2013
Messages
989
So, you want to make units attack the unit with the lowest health before they can start attacking the default targets, right? Is this exactly what you want?

It's meant to be like this, the units just attack move like normal and attack whatever they want. But if there's another unit than their current target of attack within their attack range that has less health, they should attack that first.

Basically if there's two enemies next to each other, you obviously want to first attack and kill the one which will die faster.
 
Level 9
Joined
May 21, 2014
Messages
580
Okay so I tinkered a lot of things and made the trigger as is; the trigger simply does not work as intended.

The problem of they were just facing each other for a long time is because the trigger always fires and they are basically always choosing which is which. The moment they start attacking is an unknown story for me; it seemed like the trigger gave up hope choosing for them.

What I would try (later) is to keep a Unit Group and maintain it. If the Unit is within the said Unit Group, then do not fire the trigger. Remove the on and off of the trigger. When the unit enters the trigger, store the unit first-hand. Add a condition in the trigger "if attacking unit is in Unit Group == false".

Of course, you need to remove the unit from the unit group if it dies. if it starts attacking, store the unit.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
This works:
  • Attack Focus
    • Events
      • Unit - A unit Is attacked
    • Conditions
    • Actions
      • Set TempUnit[0] = (Attacking unit)
      • Set TempUnit[1] = (Triggering unit)
      • Set TempPlayer[0] = (Owner of TempUnit[0])
      • Set TempPoint[0] = (Position of TempUnit[0])
      • Set TempReal[0] = (Life of TempUnit[1])
      • Set TempUnit[3] = No unit
      • -------- - --------
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within (Current acquisition range of TempUnit[0]) of TempPoint[0]) and do (Actions)
        • Loop - Actions
          • Set TempUnit[2] = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit[2] belongs to an enemy of TempPlayer[0]) Equal to True
            • Then - Actions
              • Set TempReal[1] = (Life of TempUnit[2])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempReal[0] Greater than TempReal[1]
                • Then - Actions
                  • Set TempReal[0] = TempReal[1]
                  • Set TempUnit[3] = TempUnit[2]
                • Else - Actions
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint[0])
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TempUnit[3] Not equal to No unit
        • Then - Actions
          • Unit - Order TempUnit[0] to Attack TempUnit[3]
        • Else - Actions
The only thing is that your unit does take a while to realize he has to actually attack after he got ordered to attack another unit.
To fix that, you should use another event which is "A unit acquires a target" but that only comes in specific unit events.
It might not be worth to go through the entire process of getting a register and cleanup algorithm set up for just this small thing.
 
Level 12
Joined
Nov 3, 2013
Messages
989
the trigger always fires and they are basically always choosing which is which
Although I agree that's what seems to be happening, it shouldn't be the case.

considering this:

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • tempUnit Not equal to tempUnit3
    • Then - Actions
      • Unit - Order tempUnit2 to Attack tempUnit
    • Else - Actions
Unless there's a unit with less health in range, there shouldn't be ANY new issued order...

So it really boggles my mind, and hence why I made the OP to begin with.

This works:
  • Attack Focus
    • Events
      • Unit - A unit Is attacked
    • Conditions
    • Actions
      • Set TempUnit[0] = (Attacking unit)
      • Set TempUnit[1] = (Triggering unit)
      • Set TempPlayer[0] = (Owner of TempUnit[0])
      • Set TempPoint[0] = (Position of TempUnit[0])
      • Set TempReal[0] = (Life of TempUnit[1])
      • Set TempUnit[3] = No unit
      • -------- - --------
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within (Current acquisition range of TempUnit[0]) of TempPoint[0]) and do (Actions)
        • Loop - Actions
          • Set TempUnit[2] = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit[2] belongs to an enemy of TempPlayer[0]) Equal to True
            • Then - Actions
              • Set TempReal[1] = (Life of TempUnit[2])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempReal[0] Greater than TempReal[1]
                • Then - Actions
                  • Set TempReal[0] = TempReal[1]
                  • Set TempUnit[3] = TempUnit[2]
                • Else - Actions
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint[0])
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TempUnit[3] Not equal to No unit
        • Then - Actions
          • Unit - Order TempUnit[0] to Attack TempUnit[3]
        • Else - Actions
The only thing is that your unit does take a while to realize he has to actually attack after he got ordered to attack another unit.
To fix that, you should use another event which is "A unit acquires a target" but that only comes in specific unit events.
It might not be worth to go through the entire process of getting a register and cleanup algorithm set up for just this small thing.

I just want the unit's to prioritize enemy units with less health, that are already within it's attack range (Otherwise I could just use the normal computer AI, which already runs across half the map chasing heroes and low health units...). Besides this point, it seems to be that there's not any particular difference between how our triggers will work?

So does the units still stand still dumb like bricks for a roughly a second before attacking with your trigger? If it only was when they change target it wouldn't be so bad, it would perhaps even make a bit of sense, but I'm not ordering anything if there isn't another target...
 
Status
Not open for further replies.
Top