[General] How to Rotate Constructed Buildings

Yes there about 10,000 different instances of this question being asked. But the solution isnt working for me. Perhaps they dont work in Reforged?


  • BuildFarm
    • Events
      • Unit - A unit Finishes construction
    • Conditions
      • (Unit-type of (Constructed structure)) Equal to Wheat Field
    • Actions
      • Set VariableSet Temp_Location_Farm = (Position of (Constructed structure))
      • Set VariableSet Temp_Angle_Farm = (Random angle)
      • Unit - Set Unit: (Constructed structure)'s Boolean Field: Is a Building ('ubdg') to Value: False
      • Wait 0.00 seconds
      • Unit - Make (Constructed structure) face Temp_Angle_Farm over 0.00 seconds
      • Unit - Move (Constructed structure) instantly to (Position of (Constructed structure)), facing Temp_Angle_Farm degrees
      • Unit - Make (Constructed structure) face Temp_Angle_Farm
      • Wait 0.00 seconds
      • Unit - Set Unit: (Constructed structure)'s Boolean Field: Is a Building ('ubdg') to Value: True
      • -------- THESE ARE DISABLED - this is what "works", but it shifts the structure... --------
      • Unit - Remove (Constructed structure) from the game
      • Unit - Create 1 Wheat Field for (Owner of (Triggering unit)) at (Temp_Location_Farm offset by (0.00, 0.00)) facing Temp_Angle_Farm degrees
In this trigger I have tried several things.

- The "face angle" action
  • The "Face angle INSTANTLY" action
  • The "Move and face angle" action


I have tried these with AND without first setting the structure's "Is a building" to false

Also Tried:

- I have edited the structure in object editor to have a positive turn speed (just in case)
- I have edited the structure to have a movement type (just in case)


Neither of these things helped
..............................................

It seems that any unit command to face an angle doesnt work for structures --- despite the 10,000 threads where people have posted that as being the answer.

I would really rather not go the route of placing a doodad ontop of my actual structure if possible
..............................................

NOTE:
I would actually be fine with the bottom solution (the one i wrote the comment "these are disabled" before). But this seems to shift the structure (it thinks it cant place it in the right spot and shifts it). I tried removing the builder prior to placing the new structure --- but for some reason "Unit - remove" on "triggering unit" didnt remove it.

EDIT: (as i wrote the above, i decided to test it, so technically not an edit but ehhh)

the constructing unit absolutely is the issue with this method (or any other units in the area that might collide with the new placed structure). I tested it using a wisp to construct it instead of peasant and it no longer shifts.

I still would prefer to just rotate it before its constructed though. I feel like that would probably be safer. (no glitches with collision with units nearby when rotating). I also planned on giving all buildings a rotate ability, so this really is pretty important to do right.

------------------------------------------

EDIT: [Solved - sort of]

- Jass solution below written by PurgeandFire. Works like a charm. Also prevents me from needing to write duplicate code (which i would have done) for when i add an ability to the buildings to turn by 15 degrees

- still not sure why the other commands dont work.
 
Last edited:
good catch on the constructing unit issue! I don't think people have really tested it much with buildings under construction, and you're right that it seems to shift the position of the building due to the peasant that's building it.

One simple work-around is to enumerate the units around the building (e.g. Pick every unit in range based off the building's collision size), hide them, set the building's position, and then show those units again. That seems to allow the engine to correctly position it in its original place. The main draw-back is that the player will lose selection of the peasant (or any units close enough to be "hidden"). If you want to avoid that side-effect, then you have a few options:
  1. Track the player's selections - you could track the player's selections before hiding the unit. Then once you show the units again, you can re-select them as needed. However, I'd be slightly wary of doing this in multiplayer as I believe selection state is local--so you have to be careful on how you code it so as not to trigger desyncs.
  2. Move the units somewhere else temporarily - if you have a "safe zone" on your map, you can temporarily move them there and then move them back. This works quite well too (since this code is all "instant", players won't even notice it visually)--but it has other side effects (e.g. this may re-trigger "Unit enters region" events).
  3. Only hide the constructing unit - the current sample code I have picks all units in range--but you might be able to get away with just hiding the constructing unit (i.e. the peasant/acolyte). That way it'll only deselect the peasant, which isn't too bad. But you will need a system to detect the constructing unit (I think we have a few snippets/systems on our site for that). And you'll just want to test it thoroughly--it might still end up repositioning the building in some cases.
But overall, there are a lot of ways to code around that side-effect. I would recommend choosing whatever works best for your map. :thumbs_up:

The one other thing to note is that buildings have quite a few quirks when it comes to facing. I'll try to explain the quirks as far as I understand it:
  1. Default model facing - in Warcraft 3, all default unit models will face "forward" (i.e. towards the y-axis), whereas all default buildings will face slightly to the side. Keep that in mind when setting the angle, as the model won't face the exact angle you specify. i.e. if you set their facing to "270", they will face these directions respectively:
    1745877502868.png
    1745877528042.png
  2. Building facing behavior - when you set a building's facing via code, it updates an internal value over time using some default turn rate in the engine. But the unit's actual visual facing in the game doesn't get "updated" until it is moved via SetUnitPosition (there may be other triggers that "refresh" it--I'm not sure). That's why most of the tricks involve "Move <unit> instantly to face <angle>" (but I believe most of the samples on the web have it in the wrong order--you should set the facing and then move it). However, due to the turn rate, you'll sometimes end up with the building at the wrong angle if you don't wait long enough before calling SetUnitPosition (because it hasn't been enough time for it to fully rotate). However, reforged introduced a special native to get around that:
    JASS:
    native BlzSetUnitFacingEx takes unit whichUnit, real facingAngle returns nothing
    This native allows you to instantly set a unit's facing, regardless of their turn rate. And it works on buildings too! But you still need to do the SetUnitPosition trick to make sure it is reflected visually.
