• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Make units return to starting point and facing angle

Status
Not open for further replies.
Level 6
Joined
Jan 16, 2013
Messages
68
Ok, so in a map I am making I have these computer controlled units. Normally, after they finish fighting they go back to where they were. However, sometimes they don't go back exactly where they were but instead some nearby point. Also they don't face the same angle as before.

Now, what I want is to make it so that every computer controlled unit(even ones that spawn later in the game) goes back to the last position AND angle it is ordered to move to using triggers. Basically, I want to make it so that those units always have a special point and angle they face that can only be changed using triggers.

I want them to go to their points and face their angles whenever they finish a fight( maybe whenever their order becomes stop or none).

Currently, I have no idea how to do that, so if someone could show me the exact triggering required or at least give me advice on how to do so then please help me! I will also give you credits in my map if I ever actually finish it.

Thank you!
 
Level 7
Joined
Jul 20, 2009
Messages
295
  • Before entering fight
    • Events
    • Conditions
    • Actions
      • Set Location[1] = (Position of (unit 1)) // Point
      • Set FacingAngle[1] = (Facing of (unit 1)) // Real
      • Set TempLocation = (Center of (Battle Field)) // Point
      • Unit - Move (unit 1) instantly to TempLocation, facing Default building facing degrees
      • Custom script: call RemoveLocation(udg_TempLocation)
  • After finishing fight
    • Events
    • Conditions
    • Actions
      • Unit - Move (unit 1) instantly to Location[1], facing FacingAngle[1] degrees
      • Custom script: call RemoveLocation(udg_Location[1])
 
ur best bet would be to store all created units in a hashtable with there location and facing angle.

u should store all units that enter map area into a unit group. ( dont destroy this group / dont use it for anything else)
when unit dies or is removed u remove the unit from the group.
doing this with hashtable u can use there key value or u can use the custom value if u use a unit indexer.

then in a periodic trigger u check all units in a group and if there order is equal to stop u move them back to that location and make them face the angle.
 
Level 6
Joined
Jan 16, 2013
Messages
68
Ok, so I figured some of it out. Now, I believe that the triggers are mostly correct except for one important issue I cannot solve.

How do I detect if a unit is idle?
I tried testing for units whose order is stop or none or whose order isn't move or attack but that doesn't work.

I was thinking about giving them all shadow meld and detect if they have the buff. However I don't want the ability to actually make them invisible and I want it to apply the buff day and night but I believe that is impossible.

So, my question now is: How to detect if a unit is idle?
 
Level 6
Joined
Jan 16, 2013
Messages
68
This appears to have the same effect that current order = none did.
When the units get in range with some undead creeps they engage. However, their order seems to be <Empty String> after engaging too. The undead creeps seem to be fine. Probably because they were ordered to attack-move to a point. I believe that Blizzard's AI doesn't actually give its units orders unless specified by a trigger.
Any other suggestions :(.
 
Level 6
Joined
Jan 16, 2013
Messages
68
  • Set Custom Value Start
    • Events
      • Map initialization
    • Conditions
    • Actions
      • For each (Integer A) from 1 to (Number of units in (Units in (Playable map area) matching (((Owner of (Matching unit)) controller) Equal to Computer))), do (Actions)
        • Loop - Actions
          • Set RandomUnit = (Random unit from (Units in (Playable map area) matching ((((Owner of (Matching unit)) controller) Equal to Computer) and (((Matching unit) is in AIUnits) Equal to False))))
          • Unit Group - Add RandomUnit to AIUnits
          • Unit - Set the custom value of RandomUnit to CustomValue
          • Set CustomValue = (CustomValue + 1)
          • Set UnitPoint[(Custom value of RandomUnit)] = (Position of RandomUnit)
          • Set UnitAngle[(Custom value of RandomUnit)] = (Facing of RandomUnit)
      • Unit Group - Pick every unit in (Units in (Playable map area) matching ((((Triggering unit) is A Hero) Equal to False) and ((((Owner of (Matching unit)) controller) Equal to Computer) and (((Matching unit) is in AIUnits) Equal to True)))) and do (Unit Group - Remove (Picked unit) from AIUnits)
  • Set Custom Value When Created
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • (((Owner of (Entering unit)) controller) Equal to Computer) and (((Entering unit) is in AIUnits) Equal to False)
    • Actions
      • Unit - Set the custom value of (Entering unit) to CustomValue
      • Set CustomValue = (CustomValue + 1)
      • Set UnitPoint[(Custom value of (Entering unit))] = (Position of (Entering unit))
      • Set UnitAngle[(Custom value of (Entering unit))] = (Facing of (Entering unit))
      • If (((Entering unit) is A Hero) Equal to True) then do (Unit Group - Add (Entering unit) to AIUnits) else do (Do nothing)
  • GoBack
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units in (Playable map area) matching ((((Owner of (Matching unit)) controller) Equal to Computer) and ((Current order of (Matching unit)) Equal to (Order(stop))))) and do (Actions)
        • Loop - Actions
          • Unit - Order (Picked unit) to Move To UnitPoint[(Custom value of (Picked unit))]
          • Wait 1.00 seconds
          • Wait until ((Current order of (Matching unit)) Equal to (Order(stop))), checking every 1.00 seconds
          • Unit - Make (Picked unit) face UnitAngle[(Custom value of (Picked unit))] over 1.00 seconds
 
