• 🏆 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] CPU Trains Units Trigger - not working

Level 18
Joined
Mar 16, 2008
Messages
721
CPU player has 4 archers that players can use to help them. When one of these dies these triggers are supposed to train another and re-order it to the original guard positions. For some reason, when udg_sentinel[3] dies, it trains 3 more archers and doesn't order them to move anywhere. I'm really stumped by this.

Any feedback would be appreciated:
  • sentinel dies 1a
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Dies
    • Conditions
      • (Dying unit) Equal to sentinels[1]
      • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
      • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
    • Actions
      • Set VariableSet sentinels[1] = No unit
      • Unit - Order Sentinel's Outpost 0221 <gen> to train/upgrade to a Archer
  • sentinel dies 1b
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Dies
    • Conditions
      • (Dying unit) Equal to sentinels[2]
      • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
      • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
    • Actions
      • Set VariableSet sentinels[2] = No unit
      • Unit - Order Sentinel's Outpost 0221 <gen> to train/upgrade to a Archer
  • sentinel dies 2a
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Dies
    • Conditions
      • (Dying unit) Equal to sentinels[3]
      • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
      • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
    • Actions
      • Set VariableSet sentinels[3] = No unit
      • Unit - Order Sentinel's Outpost 0222 <gen> to train/upgrade to a Archer
  • sentinel dies 2b
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Dies
    • Conditions
      • (Dying unit) Equal to sentinels[4]
      • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
      • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
    • Actions
      • Set VariableSet sentinels[4] = No unit
      • Unit - Order Sentinel's Outpost 0222 <gen> to train/upgrade to a Archer
  • sentinel trained 3 east
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • (Triggering unit) Equal to Sentinel's Outpost 0221 <gen>
    • Actions
      • AI - Ignore (Trained unit)'s guard position
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • sentinels[1] Equal to No unit
        • Then - Actions
          • Set VariableSet sentinels[1] = (Trained unit)
          • Unit - Order sentinels[1] to Attack-Move To sentinel_loc[1]
          • Skip remaining actions
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • sentinels[2] Equal to No unit
        • Then - Actions
          • Set VariableSet sentinels[2] = (Trained unit)
          • Unit - Order sentinels[2] to Attack-Move To sentinel_loc[2]
          • Skip remaining actions
        • Else - Actions
  • sentinel trained 3 west
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • (Triggering unit) Equal to Sentinel's Outpost 0222 <gen>
    • Actions
      • AI - Ignore (Trained unit)'s guard position
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • sentinels[3] Equal to No unit
        • Then - Actions
          • Set VariableSet sentinels[3] = (Trained unit)
          • Unit - Order sentinels[3] to Attack-Move To sentinel_loc[3]
          • Skip remaining actions
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • sentinels[4] Equal to No unit
        • Then - Actions
          • Set VariableSet sentinels[4] = (Trained unit)
          • Unit - Order sentinels[4] to Attack-Move To sentinel_loc[4]
          • Skip remaining actions
        • Else - Actions
also
  • init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet sentinels[1] = Archer 0217 <gen>
      • Set VariableSet sentinels[2] = Archer 0216 <gen>
      • Set VariableSet sentinels[3] = Archer 0218 <gen>
      • Set VariableSet sentinels[4] = Archer 0219 <gen>
 
Level 12
Joined
Jan 10, 2023
Messages
191
I have some feedback and I put together a concept of this system that you could try out if you want, there were a few 'improvements' I made related to my feedback.

Feedback:
First and foremost, I hope you know what you're doing with the AI because I will be zero help there, and simply mimicked what I saw you doing.

I didn't ever figure out what exactly was causing your issue, but it may have had something to do with the first 'potential problem' I found in this trigger, but if not maybe there is some other trigger in your map that is messing with the sentinel[#] variables ? hard to say, I didn't have the issue, although I did have to work through some of my own.

A great tip for working out your bugs is to add displayed messages to your triggers to tell you what parts are running and what parts didn't seem to work right.
  • Game - Display to (All players) the text: This Action Happened!
