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

Help me create a definitive guide to multi-storey buildings

Status
Not open for further replies.
Level 4
Joined
Jan 7, 2011
Messages
72
Hi all

I know that I'm not the first person who has wanted to create a map with multi-storey buildings. My search for how to do so has evolved into a Holy Grail-like quest since there are hints and tips scattered across dozens of threads, but no one definitive resource.

What I want to do with this thread is identify all of the problems associated with multi-storey buildings and their potential solutions. Having done so, I will then collate all of the information into a definitive guide that I am sure will help many current and aspiring mapmakers.

What features must a multi-storey building have?

1. Two (or more) floors, vertically separated, with their own doodads, destructibles, and/or units.

2. Units (especially player-controlled units) must be capable of entering each floor.

3. Floors that a player-controlled unit is not on must either be transparent or not visible to the player-controlled unit.

4. Units (especially player-controlled units) must be capable of co-existing on different floors in the same 2D location simultaneously.

5. Units (especially player-controlled units) must not interact with each other (i.e. attack each other; give items; cast spells or use abilities on each other) across different floors.

What are the problems?

1. We need to be able to track which floor units are on.

2. Unit vision on a particular floor will be obscured by higher floors.

3. Unit movement on a particular floor will be obstructed by collisions with units, doodads, and destructibles on other floors.

4. Units can interact with each other across floors provided they are within sufficient 2D proximity of each other.

What are the possible solutions?

1a. Create small regions near the entrance and exit point(s) for each floor to track whether a unit is entering it. Create an array to store the floor that each unit is on.

1b. Give every unit that you want to be capable of entering different floors the ability to fly. Track whether it enters a particular floor using regions per 1a, adjust it's flying height accordingly, and get it's current flying height whenever you need to check which floor it is on.

[Note: these solutions could fail for very complex multi-storey buildings if the regions used for tracking unit movement overlap across different floors. One way of possibly solving this would be to use the unit's last stored floor location to filter out overlapping regions.

For example, assume region A on floor 1 is the entrance point for floor 2, region B on floor 2 is the entrance point for floor 3, and both of these regions overlap each other. When a unit enters floor 1, we store its floor position accordingly. Then, when it enters those overlapping regions, we can correctly change its floor position to floor 2 - and not floor 3 - by using both the region as well as its last stored floor position.]