Don't use integer A/B they are slower and less efficient than ur own variable. Anything u use twice or more should be stores into a variable and use the variable. Do t use waits in a group loop. Don't use matching unit inside the group loop

Never use entering unit / casting unit / dying unit use triggering unit instead.
U need to use an ITE check not a wait check. Never use the wait till condition.
 
Level 6
Joined
Jan 16, 2013
Messages
68
I have a few questions:
1. When I use for every variable, what kind of variable do should that be and what should it be set to?
2. Should I use triggering unit for matching unit or what?
3. Instead of wait what should I use

Or if you don't mind posting a repaired version of my triggers would be even better.
 
1) not sure what ur asking.
2) there is no matching unit inside the pick every unit loop. u need to use picked unit.
3) u dont use a wait in this u use an ITE. and for the condition put the conditions u need then in the then block move unit back.

4) u need to redo all of ur triggers.
get rid of them all.
make a trigger that stored units into a group when the unit enters the map. then store that units position in a hashtable keyed to that unit. or use a unit indexer and store the units position using the custom value. ( dont make ur own custom value system use bribes unit indexer.

make a second trigger that removes the unit from the group if the unit dies. then remove the leaks cause by storing the units original position.

the third trigger will be ur move trigger. pick every unit in the group then use an ITE ( if then else) to check if the units current order is equal to stop. in the then block move unit back to the original position.

also plz use hidden tags ur stretching my page.
 
Level 6
Joined
Jan 16, 2013
Messages
68
What about the units that are already on the map? That do not enter it in the first place? How do I store their position? Also, instead of moving them instantly I want to order them to move their and once they get there they need to face their original facing angle.
 
Level 6
Joined
Jan 16, 2013
Messages
68
Ok... so I copy the trigger from bribe's indexer.
I make a trigger that stores a unit's position and angle in a variable when it enters the map and also store it in a group.
I made the trigger to remove units from the group when they die.

Now I stopped. I don't know what you mean by then remove the leaks cause by storing the units original position. Also, how exactly do I make the trigger that registers the units that are in the map?
Here is what I have so far:

  • Unit Indexer
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: call ExecuteFunc("InitializeUnitIndexer")
      • Custom script: endfunction
      • -------- --------
      • -------- This is the most important function - it provides an index for units as they enter the map --------
      • -------- --------
      • Custom script: function IndexUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • -------- --------
      • -------- You can use the boolean UnitIndexerEnabled to protect some of your undesirable units from being indexed --------
      • -------- - Example: --------
      • -------- -- Set UnitIndexerEnabled = False --------
      • -------- -- Unit - Create 1 Dummy for (Triggering player) at TempLoc facing 0.00 degrees --------
      • -------- -- Set UnitIndexerEnabled = True --------
      • -------- --------
      • -------- You can also customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UnitIndexerEnabled Equal to True
        • Then - Actions
          • -------- --------
          • -------- Generate a unique integer index for this unit --------
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexRecycle Equal to 0
            • Then - Actions
              • Set UDex = (UDexGen + 1)
              • Set UDexGen = UDex
            • Else - Actions
              • Set UDex = UDexRecycle
              • Set UDexRecycle = UDexNext[UDex]
          • -------- --------
          • -------- Link index to unit, unit to index --------
          • -------- --------
          • Set UDexUnits[UDex] = (Matching unit)
          • Unit - Set the custom value of UDexUnits[UDex] to UDex
          • -------- --------
          • -------- Use a doubly-linked list to store all active indexes --------
          • -------- --------
          • Set UDexPrev[UDexNext[0]] = UDex
          • Set UDexNext[UDex] = UDexNext[0]
          • Set UDexNext[0] = UDex
          • -------- --------
          • -------- Fire index event for UDex --------
          • -------- --------
          • Set UnitIndexEvent = 0.00
          • Set UnitIndexEvent = 1.00
          • Set UnitIndexEvent = 0.00
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- The next function is called each time a unit enters the map --------
      • -------- --------
      • Custom script: function IndexNewUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • Custom script: local integer ndex
      • -------- --------
      • -------- Recycle indices of units no longer in-play every (15) units created --------
      • -------- --------
      • Set UDexWasted = (UDexWasted + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UDexWasted Equal to 15
        • Then - Actions
          • Set UDexWasted = 0
          • Set UDex = UDexNext[0]
          • Custom script: loop
          • Custom script: exitwhen udg_UDex == 0
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Custom value of UDexUnits[UDex]) Equal to 0
            • Then - Actions
              • -------- --------
              • -------- Remove index from linked list --------
              • -------- --------
              • Custom script: set ndex = udg_UDexNext[udg_UDex]
              • Custom script: set udg_UDexNext[udg_UDexPrev[udg_UDex]] = ndex
              • Custom script: set udg_UDexPrev[ndex] = udg_UDexPrev[udg_UDex]
              • Set UDexPrev[UDex] = 0
              • -------- --------
              • -------- Fire deindex event for UDex --------
              • -------- --------
              • Set UnitIndexEvent = 2.00
              • Set UnitIndexEvent = 0.00
              • -------- --------
              • -------- Recycle the index for later use --------
              • -------- --------
              • Set UDexUnits[UDex] = No unit
              • Set UDexNext[UDex] = UDexRecycle
              • Set UDexRecycle = UDex
              • Custom script: set udg_UDex = ndex
            • Else - Actions
              • Set UDex = UDexNext[UDex]
          • Custom script: endloop
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • -------- --------
      • -------- Handle the entering unit (Matching unit) --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Matching unit)) Equal to 0
        • Then - Actions
          • Custom script: call IndexUnit()
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- The next function initializes the core of the system --------
      • -------- --------
      • Custom script: function InitializeUnitIndexer takes nothing returns nothing
      • Custom script: local integer i = 0
      • Custom script: local region re = CreateRegion()
      • Custom script: local rect r = GetWorldBounds()
      • Set UnitIndexerEnabled = True
      • Custom script: call RegionAddRect(re, r)
      • Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, Filter(function IndexNewUnit))
      • Custom script: call RemoveRect(r)
      • Custom script: set re = null
      • Custom script: set r = null
      • Custom script: loop
      • Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), Filter(function IndexUnit))
      • Custom script: set i = i + 1
      • Custom script: exitwhen i == 16
      • Custom script: endloop
      • -------- --------
      • -------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
      • -------- --------
      • Set UnitIndexEvent = 3.00
      • Set UnitIndexEvent = 0.00
  • Store Point and Angle
    • Events
      • Unit - A unit enters (Entire map)
    • Conditions
    • Actions
      • Unit Group - Add (Triggering unit) to UnitGroup
      • Set UnitPoint[(Custom value of (Triggering unit))] = (Position of (Triggering unit))
      • Set UnitAngle[(Custom value of (Triggering unit))] = (Facing of (Triggering unit))
  • Unit Dies
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Unit Group - Remove (Triggering unit) from UnitGroup
 