Other than that, here in this trigger I think you have some potential problems that you didn't seem to notice.
  • sentinel dies 1a
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Dies
    • Conditions
      • (Dying unit) Equal to sentinels[1]
      • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
      • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
    • Actions
      • Set VariableSet sentinels[1] = No unit
      • Unit - Order Sentinel's Outpost 0221 <gen> to train/upgrade to a Archer
Four things about this trigger:
1. If Player 10 doesn't have enough Gold or Lumber, then sentinels[1] doesn't get set equal 'No Unit', same for all sentinels[1-4].
2. Can Player 10 get more Gold or Lumber somehow? If so, then we have the problem that Player 10 doesn't know what Sentinel to train or which outpost to train them at when they do get the Gold or Lumber later.
3. What about food? Do Archers cost zero food? Is there no way Player 10 could run out of food?
4. Do Archers need to cost Gold and Lumber? It really isn't a big deal, but having them use only one resource could have made one of my triggers a little bit better.. anyway it doesn't matter much. I'll point it out below in my comments when it comes up.

I could give more general feedback but I think a lot of that will be stated by the difference between how I made my version that I will share below:

To give an overview, I reduced the number of triggers by combining the triggers that share common events, I could explain when and why you would do this in more detail. This isn't always what you want to do, but in this case I recommend it.

My system assumes that Player 10 could acquire additional Gold or Lumber after the fact and it also assumes food shortage will not become a factor. If either of these are not true, changes will need to be made.

I added some new variables so here's an updated list of all of them:
unit array - sentinels
point array - sentinel_loc
unit array - outposts
integer array - outpostGuardCount
integer array - outpostQueue
integer - queueSize

And the triggers:
Init
  • Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- The resources were just for testing so that four sentinels would respawn before I have to type 'greedisgood 130' --------
      • Player - Set Player 10 (Light Blue).Current gold to 520
      • Player - Set Player 10 (Light Blue).Current lumber to 40
      • -------- If you don't mind starting with zero, it's going to help our numbers a lot --------
      • -------- Plus this will help you scale this system up to include more Outposts or Sentinels per Outpost --------
      • Set VariableSet sentinels[0] = Archer 0000 <gen>
      • Set VariableSet sentinels[1] = Archer 0001 <gen>
      • Set VariableSet sentinels[2] = Archer 0002 <gen>
      • Set VariableSet sentinels[3] = Archer 0003 <gen>
      • -------- Let's make these varables, it will help later. Plus you could add Ouposts more easily --------
      • Set VariableSet outposts[0] = Ancient of War 0004 <gen>
      • Set VariableSet outposts[1] = Ancient of War 0005 <gen>
      • -------- If you increase the number of Sentinels per Outpost, increase it here too --------
      • Set VariableSet outpostGuardCount[0] = 2
      • Set VariableSet outpostGuardCount[1] = 2
      • -------- If you start to add many more Outposts or Sentinels, we should restructure this trigger into a loop --------
      • -------- I'm not sure what kind of AI you're using, but if you are doing this later in yor triggers, I'm assuming you should also do it here --------
      • -------- I might be mistaking, like I said, the AI is what I know the least about --------
      • AI - Ignore sentinels[0]'s guard position
      • AI - Ignore sentinels[1]'s guard position
      • AI - Ignore sentinels[2]'s guard position
      • AI - Ignore sentinels[3]'s guard position
      • Set VariableSet sentinel_loc[0] = (Position of sentinels[0])
      • Set VariableSet sentinel_loc[1] = (Position of sentinels[1])
      • Set VariableSet sentinel_loc[2] = (Position of sentinels[2])
      • Set VariableSet sentinel_loc[3] = (Position of sentinels[3])

