• 🏆 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] Detecting move ability without checking for Amov or checking movement speed

Status
Not open for further replies.
Level 8
Joined
Jul 6, 2012
Messages
65
Current conditions I use

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Current movement speed of (Triggering unit)) Greater than 0.00
      • (Level of AMov for (Triggering unit)) Greater than 0
    • Then - Actions
      • stuff
    • Else - Actions
      • other stuff
Works fine. Detects units which can't move in general (e.g. wards and buildings), and detects ensnared/entangled units.


Problem: It fails to detect rooted night elf ancients. All ancients have movement enabled ("foot"), and have movement speed set (40), so they meet my current conditions. But I don't want them to, since rooted ancients cannot move.

So is there a third condition to check whether a unit is able to move? Like do rooted ancients have some special status or something which could be checked for?

Workarounds I want to avoid:
1. Using any checks requiring a new trigger (e.g. detect ancients using the root ability)
2. Add a unit type check for every ancient
3. Changing any values in the object editor (no setting ms to 0, or disabling movement)


Edit: I might have posted in the wrong section.
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Root and unroot are abilities, so you can probably catch them with spellcast events. Otherwise they are definitely orders you can catch but that's a little dicier. When a unit casts the root ability add it to a group, when it unroots remove it from the group (or the other way around if the ancients always start rooted), then in your movement trigger additionally check if the unit is/isn't in that group.
 
There is also the return value of a "move" order (The game tells you, if an given order was a success or it fails), requiers jass (custom script) also this apporach has the side effect of destroying the unit's current order.
Edit: Making it often unpracticable.
  • Custom script: local unit u = GetTriggerUnit()
  • Custom script: if IssuePointOrder(u, "move", GetUnitX(u), GetUnitY(u)) then
  • Game - Display to (All players) for 5.00 seconds the text: Can move
  • Custom script: else
  • Game - Display to (All players) for 5.00 seconds the text: Can not move
  • Custom script: endif
Edit: That would also work with the GUI Actions.
  1. Give an "move" order somewhere
  2. Check if current order is "move"
    • true, can move
    • false, can not move
 
Last edited:
Level 12
Joined
Nov 3, 2013
Messages
989
The unit type/id doesn't change, the ability ID of the ability doesn't change (though that would've been weird), there's no buff, and you can't detect whether an ability is toggled on or off (something like IsAbilityToggledOn takes unit whichUnit integer abilityId returns boolean.

And the movement speed is more than 0 even when the ancient is rooted (otherwise you wouldn't have made this topic, at least that's what I'm assuming).


There's
  • ((Triggering unit) is Snared) Equal to True
But that one is already taken care of by checking for movement speed, and I haven't seen any equivalent "is Rooted".

So... No? There doesn't appear to be any way to do what you ask of.


With that said, you technically can still make it all in one trigger. And maybe if you explained why you don't want to use any of the perfectly viable work-arounds like adding all rooted ancients to a unit group and check whether the unit is in said unit group isn't something you would want then maybe you could still find some help.
 
Level 8
Joined
Jul 6, 2012
Messages
65
There is also the return value of a "move" order (The game tells you, if an given order was a success or it fails), requiers jass (custom script) also this apporach has the side effect of destroying the unit's current order.
Edit: Making it often unpracticable.
  • Custom script: local unit u = GetTriggerUnit()
  • Custom script: if IssuePointOrder(u, "move", GetUnitX(u), GetUnitY(u)) then
  • Game - Display to (All players) for 5.00 seconds the text: Can move
  • Custom script: else
  • Game - Display to (All players) for 5.00 seconds the text: Can not move
  • Custom script: endif
Edit: That would also work with the GUI Actions.
  1. Give an "move" order somewhere
  2. Check if current order is "move"
    • true, can move
    • false, can not move

How would this detect a move command when you are literally unable to give the treants that order in the first place? They do not have the move ability in their HUD, so you can't give them a move order since that requires you to select the move ability and target a point. Right-clicking also wouldn't work, because that's a smart order, and it does more than just move (attack for protectors, set rally point, or select shop hero).


With that said, you technically can still make it all in one trigger. And maybe if you explained why you don't want to use any of the perfectly viable work-arounds like adding all rooted ancients to a unit group and check whether the unit is in said unit group isn't something you would want then maybe you could still find some help.

This is more of a learning thread, rather than an ask for help. I could just use the workaround, yes, but I thought maybe someone here knows a clean way to detect such units without using workarounds like listing every treant, or throwing units in groups when root is used. Workarounds are fine for personal use, but can get tedious when you try to implement the codes into other maps.
 
My answer is a workaround.
It works by giving a "move" order by code/Trigger, now if the unit can perform the order "move" its current order is "move", but if it is not able to perform "move" its current order can not be "move" and so one would have a way to identify such units beeing unable to perform move orders.
But Sideeffect destroys the tested units current order if it can move.
 
You could check for the unit name, check if its an ancient, new natives allow us to have an easier method of what Tasyen suggested. Lots of options, others include mixing to improve previous methods for better methods like adding in ability checks or other possibilities.

[trigger=]
Untitled Trigger 004
Events
Player - Player 1 (Red) skips a cinematic sequence
Conditions
Actions
Unit Group - Pick every unit in (Units currently selected by Player 1 (Red)) and do (Actions)
Loop - Actions
Custom script: call BlzUnitDisableAbility( GetEnumUnit(), 'Amov', false, false )
Unit - Order (Picked unit) to Move To (Center of (Playable map area))
[/trigger]

[trigger=]
Untitled Trigger 005
Events
Unit - A unit Is issued an order targeting a point
Conditions
Actions
Game - Display to (All players) the text: ((Name of (Triggering unit)) + ( has tried to + (String((Issued order)))))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Triggering unit) is An Ancient) Equal to True
Then - Actions
Custom script: call BlzUnitDisableAbility( GetEnumUnit(), 'Amov', false, true )
Else - Actions
[/trigger]


