• 🏆 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] make neutral unit attack without stopping

Status
Not open for further replies.
Level 21
Joined
Mar 29, 2020
Messages
1,237
hey all, need help with a trigger I'm trying to build - if any hero picks up item X make unit Y chase and attack him. i succeeded in making a basic trigger for this, but the unit stops attacking soon after, and if the hero is far enough - will just turn around before getting there. how can I make unit Y continuously attack whichever hero is carrying item x?

thanks!
 
Last edited:
Level 14
Joined
Feb 7, 2020
Messages
387
  • basic attack timer
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (taurenUnit has an item of type Blood Key) Equal to True
          • (taurenUnit is alive) Equal to True
          • (tuskarrHealerUnit is alive) Equal to True
        • Then - Actions
          • Unit - Order tuskarrHealerUnit to Attack taurenUnit
        • Else - Actions
          • Trigger - Turn off (This trigger)
As Warseeker stated, you could easily create the most basic agent timer ever and make the unit or unit group attack the desired unit. Add other conditions to turn it off as necessary (item dropped, other map-specific things). You would simply enable it whenever you wanted it to run via other triggers:

  • Trigger - Turn on (basic attack timer)
I suspect you'll want groups to attack and not just single units. If so, I reference this short tutorial so I don't have to retype it all: Convenient Unit Group Filtering in GUI

:ogre_haosis:
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
thanks!

I had tried using a periodic timer, but when I did that I couldn't target the hero who picked it up as "triggering unit" and couldn't figure out how to target [any hero who picks up the item]. the trouble was getting it to attack not a set unit, but whoever picks up the item.
I just got it to work by using:


Events
Time - Every 1.00 seconds of game time
Conditions
(Sulfira 0005 <gen> has Crown of the dragon 0004 <gen>) Equal to False
Actions
Unit Group - Pick every unit in (Units in (Playable map area) matching (((Matching unit) has Crown of the dragon 0004 <gen>) Equal to True)) and do (Unit - Order Sulfira 0005 <gen> to attack (Picked unit))

thanks for the help!
 
Level 12
Joined
Jan 30, 2020
Messages
875
Honestly guys using periodic events for something like this is horrible coding, no offense.

if you use EVENT_UNIT_PICKUP_ITEM to detect when the item is picked up by X, and then order Y to attack X, all you have to do to make sure it keeps attacking it is :

Use the event : a unit is issued an order with no target, with the condition that the order is "stop" and with the action to order Y to "attack" with X as target.

By doing this, Y would have no reason to stop attacking X.
 
Level 14
Joined
Feb 7, 2020
Messages
387
Honestly guys using periodic events for something like this is horrible coding, no offense.

if you use EVENT_UNIT_PICKUP_ITEM to detect when the item is picked up by X, and then order Y to attack X, all you have to do to make sure it keeps attacking it is :

Use the event : a unit is issued an order with no target, with the condition that the order is "stop" and with the action to order Y to "attack" with X as target.

By doing this, Y would have no reason to stop attacking X.

Except in any interaction with any kind of movement system (knockback), where the unit is computer-controlled, line of sight becomes obstructed, or if the attacker is targeted by a basic hero stun (combined with line of sight obstruction) -- which I actually tested in the attached map for giggles. Maybe I missed something?

And I assume the unit in question from OP is a boss or something that won't be receiving direct orders (acquisition return pathing doesn't get raised as a stop or move order).

Also, what's with your first sentence? No one is offended; they're probably annoyed. The arrogant programmer stigma is a relic of the past (I thought, at least).
 

Attachments

  • kekw.w3m
    13.1 KB · Views: 26
Level 21
Joined
Mar 29, 2020
Messages
1,237
Honestly guys using periodic events for something like this is horrible coding, no offense.



what does that mean practically? what negative results will "horrible coding" have? because as of now it works.... ("if it ain't broke..."). also I don't understand what you wrote after that... I'm have a pretty bad case of noobism and have no idea how to implicate what you wrote (assuming it has a significant advantage over my sloppy GUI), so if you could break it down into layman terms that would help...


also - I would really want the chasing unit to engage any units that attack it along the way to the unit it is chasing and then continue in pursuit, so if any of you can help me figure out that one it would be great.
 
Level 12
Joined
Jan 30, 2020
Messages
875
I know what you mean with LOS obstruction and incapacitating spells.
But thats exactly when (at least in my experience) they get ordered to "stop".

