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

Detecting unit begins training and is issued an order targeting a point

Status
Not open for further replies.
[SOLVED]

Alright so I have this trigger where I both need to detect if a unit begins training a unit or a unit is issued an order targeting a point (I think).

I've got this so far:

  • Unit Started Build
    • Events
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Begins training a unit
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 1 (Red)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Issued order) Equal to (Order(build))
        • Then - Actions
        • Else - Actions
I use a custom currency system and I want to cancel the construction if the player has insufficient funds. I assume this is best to do when the build order is issued rather then the construction itself.
How can I merge the two actions into this one trigger?
 
Last edited:
Just use a unit is issued an order. Then set conditions. Then cancel.

The order ID is the ID of the unit being built. Hit cntrl-D in OE to view these IDs.

Use this to find the order IDs.

  • OderChecker
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
      • (Owner of (Triggering unit)) Equal to (==) Player 1 (Red)
    • Actions
      • Game - Display to (All players) the text: (String((Issued order)))
      • Custom script: call BJDebugMsg(I2S(GetIssuedOrderId()))
 
Just use a unit is issued an order. Then set conditions. Then cancel.

The order ID is the ID of the unit being built. Hit cntrl-D in OE to view these IDs.

Hm right.
Training is an order to I take. So instead of using "A unit Begins training a unit" I could also detect this as an order instead? Because that would make it easier to merge.
 
Why do you need Unit is issued an order targeting a point? Merging does not seem like a good idea. Why not use 2 triggers?

  • Learn WarStomp
    • Events
      • Unit - A unit Is issued an order with no target
    • Conditions
    • Actions
      • --------- Use the checker to get the order, then set it as an integer -------
      • Set DA_Int = (Integer(1227894833))
      • Custom script: if (GetIssuedOrderId() == udg_DA_Int) then
      • -------------- if/then and now cancel the build order ----------------
      • Custom script: call IssueImmediateOrderById(udg_DA_Dummy, 851976)
      • Custom script: endif
 
Why do you need Unit is issued an order targeting a point? Merging does not seem like a good idea. Why not use 2 triggers?

Oh. As I wrote. I wanted to detect the construction before the actual construction. So the unit don't move to the build area unless sufficient funds is in stock.

And because the two triggers will be exactly identical except for the action.
 
The all you need is my trigger above. No need to do both. Just find the order and cancel it before it's even sent to build. Check out the trigger I just added for the cancel order string.

As a pure GUI user that is a rather confusing trigger ;)
I can't even set an integer var to that value (1227894833).

I get what is going on. But fx. the if/then/else. Do I just throw my GUI in between the GetIssuedOrderId and the cancel order script?
 
No. Sorry. It needs to be a string to integer conversion. So the ID is an integer but because it is too long, you need to use a string. The variable DA_Int is an integer.

This will cancel the order: call IssueImmediateOrderById(GetTriggerUnit(), 851976)

Sorry, I left my dummy unit in there before. You can also set triggering unit = Unit. The in JASS it's "udg_Unit" (without quotes).

The trigger is complete as it. The only part you need to add is the order ID. i.e. (1227894833). To find this run your map with the order ID checker. Order the unit to build. The trigger will print the order ID on the screen for you. Write it down and add it to your trigger.
 
No. Sorry. It needs to be a string to integer conversion. So the ID is an integer but because it is too long, you need to use a string. The variable DA_Int is an integer.

Eventually I figured this out by reading this post :)
http://www.hiveworkshop.com/forums/world-editor-help-zone-98/event-response-training-unit-225653/


