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

Status
Not open for further replies.
Level 2
Joined
May 18, 2018
Messages
12
So I was making a trigger that would let my own base unit producing buildings to auto-train the unit that I had chosen and will continue to do so unless I cancel the progress then the loop will stop.
It worked but there is one problem I can't upgrade the town hall (or other main bases buildings to unlock the next tier unit if I had trained a peasant there)
So how do I fix this
Capture.PNG

here is the trigger that I used.
 
Level 39
Joined
Feb 27, 2007
Messages
5,021
Post triggers by right-clicking and selecting "copy as text" then paste here between [trigger][/trigger] tags instead of having to upload screenshots. Your problem is you picked "all units owned by player 1" and ordered them to train another, rather than just ordering the base unit that trained it. Instead use this action:

Unit - Order (Triggering unit) to train/upgrade to a (Trained unit-type)
 
Level 2
Joined
May 18, 2018
Messages
12
Post triggers by right-clicking and selecting "copy as text" then paste here between [trigger][/trigger] tags instead of having to upload screenshots. Your problem is you picked "all units owned by player 1" and ordered them to train another, rather than just ordering the base unit that trained it. Instead use this action:

Unit - Order (Triggering unit) to train/upgrade to a (Trained unit-type)
Still had the bug bud. I tested it with Townhall after training a peasant can't upgrade to Keep, the icon just goes dark, you can't click it.
 
Level 39
Joined
Feb 27, 2007
Messages
5,021
I tested it with Townhall after training a peasant can't upgrade to Keep, the icon just goes dark, you can't click it.
Never run into this before but it's definitely some sort of bug where constantly looping the train order like that gets any building that can upgrade stuck thinking its constantly training units and never re-enables the ability to upgrade. The upgrade should only be disabled while the building is training a unit, but for some reason it's not going back to normal status when the build queue is cleared. If you put a "Wait 0.00 seconds" (not actually a 0 second wait, but it waits the minimum) before reissuing the order it works just fine. TriggerExecute, TriggerEvaluate, and ExecuteFunc() seem not to work here (no idea why) but a 0.00 timeout timer gets the training to work just fine.

The only problem you run into is that if multiple buildings create a unit at exactly the same moment (double click your town hall to select them all then click train a peasant and all of them will get a unit in their build queue simultaneously which then is trained simultaneously) only 1 of them will continue to autobuild. Even if you manually add more units to each building's queue they won't make more once the queue is finished. If you desynch the building slightly by starting one Town Hall building peasants before another one then they can all be autobuilding simultaneously. If nobody has a workaround to suggest (I don't see one if the other execute methods don't work) and this severly impacts your map (lots of players group buildings via hotkeys and build large armies simultaneously from them) Only way I see to avoid this issue is to handle upgrades through triggers rather than using wc3's basic building upgrade system.

You'll need 3 global variables and two triggers:
  • Autobuild Loop
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
      • -------- Other conditions you want --------
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempUType = (Unit-type of (Trained unit))
      • Countdown Timer - Start TempTimer as a One-shot timer that will expire in 0.00 seconds
  • Autobuild Timer
    • Events
      • Time - TempTimer expires
    • Conditions
    • Actions
      • Unit - Order TempUnit to train/upgrade to a TempUType
 
I also think Pyrogasm is right that it requires some timeout. Not sure you're okay with a custom script line, but if you're interested you alternatively to Pyrogasm's way could check out the demo here, TrainingDetection. The system is for cases like this actually, that you can safely make an order after a 0-wait time, or some longer and to get the last trained unit type.

The usage would look something like:
  • Auto-Train
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
    • Actions
      • Wait 0.00 seconds
      • Set u = (Triggering unit)
      • Custom script: call IssueImmediateOrderById(udg_u, GetLastTrainedObjectId(udg_u))
(only the unit variable needs to be changed in case of other usage)
The con is, you need to import jass libraries.
The pro is, you can also train "last unit type" not dependant from a static timeout, but also for example if new food cap gets free, or so.
 
Level 39
Joined
Feb 27, 2007
Messages
5,021
And if you don't wanna use Bo's system heres the "GUI" version that works for any number of units training simultaneously. The GUI implementation of timers is so fucked up that even if you shadow a global timer variable as a local there's no way to get it to actually run anything when it expires. Add to that you can't guarantee 1 trigger goes in war3map.j above another so you can TimerStart() to its action function, can't get handle keys of variables (only event responses) and that you can't save unit-type in a hashtable even though they're just integers... you end up with this abomination. I don't believe anything in the cs lines has to be edited to match variables, as I used bj_lastStartedTimer there.

  • AutoTrain Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set AutoTrainHash = (Last created hashtable)
  • AutoTrain Order
    • Events
      • Unit - A unit Finishes training a unit
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempUnit2 = (Trained unit)
      • Custom script: call ExecuteFunc("AutoTrain_StartForReal")
      • Custom script: endfunction
      • -------- - --------
      • -------- - --------
      • Custom script: function AutoTrain_Finish takes nothing returns nothing
      • Custom script: set bj_lastStartedTimer = GetExpiredTimer()
      • Set TempInt = (Key (Expiring timer))
      • Unit - Order (Load 0 of TempInt in AutoTrainHash) to train/upgrade to a (Unit-type of (Load 1 of TempInt in AutoTrainHash))
      • Hashtable - Clear all child hashtables of child TempInt in AutoTrainHash
      • Custom script: call DestroyTimer(bj_lastStartedTimer)
      • Custom script: endfunction
      • -------- - --------
      • -------- - --------
      • Custom script: function AutoTrain_StartForReal takes nothing returns nothing
      • Custom script: set bj_lastStartedTimer = NewTimer()
      • Custom script: call TimerStart(bj_lastStartedTimer, 0.00, false, function AutoTrain_Finish)
      • Set TempInt = (Key (Last started timer))
      • Hashtable - Save Handle OfTempUnit as 0 of TempInt in AutoTrainHash
      • Hashtable - Save Handle OfTempUnit2 as 1 of TempInt in AutoTrainHash
 
Status
Not open for further replies.
Top