RvS Mapping Tutorials
Odds & Ends
Navigation
RvS Mapping: Doors, Ladders, and Damage Models
-by Beckett, last updated March 24, 2003
This tutorial will show you how to implement doors that open, windows that break, ladders and stairs that can be climbed, and objects that can be damaged. If you follow my instructions precisely, these elements will work as smoothly in your map as they do in the official campaign.

This tutorial assumes that you are already familiar with UnrealED and know how to load a simple custom map into Raven Shield. If this is not the case, take a look at my earlier tutorial,
Building Your First Raven Shield Map, and then come back to this one. I'm not going to spend much time in this tutorial dealing with textures, lighting, insertion points, or path nodes. I'll assume you know what you're doing and can improvise these as you go along.

Adjusting Level Properties

Before we do anything else, let's setup the map so that it will operate properly in the planning stage and in the in-game map view. Click the "View" menu in the editor and choose "Level Properties". Expand "R6Planning". Expand R6PlanningMaxVector, change X to "5000", and change Y to "5000". Expand R6PlanningMinVector, change X to "-5000", and change Y to "-5000". This will allow the player to scroll/reposition the map during the planning stage.

As I explained a bit in my first tutorial, to allow your map to work with the planning stage--which displays one floor of the map at a time--you need to assign a number to each floor in the level properties, and then assign elements (walls, floors, doors, stairs, ladders, static meshes, etc.) to each floor, using those numbers. The editor assumes that the higher the number, the higher the floor. I recommend always naming your ground floor "100", so that your basement becomes "99" and your third floor becomes "102". In this case, we'll be building a two story cabin plus a basement, so set R6PlanningMinLevel to "99" and R6PlanningMaxLevel to "101". Close the level properties window.

Building a multi-floor structure