My TD creeps are Balls, computer controlled.
They follow waypoints, and I just reorder them to move to the next waypoint when they reach their current destination (except when they get blocked).

The only times they stop, is when they get blocked or lose their target from sight before changing targets (my TD's towers can move when necessary).

So I have to detect when they self-order to stop, if I don't intercept that event to reorder them, they will never go to the next waypoint.

As for the no offense, I might be wrong as English is not my mother tongue, but I always feel like I need to tell people I do not mean to offend them, when I emit strong criticism about their ideas - especially when they mean to help.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
if you use EVENT_UNIT_PICKUP_ITEM to detect when the item is picked up by X, and then order Y to attack X, all you have to do to make sure it keeps attacking it is :

Use the event : a unit is issued an order with no target, with the condition that the order is "stop" and with the action to order Y to "attack" with X as target.

By doing this, Y would have no reason to stop attacking X.

now that I understand GUI a little better I tried to clean up my code and do what you said, as it really seemed silly to have it all based on periodics - which were colliding with each other and making the unit in question move really weirdly, and probably take up a lot of unnecessary memory. but not it doesn't work. as @Planetary said - it gets to a certain range from it's starting point and then turns back to the starting point.

I think the reason this happens is bc - it's not just a stop order, but rather specific internal creep orders to go back to it's starting point.

any idea how I can access the general "creep-go home" command, to negate it?
 
Level 12
Joined
Jan 30, 2020
Messages
875
This is probably just an issue with the guard positions for the creeps.

Try :
  • Actions
    • AI - Ignore the guard positions of all Neutral Hostile units
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
This is probably just an issue with the guard positions for the creeps.

Try :
  • Actions
    • AI - Ignore the guard positions of all Neutral Hostile units

nope... that isn't a permanent order. that cancels the order initially, but soon after it is returned (the result is pretty much identical to not ordering that at all...). and ordering that on a periodic basis would pretty much bring me back to square one.

is there a way I could detect when a unit is ordered to go back to it's starting point? (basically - how what type of condition can fond out which point is the target point of issued order)

thanks!
 
Level 12
Joined
Jan 30, 2020
Messages
875
I seems to remember that, like @doom_sheep mentioned, that if you use a Neutral player rather than a computer controlled player for your creeps, you won't be able to sort the issue, because guard positions are hardcoded for these players.

To prove this, set the owner of the creeps as one of the players (just for the test), use the action to remove guard positions for that player at Map Init, and seethe result.

They will behave like you expect.

In other words, there is no way to get rid of guard positions (as far as I know) if you keep Neutral Hostile as the owner of the creeps.

In my map, creeps are owned by Player 9 and never stop an attack when they are ordered to (hell I even had to add a special trigger to stop them from attacking in order to prevent them to decimate the player's mazes).
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
So actually I found a solution that does work with neutral hostile. this is based on the fact that the order that the AI keeps issuing to the creeps is to return their starting point. At initialization I saved the starting point of the unit and pinpointed it in a tiny region:
  • set starting point
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set startpoint = (Position of Anacalagon 0005 <gen>)
      • Set startregion = (Region centered at startpoint with size (1.00, 1.00))
and then I just re-issued all orders that started out as:
  • cant stop
    • Events
      • Unit - Anacalagon 0005 <gen> Is issued an order targeting a point
    • Conditions
      • (Issued order) Equal to (Order(move))
      • (startregion contains (Target point of issued order)) Equal to True
and so far this works for me with no problems.
thanks for the help:thumbs_up:
 
Last edited:
Level 12
Joined
Jan 30, 2020
Messages
875
Well thats quite a smart way of doing things, well done !
Thats why I never positively say that something is 100% impossible :D

The clever part is that, knowing that you never order this unit to target a Point yourself (but only to target a unit), then in clearly only intercepts the AI's order.

It would be interesting to review all the order IDs (I know someone made a list of all existing IDs in game but I can't remember all the identified corresponding orders) to see if the specific order to return to position cannot be accessed. This way, your method would also work in caste you would need to order this unit to move or attack to a point. But I am just extrapolating...

Anyways happy to see your problem is solved :)
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
neutrals are permanently retarded

You may have had a point lol

First bug with this system - even though it initially works smoothly, sometimes it seems like the unit randomly changes his guard position to his current location. this messes up my whole system, since the internal periodic timer that pushes him to go back home is the thing triggering my entire system, and now he just sits wherever he is and "ignores his job".

how could I detect this happening so I could stick his guard position back where it should be?
 
Level 12
Joined
Jan 30, 2020
Messages
875
Well why not simply save the unit position when the hero pick the item ?

Fact is what you should do is this, then to detect when your unit is ordered back to guard position, you order it to attack your hero (thats not a point).
And when there is no more reason to attack (when the hero drops the item?), just disable the trigger fixing the guard positions and order your unit to go back to its original position you saved.

hero picks item -> save Anacalagon 0005 <gen> 's position is variable DragonPos
Then
Anacalagon 0005 <gen> Is issued an order targeting a point -> Order Trigger unit to attack taurenUnit (no need for condition as you never order the dragon yourself except in the next trigger)

taurenUnit drops the item -> Disable Trigger *the name of the trigger above* -> Order Anacalagon 0005 <gen> to move to DragonPos

Sorry I am not working on GUI right now so I couldn't type the triggers precisely, but I hope you get the idea.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
I'm not sure how this would help me. my problem is that once Anacalagon 0005 <gen> re-assigns it's guard position to where it is - it stops getting issued orders bc it is already where it is "supposed" to be. me saving it's position wouldn't help bc I'm using the AI generated events - which stop happening. maybe I didn't understand what you were saying correctly...
 
Level 12
Joined
Jan 30, 2020
Messages
875
Can we see your complete trigger where you intercept the AI orders ?

Actually maybe all the triggers related to this hero picking up item - dragon attacking him thing you are trying to get to work :)
 
Level 23
Joined
Oct 18, 2008
Messages
937
You may have had a point lol

First bug with this system - even though it initially works smoothly, sometimes it seems like the unit randomly changes his guard position to his current location. this messes up my whole system, since the internal periodic timer that pushes him to go back home is the thing triggering my entire system, and now he just sits wherever he is and "ignores his job".

how could I detect this happening so I could stick his guard position back where it should be?

you might as well just make a system that replaces all commands given to the unit and turn it off when you want to give him one he should actually follow
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
Can we see your complete trigger where you intercept the AI orders ?

Actually maybe all the triggers related to this hero picking up item - dragon attacking him thing you are trying to get to work :)