Edit: Just realized by what you said at the start of this thread, you are right about all the ancients having 40 movement speed so isn't that another option you can use for checking?
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Because the 2 methods built into the game that 'should' check for movement (checking 'Amov' and ms == 0) don't work on ancients, any solution is inherently a "workaround". So, pick your favorite workaround. There is no non-workaround way to figure this out, but the solutions suggested here are numerous and should generally be sufficient for your purposes.

That's a workaround I want to avoid, as I already said it OP, because I want to keep it all in one trigger.
That is an incredibly naïve restriction to put on a solution. Most problems you need to solve when modding are not going to have a 'single trigger solution', because it's just not the way GUI is structured (1 set of events, conditions, actions per trigger). It's an arbitrary restriction that only makes you reject valid, simple solutions to the problem you're solving. Trigger groups are a thing, as are comment triggers you can use to make it very clear which of your triggers work in concert with which other ones.

Workarounds are fine for personal use, but can get tedious when you try to implement the codes into other maps.
Explain how this could be in any way tedious? The Editor automatically creates the group variable when you paste the trigger. The group solution doesn't interfere with or change anything about the game state, it is literally just collecting data about units using the root ability and then allowing you to reference it later. Something like Tasyen's solution (also perfectly reasonable) does mess with unit current orders and so could in theory muck something up in the game if you aren't careful to re-issue the previous order. That's a one-trigger-solution that causes actual impact to your map where 2/3 triggers would not!

Anyone who wants to copy your code into another map can copy 1 trigger as easily as they can copy a whole category of triggers. If you really care that it's all self-contained in one trigger visually, you should learn to program in JASS because that totally desyncs the physical triggers you see in the editor from whatever effects your code actually has in your map, thus allowing one 'visual trigger' that does many different things.

Edit: Just realized by what you said at the start of this thread, you are right about all the ancients having 40 movement speed so isn't that another option you can use for checking?
They have 40 ms regardless of whether or not they're rooted, so while checking for that can determine if something is an ancient, it can't distinguish between a rooted one and a non-rooted one.
 
Level 8
Joined
Jul 6, 2012
Messages
65
Because the 2 methods built into the game that 'should' check for movement (checking 'Amov' and ms == 0) don't work on ancients, any solution is inherently a "workaround". So, pick your favorite workaround. There is no non-workaround way to figure this out, but the solutions suggested here are numerous and should generally be sufficient for your purposes.

The question was, is there some "hidden" function somewhere in the game that could be used to detect units which can't move.

Example: There are 2 ways to move units with triggers. But only one of them is available in GUI by default, while the other requires jass or a custom script. There are lots of functions not available in the GUI editor, so I was asking if there are similar alternatives for detecting units which can't move. The answer seems to be no.


Another question that might work here if it is possible: Is it possible to detect whether an ability is hidden or not? Because it seems like rooting a treant does hide the move ability, so being able to detect that should work. If that's possible, then this would be the best workaround.

Explain how this could be in any way tedious?

When using list of units as a work around, it would tedious for maps where you have custom units with similar problems, or when your custom map changed the treants so they don't have this problem anymore. You'd need to adapt the list.

When using unitgroup and putting units using root into that group, it would be tedious for maps which use the root ability in other ways, or have custom abilities using root as their base spells.