We're going to build a small cabin. First, select a terrain texture and carve out a cube sized Height=1280,Width=1280,Breadth=1280. We won't bother with a skybox, but this is our outdoor area. Now select any wall texture you like, and add a hallow cube sized Hollow=True,Height=832,Width=800,Breadth=800,Wallthinkness=32. Align the bottom of our cabin with the ground, and center it in the 'yard'. Place an insertion zone and at least one path node in the front yard. (Make sure to change the "R6Planning" settings for the insertion zone--setting both floor parameters to "100"--
as covered in my earlier tutorial; if you don't, you'll get build errors and the insertion zone won't work right in the planning stage.) Right click the floor inside the cabin and choose "Surface Properties". Select the "Walkable" checkbox. Since this is the ground floor, set main floor to "100" and sec. floor to "100". Assign the same settings to the ground outside.


Now let's build a loft inside. Create a solid cube sized Hallow=False,Height=16,Width=384,Breadth=768. Position it along the back wall so that the floor of the loft (meaning, the top of the brush) is around 416 units above the floor of the cabin. This height is important because later we will be building a ladder up to the loft. (If you can't get the position exact, don't panic. You can reposition the ledge later, after you place the ladder.) Right click the floor of the loft and choose "Surface Properties". Select the "Walkable" checkbox. Set main floor to "101" and sec. floor to "101". Now select all the inside walls of the cabin, right click, and choose "Surface Properties". Select the "Wall" checkbox. Since these walls span two floors, set main floor to "100" and sec. floor to "101". Click the "Apply" button and close the surface properties window.

We also need to build a basement. Select an appropriate texture. Carve out a solid cube sized Height=240,Width=768,Breadth=768, just below ground level (so that a 16 unit ceiling remains between the two floors). And now we need a way to get down to the basement. Carve a cube sized Height=16,Width=272,Breadth=640 out of the basement ceiling, along the back/right corner of the cabin. You should be able to peek down into the basement now; We'll be placing a staircase here later. Right click the floor of the basement and choose "Surface Properties". Select the "Walkable" checkbox. Set main floor to "99" and sec. floor to "99". Select all the basement walls, right click, and choose "Surface Properties". Select the "Wall" checkbox. Set main floor to "99" and sec. floor to "99". You should have the hang of this by now...

Good we're done with the boring part and ready to cover the important stuff. Drop some lights throughout the cabin, and then rebuild and save your level if you haven't yet. Hopefully, the inside of your cabin looks like this:


Creating a Rotating Door

Let's give our cabin a front door. Carve a cube sized Height=232,Width=16,Breadth=136 out of the front wall, aligned just above the cabin floor (not the ground outside), to use as a doorway. Open the static mesh browser. Open "Oil_Refinery_SM.usx", choose "door_frame", and select "DoorFrame_18". Right click on the cabin floor and choose "Add Static Mesh'Oil_Refinery_SM.doorframe.DoorFrame_18'". Position the doorframe in the doorway so that it does not stick out of the wall on either side; make sure the wall does not show through it anywhere (this will take some fine-tune placement). We'd better add a doorstep outside. Create a solid cube sized Height=8,Width=128,Breadth=136 and place it on the ground outside the door. Don't forget to edit the surface properties so that it shows up in the planning stage. (You knew I was going to say that.)

Open the actor class browser. Expand "R6Interactive Object | R6IActionObject" and select "R6IORotatingDoor". Right click on the ground in front of the doorway and choose "Add R6IORotatingDoor Here". A little dragon head will appear; double click on him to open the properties window. Expand "Display" and change DrawType to "DT_StaticMesh". Scroll down, select Static Mesh, and click the "..." button. Browse to "Oil_Refinery_SM.Door" and select "porte_Metal_BWindow_L". Return to the properties window, and click the "Use" button. Rotate and position the door perfectly in the doorway, so that the blue line leads to the inside of the cabin; then go back to the properties window.

Expand "R6DoorProperties". To lock this door, set m_blsDoorLocked to "True". If you would like the door to begin partially open, set m_iInitialOpeningDeg to the desired angle (ideally a number between "0" and "90"). By default, a door will open to a maximum angle of 90 degrees. Unless you've placed your doorway right along the left wall we can afford to open it a bit wider than that, so change m_iMaxOpeningDeg to "120" (for the most realistic appearance, the door should be allowed to swing open until it hits the inside wall).

Expand "R6Planning" and set m_iPlanningFLoor_0 to "100" and m_iPlanningFLoor_1 to "100". Expand "R6DoorSounds", select "m_OpeningSound", and click the "..." button. Open "Movers_OilRefineryDoors.uax" and select "Play_OilMetalDoorOpen". Return to the properties window and click the "Use" button. select "m_ClosingSound", and click the "..." button. Choose "Movers_OilRefineryDoors" and select "Play_OilMetalDoorClose". Return to the properties window and click the "Use" button. If you'd like, continue assigning sounds from the Movers_OilRefineryDoors.uax and Movers_CommonDoors.uax packages. Finally, expand "Collision" and set bBlockKarma to "True".

If this is a wooden door, and you want it to be destructible, expand “R6Damage”, and set m_iHitPoints to "2000" (higher hit points, of course, will require more firepower to destroy). Select m_StateList and click the "Add" button. Set fDamagePercentage to "15" (this will spawn the door as 15% damaged right off the bat). Select ActorList and click the "Add" button on that line. Select ActorToSpawn and choose "R6BreakableDoor" from the dropdown list. This will cause the splintering wood animation to appear once the door experiences 100% damage. Select RandomMeshes and click the "Add" button. Change iPercentage to "100" and leave Mesh set to "None". This will cause the original static mesh door to disappear when 100% damage is reached.

Now, rebuild the map. Notice the engine has automatically created two new actors, one on each side of the door. These are advanced path nodes used by the AI to navigate through the door. Take a look at some of the property settings for these, if you'd like. The good news is we don't need to mess with them... our door now works perfectly! Not only can we enter our cabin now, we can order our team to breach and clear.


Creating a Breakable Window

We're going to place a 256x128 window in the front wall of our cabin. Carve a a cube sized Height=128,Width=16,Breadth=256 out of the front wall, around eye level. Open the static mesh browser. Open "Streets_SM.usx", choose "Cadres", and select "Cadre_fen". Right click on the cabin floor and choose "Add Static Mesh'Streets_SM.Cadres.Cadre_fen'". Rotate the window frame so that it is wider than it is tall. We're going to use two window frames to make our window. So position this frame to fill one half of the carved out area. It should stick out from the wall 3 or 4 units. It's alright if it overlaps the BSP wall, but make it's positioned so that none of the wall shows through the frame. With the frame still selected, press "Ctrl-C" to copy it to your clipboard and then press "Ctrl-V" to paste a duplicate version. Position the new frame so that the two frames meet in the center of the wall. Select both frames, and in the properties window expand "R6Planning" and set both m_iPlanningFloor_0 and m_iPlanningFloor_1 to "100". (Whenever you create a window, you should set the windowframe, rather than the window pane to appear in the planning stage).

Open the actor class browser. Expand "R6Interactive Object | R6IActionObject" and select "R6IOSlidingWindow". Right click in our window frame and choose "Add R6IOSlidingWindow Here". The window is currently invisible, so don't bother looking around for it. Instead, click on the "Search for Actors" button (represented by binoculars) in the toolbar, select "R6IOSlidingWindow0", and click the "Goto Actor" button. Now that we've got him selected, click the "Actor Properties" button in the toolbar. Expand "Display" and select "StaticMesh". Click the "..." button. Open "R6ActionObjects.usx", choose "Breakable_Glass", and select "Breakable_Glass.Glass_256x128". Return to the properties window and click the "Use" button. It will actually look like a window pane now. Rotate and position the pane in the center of our window frames and then return to the properties window.

Expand "R6Damage". Set m_bBreakableByFlashbang to "True". This refers to the flashbang explosion, not to throwing the flashbang through the window. Set m_fAIBreakNoiseRadius to "1500". This, of course, affects how far away terrorists will hear the sound of glass breaking. Set m_iHitPoints to "1000"; we should be able to punch through that in one shot.

Select m_StateList and click the "Add" button. Make sure fDamagePercentage is set to "0"; this will spawn the window with no initial damage. (Note that this setting was incorrectly explained in the first version of this tutorial. fDamagePercentage indicates damage that is already done to the object at the start of the round.)

Select ActorList and click the "Add" button on that line. Select ActorToSpawn and choose "R6BreakableGlass_256x128" from the dropdown list. This will cause the breaking glass animation to appear once the window experiences 100% damage. Notice how it is possible to to spawn different actors when different levels of damage occur, in order to show increasing degradation of an object; of course that wouldn't make sense for our fragile window.

At this point, a breaking glass animation will run when the window is shot, however the original static mesh doesn't automatically disappear. So select RandomMeshes and click the "Add" button. Change fPercentage to "100" and leave Mesh set to "None". Now, our window pane will disappear at the same moment that the room is showered with broken glass.

Let's add the sound of breaking glass. Expand "SoundList", click the "Add" button, then click the "..." button. Open "Objects_MediumWindows.uax", and select "Play_random_MedWindows". Return to the properties window and click the "Use" button. One more thing. By default, terrorists and operatives won't see each other through the window. So, expand "Collision" and set m_bSeeThrough to "True". Also, set m_bBulletGoThrough to "True" or the terrorists and operatives won't know they can shoot through it and they will just keep yelling insults at each other through the window (I'm serious). Close out of the properties.

