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

Problem with issued orders.

Status
Not open for further replies.
Hi everyone

I tried to make a trigger that makes an owned unit uncontrollable. The concept is to have a bool that, when true, that order will be replaced with the original order. However I got quite some interesting results.

(uses Bribe's unit indexer)
Sample 1:
  • Sample 1
    • Events
      • Unit - A unit Is issued an order with no target
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CancelOrder[(Custom value of (Triggering unit))] Equal to True
        • Then - Actions
          • Game - Display to (All players) the text: Cancel
          • Set Temp_Int = (Custom value of (Triggering unit))
          • Set CancelOrder[Temp_Int] = False
          • Unit - Pause UDexUnits[Temp_Int]
          • Unit - Order UDexUnits[Temp_Int] to Stop
          • Unit - Unpause UDexUnits[Temp_Int]
          • Set CancelOrder[Temp_Int] = True
        • Else - Actions
          • Game - Display to (All players) the text: continue
This trigger works well and even prevents you from casting instant spells, but it seems to create an infinite loop without crashing the game. My question is, why does this trigger keeps repeating? The "Else" actions doesn't do anything to trigger the trigger.

Sample 2:
  • Sample 2
    • Events
      • Unit - A unit Is issued an order with no target
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CancelOrder[(Custom value of (Triggering unit))] Equal to True
        • Then - Actions
          • Game - Display to (All players) the text: Cancel
          • Set Temp_Int = (Custom value of (Triggering unit))
          • Set CancelOrder[Temp_Int] = False
          • Unit - Pause UDexUnits[Temp_Int]
          • Unit - Order UDexUnits[Temp_Int] to Stop
          • Unit - Unpause UDexUnits[Temp_Int]
        • Else - Actions
          • Game - Display to (All players) the text: continue
          • Wait 0.00 seconds
          • Set Temp_Int = (Custom value of (Triggering unit))
          • Set CancelOrder[Temp_Int] = True
This trigger doesn't create the infinite loop problem, but it does allows you to cast instant spells. So my question is, why does the first trigger prevent instant spells? Everything from the start to the line where the unit is unpaused is exactly the same...

Thank you for your time.
 

Attachments

  • uncontrollable.w3x
    23.4 KB · Views: 67
this should be the reason:
  • Unit - A unit Is issued an order with no target

Instant spells also fire that event.

Then you do this:
  • Unit - Order UDexUnits[Temp_Int] to Stop
haven't tested yet, but doesn't paused units who are given orders fire the order events? if so, this causes the system to recursively run
The solution is to turn off the trigger (that trigger), order the unit to stop, then turn it on again. This also allows you not to use that boolean array variable
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Pause an unit, indeed fire a point target order (center of the map (0,0) and order 851972 if i remember correcty)

The same order fire when an unit is stunned, excepted it is a target order, and the target is the widget which has stunned the unit.

This special order has no string equivalent, i suggest you filter the orders inside the trigger condition.
 
Set CancelOrder[Temp_Int] = True

That line from Trigger 1. That also can cause infinite loop

I know, that is the purpose of the boolean - to prevent it. I still don't understand why only 1 trigger prevent spells. An interesting thing is, without the 0 second wait (I know the wait function is inaccurate) the trigger doesn't block any command.

Pause an unit, indeed fire a point target order (center of the map (0,0) and order 851972 if i remember correcty)

The same order fire when an unit is stunned, excepted it is a target order, and the target is the widget which has stunned the unit.

This special order has no string equivalent, i suggest you filter the orders inside the trigger condition.

Thanks for the info Troll, I never knew pauses and stuns does that. I'll look into it :thumbs_up:
 
on the very last line in the "else" block. The "else" condition should be executed when the trigger is triggered for the second time by the function when the unit is ordered to stop.

I'll try to make sample 2 more clear.

First, the player orders the unit to go somewhere. Since Cancel order is true, the unit will be ordered to stop, triggering the trigger for the second time. However, before the stop order, I set cancel order to false. So when the trigger is executed because of the "stop" order, the else block should be executed that makes the boolean true again.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Ok, just tested and the order which i'm talking about is 851973.

You need to filter it because pause and/or unpause is not instant but delayed, so your boolean is not enough.

Since it has no string order, i suppose that checking if the string order is different to null would be enough.

But i won't work on loaded saved games.
Because OrderId2String will return null even with a valid order.
Same for UnitId2String btw.

You could also use a Timer(0) instead of pause/unpause.
 
So a 0 timer also takes more than 0 seconds to fire?

I've read articles about pausing units and apparently it has bad side effects. I encountered a snippet that pauses units without any side effects (but the unit will forget his order) that I will use in my map instead. So I guess I have to find another approach... indiesummons won't work because of syntax errors.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
JASS:
library StopOrder

    globals
        private timer Tim_stop_order = CreateTimer()
        private integer N=0
        private unit array Units
        private boolean array Do_stun_order
        private trigger array Trigger
        private constant integer ORDER_STUN=851973
        private constant integer ORDER_STOP=851972
    endglobals

    private function DoTheStuff takes nothing returns nothing
        local boolean isTrigOn
        loop
        exitwhen N==0
            set N=N-1
            set isTrigOn=IsTriggerEnabled(Trigger[N])
            call DisableTrigger(Trigger[N])
            if Do_stun_order[N] then
                call IssueImmediateOrderById(Units[N],ORDER_STUN)
            else
                call IssueImmediateOrderById(Units[N],ORDER_STOP)
            endif
            if isTrigOn then
                call EnableTrigger(Trigger[N])
            endif
            set Trigger[N]=null
            set Units[N]=null
        endloop
    endfunction

    function StopOrder takes nothing returns nothing
        local eventid ev = GetTriggerEventId()
    
        if GetIssuedOrderId() == ORDER_STUN then
            return
        endif
    
        set Do_stun_order[N] = not(ev==EVENT_UNIT_ISSUED_ORDER or ev==EVENT_PLAYER_UNIT_ISSUED_ORDER)
        set Units[N]=GetTriggerUnit()
        set Trigger[N]=GetTriggeringTrigger()
        set N=N+1
        call TimerStart(Tim_stop_order,0,false,function DoTheStuff)
        set ev=null
    endfunction

endlibrary
And in your GUI trigger just use the custom script :
call StopOrder()

Note that is not perfect, because for no target orders, the order stop will be given instead of the previous one.
For example if it was holdposition, then it will be stop.
It could be done but we need to track all orders and store them.
There is such a library lying somewhere, on wc3c i think.

This is vJass but we can make it simple jass easily.
Remove library, endlibrary, globals, endglobals, private, and use GUI variables instead.
 
Last edited:
Thanks for the library ^^ It works but not if I use it in conditions...
  • Sample 1 Copy
    • Events
      • Unit - A unit Is issued an order with no target
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CancelOrder[(Custom value of (Triggering unit))] Equal to True
        • Then - Actions
          • Set Temp_Int = (Custom value of (Triggering unit))
          • Set CancelOrder[Temp_Int] = False
          • Custom script: call StopOrder()
          • Set CancelOrder[Temp_Int] = True
        • Else - Actions
          • Game - Display to (All players) the text: continue
I was actually considering making a system where you can save and call orders :p I didn't knew there is one already. Once again, thanks.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
You mean the GUI code you show above doesn't work ?
Then there is something wrong with your method.

I mean it should work, are you sure the function StopOrder is called ? Put a text message before the custom script.

EDIT :
Also, i've realized that i disabled/enabled your trigger without checking if it was enabled ot not.
It's fixed now, i've edited my code.
 
Last edited:
Status
Not open for further replies.
Top