This tutorial will cover how to add a very basic control volume with working Status Bar. There are three versions to this tutorial. Version 1 must be completed before you can add the optional code of either version 2 or version 3.
This tutorial does not provide code for another player or team capturing an already captured volume, nor combined capture efforts of more than one player. You'll need to work that out for yourself.
When finished, you will be able to add a volume to your level in the Editor via: Brush->Add Volume->SFControlVolume
Flash Setup

Uploaded with ImageShack.us
Version 1 - Status Bar Centered on HUD
New UnrealScript Class - SFControlVolume.uc
Next, we create the actual placeable control volume that you can add anywhere in your map.
New UnrealScript Class - SFVolumeControlTimer.uc
Now we create the timer class. This class simply executes the SFControlVolume::StartControlling function every time it ticks.
New UnrealScript Class - SFControlVolumeMovie.uc
And finally, we create the Movie Player class for our status bar.
Version 2 - Status Bar Floating in Game World
If you want the status bar physically in the game world, at the center of the volume, first modify the SFControlVolume class.
NOTE: You will be able to add multiple control volumes to your level, but you must create a unique Material and TextureRenderTarget2D for each volume.
UnrealScript - SFControlVolume.uc Modifications
New UnrealScript Class - SFControlVolumeMesh.uc
Now create a new class. This class will be used to display the status bar in the game world.
Version 3 - Status Bar on HUD at Relative Position
This version draws the status bar on the HUD at the relative position of the volume using Canvas Project. As you look around, the status bar will move on the HUD so that it is still in the same relative position.
NOTE: If you have done the Version 2 modifications to your code, undo them.
UnrealScript - Hud Wrapper Modifications
You must revise the PostRender() function of your HUD Wrapper:
UnrealScript - SFControlVolumeMovie.uc Modifications
First, add two new global variables:
Next, add these three (red) lines of code to the Start() function:
Then add this function, right after the UpdateStatusBar() function.
UnrealEd Setup
Version 2 Only

Uploaded with ImageShack.us
Final Result

Uploaded with ImageShack.us
- Version 1 [REQUIRED] The status bar will be drawn to the screen, centered on the HUD.
- Version 2 [Optional] The status bar is displayed as a hovering bar at the center of the control volume. It is physically in the game world, and always faces the player.
- Version 3 [Optional] The bar is again drawn on the HUD, this time at the relative position of the control volume, using Canvas.Project. The status bar moves around the HUD as the player moves, always positioned relative to the location of the control volume.
This tutorial does not provide code for another player or team capturing an already captured volume, nor combined capture efforts of more than one player. You'll need to work that out for yourself.
When finished, you will be able to add a volume to your level in the Editor via: Brush->Add Volume->SFControlVolume
Flash Setup
- Create a new AS 2 document.
- Set the Document dimensions to 512x256
- IMPORTANT: Set the Document background to black.
- Create a blue rectangle in the center of the document.
- Convert it to a Movie Clip.
- Give it an instance name of BlueStatusBar.
- Save and Publish the SWF to your UDK install under /UDKGame/Flash/UDKSFTutorial/CVStatusBar.SWF.
- Import the SWF into UDK.