It's time to test out your new, breakable window.


Implementing a Working Ladder

Open the Static mesh browser, open "Oil_Refinery_SM.usx" and select "Ladder.Ladder_440". Right click on the floor of the cabin and choose "Add Static Mesh Oil_Refinery_SM.Ladder.Ladder_440 Here". Position the ladder so that it leads from the cabin floor to the loft, without overlapping either plane.

Return to the static mesh browser, browse to "Oil_Refinery_SM.Collision_Hull" and select "CH_ladder". Right click in the map and choose "Add Static Mesh Oil_Refinery_SM.Collision_Hull.CH_ladder Here". Position the collision hull in pretty much exact same position as the ladder, aligning the base to the floor of the cabin. The ladder will be a tiny bit taller than the top of the collision hull, as it should be. The top of the collision hull should line up pretty close to the floor of the loft; if it doesn't, adjust the vertical position of the loft. Don't worry if you can't do a perfect per-unit alignment; this doesn't need to be as precise as a BSP brush intersection. This collision hull will keep our operatives from falling through the ladder during the climbing animation. However, there are few things we need to adjust on it. Double click the collision hull to open the properties window, and expand "Collision". Change m_bBulletGoThrough to "True". Set m_bSeeThrough to "True". Expand "R6Planning" and set m_DisplayFLag to "DF_ShowOnlyInPlanning". Close the properties window.