If you put all that information together, you can make a small system like this one to instantly set a building's facing, even when under construction:
  • SetBuildingFacing
    • Events
    • Conditions
    • Actions
      • -------- --------
      • -------- Parameters: --------
      • -------- - SBF_InputUnit => The structure to change the facing of --------
      • -------- - SBF_InputFacing => The value to set it to --------
      • -------- --------
      • Custom script: local real originalX = GetUnitX(udg_SBF_InputUnit)
      • Custom script: local real originalY = GetUnitY(udg_SBF_InputUnit)
      • Custom script: local real collisionSize = BlzGetUnitCollisionSize(udg_SBF_InputUnit) + 128 // Add some buffer range in case the collision is inaccurate
      • Custom script: local group toHide = CreateGroup()
      • Custom script: local group toShow = CreateGroup()
      • Custom script: local unit enumUnit = null
      • -------- --------
      • -------- Queue setting the unit's facing (ignoring turn rate) --------
      • -------- --------
      • Custom script: call BlzSetUnitFacingEx(udg_SBF_InputUnit, udg_SBF_InputFacing)
      • -------- --------
      • -------- Enumerate the units within the collision range of the structure, and hide them --------
      • -------- --------
      • Custom script: call GroupEnumUnitsInRange(toHide, originalX, originalY, collisionSize, null)
      • Custom script: loop
      • Custom script: set enumUnit = FirstOfGroup(toHide)
      • Custom script: exitwhen enumUnit == null
      • Custom script: if enumUnit != udg_SBF_InputUnit then
      • Custom script: call ShowUnit(enumUnit, false)
      • Custom script: call GroupAddUnit(toShow, enumUnit)
      • Custom script: endif
      • Custom script: call GroupRemoveUnit(toHide, enumUnit)
      • Custom script: endloop
      • -------- --------
      • -------- Reset the structure's position to force the facing to be updated --------
      • -------- --------
      • Custom script: call SetUnitPosition(udg_SBF_InputUnit, originalX, originalY)
      • -------- --------
      • -------- Show any of the units that were hidden --------
      • -------- --------
      • Custom script: loop
      • Custom script: set enumUnit = FirstOfGroup(toShow)
      • Custom script: exitwhen enumUnit == null
      • Custom script: call ShowUnit(enumUnit, true)
      • Custom script: call GroupRemoveUnit(toShow, enumUnit)
      • Custom script: endloop
      • Custom script: call DestroyGroup(toHide)
      • Custom script: call DestroyGroup(toShow)
      • Custom script: set toHide = null
      • Custom script: set toShow = null
      • -------- --------
      • -------- Reset the parameters --------
      • -------- --------
      • Custom script: set udg_SBF_InputUnit = null
      • Custom script: set udg_SBF_InputFacing = 0.00
Then to use it, simply set up the parameters with the building you want to adjust the facing for and the desired angle, and then run the trigger:
  • ConstructionSample
    • Events
      • Unit - A unit Begins construction
    • Conditions
    • Actions
      • Set VariableSet SBF_InputUnit = (Constructing structure)
      • Set VariableSet SBF_InputFacing = 90.00
      • Trigger - Run SetBuildingFacing <gen> (ignoring conditions)
1745876013475.png

You'll notice in the screenshot above that even when under construction, the facing is being reflected correctly. All the buildings have a facing of 90 degrees (except the farm which was pre-placed on the map as a reference). Feel free to play around with the sample map, just note that it was saved on the latest patch:
 

Attachments

  • RotateBuildingsSample.w3m
    18.9 KB · Views: 2
Rotating Buildings
I don't see why this wouldn't work. Maybe something with those waits and unit commands you added is causing it to bug out.
I put the waits when it wasnt working, to see if that would help (has helped me in past when things seemed to not work despite all signs pointing to the fact that they should).

I also did the different facing commands solo (without any other things added). This was just the conglomerate of things i tried and my last ridiculous effort to see if i could get something to work.
Feel free to play around with the sample map, just note that it was saved on the latest patch
Thank you for this! I will give it a try later tonight. I am always reluctant to write JASS custom scripts myself as, without some form of intellisense, im basically inept lol.

EDIT: used the custom script, made it random angle instead of 90, and works like a charm. Thanks!
EDIT 2: had to change the 128 buffer to 256. specifically in case of town hall and having it triggered via an ability that turns it 15 degrees at a time
 
Last edited:
Top