its kinda long:gg::

what all of this does - if anyone picks up Crown of the dragon 0004 <gen> the dragon will chase them across map and devour them (and then take the item after the hero dies). if the item is dropped it will pick it up. then it takes the item to where it is supposed to be, and goes back to it's lair.

  • eat him
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0004 <gen>
      • (Triggering unit) Not equal to Anacalagon 0005 <gen>
    • Actions
      • If ((Anacalagon 0005 <gen> is Sleeping) Equal to True) then do (Unit - Wake up Anacalagon 0005 <gen>) else do (Do nothing)
      • Unit - Order Anacalagon 0005 <gen> to Neutral - Devour (Triggering unit)
  • pick up crown
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0004 <gen>
      • (Triggering unit) Not equal to Anacalagon 0005 <gen>
    • Actions
      • Wait 0.10 seconds
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Crown of the dragon 0004 <gen> is owned) Equal to False
        • Then - Actions
          • Unit - Order Anacalagon 0005 <gen> to Right-Click Crown of the dragon 0004 <gen>
        • Else - Actions
  • bring home
    • Events
      • Unit - Anacalagon 0005 <gen> Acquires an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0004 <gen>
    • Actions
      • Set TempPoint = (Center of home of crown <gen>)
      • Unit - Order Anacalagon 0005 <gen> to drop Crown of the dragon 0004 <gen> at TempPoint
      • Custom script: call RemoveLocation(udg_TempPoint)
  • go home
    • Events
      • Unit - Anacalagon 0005 <gen> Loses an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0004 <gen>
    • Actions
      • Wait 6.00 game-time seconds
      • Set SleepPoint = (Random point in dragon lair <gen>)
      • Unit - Order Anacalagon 0005 <gen> to Move To SleepPoint
      • Custom script: call RemoveLocation(udg_SleepPoint)
  • cant stop
    • Events
      • Unit - Anacalagon 0005 <gen> Is issued an order targeting a point
    • Conditions
      • (Issued order) Equal to (Order(move))
      • (startregion contains (Target point of issued order)) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Crown of the dragon 0004 <gen> is owned) Equal to True
          • (Anacalagon 0005 <gen> has Crown of the dragon 0004 <gen>) Equal to False
        • Then - Actions
          • Set crownholder = (Units in (Playable map area) matching (((Matching unit) has Crown of the dragon 0004 <gen>) Equal to True))
          • Unit Group - Pick every unit in crownholder and do (Unit - Order Anacalagon 0005 <gen> to Neutral - Devour (Picked unit))
          • Custom script: call DestroyGroup( udg_crownholder )
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Crown of the dragon 0004 <gen> is owned) Equal to False
              • (Crown of the dragon 0004 <gen> is in home of crown <gen>) Equal to False
            • Then - Actions
              • Unit - Order Anacalagon 0005 <gen> to Right-Click Crown of the dragon 0004 <gen>
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Anacalagon 0005 <gen> has Crown of the dragon 0004 <gen>) Equal to True
                • Then - Actions
                  • Set TempPoint = (Center of home of crown <gen>)
                  • Unit - Order Anacalagon 0005 <gen> to drop Crown of the dragon 0004 <gen> at TempPoint
                  • Custom script: call RemoveLocation(udg_TempPoint)
                • Else - Actions
  • set starting point
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set startpoint = (Position of Anacalagon 0005 <gen>)
      • Set startregion = (Region centered at startpoint with size (1.00, 1.00))