Now comes the cool part. We're going to create a VOLUME in front of the ladder! Create a solid cylinder builder brush sized Sides=8,Height=500,OuterRadius=50. Position the brush so that it sits on the floor of the cabin, surrounding the area in front of the ladder. The cylinder should overlap the static meshes slightly and should be about a foot taller than the ladder. Now, click the "Volume" button on the left menu (represented by a 3d cube) and select "R6LadderVolume" (make sure you don't accidentally select "LadderVolume"). Now move your builder brush out of the way and double click on the frame of our R6LadderVolume to open the properties window. Expand "R6Planning". Set m_iPlanningFLoor_0 to "100" and m_iPlanningFloor_1 to "101". Expand "R6Sound", select m_SlideSound, and click the "..." button. Open "Foley_MetalLadder.uax" and select "Play_MetalSlide". Return to the properties window and click the "Use" button. There are other sounds you can assign as well, but we're not going to take the time to right now.

Close the properties window and rebuild your map. Notice the engine has automatically created two new actors (they are advanced path nodes, technically called "AutoLadders") at the top and bottom of our R6LadderVolume. They are automatically positioned where they should be, and if you check their R6Planning settings, you'll see that they have already inherited the correct settings to appear correctly in the planning stage.

Save your map and try it out in game. Not only can you climb and descend the ladder, you can order your team to do so. Plus, notice that in the planning stage, you can switch the view from one floor to the next by clicking on the ladder icon on the 2d map. If you encounter any odd behavior (swimming in mid air, falling off the ladder, etc.) you just need to adjust the positioning of the collision hull and volume cylinder. Don't be afraid to delete the objects and start over if necessary.


Implementing a Working Staircase

After that, stairs should be easy, right? Open the Static mesh browser, open "Oil_Refinery_SM.usx" and select "Yellow_stairs_welded.Yellow_stairs_welded". Right click on the floor of the basement and choose "Add Static Mesh Oil_Refinery_SM.Yellow_stairs_welded.Yellow_stairs_welded Here". Rotate and position the stairs so that they lead down from the ground floor to the basement without any gaps at the top or bottom. The the top step (not the top edge) should align with the ground floor and the bottom edge might actually stick through the basement floor a bit.