Uploaded with ImageShack.us
Version 1 - Status Bar Centered on HUD
New UnrealScript Class - SFControlVolume.uc
Next, we create the actual placeable control volume that you can add anywhere in your map.
Code:
class SFControlVolume extends Volume placeable; var bool bControlled; var int ElapsedTime; var int PercentCaptured; // Editable Properties var (TimeToControl) int TimeToControl; var (TimeToControl) float UpdateRate; var () SwfMovie Movie; var Info ControlTimer; var SFControlVolumeMovie CVMovie; event PostBeginPlay() { Super.PostBeginPlay(); ControlTimer = Spawn(class'SFVolumeControlTimer', self); } event Touch (Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal) { Super.Touch(Other,OtherComp,HitLocation,HitNormal); if(!bControlled) { // Turn on the timer, and have it tick every X seconds, where X = UpdateRate. ControlTimer.SetTimer(UpdateRate,true); } // Only display the status bar when the player has touched/is in the volume. CreateControlVolumeMovie(); UpdateStatusBar(); } event UnTouch ( Actor Other ) { Super.UnTouch(Other); // Reset capture timer. ControlTimer.ClearTimer(); // Close the status bar when the player leaves the volume. CVMovie.Close(true); CVMovie = none; if(!bControlled) { ElapsedTime = 0; } } function StartControlling(SFVolumeControlTimer VC) { local int PercentCaptured; if (VC == ControlTimer) { ElapsedTime++; `log("Time to capture: " @ TimeToControl - ElapsedTime); UpdateStatusBar(); // Once we reach the total time to control, capture the volume and clear the timer. if(ElapsedTime >= TimeToControl) { `log("Captured!"); bControlled = true; ControlTimer.ClearTimer(); } } } function UpdateStatusBar() { PercentCaptured = (100 * float(ElapsedTime)) / float(TimeToControl); CVMovie.UpdateStatusBar(self, PercentCaptured); } function CreateControlVolumeMovie() { CVMovie = new class'SFControlVolumeMovie'; CVMovie.MovieInfo = Movie; CVMovie.SetTimingMode(TM_Real); CVMovie.Start(); } defaultproperties { TimeToControl = 100 UpdateRate = 0.1 }
Now we create the timer class. This class simply executes the SFControlVolume::StartControlling function every time it ticks.
Code:
class SFVolumeControlTimer extends Info; var SFControlVolume CV; event PostBeginPlay() { Super.PostBeginPlay(); CV = SFControlVolume(Owner); } event Timer() { CV.StartControlling(self); } defaultproperties { TickGroup = TG_PreAsyncWork bStatic = false RemoteRole = ROLE_None }
And finally, we create the Movie Player class for our status bar.
Code:
class SFControlVolumeMovie extends GFxMoviePlayer; var GFxObject StatusBarMC; function bool Start(optional bool StartPaused = false) { Super.Start(); Advance(0); StatusBarMC = GetVariableObject("_root.BlueStatusBar"); return true; } function UpdateStatusBar(SFControlVolume CV, int PercentCaptured) { local GFxObject.ASDisplayInfo DI; DI.hasXScale = true; DI.hasAlpha = true; DI.XScale = PercentCaptured; DI.Alpha = 100; if (DI.XScale >= 100) { DI.XScale = 101; } else if (DI.XScale == 0) { DI.XScale = 1; DI.Alpha = 0; } StatusBarMC.SetDisplayInfo(DI); } defaultproperties { bDisplayWithHudOff = false }
Version 2 - Status Bar Floating in Game World
If you want the status bar physically in the game world, at the center of the volume, first modify the SFControlVolume class.
NOTE: You will be able to add multiple control volumes to your level, but you must create a unique Material and TextureRenderTarget2D for each volume.
UnrealScript - SFControlVolume.uc Modifications
Code:
// Add these global vars to the top of the class var () StaticMesh Mesh; var () vector TranslationOffset; var () array<MaterialInterface> Materials; var () TextureRenderTarget2D RenderTexture; var SFControlVolumeMesh CVMesh; // Add this code to the event Touch() function, just after Super.Touch(); CVMesh = Spawn(class'SFControlVolumeMesh'); CVMesh.Mesh.SetStaticMesh(Mesh); CVMesh.Mesh.SetMaterial(0,Materials[0]); CVMesh.SetLocation(self.Location + TranslationOffset); CVMesh.PC = Other; // Add this line of code to the event UnTouch() function CVMesh.Destroy(); // Add this line of code to the CreateControlVolumeMovie() function, after CVMovie.MovieInfo = Movie; CVMovie.RenderTexture = RenderTexture;
Now create a new class. This class will be used to display the status bar in the game world.
Code:
class SFControlVolumeMesh extends StaticMeshActor placeable; var vector PlayerLoc; var actor PC; var() editinline const StaticMeshComponent Mesh; function Tick(float fDeltaTime) { Super.Tick(fDeltaTime); // Always face the player PlayerLoc = PC.Location; SetRotation(Rotator(PlayerLoc - self.Location)); } defaultproperties { bStatic = false bMovable = true Begin Object class=StaticMeshComponent Name=StaticMeshComp1 CollideActors = False BlockActors = false BlockRigidBody = False End Object Mesh = StaticMeshComp1 Components.Add(StaticMeshComp1) }
Version 3 - Status Bar on HUD at Relative Position
This version draws the status bar on the HUD at the relative position of the volume using Canvas Project. As you look around, the status bar will move on the HUD so that it is still in the same relative position.
NOTE: If you have done the Version 2 modifications to your code, undo them.
UnrealScript - Hud Wrapper Modifications
You must revise the PostRender() function of your HUD Wrapper:
Code:
event PostRender() { local SFControlVolume SFCV; super.PostRender(); // Find all control volumes in the level foreach WorldInfo.AllActors(class'SFControlVolume',SFCV) { //Project 3D world position of control volume to 2D screen position if (SFCV.CVMovie != none) { SFCV.CVMovie.UpdatePosition(Canvas.Project(SFCV.Location)); } } // Tick HUD if (HudMovie != none) { HudMovie.TickHud(0); } }
UnrealScript - SFControlVolumeMovie.uc Modifications
First, add two new global variables:
Code:
var int Width, Height;
Code:
function bool Start(optional bool StartPaused = false) { local float x0, y0, x1, y1; super.Start(); Advance(0.0); StatusBarMC = GetVariableObject("_root.BlueStatusBar"); GetVisibleFrameRect(x0, y0, x1, y1); Width = x1-x0; Height = y1-y0; return true; }
Code:
function UpdatePosition(Vector ScreenPos)
{
self.SetViewPort(ScreenPos.X,ScreenPos.Y,Width,Height);
}
UnrealEd Setup
- Ok, now add the control volume to your level, using a BSP builder brush.
- Go into the properties of the volume (F4).
- Set the Time To Control. (Maximum number of ticks to capture)
- Set the Update Rate. (How often you want the status bar to 'tick' in seconds; Lower numbers = faster tick time)
- Set the Movie field to the SWF you imported earlier.
- Save the level and test!
Version 2 Only
- Do the steps above, then...
- Open the Content Browser.
- Create a new TextureRenderTarget2D, name it whatever you like, and set its resolution to 512x256 to match the SWF.
- Create a new Material, and name it whatever you like.
- In the Material, add a new TextureSample
- Insert the TextureRenderTarget2D you created in the new TextureSample's Texture Field.
- Connect the Diffuse Output (black square) of the TextureSample to the Diffuse input of the Material.
- Set the Blend Mode of the Material to BLEND_AlphaComposite.
- Add Color->New Desaturation.
- Add Parameters->New ScalarParameter.
- Set the Default Value of the Parameter to -20.
- Wire the Diffuse Output (black square) of the TextureSample to A on Desaturation.
- Wire the Param 'None' to B on Desaturation.
- Wire the Output of Desaturation to Opacity and Emissive on the Material.
- Close the Material window and save.
- Save the package with your new material and render texture.

Uploaded with ImageShack.us
- Go into the properties of the volume (F4).
- Set the Mesh field to a plane shaped mesh, such as found at: dwStaticMeshes.Plane
- Set the Translation Offset. (This moves the status bar relative to the center of the control volume)
- Add a new Material slot.
- Assign the new material you created to Material slot 0.
- Assign the TextureRenderTarget2D you created to the RenderTexture field.
- Save the level and test!
Final Result

Uploaded with ImageShack.us
Comment