more on the map: [Altered Melee] - Dragon Bait
(before I redid the triggers)

you might as well just make a system that replaces all commands given to the unit and turn it off when you want to give him one he should actually follow
I don't exactly get what you mean and how that is different from what i did.

also - I could always go back to triggering all of this periodically... I'm just being stubborn and trying to find a better way...

another Important detail - I think I found out what makes anacalagon change guard position - I think it has to do with using devour, and missing the target. also I think its linked with the command string "null" which it usually gets around then (I have been following it's issued command strings with a notifying trigger) - any Idea what that does?

edit: - I thought maybe it had to do with sleeping, so I disabled sleep but forgot to update the trigger. in any case - thats not the problem here...

edit: I just found this "action", so problem should be solved if this is permanent:
  • lock guard position
    • Events
      • Map initialization
    • Conditions
    • Actions
      • AI - Lock guard position of Anacalagon 0005 <gen>
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
To check when a unit becomes idle:
  • (Current order of (Triggering unit)) Equal to (Order(stand down))
Unfortunately, "stand down" doesn't fire any Order Events (a unit is issued an order...). However, like the condition shows, you can check if the current order of your unit is equal to it.
 
Level 12
Joined
Jan 30, 2020
Messages
875
Ok there is a lot that needs to change in your triggers.

This is quite unecessary for example :
  • Set crownholder = (Units in (Playable map area) matching (((Matching unit) has Crown of the dragon 0004 <gen>) Equal to True))
  • Unit Group - Pick every unit in crownholder and do (Unit - Order Anacalagon 0005 <gen> to Neutral - Devour (Picked unit))
It seems you only have one dragon and one crown.
So why don't you simply use 2 global variables, 1 to store if the item is owned or not (boolean) and the other to store the unit who picked the item ?
Then you could easily alter some of your triggers this way :
(I used similar names to avoid confusion)

  • Picked
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0001 <gen>
    • Actions
      • Set VariableSet isOwned = True
      • Set VariableSet Holder = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Anacalagon 0000 <gen> is sleeping) Equal to True
          • (Triggering unit) Not equal to Anacalagon 0000 <gen>
        • Then - Actions
          • Unit - Wake up Anacalagon 0000 <gen>
          • Unit - Order Anacalagon 0000 <gen> to Neutral - Devour ( Holder )
        • Else - Actions
  • Dropped
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0001 <gen>
    • Actions
      • Set VariableSet isOwned = False
      • Set VariableSet Holder = No unit
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering unit) Equal to Anacalagon 0000 <gen>
        • Then - Actions
          • Unit - Order Anacalagon 0000 <gen> to Move To (Random point in Dragon Lair <gen>)
        • Else - Actions
          • Unit - Order Anacalagon 0000 <gen> to Right-Click Crown of the dragon 0001 <gen>
  • Fix AI
    • Events
      • Unit - Anacalagon 0000 <gen> Is issued an order targeting a point
    • Conditions
      • (Issued order) Equal to (Order(move))
    • Actions
      • If (isOwned Equal to True) then do (Unit - Order Anacalagon 0000 <gen> to Neutral - Devour Holder) else do (Unit - Order Anacalagon 0000 <gen> to Right-Click Crown of the dragon 0001 <gen>)