I'm working on a custom disable status effect, and I aim for it to be easy to implement into new/other maps.
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
When using unitgroup and putting units using root into that group, it would be tedious for maps which use the root ability in other ways, or have custom abilities using root as their base spells.
If the root ability is being used in the map, then it is doing its intended job of making units unable to move when they otherwise would be able to and those units will fail both of the checks that you found don't work on rooted Ancients, so... no that is not something that causes a problem. In fact, it's working as intended because every unit that roots itself would need to be detected in the same way. If for some reason the map is using Root/Unroot as a base ability for something other than rooting the unit in place instead of literally any other non-target unit ability or channel with a custom base order, then the issue is using root for that non-rooting purpose, not using a spellcast/order trigger to detect rooted units.

The question was, is there some "hidden" function somewhere in the game that could be used to detect units which can't move.
No, your question was "So is there a third condition to check whether a unit is able to move? Like do rooted ancients have some special status or something which could be checked for?" which is really not phrased at all in the same way. We're not psychic. If you ask for a solution to a problem we give you the solution we know works and would use ourselves. If you want to know if there's something hidden from GUI that you could use, then phrase your question to indicate that's what you want.

Another question that might work here if it is possible: Is it possible to detect whether an ability is hidden or not?
No. Or rather, yes but it is a workaround you're not going to like.
  1. Select the unit for its owning player and force the hotkey of the ability you want to test, then listen for orders issued to that unit.
  2. If the ability you're testing has no target and the unit isn't issued an order within 1 frame (maybe at maximum 2/30 of a second? it depends on game framerate of course) then the ability was hidden. If the unit is issued an order then the ability is not hidden and you need to interrupt the order to avert the spell cast.
  3. If the ability you're testing has a target (unit, point, destructable), wait one frame, make sure the unit is still selected for the player and force the S hotkey. If the unit is ordered to stop within 1 further frame then the ability was hidden. If the unit is not ordered to stop within one frame then the ability was not hidden and you should clear the player's selection to exit the spell casting interface.
It's really not a good solution because checking the unit order immediately doesn't show the new order if the key was successfully forced. UI key forces take a frame to actually happen and there's no real way to know how long that takes to happen because it's dependent on the current framerate of the game. At least that's what my mucking about with UI key forces has led me to believe.
 
Level 15
Joined
Aug 14, 2007
Messages
936
Hang on doing more testing :D

Edit: There's a generic trigger that I used before but it requires memory, you save all location of units in the map and compare current location with the memory location, if the distance difference is greater than 0 then you can safely say that it moved, this can be intensive unless you check it with the memory specifically for that unit. There's a way around it, you can use loops to check if it's the unit you are using. By saving memory of unit and location in the loop or using a hashtable.
 
Last edited:
Level 8
Joined
Jul 6, 2012
Messages
65
Hang on doing more testing :D

Edit: There's a generic trigger that I used before but it requires memory, you save all location of units in the map and compare current location with the memory location, if the distance difference is greater than 0 then you can safely say that it moved, this can be intensive unless you check it with the memory specifically for that unit. There's a way around it, you can use loops to check if it's the unit you are using. By saving memory of unit and location in the loop or using a hashtable.

Problem with this is, it would also detect teleportation spells, or anything using movement via triggers. I only need detection for units without the move ability, and units which have their move ability disabled (e.g. ensnared).

No, your question was "So is there a third condition to check whether a unit is able to move? Like do rooted ancients have some special status or something which could be checked for?" which is really not phrased at all in the same way. We're not psychic. If you ask for a solution to a problem we give you the solution we know works and would use ourselves. If you want to know if there's something hidden from GUI that you could use, then phrase your question to indicate that's what you want.

Uhm, yes it is? I asked for a condition like one of the 2 I already mentioned. A third condition (probably not available in GUI) which could be used to detect moveability of a unit. And further below I specifically clarified that I'm not looking for workarounds like unit groups or checking for ability usage, but yet everyone but one guy posted workarounds (some of which I already mentioned in OP).


Anyway, I got my answer, so this thread is done.
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Uhm, yes it is? I asked for a condition like one of the 2 I already mentioned. A third condition (probably not available in GUI) which could be used to detect moveability of a unit.
This is more of a learning thread, rather than an ask for help.
That is what you didn't put in your post but is what you were explicitly looking for. Using phrases like "another way" invites suggestions that are inherently workarounds. Yes, I am at fault for not fully reading the end of your post.
but yet everyone but one guy posted workarounds
If everyone gives you "workarounds" maybe the answer is that the simple check you want doesn't exist. But it seems you understand that now.
 
Status
Not open for further replies.
Top