i dont need to se bribes indexer.

u need a unit array / a point array / a real array.
store the unit into the array using the units custom value. also store the units location in the point array by using its custom value and its facing angle in the real array using the custom value.

points leak. position of / center of / offset. u need to clean these by removing the location when that unit is removed from the group. check out the tutorial things that leak.

for the units in the map. use a trigger with event 0.00
use a unit group to get all units in the map area. then add them to the array using there custom value. then add them to the permanent group.
 
Level 6
Joined
Jan 16, 2013
Messages
68
Ok this is what I have now:


  • Start
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to PermanentGroup
          • Set Units[(Custom value of (Picked unit))] = (Picked unit)
          • Set UnitPoint[(Custom value of (Picked unit))] = (Position of (Picked unit))
          • Set UnitAngle[(Custom value of (Picked unit))] = (Facing of (Picked unit))
  • Unit Dies
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Unit Group - Remove (Triggering unit) from PermanentGroup
  • Start
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to PermanentGroup
          • Set Units[(Custom value of (Picked unit))] = (Picked unit)
          • Set UnitPoint[(Custom value of (Picked unit))] = (Position of (Picked unit))
          • Set UnitAngle[(Custom value of (Picked unit))] = (Facing of (Picked unit))
  • Return
    • Events
      • Time - Every 2.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in PermanentGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of (Picked unit)) Equal to (Order(<Empty String>))
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Region centered at UnitPoint[(Custom value of (Picked unit))] with size (50.00, 50.00)) contains (Picked unit)) Equal to True
                • Then - Actions
                  • Unit - Make (Picked unit) face UnitAngle[(Custom value of (Picked unit))] over 1.00 seconds
                • Else - Actions
                  • Unit - Order (Picked unit) to Attack-Move To UnitPoint[(Custom value of (Picked unit))]
            • Else - Actions
              • Do nothing


I had to change it to <Empty String> because it didn't work with stop.
I didn't add that custom script about the leak because I wasn't sure what exactly to type in even after reading a bit about Things that Leak.

For now it seems to be working perfectly, so thank you for sticking with me through this :).

I believe that my biggest problem might have actually been picking move to instead of attack move to in the first place.
 
Last edited:
Status
Not open for further replies.
Top