• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Replace unit for last replaced unit (It's more complicated than that)

Status
Not open for further replies.
Level 2
Joined
May 2, 2016
Messages
9
Housing automatic upgrade system (Complicated problem) NEED HELP!

I am currently working on a city construction game style. For now, I want to upgrade my houses automatically every amount of times.

For example, if I build a tent (the first tier of housing), the tent will be replaced with a fortified tent, 60 seconds later. This is easily done. Then, I want the fortified tent to automatically be replaced with a house after another 60 second. The complicated thing is this: I want to replace this specific building that the worker has build, but I can only see this trigger to do this: Replace last replaced unit for a house.

If I build only one tent, this system work perfectly fine. But..

The problem with this is if I build many tent, the trigger will only replace the last replaced unit, so only the last tent that has been replaced into a fortified tent will be replaced into a house. All the other fortified tent will never be replaced into a house automatically since the trigger only replace the last replaced unit.

I didn't find any solution yet. Please help me out!

Currently, here is my trigger:


  • Events
    • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Constructed structure)) Equal to Tent
    • Actions
      • Wait 60.00 seconds
      • Unit - Replace (Constructed structure) with a Fortified Tent using The new unit's default life and mana
      • Special Effect - Create a special effect at (Position of (Constructed structure)) using Abilities\Spells\Other\Awaken\Awaken.mdl
      • Wait 90.00 seconds
      • Unit - Replace (Last replaced unit) with a Small Farm using The new unit's default life and mana
      • Special Effect - Create a special effect at (Position of (Constructed structure)) using Abilities\Spells\Other\Awaken\Awaken.mdl
 
Last edited:
Level 4
Joined
Apr 28, 2016
Messages
33
I think you should use variable, example:
- condition for create a house level 1
- for every 60 second event, replace house level 1
- set TempHouse = last replaced unit

Or if that a building, maybe you can use "upgrade building" in object editor, and use trigger to set time every 60 second to upgrade a house level 1, 2, and so on
 
Level 25
Joined
Sep 26, 2009
Messages
2,387
This can be easy if you globally upgrade buildings once every 60 seconds (this may upgrade a building that was up for e.g. 5 seconds only, because you upgrade all globally). It can be more complicated if you upgrade a building only after that specific building was up for 60 seconds, but still doable.

Instead of a unit variable I advise using unit group. When unit is replaced, check if it is correct unit type (e.g. if it is building) and put it into the unit group.
When you want to upgrade your buildings, pick all units in that unit group and upgrade them.
 
Level 2
Joined
May 2, 2016
Messages
9
@Crabas Sakti. That won't work because it will replace every house at the same time every 60 second. It's not supposed to be for every 60 second event. I don't want every building to upgrade instantaneously.

***It can be more complicated if you upgrade a building only after that specific building was up for 60 seconds, but still doable.***

This is exactly what I want. But you say it's doable? Do you know how to do it??
 
Last edited by a moderator:
Level 25
Joined
Sep 26, 2009
Messages
2,387
In that case you could use dynamic indexing.

What you would need for this:
2 triggers,
1 unit array (for buildings that will be replaced)
1 integer array (as a countdown timer for each building in the unit array)
1 integer variable (as an index so we know how many buildings are currently undergoing the 60 second phase)

The first trigger detects when building is replaced, the second trigger fires periodically (e.g. every second) and serves as a countdown timer for all buildings in the 60-second phase. There is a good tutorial on dynamic indexing found here http://www.hiveworkshop.com/forums/...orials-279/visualize-dynamic-indexing-241896/
 
Level 2
Joined
May 2, 2016
Messages
9
In that case you could use dynamic indexing.

What you would need for this:
2 triggers,
1 unit array (for buildings that will be replaced)
1 integer array (as a countdown timer for each building in the unit array)
1 integer variable (as an index so we know how many buildings are currently undergoing the 60 second phase)

The first trigger detects when building is replaced, the second trigger fires periodically (e.g. every second) and serves as a countdown timer for all buildings in the 60-second phase. There is a good tutorial on dynamic indexing found here http://www.hiveworkshop.com/forums/...orials-279/visualize-dynamic-indexing-241896/

But this will still make every building upgrade simultaneously every 60 seconds, there is no change at all. They will all upgrade simultaneously every 60 seconds of game time. And if a building just upgraded while the trigger has 10 seconds remaining before the loop of 60 seconds end, the house will upgrade after only 10 seconds!
 
Level 2
Joined
May 2, 2016
Messages
9
I have heard somewhere long ago that every single unit in the game has its own code. Even if two unit are the same type, they will each possess their own code. This way, my problem can maybe be solved. Unfortunately, I don't know much about this.

I also wonder if it's possible to run a single trigger many times at the same times (For each house that is currently in the game)?
 
Level 25
Joined
Sep 26, 2009
Messages
2,387
But this will still make every building upgrade simultaneously every 60 seconds, there is no change at all. They will all upgrade simultaneously every 60 seconds of game time. And if a building just upgraded while the trigger has 10 seconds remaining before the loop of 60 seconds end, the house will upgrade after only 10 seconds!
Nope, not at all. The tutorial about dynamic indexing shows just what you want - each instance (in this case each replaced building) has its own timer separate from others.