Return to the static mesh browser, browse to "Oil_Refinery_SM.Collision_Hull" and select "In_Level100". Right click in the map and choose "Add Static Mesh Oil_Refinery_SM.Collision_Hull.In_Level100 Here". This collision hull appears as a ramp. Position the ramp so that it sits just along the top edge of the stairs. If you leave stairs sticking through, you'll get a head bob when you walk down them. Once it's positioned, double click the collision hull to open the properties window, and expand "Collision". Change m_bBulletGoThrough and m_bSeeThrough to "True" (don't worry, bullets will still bounce off of the solid parts of these stairs). Leave bBlockKarma set to "False", since we want the dead bodies to be blocked by the steps themselves, rather than slide down the invisible ramp of our collision hull. Expand "R6Planning" and set m_blsWalkable to "True" and m_DisplayFLag to "DF_ShowOnlyInPlanning". Set m_iPlanningFloor_0 to "99" and m_iPlanningFloor_1 to "100". Close the properties window.

Now we're going to create another volume. Create a cube builder brush sized Height=400,Width=272,Breadth=544. Position it to sit on the basement floor and completely encompass the stairs and collision hull (the top should extend several feet above the top of the stairs). Click the "Volume" button on the left menu (represented by a 3d cube) and select "R6StairVolume". Then, move your builder brush out of the way and double click on the frame of theR6StairVolume to open the properties window. Expand "R6Planning". Set m_iPlanningFloor_0 to "99" and m_iPlanningFloor_1 to "100". When we created the volume, an "R6StairOrientation" (represented by a large double arrow) should have been created as well. If necessary, reposition this actor to sit centered, vertically and horizontally, midway up the stairs. Double-click the R6StairOrientation to open the properties window. Expand "R6Planning". Set m_iPlanningFloor_0 to "99" and m_iPlanningFloor_1 to "100".

Close the properties window and rebuild your map. The engine will automatically create two new actor icons (which are--you guessed it--advanced path nodes). If everything was positioned correctly, one icon will appear at the top of your stairs and the other will appear at the bottom. If they end up under your stairs instead, I recommend you adjust the position of your stairs and collision hull and then delete and recreate your volume, repeating the steps above. If, instead, these icons get embeded in your geometry (you'll get a rebuilding error if this happens), simply move the R6Stair Orientation to a higher vertical position and make sure the red arrow is pointed to the top of the stairs; then try rebuilding again.

Save your map and try it out in-game. You should now be able to place planning waypoints throughout the entire map! You will also be able to order your team to move into the basement, however keep in mind that if you haven't placed good node points, and your team is too far away, they might be resistant to your orders.


Creating Damageable Objects

We're almost done, but I know there's one more thing you're wondering about. The breaking glass was cool, but what else can we destroy? Well, how about a personal computer? If you understood everything we did with the window pane, I'll bet you have some idea of how we're going to pull this off.

Now that we can get in and out of the basement, let's drop a desk down there. Open the static mesh browser, open "Bank_SM.usx", find "Bank_SM.Bureau3eC" (it's not in a category, so you'll need to press the "All" button and do some scrolling to get to it), and place it somewhere on the basement floor. Don't forget to assign a PlanningFloor to the desk so it shows up on the planning map (we won't bother for the computer, we just don't want our crack team stumbling over a desk that the intel guys didn't warn them about). Also, make sure you have some bright lights in the basement so you'll be able to see the damage modeling that we're going to implement.

Open the Actor Classes browser and select "R6InteractiveObject" (no need to expand it). Right click on the desk and choose "Add R6InteractiveObject Here"; a little dragonhead icon will appear. Double click on him to open the properties window, and expand "Display". Change DrawType to "DT_StaticMesh". Select StaticMesh and click the "..." button. Select "Computer", return to the properties window, and then click the "Use" button. You may need to reposition the computer a bit so that it is sitting properly on top of the desk.

Expand "R6Damage". Set m_fAIBreakNoiseRadius to "1000". Set m_iHitPoints to "1000". Select StateList and click the "Add" button. Select RandomMeshes and click the "Add" button. Set fPercentage to "100". Select "Mesh", click the "..." button, select Bank_SM.BreakableObject.Computer_Broken, return to the properties window, and click the "Use" button. Select SoundList and click the "Add" button. Click the "..." button, open "SFX_Bank.uax", and select "Play_Bank_CPUCrash". Return to the properties window and click the "Use" button.

Let's add a monitor as well. Open the Actor Classes browser nd select "R6InteractiveObject" again. Right click on top of the desk and choose "Add R6InteractiveObject Here". Double click on the new icon to open the properties window, and expand "Display". Change DrawType to "DT_StaticMesh". Select StaticMesh and click the "..." button. Select "ComputerScreen" (again, there's no category), return to the properties window, and then click the "Use" button. Reposition the monitor on top of the CPU, if necessary.

Expand "R6Damage". Set m_fAIBreakNoiseRadius to "1000". Set m_iHitPoints to "1000". Select StateList and click the "Add" button. Select ActorList and click the "Add" button. Set ActorToSpawn to "R6Breakable_TV" (you'll notice some other really interesting options in that dropdown list). Select RandomSkins and click the "Add" button. Set fPercentage to "100". Select "Skin" and click the "Add" button. Select the "[0]" line that was just created (under "Skin"). The "..." button didn't work me at this point; if that's the case for you, type this in directly: "Texture'Bank_TSM.BreakablaObject.ComputerScreen_Broken'". Finally, Select SoundList and click the "Add" button. Click the "..." button, select "SFX_Bank.Play_BankScreenCrash". Return to the properties window and click the "Use" button.

Load the game and try it out. Did you catch that there are two different things going on with the CPU and monitor? The CPU simply switches the static mesh to a different model when 100% damage is reached. The monitor, however, applies a new texture to the existing static mesh. Of course, it's all the same to the player.


Conclusion

Hopefully I've not only taught you some good tricks, but given you some idea of what the Unreal editor and the R6 classes are capable of. For example, want to create a wooden door that gets shredded by assault gun fire? Need to create a two part staircase with a landing in the middle? Ideas like this shouldn't be difficult to implement if you apply the principles outlined above.

If you've read my first tutorial, you know how to spawn terrorists. Drop some in your new cabin and clean the place out. You've earned it.

I hope you found this tutorial helpful. If there's anything I've gotten wrong, please let me know and I'll correct the information. Email me if you have any questions or mapping issues you'd like to discuss.
-Beckett

Display a printable version of this article


© 2005, RvSMaps.com, all rights reserved
Send questions, critiques, etc. to http://www.juncmodule.net/rvs/rvsmaps/content/contact.htm