Seems much easier this way, don't you think ?
I think the other triggers are ok.

EDIT : forgot some actions in the dropping trigger - fixed.
EDIT 2 : dam I forgot the fact that I order the dragon to "MOVE" to the Lair, maybe use the Lair itself (building i suppose) and the Drop trigger instead becomes :
  • Dropped
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0001 <gen>
    • Actions
      • Set VariableSet isOwned = False
      • Set VariableSet Holder = No unit
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering unit) Equal to Anacalagon 0000 <gen>
        • Then - Actions
          • Unit - Order Anacalagon 0000 <gen> to Right-Click Dragon Lair 0002 <gen>
        • Else - Actions
          • Unit - Order Anacalagon 0000 <gen> to Right-Click Crown of the dragon 0001 <gen>
EDIT 3 :
Mmm seems I am a bit tired, had to fix the Picked trigger, because it would not work if the dragon was not sleeping :
  • Picked
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Item being manipulated) Equal to Crown of the dragon 0001 <gen>
    • Actions
      • Set VariableSet isOwned = True
      • Set VariableSet Holder = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering unit) Not equal to Anacalagon 0000 <gen>
        • Then - Actions
          • If ((Anacalagon 0000 <gen> is sleeping) Equal to True) then do (Unit - Wake up Anacalagon 0000 <gen>) else do (Do nothing)
          • Unit - Order Anacalagon 0000 <gen> to Neutral - Devour (Triggering unit)
        • Else - Actions
 
Last edited:
Level 21
Joined
Mar 29, 2020
Messages
1,237
problem should be solved if
...it wasn't... this trigger did not change anything. The problem is (almost) definitely triggered by devour. twice in a row it happened while trying to devour the computer controlled player's hero, but not consistently (one of the times this happened tried to see if that would snap it back into action, but then it just chased the hero who attacked it across the map:confused:2). the order before the fluke both times was 'load', as in some part of the command of devour (or probably 'devour cargo' to be precise).

(Order(stand down))
I'm trying to figure out where to stick this..

(building i suppose)
nope, it's a region (open cave). I could stick a dummy unit there, I'll see if that helps.


So I'll try to rebuild this system and see if that solves the issue.. thanks guys!

EDIT: also, in "Fix AI", you have anacalagon devouring himself.... so I'll change that...
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
Isn't the issue that your Unit becomes idle?

If so, after it tries to cast devour check if it's current order is "stand down" and if it is then force it to move to the appropriate location.

You might need to add a Wait to give it enough time for the unit to become idle.

Also, Devour can fail to eat it's target if the target moves out of the way in time.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
Isn't the issue that your Unit becomes idle?

If so, after it tries to cast devour check if it's current order is "stand down" and if it is then force it to move to the appropriate location.

You might need to add a Wait to give it enough time for the unit to become idle.

Also, Devour can fail to eat it's target if the target moves out of the way in time.

I meant bc the unit is getting issued the devour order possibly long before it does it. so I guess I could just add a crazy long wait, but then if it does get issued te order when it is close to the target it will sit idle for a while before rebooted...
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
I'm still not 100% certain as to what's going wrong, but I meant that you should check after it tries to cast the ability.

A unit stops casting an ability
Ability = Devour
Wait 1.00 Second
If Current order of Triggering Unit = "stand down" then Order Triggering Unit to move to Point
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
so far it seems like the combination of responding to "stand down", and locking the guard point of the unit make this problem stop happening. I still plan on cleaning up the code like macadamia suggested but didn't yet. if I bump into further trouble with this I'll be back:cool:2 . thanks a lot!
 
Level 12
Joined
Jan 30, 2020
Messages
875
I am happy things turned out that way !

As for my code, note it was more for the general idea than for the precision, as I made a few silly mistakes.

Good luck wit you project :)
 
Level 23
Joined
Oct 18, 2008
Messages
937
missing devour is a whole another bug. it causes the caster to get into a stupid state where it thinks it's doing something but isn't and will sit still until given a new order.

I don't exactly get what you mean and how that is different from what i did.
replace any conditions in your order detection trigger with "ordered unit equal to ancalagon" and at every point where you give him an order add "turn off order detection trigger" above and "turn on order detection trigger" below. though as I explained that probably won't fix the thing with devour.
 
Status
Not open for further replies.
Top