I may have confused you here. As a 60-second phase I meant the time the building "waits" before it gets replaced, not an event. The event for the loop trigger should fire for example every 1 seconds.
 
Level 2
Joined
May 2, 2016
Messages
9
Nope, not at all. The tutorial about dynamic indexing shows just what you want - each instance (in this case each replaced building) has its own timer separate from others.

I may have confused you here. As a 60-second phase I meant the time the building "waits" before it gets replaced, not an event. The event for the loop trigger should fire for example every 1 seconds.

I see what you did there. Ok I completely misunderstood you then, but now I think I start to understand more, since I started to read this tutorial. This is on a completely another level then!! Omg you must be one genius person to understand all of this! XD This stuff is so damn complicated for me.
 
You'll get it. It does about what you want. It gives each unit a number. Then it keeps track of stats that relate to that unit by using that number. In the end it de-indexes, so that it is only keeping track of units needed to perform the function.

I think I have a trigger that does something close to what you want. I will post it in a second.

  • Goblin birth animation
    • Events
      • Unit - A unit Begins construction
    • Conditions
      • Multiple ConditionsOr - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Constructing structure)) Equal to (==) Goblin Hut
          • (Unit-type of (Constructing structure)) Equal to (==) Goblin Factory
    • Actions
      • Set GH_Int = (GH_Int + 1)
      • Set GH_Counter[GH_Int] = 100
      • Set GH_Hut[GH_Int] = (Constructing structure)
      • Set GH_Loc[GH_Int] = (Position of GH_Hut[GH_Int])
      • Unit Group - Add GH_Hut[GH_Int] to GH_Group
        • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Unit-type of (Constructing structure)) Equal to (==) Goblin Hut
          • Then - Actions
            • Animation - Play GH_Hut[GH_Int]'s stand work animation
          • Else - Actions
      • Custom script: call RemoveLocation(udg_GH_Loc[udg_GH_Int])
      • Trigger - Turn on GH birth animation loop <gen>
  • GH birth animation loop
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Do Multiple ActionsFor each (Integer GH_LoopIndex) from 1 to GH_Int, do (Actions)
        • Loop - Actions
          • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • GH_Counter[GH_LoopIndex] Greater than (>) 0
              • (GH_Hut[GH_LoopIndex] is alive) Equal to (==) True
            • Then - Actions
              • Set GH_Fx[GH_LoopIndex] = (Last created special effect)
              • Set GH_Counter[GH_LoopIndex] = (GH_Counter[GH_LoopIndex] - 1)
                • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • (Unit-type of GH_Hut[GH_LoopIndex]) Equal to (==) Goblin Hut
                  • Then - Actions
                    • Animation - Change GH_Hut[GH_LoopIndex]'s size to ((60.00 - ((Real(GH_Counter[GH_LoopIndex])) x 0.60))%, 100.00%, 100.00%) of its original size
                  • Else - Actions
              • Special Effect - Create a special effect attached to the origin of GH_Hut[GH_LoopIndex] using Objects\Spawnmodels\Undead\ImpaleTargetDust\ImpaleTargetDust.mdl
              • Set GH_Fx[GH_LoopIndex] = (Last created special effect)
              • Special Effect - Destroy GH_Fx[(GH_LoopIndex - 1)]
            • Else - Actions
              • Special Effect - Destroy GH_Fx[GH_LoopIndex]
              • Unit Group - Remove GH_Hut[GH_LoopIndex] from GH_Group
              • Set GH_Hut[GH_LoopIndex] = No unit
                • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • (Number of units in GH_Group) Equal to (==) 0
                  • Then - Actions
                    • Trigger - Turn off (This trigger)
                    • Set GH_Int = 0
                  • Else - Actions
Note: This (Set GH_Int = 0) is an imperfect de-index. It is better to follow the method of the tutorial.


This created an animated birth sequence for building a Goblin Hut or Factory. It made them start small and grow until full size. I added some dust to show more of a work effect.

Here are some other ways I found to do a work-around without dynamic indexing.

  • UD Birth
    • Events
      • Unit - A unit Begins construction
    • Conditions
      • (Unit-type of (Constructing structure)) Equal to (==) Corruption Tower
    • Actions
      • Set tempp1 = (Position of (Constructing structure))
      • Unit - Create 1 Build Dummy for Neutral Passive at tempp1 facing Default building facing (270.0) degrees
      • Unit - Add a 37.00 second Generic expiration timer to (Last created unit)
      • Animation - Change (Last created unit)'s vertex coloring to (70.00%, 100.00%, 100.00%) with 0.00% transparency
      • Special Effect - Create a special effect attached to the origin of (Last created unit) using SharedModels\UBirth.mdl
      • Set T_Fx[(Integer((X of tempp1)))] = (Last created special effect)
      • Custom script: call RemoveLocation(udg_tempp1)
  • Birth Animation Stop
    • Events
      • Unit - A unit Finishes construction
      • Unit - A unit Cancels construction
      • Unit - A unit Dies
    • Conditions
      • Multiple ConditionsOr - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Triggering unit)) Equal to (==) Pandaren Hut
          • (Unit-type of (Triggering unit)) Equal to (==) Death Tower
          • (Unit-type of (Constructing structure)) Equal to (==) Corruption Tower
    • Actions
      • Set tempp1 = (Position of (Triggering unit))
      • Special Effect - Destroy T_Fx[(Integer((X of tempp1)))]
      • Custom script: call RemoveLocation(udg_tempp1)