2. Hide units and destructibles using GetLocalPlayer() (see: http://www.hiveworkshop.com/forums/world-editor-help-zone-98/getlocalplayer-faq-224876/)

[Note: I am assuming additional problems may arise if a player controls more than one unit.]

3a. Remove pathing from all doodads and destructibles used to create buildings, and use pathing blockers to control pathing instead. Use ground pathing blockers for the ground floor and flying pathing blockers for the second storey. Give units that enter the second storey the ability to fly so that they aren't obstructed by ground level units or pathing blockers.

[Note: This won't work for more complex buildings with more than two storeys.]

3b. Remove pathing from all doodads and destructibles used to create buildings, and use pathing blockers to control pathing instead. Create regions near each pathing blocker to track whether a unit is approaching it. Disable collisions for units when they enter the building. Enable collisions when units enter a region indicating that they are approaching a pathing blocker. Disable collisions when they exit those same regions. Filter out regions from floors other than the one that a unit is on using the method described under 1b.

[Note: While this should work for complex buildings with more than two floors, it is not a guaranteed solution for unit collisions since two or more units might obstruct each other if they have collisions turned on having entered overlapping regions used to monitor their proximity to pathing blockers. However, it might be possible to circumvent this possibility by constructing buildings very strategically such that the pathing blocking regions on each floor don't overlap significantly or at all.]

3c. Combine 1b and 3a or 3b. Track every unit's 2D co-ordinates and compare their flying height when they are about to collide. If their flying heights are the same, then turn collisions off for them and turn them back on when they are no longer within 2D proximity of each other.

4. Hide units and destructibles using GetLocalPlayer() so that units on different floors can't interact.

[Note: I am assuming this won't work if a player controls more than one unit.]

Please help me with this guide!

I'm far from being an expert, so I would greatly appreciate suggestions and corrections from other mapmakers.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
3b: You could add a integer value to the unit entering the floors so 1 could be floor 1 etc (unit indexing is needed). This can then be used for conditions to check on which floor they are (thus changing flying height depending on the floor level whenever they move over a pathing blocker).

4 and 3b: When you want to remove the collision from units when they overlap, try adding the ability 'Aeth' (Ghost (Visible)) whenever they enter the regions or get close to other units on different floors.

I don't see how your 4th answer can work. They might not be abled to interact with eachother, but still they are set invisible which can be troublesome. I'd go for something like detecting wether a spell is cast towards an enemy on a different floor (integer added in my 3b answer) or attacked on a different floor and then order the casting unit or attacking unit to stop. I'm still unsure about item transfers. Is there an event for a unit acquires an item from another unit and then detect which unit gave the item? I haven't got the editor over here right now.


This is quite a complex thing to get working and I fully support you. If you could get some things to work and provide a test map that would be wonderful. +rep for keeping up the good work.
 
Level 4
Joined
Jan 7, 2011
Messages
72
Many thanks for your input, Hash!

Will units with the "Aeth" ability be blocked by pathing blockers? If not, that might work better than the flying ability. Either way, it is worth considering, since the use of flying comes with its own set of contingencies.

I should have explained number 4 better. Correct me if I am wrong, but if two units that aren't controlled by the same player can't see each other, then they can't target each other - thus, they couldn't exchange items, directly attack each other, or cast spells / use abilities on each that require direct targeting.

Interaction between multiple units controlled by the same player obviously throws a wrench in the works as do area effect spells and other abilities that don't require targeting. However, as you point out, it should be possible to circumvent this by tracking unit floor levels.

Ultimately, I want to use all of this information to create a test map that will benefit the rest of the community. I plan on creating a single-unit player map first since it will be less complex than one involving multiple units per player, and I suspect that this will be sufficient for many mapmakers since a multi-storey building system lends itself to RPG maps where players typically have a single unit.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
You can not hide a unit locally for a specific player if that unit is going to be interacted with by another player. That's the main problem you're having since it'll cause a desync. But that ofcourse depends on which method you use for hiding the unit.
(moving it locally, hiding it locally, changing the vertex color locally)

It depends on the hiding method ofcourse. Vertex coloring might work but I'm not sure about that. For example: if it only changes the vertex color, then won't the enemy unit still be abled to attack it? Vertex coloring is indeed something that other players can not interact with so this should be fine but I don't know if it'll solve the multiple-floor interaction problem.

In other words: your solution for 4. probably won't work at all on multiplayer.
Just don't hide things locally if players can interact with them. It'll most probably cause a desync. Unless done with vertex coloring, but then again I haven't used vertex coloring with interactable units yet so I wouldn't know.

Which is why I suggested detecting actions done by the unit towards the other unit and ordering the unit to stop that action. This however could be kind of buggy and a better solution needs to be thought of in order to make this look natural.
A few possibilities like making the unit invisible instead of hiding it or making it temporarily allied when being attack to break the actual attack might possibly work but you'll have to do some tests to find the right way of doing this.

For single player it shouldn't be that much of a hassle to get it working I suppose. It's in particular hard to get it working on multiplayer.
 
Last edited:
Level 4
Joined
Jan 7, 2011
Messages
72
At what point would a desync occur?

(a) When a unit is hidden locally?
(b) When a unit is hidden locally and is capable of interaction with another unit?
(c) When a unit is hidden locally and actually interacts with another unit?

I am assuming the answer is (c), but if you can confirm this for me I would really appreciate it since it will clarify the scope of potential solutions (obviously desyncs could occur with (a) due to poor coding, but kindly assume that proper coding is being used for the purpose of my question).

One convenient workaround for all of this would be to allocate each building level to a different region, move units to the relevant region as they ascend or descend levels, and set camera bounds to create the illusion of a multi-storey building. It's not aesthetically ideal and could sacrifice a significant volume of map space depending on the overall size of the map and number of multi-storey buildings, but it should work as a last resort.
 
Level 4
Joined
Jan 7, 2011
Messages
72
Per your suggestion of ordering units to stop an action that involves interacting with a unit on a different level, would temporarily pausing the unit serve as a "universal" tactic for preventing all possible interaction (swapping items; attacking; using abilities) so that we don't need a different tactic for each type of interaction?
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
never hide a unit locally execpt for units with the "locust" ability, set their transparency natively.
 
Level 4
Joined
Jan 7, 2011
Messages
72
But units with the locust ability would be unselectable, wouldn't they?

Please explain what you mean by setting transparency "natively".
 
Status
Not open for further replies.
Top