Sentinel Dies
  • Sentinel Dies
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Dies
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Dying unit) Equal to sentinels[0]
          • (Dying unit) Equal to sentinels[1]
          • (Dying unit) Equal to sentinels[2]
          • (Dying unit) Equal to sentinels[3]
    • Actions
      • -------- We use the Or condition above so that if some non sentinel unit owned by Player 10 dies, we don't bother with all of this --------
      • -------- It's hard to tell if this is necessary from my perspective, so you'll have to decide. --------
      • -------- The following Loop needs to start at the lowest number Sentinel (currently '0') and end at the highest number Sentinel (currently '3') --------
      • For each (Integer A) from 0 to 3, do (Actions)
        • Loop - Actions
          • -------- Here we again check if the unit was Sentinel, but now we are determining which Sentinel it is --------
          • -------- If Player 10 has only a few units, we could skip the Or conditions and just jump right to this If/Then/Else Action inside the Loop Integer A Action --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Dying unit) Equal to sentinels[(Integer A)]
            • Then - Actions
              • Set VariableSet sentinels[(Integer A)] = No unit
              • -------- This is a debug message, you should delete it --------
              • Game - Display to (All players) the text: (Sentinel: |cffffff00 + ((String((Integer A))) + |r has died))
              • -------- If Player 10 has the resources and the Sentinel Queue is empty, they will immediately begin training a Sentinel at the appropriate Outpost --------
              • -------- Otherwise, the Sentinel will be added to the Sentinel Queue --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
                  • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
                  • queueSize Equal to 0
                • Then - Actions
                  • -------- This is a debug message, you should delete it --------
                  • Game - Display to (All players) the text: |rImmediate Respawn...
                  • -------- This is where making the Outposts into variables and changing the way we number our variable index pays off --------
                  • -------- If Sentinel[0] or Sentinel[1], then 0/2=0 and 1/2=0 (because 0.5 isn't an Integer and so it rounds down --------
                  • -------- If Sentinel[2] or Sentinel[3], then 2/2=1 and 3/2=1 (because 1.5 isn't an Integer and so it rounds down --------
                  • -------- You're going to see this trick a lot, so I'm not going to explain it every time --------
                  • -------- To increase the number of Sentinels per Outpost, change ((Integer A) / 2) to ((Integer A) / 3) --------
                  • -------- You have to make some more changes below in the 'Else' section --------
                  • -------- You will also have to make similar changes to the other triggers, it is explained in each of those trigger's comments --------
                  • Unit - Order outposts[((Integer A) / 2)] to train/upgrade to a Archer
                • Else - Actions
                  • -------- I'll explain the Sentinel Queue more in the Sentinel Queue trigger --------
                  • -------- To increase the number of Sentinels per Outpost, change all ((Integer A) / 2)s to ((Integer A) / 3) --------
                  • -------- You have to make some more changes above in the 'Then' section --------
                  • -------- You will also have to make similar changes to the other triggers, it is explained in each of those trigger's comments --------
                  • Set VariableSet queueSize = (queueSize + 1)
                  • Set VariableSet outpostQueue[queueSize] = ((Integer A) / 2)
                  • Set VariableSet outpostGuardCount[((Integer A) / 2)] = (outpostGuardCount[((Integer A) / 2)] - 1)
                  • -------- This is a debug message, you should delete it --------
                  • Game - Display to (All players) the text: |rAdded to Queue
                  • Trigger - Turn on Sentinel Queue <gen>
            • Else - Actions

Sentinel Trained
  • Sentinel Trained
    • Events
      • Unit - A unit owned by Player 10 (Light Blue) Finishes training a unit
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Triggering unit) Equal to outposts[0]
          • (Triggering unit) Equal to outposts[1]
    • Actions
      • -------- If you add more Outposts, you will need to add them to the Or condition above --------
      • -------- This will likely seem like overkill or unnecessary, but like I said, I was aiming for it to be scalable --------
      • -------- The following Loop needs to start at the lowest number Outpost (currently '0') and end at the highest number Outpost (currently '1') --------
      • For each (Integer A) from 0 to 1, do (Actions)
        • Loop - Actions
          • -------- Here we again check if the training unit was an Outpost, but now we are determining which Outpost it is --------
          • -------- If Player 10 has only a few units that can train units, we could skip the Or conditions and just jump right to this If/Then/Else Action inside the Loop Integer A Action --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering unit) Equal to outposts[(Integer A)]
            • Then - Actions
              • -------- Again, just copying what I saw with AI --------
              • AI - Ignore (Trained unit)'s guard position
              • -------- This first If/Then/Else checks if the first of the two Sentinels exists, if not then the new unit becomes the first Sentinel --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • sentinels[((Integer A) x 2)] Equal to No unit
                • Then - Actions
                  • Set VariableSet sentinels[((Integer A) x 2)] = (Trained unit)
                  • -------- This is a debug message, you should delete it --------
                  • Game - Display to (All players) the text: (|rSpawning Sentinel: |cffffff00 + (String(((Integer A) x 2))))
                  • Unit - Order (Trained unit) to Attack-Move To sentinel_loc[((Integer A) x 2)]
                  • Skip remaining actions
                • Else - Actions
              • -------- This first If/Then/Else checks if the second of the two Sentinels exists, if not then the new unit becomes the second Sentinel --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • sentinels[(((Integer A) x 2) + 1)] Equal to No unit
                • Then - Actions
                  • Set VariableSet sentinels[(((Integer A) x 2) + 1)] = (Trained unit)
                  • -------- This is a debug message, you should delete it --------
                  • Game - Display to (All players) the text: (|rSpawning Sentinel: |cffffff00 + (String((((Integer A) x 2) + 1))))
                  • Unit - Order (Trained unit) to Attack-Move To sentinel_loc[(((Integer A) x 2) + 1)]
                  • Skip remaining actions
                • Else - Actions
              • -------- If we wanted to add a third Sentinel to each base, change all the ((Integer A) x 2)s to ((Integer A) x 3) --------
              • -------- And then make a new If/Then/Else like the one above but change all of the (((Integer A) x 3) + 1 )s to (((Integer A) x 3) + 2) --------
              • -------- Or simply remove the Condition below that says, 'True Equal to False' and make the other necessary changes --------
              • -------- Repeat this pattern for more Sentinels, increase the mulitple to the total Sentinels per Outpost, and add an If/Then/Else for the Sentinal, increasing the constant --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • True Equal to False
                  • sentinels[(((Integer A) x 3) + 2)] Equal to No unit
                • Then - Actions
                  • Set VariableSet sentinels[(((Integer A) x 3) + 2)] = (Trained unit)
                  • -------- This is a debug message, you should delete it --------
                  • Game - Display to (All players) the text: (|rSpawning Sentinel: |cffffff00 + (String((((Integer A) x 3) + 2))))
                  • Unit - Order (Trained unit) to Attack-Move To sentinel_loc[(((Integer A) x 3) + 2)]
                  • Skip remaining actions
                • Else - Actions
              • -------- You will also have to make similar changes to the other triggers, it is explained in each of those trigger's comments --------
            • Else - Actions