See how I used the x value of the position to create an index. It's totally cheating and if someone built again on the same x axis then you might get a bug. However, I never had this happen in all of my tests. This trigger was intended to add the actual birth animation models to build units without the animation.

I used special effects in this second demo but you can use units the same way.
 
Level 2
Joined
May 2, 2016
Messages
9
I started to understand everything except for one variable: GH_LoopIndex, or in the tutorial it's SL_Loop_Integer. What type of variable is it? And why do you not set the variable in any trigger? I only see this variable in the condition.
 
You can use (Loop for integer A) but that is not recommended. It's a preset. We create a new integer variable so that if multiple triggers run loops they don't interfere with eachother. I often name this variable Loop_A. It's default is 0 as with all integer variables and the loop sets it as 1, 2, 3, 4, etc. until it reaches the limit, which is often another variable. But it could just loop from 1 to 10. It is a very handy function.
 
Level 2
Joined
May 2, 2016
Messages
9
I have finally solved the problem!!!! Thank to you guys!! Here is what I did!!

I use one trigger for every houses upgrade. If I have 10 upgrades for housing, there will be 10 triggers total.

  • House1
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Constructed structure)) Equal to Tent
    • Actions
      • Set SL_index = (SL_index + 1)
      • Set House_upgrade[SL_index] = (Constructed structure)
      • Set Upgrade_Counter[SL_index] = 0
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SL_index Equal to 1
        • Then - Actions
          • Trigger - Turn on house upgrade <gen>
        • Else - Actions
  • house upgrade
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer SL_loop_integer) from 1 to SL_index, do (Actions)
        • Loop - Actions
          • Set Upgrade_Counter[SL_loop_integer] = (Upgrade_Counter[SL_loop_integer] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Upgrade_Counter[SL_loop_integer] Greater than or equal to 10
            • Then - Actions
              • Unit - Replace House_upgrade[SL_loop_integer] with a Fortified Tent using The new unit's default life and mana
              • Special Effect - Create a special effect at (Position of House_upgrade[SL_loop_integer]) using Abilities\Spells\Other\Awaken\Awaken.mdl
              • Set SL_index1 = (SL_index1 + 1)
              • Set House_upgrade1[SL_index1] = (Last replaced unit)
              • Set Upgrade_Counter1[SL_index1] = 0
              • -------- UPGRADES1 VARIABLES RESET --------
              • Set House_upgrade[SL_loop_integer] = House_upgrade[SL_index]
              • Set Upgrade_Counter[SL_loop_integer] = Upgrade_Counter[SL_index]
              • Set SL_index = (SL_index - 1)
              • Set SL_loop_integer = (SL_loop_integer - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SL_index Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SL_index1 Equal to 1
        • Then - Actions
          • Trigger - Turn on house upgrade Copy <gen>
        • Else - Actions
  • house upgrade 2
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer SL_loop_integer1) from 1 to SL_index1, do (Actions)
        • Loop - Actions
          • Set Upgrade_Counter1[SL_loop_integer1] = (Upgrade_Counter1[SL_loop_integer1] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Upgrade_Counter1[SL_loop_integer1] Greater than or equal to 10
            • Then - Actions
              • Unit - Replace House_upgrade1[SL_loop_integer1] with a Small Farm using The new unit's default life and mana
              • Special Effect - Create a special effect at (Position of House_upgrade1[SL_loop_integer1]) using Abilities\Spells\Other\Awaken\Awaken.mdl
              • -------- UPGRADES1 VARIABLES RESET --------
              • Set House_upgrade1[SL_loop_integer1] = House_upgrade1[SL_index1]
              • Set Upgrade_Counter1[SL_loop_integer1] = Upgrade_Counter1[SL_index1]
              • Set SL_index1 = (SL_index1 - 1)
              • Set SL_loop_integer1 = (SL_loop_integer1 - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SL_index1 Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
and so on.. 10 times total.
 
If I'm right, local variable are pretty much the easiest solution?

local unit u = Constructed Structure? and then within a custom script
set udg_myUnit = u
Replace myUnit which should link to local unit which is independant of each occurence of your trigger

But then again, the margin of error in wait can be daunting for some. Plus using Dynamic Indexing is a good practice.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
I feel that a 60 second wait is quite a lot for dynamic indexing with a 1 second interval... which doesnt give you properly timed upgrades if you ask me :D

Working with timers or local variables is the best practise in this case.

If you dont want to do that, you should at least merge the triggers with the same events:
house upgrade and house upgrade 2 can very easily be in one trigger.
Better yet, you could make one nice trigger that would do all different upgrades if you store the upgraded building type in variables as well.
 
Status
Not open for further replies.
Top