In between your posts I came up with this:

  • Unit Started Training
    • Events
      • Unit - A unit Is issued an order with no target
      • Unit - A unit Is issued an order targeting a point
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 1 (Red)
    • Actions
      • Set stringOrderCheck = (String((Issued order)))
      • -------- ------------------------------ ------------------------------ --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Issued order) Equal to (Order(build))
        • Then - Actions
          • Set stringOrderCheck = build
        • Else - Actions
      • -------- ------------------------------ ------------------------------ --------
      • For each (Integer integer_001) from 1 to 123, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • integer_001 Equal to (Point-value of (Unit-type(stringOrderCheck)))
            • Then - Actions
              • -------- ------------------------------ ------------------------------ --------
              • Game - Display to (All players) the text: stringOrderCheck
              • -------- ------------------------------ ------------------------------ --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • (GameVari_GoldTotal - GameVari_UnitGoldCost[(Point-value of (Unit-type(stringOrderCheck)))]) Greater than or equal to 0.00
                      • (GameVari_GoldTotal - GameVari_UnitLumberCost[(Point-value of (Unit-type(stringOrderCheck)))]) Greater than or equal to 0.00
                      • (GameVari_GoldTotal - GameVari_UnitIronCost[(Point-value of (Unit-type(stringOrderCheck)))]) Greater than or equal to 0.00
                • Then - Actions
                  • -------- ------------------------------ Deduct costs ------------------------------ --------
                  • Set GameVari_GoldTotal = (GameVari_GoldTotal - GameVari_UnitGoldCost[(Point-value of (Unit-type(stringOrderCheck)))])
                  • Set GameVari_LumberTotal = (GameVari_LumberTotal - GameVari_UnitLumberCost[(Point-value of (Unit-type(stringOrderCheck)))])
                  • Set GameVari_IronTotal = (GameVari_IronTotal - GameVari_UnitIronCost[(Point-value of (Unit-type(stringOrderCheck)))])
                  • -------- ------------------------------ ------------------------------ --------
                  • Trigger - Run Update multiboard <gen> (checking conditions)
                • Else - Actions
                  • Custom script: call IssueImmediateOrderById( GetTriggerUnit(), 851976 )
                  • Game - Display to (All players) the text: You are low on one ...
              • -------- ------------------------------ ------------------------------ --------
              • Set stringOrderCheck = <Empty String>
            • Else - Actions
This seem to be doing exactly what I need. The only thing is.
The "Custom script: call IssueImmediateOrderById( GetTriggerUnit(), 851976 )" in the last else does not cancel the building/trained unit.
Well not the FIRST building/unit that exceeds the current resources in stock.
The message is shown though: "You are low on one ..."

However.
If I click to train/build a second unit which exceed the current amount of resources the first will be canceled, but now this second one will continue to train/build.
 
I use a custom currency system and I want to cancel the construction if the player has insufficient funds.
If it is exactly this, then you only need to detect a point order.
The orderId will match the unt type id (raw code from object editor).

Side question, do you know about hashtables? It would help to make the lookup simpler.
 
If it is exactly this, then you only need to detect a point order.
The orderId will match the unt type id (raw code from object editor).

Side question, do you know about hashtables? It would help to make the lookup simpler.

No I also need to detect if a unit is trained.

I know very little of hashtables. I have used them for minor stuff but that's it. I would rather not dabble into that right now.
 
Without hashtables I can imagine similar like:

Setup:
  • Set DefaultUnitType[1] = SuperFootman
  • Set DefaultCustomCosts[1] = 500
  • ...
  • Set DefaultUnitType[2] = SuperDuperFootman
  • Set DefaultCustomCosts[2] = 1000
onOrder:
  • Custom script: set udg_UnitType = GetIssuedOrderId()
  • ---
  • For each (IntegerLoopInt) from 1 to 123, do (Actions)
    • Loop - Actions
      • If - UnitType == DefaultUnitType[LoopInt] Then
        • ---
        • --- Unit Type has matches , make checks /actions with DefaultCustomCosts
UnitType is a unittype variable. In JASS it will be seen as integer (it actually is), so we can it equal to GetIssuedOrderId(), which will return the current order id.

With hashtable it is without any loop. But you maybe should get it to work, and then you still can change/optimize it if needed.
 
Without hashtables I can imagine similar like:

But that already work. And yes it really is something like that I'm doing :)

I change the trigger so I now have two opening triggers instead.
Now I deduct resources when the actual construction of the building is begun instead of its building area is clicked. To avoid abuse.