Sentinel Queue
  • Sentinel Queue
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
      • (Player 10 (Light Blue) Current gold) Greater than or equal to 130
      • (Player 10 (Light Blue) Current lumber) Greater than or equal to 10
    • Actions
      • -------- This turns off the Sentinel Queue when it is empty --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • queueSize Equal to 0
        • Then - Actions
          • -------- This is a debug message, you should delete it --------
          • Game - Display to (All players) the text: |rEnd of Unit Queue
          • Trigger - Turn off (This trigger)
          • Skip remaining actions
        • Else - Actions
          • -------- This is a debug message, you should delete it --------
          • Game - Display to (All players) the text: |rSelecting Queued ...
      • -------- This first check is determining whether the next Sentinel in line to respawn has another Sentinel at its Outpost --------
      • -------- If there is no other Sentinel, this Outpost needs a Sentinel right away --------
      • -------- But if there is a Sentinel at this Outpost, we should check if another Outpost needs one more --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • outpostGuardCount[outpostQueue[1]] Equal to 0
        • Then - Actions
          • -------- Turns out the first Outpost did need a Sentinel right away --------
          • Unit - Order outposts[outpostQueue[1]] to train/upgrade to a Archer
          • Set VariableSet outpostGuardCount[outpostQueue[1]] = (outpostGuardCount[outpostQueue[1]] + 1)
          • -------- This is a debug message, you should delete it --------
          • Game - Display to (All players) the text: (|rTraining queued Archer at Priority FIFO Outpost: |cffffff00 + (String(outpostQueue[1])))
          • -------- This Loop for Integer A from 1 to queueSize is shifting the Sentinels in the queue and removing this one --------
          • For each (Integer A) from 1 to queueSize, do (Actions)
            • Loop - Actions
              • Set VariableSet outpostQueue[(Integer A)] = outpostQueue[((Integer A) + 1)]
          • -------- Lastly, we reduce the queue size --------
          • Set VariableSet queueSize = (queueSize - 1)
        • Else - Actions
          • -------- Turns out the first Outpost did NOT need a Sentinel right away --------
          • -------- Let's check if another Outpost needs a Sentinel more --------
          • For each (Integer A) from 2 to queueSize, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • outpostGuardCount[outpostQueue[(Integer A)]] Equal to 0
                • Then - Actions
                  • -------- Turns out the another Outpost did need a Sentinel more --------
                  • Unit - Order outposts[outpostQueue[(Integer A)]] to train/upgrade to a Archer
                  • Set VariableSet outpostGuardCount[outpostQueue[(Integer A)]] = (outpostGuardCount[outpostQueue[(Integer A)]] + 1)
                  • -------- This is a debug message, you should delete it --------
                  • Game - Display to (All players) the text: (|rTraining queued Archer at Priority Non-FIFO Outpost: |cffffff00 + (String(outpostQueue[(Integer A)])))
                  • -------- This Loop for Integer B from 2 to queueSize is shifting the Sentinels in the queue and removing this one --------
                  • For each (Integer B) from 2 to queueSize, do (Actions)
                    • Loop - Actions
                      • Set VariableSet outpostQueue[(Integer B)] = outpostQueue[((Integer B) + 1)]
                  • -------- We reduce the queue size --------
                  • Set VariableSet queueSize = (queueSize - 1)
                  • -------- We skip the remaining actions because otherwise it's big waste of time and asking for trouble --------
                  • Skip remaining actions
                • Else - Actions
          • -------- If the trigger is still running, that means that no Priority Outpost was found --------
          • -------- If a Priority Outpost was found, it would have skipped the remaining actions and the trigger would be over --------
          • -------- So since there is no Priority, we will just go with FIFO, or would it be FOFI ? --------
          • Unit - Order outposts[outpostQueue[1]] to train/upgrade to a Archer
          • Set VariableSet outpostGuardCount[outpostQueue[1]] = (outpostGuardCount[outpostQueue[1]] + 1)
          • -------- This is a debug message, you should delete it --------
          • Game - Display to (All players) the text: (|rTraining queued Archer at Non-Priority FIFO Outpost: |cffffff00 + (String(outpostQueue[1])))
          • -------- This Loop for Integer A from 1 to queueSize is shifting the Sentinels in the queue and removing this one --------
          • For each (Integer A) from 1 to queueSize, do (Actions)
            • Loop - Actions
              • Set VariableSet outpostQueue[(Integer A)] = outpostQueue[((Integer A) + 1)]
          • -------- Lastly, we reduce the queue size, no need to skip any remaining actions this time.. --------
          • Set VariableSet queueSize = (queueSize - 1)

