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
|