The issue remain though. And this is what I need a solution to now.
The cancel script does not trigger on the first unit/building that exceeds the current amount of resources.
I think I know why. Because the unit trained/building constructed, is not being trained/constructed yet by the time the trigger reaches the cancel script.

Build building:
  • Unit Start Build
    • Events
      • Unit - A unit Begins construction
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 1 (Red)
    • Actions
      • Set stringOrderCheck = (String((Unit-type of (Constructing structure))))
      • Trigger - Run Unit Started Training <gen> (checking conditions)
Train Unit:
  • Unit Start Train
    • Events
      • Unit - A unit Is issued an order with no target
    • Conditions
      • (Owner of (Triggering unit)) Equal to Player 1 (Red)
    • Actions
      • Set stringOrderCheck = (String((Issued order)))
      • Trigger - Run Unit Started Training <gen> (checking conditions)
Check if sufficient funds:
  • Unit Started Training
    • Events
    • Conditions
    • Actions
      • -------- ------------------------------ ------------------------------ --------
      • For each (Integer integer_001) from 1 to 123, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • integer_001 Equal to (Point-value of (Unit-type(stringOrderCheck)))
            • Then - Actions
              • -------- ------------------------------ ------------------------------ --------
              • Game - Display to (All players) the text: stringOrderCheck
              • -------- ------------------------------ ------------------------------ --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • (GameVari_GoldTotal - GameVari_UnitGoldCost[(Point-value of (Unit-type(stringOrderCheck)))]) Greater than or equal to 0.00
                      • (GameVari_GoldTotal - GameVari_UnitLumberCost[(Point-value of (Unit-type(stringOrderCheck)))]) Greater than or equal to 0.00
                      • (GameVari_GoldTotal - GameVari_UnitIronCost[(Point-value of (Unit-type(stringOrderCheck)))]) Greater than or equal to 0.00
                • Then - Actions
                  • -------- ------------------------------ Deduct costs ------------------------------ --------
                  • Set GameVari_GoldTotal = (GameVari_GoldTotal - GameVari_UnitGoldCost[(Point-value of (Unit-type(stringOrderCheck)))])
                  • Set GameVari_LumberTotal = (GameVari_LumberTotal - GameVari_UnitLumberCost[(Point-value of (Unit-type(stringOrderCheck)))])
                  • Set GameVari_IronTotal = (GameVari_IronTotal - GameVari_UnitIronCost[(Point-value of (Unit-type(stringOrderCheck)))])
                  • -------- ------------------------------ ------------------------------ --------
                  • Trigger - Run Update multiboard <gen> (checking conditions)
                • Else - Actions
                  • Custom script: call IssueImmediateOrderById( GetTriggerUnit(), 851976 )
                  • Game - Display to (All players) the text: You are low on one ...
              • -------- ------------------------------ ------------------------------ --------
              • Set stringOrderCheck = <Empty String>
            • Else - Actions
 
The first should be a Point-Order event I believe.
What is with these point values? What are they used for?

Really?
I mean. I've just said the triggers work as I want them to.
The point values used are irrelevant and just refers to a "database" or real array if you wish. I would just like an answer or solution to my problem.

I just need to know why the cancel script is not canceling the first unit/building, trained/built, that exceeds the amount of resources in stock.
 
I'm not fully aware of all conditions yet, so it's not easy to say.
What I can imagine from your described scenario is that you:

1) build the building
2) train units

And I guess the bug only occurs in this "train units" event?
If so, it might be some mismatching behvaiour with order of execution
So I mean the "cancel" order maybe fires before the building starts training the unit.
So it makes "cancel", and then just trains the unit. If it is only 1 unit in training queue, it will seem like the "cancel" is ignored.
But if there are already some units in queue, then the "cancel" order will match and it will cancel the current train.
 
Oh ya. I forgot to mention that. For some reason the cancel order gets in front of the train order. I'm not sure how that happens but if you check with my order checker you get:

851976
custom_o001

The wait will fix this and at 0.00 should never cause any problem.

That explains the behavior, how odd as it may be.
So I think my trigger is working correctly now without any issues.

Thanks for the help :)
 
Status
Not open for further replies.
Top