As for what I said about using only one resource:
If the Archer only used Gold, then in the trigger 'Sentinel Queue' we could use this event:
  • Player - Player 10 (Light Blue)'s Current gold becomes Greater than or equal to 130.00
Instead of this event:
  • Time - Every 0.50 seconds of game time
As it stands, using both Gold and Lumber, we would have to use both of these events to achieve the same result:
  • Player - Player 10 (Light Blue)'s Current gold becomes Greater than or equal to 130.00
  • Player - Player 10 (Light Blue)'s Current lumber becomes Greater than or equal to 10.00
But if Player 10 somehow suddenly gets enough resources for two Sentinels at the same time, this trigger would fire for the Gold and for the Lumber, and then when a Unit begins training, it would fire twice more, because the Gold changed to something greater than 130, and the Lumber changed to something greater than 10...

That is why I made it work on a timer, but I think it would be better if it worked based on a single resource because then the units would begin training as soon as possible, without delay. The timed queue system I made takes 0.50 seconds between each unit spawn.

On the other hand, if it is unlikely that Player 10 even suddenly gets several hundred Gold (260+) at a time, it shouldn't be an issue. Then again, this could be as easy as selling an item.
 

Attachments

  • Sentinel Respawn Demo.w3m
    29.2 KB · Views: 1
Last edited:
Top