Creating the classes

EDIT: I’ve noticed that there was a mistake to the Light Environment section. I forgot to include “Class=DynamicLightEnvironment” under the “//Setting up the light environment” section. It should work correctly now.

You’ll need a total of four classes to get this to work. The first of which is your YourGameInfo class.

[code]
class YourGameInfo extends GameInfo; //This line tells UDK that you want to inherit all of the functionality of GameInfo.uc, and< add your own. The name after "class" must match the file name.
DefaultProperties //Self explanatory
{
bDelayedStart = false
PlayerControllerClass = class ‘YourGame.YourGamePlayerController’ //Setting the Player Controller to your custom script
DefaultPawnClass = class ‘YourGame.YourGamePawn’ //Setting the Pawn to your custom script
}[/code]

Now that we have our initial game set up, we’ll need to add a a pawn to manipulate inside of the game. Here is the YourGamePawnclass.

[code]
simulated function name GetDefaultCameraMode(PlayerController RequestedBy)
{
return ‘ThirdPerson’;
}

DefaultProperties
{

//Setting up the light environment
Begin Object Class=DynamicLightEnvironment Name=MyLightEnvironment
ModShadowFadeoutTime=0.25
MinTimeBetweenFullUpdates=0.2
AmbientGlow=(R=.01,G=.01,B=.01,A=1)
AmbientShadowColor=(R=0.15,G=0.15,B=0.15)
LightShadowMode=LightShadow_ModulateBetter
ShadowFilterQuality=SFQ_High
bSynthesizeSHLight=TRUE
End Object
Components.Add(MyLightEnvironment)
//Setting up the mesh and animset components
Begin Object Name=InitialSkeletalMesh
CastShadow=true
bCastDynamicShadow=true
bOwnerNoSee=false
LightEnvironment=MyLightEnvironment;
BlockRigidBody=true;
CollideActors=true;
BlockZeroExtent=true;
//What to change if you’d like to use your own meshes and animations
PhysicsAsset=PhysicsAsset’CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics’
AnimSets(0)=AnimSet’CH_AnimHuman.Anims.K_AnimHuman_AimOffset’
AnimSets(1)=AnimSet’CH_AnimHuman.Anims.K_AnimHuman_BaseMale’
AnimTreeTemplate=AnimTree’CH_AnimHuman_Tree.AT_CH_Human’
SkeletalMesh=SkeletalMesh’CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode’
End Object
//Setting up a proper collision cylinder
Mesh=InitialSkeletalMesh;
Components.Add(InitialSkeletalMesh);
CollisionType=COLLIDE_BlockAll
Begin Object Name=CollisionCylinder
CollisionRadius=+0023.000000
CollisionHeight=+0050.000000
End Object
CylinderComponent=CollisionCylinder
[/code]

Our Game and Pawn are all set up, but now we’ll need a way to interact with this pawn. That’s where the YourGamePlayerController class comes it. This is what allows us to actually control our pawn on screen. Β There’s quite a bit of code there, but most of it is heavily annotated, so if you break it down it should be pretty easy to understand.

Not all of it is needed either.

[code]
class YourGamePlayerController extends GamePlayerController;

var float PreDist; //tore our previous camera distance so that when we switch back to the normal camera, we’ll be at our original setting.

simulated event PostBeginPlay() //This event is triggered when play begins
{
super.PostBeginPlay();
Log("I am alive!"); //This sends the message "I am alive!" to thelog (to see the log, you need to run UDK with the -log switch)
}

//Functions for zooming in and out
exec function NextWeapon() /*The "exec" command tells UDK that this function can be called by the console or keybind.
We’ll go over how to change the function of keys later (if, for instance, you didn’t want you use the scroll wheel, but page up and down for zooming instead.)*/
{
if (PlayerCamera.FreeCamDistance < 512) //Checks that the the value FreeCamDistance, which tells the camera how far to offset from the view target, isn’t further than we want the camera to go. Change this to your liking.
{
`Log "MouseScrollDown"); //Another log message to tell us what’s happening in the code
PlayerCamera.FreeCamDistance += 64*(PlayerCamera.FreeCamDistance/256); /*This portion increases the camera distance.
By taking a base zoom increment (64) and multiplying it by the current distance (d) over 256, we decrease the zoom increment for when the camera is close,
(d < 256), and increase it for when it’s far away (d > 256).
Just a little feature to make the zoom feel better. You can tweak the values or take out the scaling altogether and just use the base zoom increment if you like */
}
}

exec function PrevWeapon()
{
if (PlayerCamera.FreeCamDistance > 64) //Checking if the distance is at our minimum distance
{
`Log("MouseScrollUp");
PlayerCamera.FreeCamDistance -= 64*(PlayerCamera.FreeCamDistance/256); //Once again scaling the zoom for distance
}
}

DefaultProperties
{
CameraClass=class ‘YourGameCamera’ //Telling the player controller to use your custom camera script
DefaultFOV=90.f //Telling the player controller what the default field of view (FOV) should be
}

exec function ShoulderCam() // Declaring our ShoulderCam function that we bound to
{
`Log("Shoulder Camera"); // Yet another log…
PreDist = PlayerCamera.FreeCamDistance; //Storing our previous camera distance…
YourGameCamera(PlayerCamera).CameraStyle = ‘ShoulderCam’; //Type casting our camera script to access the variable CameraStyle
}

exec function ReturnCam() //This is called on release of left shift
{
`Log("Main Camera");
PlayerCamera.FreeCamDistance = PreDist; // Restoring the previous camera distance
YourGameCamera(PlayerCamera).CameraStyle = ‘ThirdPerson’; // Restoring the previous camera style
}
[/code]

The last thing we’re going to need is the camera system itself. We’re going to call this YourGameCamera.Β  There’s a lot of code in here, but most of it is heavily annotated, so if you break it down into bits it is actually pretty easy to understand.

Much of the code is not needed, but allows for us to easily switch between camera styles by simply swapping out a few lines of code. By default, this camera style is configured to have a free (mouse controlled) third person perspective, then by hitting a key of our choice (shift in this example), the camera will quickly zoom into an over the shoulder view for our character. Upon release, the camera will return to its previous state.

[code]
class YourGameCamera extends Camera;

// initializing static variables
var float Dist;
var float TargetFOV;
var float TargetZ;
var float Z;
var float TargetOffset;
var float Offset;
var float pival;

DefaultProperties
{
FreeCamDistance = 256.f
pival = 3.14159;
}

function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
{
//Declaring local variables
local vector Loc, Pos, HitLocation, HitNormal;
local rotator Rot;
local Actor HitActor;
local CameraActor CamActor;
local bool bDoNotApplyModifiers;
local TPOV OrigPOV;

// store previous POV, in case we need it later
OrigPOV = OutVT.POV;

// Default FOV on viewtarget
OutVT.POV.FOV = DefaultFOV;

// Viewing through a camera actor.
CamActor = CameraActor(OutVT.Target);
if( CamActor != None )
{
CamActor.GetCameraView(DeltaTime, OutVT.POV);

// Grab aspect ratio from the CameraActor.
bConstrainAspectRatio = bConstrainAspectRatio || CamActor.bConstrainAspectRatio;
OutVT.AspectRatio = CamActor.AspectRatio;

// See if the CameraActor wants to override the PostProcess settings used.
CamOverridePostProcessAlpha = CamActor.CamOverridePostProcessAlpha;
CamPostProcessSettings = CamActor.CamOverridePostProcess;
}
else
{
// Give Pawn Viewtarget a chance to dictate the camera position.
// If Pawn doesn’t override the camera view, then we proceed with our own defaults
if( Pawn(OutVT.Target) == None ||
!Pawn(OutVT.Target).CalcCamera(DeltaTime, OutVT.POV.Location, OutVT.POV.Rotation, OutVT.POV.FOV) )
{
// don’t apply modifiers when using these debug camera modes.
bDoNotApplyModifiers = TRUE;

switch(CameraStyle)
{
case ‘Fixed’ : // No update, keeps previous view
OutVT.POV = OrigPOV;
break;
case ‘ThirdPerson’ : //Enters here as long as CameraStyle is still set to ThirdPerson
case ‘IsometricCam’ : //Isometric camera
case ‘ShoulderCam’ : //Side Scrolling Camera for Mega Man 2
case ‘FreeCam’ :

Loc = OutVT.Target.Location; // Setting the camera location and rotation to the viewtarget’s
Rot = OutVT.Target.Rotation;

if (CameraStyle == ‘ThirdPerson’)
{
Rot = PCOwner.Rotation; //setting the rotation of the camera to the rotation of the pawn
TargetZ = 0;
TargetFOV = 90;
TargetOffset = 0;
}

if (CameraStyle == ‘IsometricCam’) // A basic if statement
{
/*Rot.pitch = -10000;*/
/*Rot.yaw = -5500; With these two statements, we’re telling the camera to stay fixed at these rotation values, provided by rahatropa */
Rot = PCOwner.Owner.Rotation;
TargetZ = 300;
TargetFOV = 90.f;
TargetOffset = 100;
FreeCamDistance = 64;

}

if (CameraStyle == ‘ShoulderCam’)
{
Rot = PCOwner.Rotation;
FreeCamDistance = 64;
TargetFOV = 60.f;
TargetZ = 32;
TargetOffset = 32;
}

//OutVT.Target.GetActorEyesViewPoint(Loc, Rot);

if(CameraStyle == ‘FreeCam’)
{
Rot = PCOwner.Rotation;
}

Loc += FreeCamOffset >> Rot;
Loc.Z += Z; // Setting the Z coordinate offset for shoulder view

//Linear interpolation algorithm. This is the "smoothing," so the camera doesn’t jump between zoom levels
if (Dist != FreeCamDistance)
{
Dist = Lerp(Dist,FreeCamDistance,0.15); //Increment Dist towards FreeCamDistance, which is where you want your camera to be. Increments a percentage of the distance between them according to the third term, in this case, 0.15 or 15%
}
if (Z != TargetZ)
{
Z = Lerp(Z,TargetZ,0.1);
}
if (DefaultFOV != TargetFOV)
{
DefaultFOV = Lerp(DefaultFOV,TargetFOV,0.1);
}
if (Offset != TargetOffset)
{
Offset = Lerp(Offset,TargetOffset,0.1);
}

Pos = Loc – Vector(Rot) * Dist; /*Instead of using FreeCamDistance here, which would cause the camera to jump by the entire increment, we use Dist, which increments in small steps to the desired value of FreeCamDistance using the Lerp function above*/
// Setting the XY camera offset for shoulder view
Pos.X += Offset*sin(-Rot.Yaw*pival*2/65536);
Pos.Y += Offset*cos(Rot.Yaw*pival*2/65536);
// @fixme, respect BlockingVolume.bBlockCamera=false

//This determines if the camera will pass through a mesh by tracing a path to the view target.
HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12));
//This is where the location and rotation of the camera are actually set
OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation;
OutVT.POV.Rotation = Rot;

break; //This is where our code leaves the switch-case statement, preventing it from executing the commands intended for the FirstPerson case.

case ‘FirstPerson’ : // Simple first person, view through viewtarget’s ‘eyes’
default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
break;

}
}
}

if( !bDoNotApplyModifiers )
{
// Apply camera modifiers at the end (view shakes for example)

ApplyCameraModifiers(DeltaTime, OutVT.POV);
}
//`log( WorldInfo.TimeSeconds @ GetFuncName() @ OutVT.Target @ OutVT.POV.Location @ OutVT.POV.Rotation @ OutVT.POV.FOV );
}
[/code]

46 thoughts on “Creating the classes

  1. Warning/Error Summary
    ———————
    D:UDKUDK-2012-03Binaries..DevelopmentSrcYourGameClassesYourGamePawn.uc : Error, Bad class definition ”/”/1699/1699

    Failure – 1 error(s), 0 warning(s)

    did I do this the wrong way?
    much thanks if you can help

  2. oh when you paste it here it shows correctly but when I look at your code in Firefox it shows as “Loc += FreeCamOffset > > Rot;”
    or: “Loc += FreeCamOffset “ampersand gt; “ampersand gt;” Rot;”

  3. Second that, my character wont pick up weapons either, I even created my own weapon class and tried that and he still wont?! does this mean because of the mesh the weapons need to be attached to the sockets? but even so surely you can implement weapons in that game that can be picked u p??

  4. Yeah, web browsers tend to throw in the actual hexidecimal characters in place of what should be there (for example ), so if you see any of those, please let me know and I can correct it.

    As far as the character not picking up weapons, I remember running into that issue a long time ago, but forgot how I resolved that. I *THINK* it had something to do with a bool in the default properties for something like “bCanCarryInventory” or something similar.

    I wish I could be more helpful, but it’s been some time since I’ve written this. :/

    I did write a much cleaner version of everything in my book, so shoot me a message on twitter (@DaveVoyles) and I can help you out on there.

  5. ok mate will do I just bought two books one the Mastering UDK Game Development [eBook] and the other UnrealScript Game Programming Cookbook [eBook] which im sure you wrote one or both lol but unfortunately you have custom weapons but not a fix for this I will message you on twitter now πŸ™‚

  6. Yup, that was it!

    I thought they were going to include the source code with the book, but I guess they didn’t.

    Regardless, I have it all for you!

    As far as the inability to pickup the weapons, try adding this line of code under defaultProperties for your pawn:

    DefaultProperties{
    ....
    bCanPickupInventory=True
    ...
    }

  7. well he picks it up from the weapon pick up factory, then an on screen string appears ‘Link Gun’, then that’s it no gun in hands no way of getting it out! ? any ideas ?

  8. Hmmm that’s odd.

    Like I said, when writing the book I ran across a way of doing this so that it does pick up the weapon correctly. Not sure why it doesn’t do it here though :/.

    Honestly, I would scrape this code and not bother doing this, as the source code with the book is so much cleaner.

    I’m at GDC right now, so it’s difficult for me to go back and forth. I just happen to be writing in the press room at the moment.

  9. I think it has something to do with the RhonePlayerController class extending from GamePlayerController,
    the RhonePawn class extending from the GamePawn and the
    RhoneGameInfo class extending from GameInfo. Now if I extend them from UTPlayerController and UTPawn I can start with a gun, pick up guns and use them and switch between weapons. BUT I lose all the functionality of my camera by changing these settings. So is there something I need to change in a config file do I possibly need to add [RhoneGame.RhoneGame] to a config file with some settings?? this has really stumped me but I know im getting closer. Please please help πŸ™‚

  10. also I have added the RhoneGame.RhoneGame to the config files for game type and server and of course set it to RhoneGameInfo in the editor to get the camera functionality. We just need to get this gun from being picked up and putting a string on the screen to the pawn actually holding it and firing it.

  11. Ah ok, so it had to do with which classes we were extending from.I figured that’s what the solution was, but I just didn’t have the time to sift through all of the code at the moment.

    I like to go down as deep in the parent classes as I can, in order to remove all of the Unreal Tournament functionality. A lot of it is great, but it causes many issues too, because you need to know their classes in-and-out, otherwise you have conflicts like that.

    Do you know what the exact issue was? I’d like to know so that I can post the solution here, and clean up the code above. Thanks for following along!

  12. Hey bro would just like to say the problem is solved thanks to this brilliant guy who made an extension tutorial for the Gears of war style camera! the tutorial can be found here

    http://forums.epicgames.com/threads/804974-GoW-Camera-Tutorial-extension

    so if you would like to reference it in your tutorial or even go through the code and amend yours then that would be kool

    the video of it working can be seen here but I think its still uploading at the present moment so bare with it! Youtube like taking their time on processing things lol

    Phew glad that is over with was very frustrating. The best bit about the extension is the added Right Mouse Button feature with the Call of Duty style Aim Zoom instead of the alternate firing think that just perfects it so thank you to you all and when is your next book due out I look forward to it??

  13. I only have one small error now and that is when I run my level from the batch file it starts in the basic fps mode its not picking up my game info code! hmmm any suggestions??

  14. Oh and I forgot to mention that yes I have used GameInfo in the editor and the config files, that also include RhoneGameInfo in the editor as well as rhonegame now they both work with all the code and camera when testing in the editor, but for some reason not when I run the level through the batch file! Just one thing after another lol

  15. Hmmm that’s odd. Write your batch code in here and I’ll look at it.

    I was going to tell you to do exactly that (in your follow up post), so that resolves the editor issue, but I’m not sure about the batch. You may have to tell it exactly which level to use and which gametype to run, similar to how you would add the properties to the shortcut on your desktop exe.

    By using things like “C:/UDk/UDK.exe/ -Level1, – Godmode, etc)

  16. I really don’t know. You’re telling it to do exactly what I would have done. Your best bet at this point may be to drop it in the forums. Wish I could be more helpful :/

  17. This might help you a bit better to help me, as I am a n00b in the unrealscript it might be a bit messy lol, the code compiles successfully with 4warnings which I can live with. So as we know it work fine in the editor but not the batch file.

    ==========================================================================
    RhoneGame.uc

    class RhoneGame extends UTDeathmatch;

    var int EnemiesLeft;
    var array EnemySpawners;

    var float MinSpawnerDistance, MaxSpawnerDistance;

    simulated function PostBeginPlay()
    {
    local RhoneEnemySpawner ES;

    super.PostBeginPlay();

    GoalScore = EnemiesLeft;

    foreach DynamicActors(class’RhoneEnemySpawner’, ES)
    EnemySpawners[EnemySpawners.length] = ES;
    }

    function ActivateSpawners()
    {
    local int i;
    local array InRangeSpawners;
    local RhonePlayerController PC;

    foreach LocalPlayerControllers(class’RhonePlayerController’, PC)
    break;
    if(PC.Pawn == none)
    {
    SetTimer(1.0, false, ‘ActivateSpawners’);
    return;
    }

    for(i=0; i MinSpawnerDistance && VSize(PC.Pawn.Location – EnemySpawners[i].Location) < MaxSpawnerDistance)
    {
    if(EnemySpawners[i].CanSpawnEnemy())
    InRangeSpawners[InRangeSpawners.length] = EnemySpawners[i];
    }
    }

    if(InRangeSpawners.length == 0)
    {
    `log("No enemy spawners within range!");
    SetTimer(1.0, false, 'ActivateSpawners');
    return;
    }

    InRangeSpawners[Rand(InRangeSpawners.length)].SpawnEnemy();

    SetTimer(1.0 + FRand() * 3.0, false, 'ActivateSpawners');
    }

    function ScoreObjective(PlayerReplicationInfo Scorer, Int Score)
    {
    local int i;

    EnemiesLeft–;
    super.ScoreObjective(Scorer, Score);

    if(EnemiesLeft == 0)
    {
    for(i=0; i> Rot;
    Loc.Z += Z; // Setting the Z coordinate offset for shoulder view

    //Linear interpolation algorithm. This is the “smoothing,” so the camera doesn’t jump between zoom levels
    if (Dist != FreeCamDistance)
    {
    Dist = Lerp(Dist,FreeCamDistance,0.15); //Increment Dist towards FreeCamDistance, which is where you want your camera to be. Increments a percentage of the distance between them according to the third term, in this case, 0.15 or 15%
    }
    if (Z != TargetZ)
    {
    Z = Lerp(Z,TargetZ,0.1);
    }
    if (DefaultFOV != TargetFOV)
    {
    DefaultFOV = Lerp(DefaultFOV,TargetFOV,0.1);
    }
    if (Offset != TargetOffset)
    {
    Offset = Lerp(Offset,TargetOffset,0.1);
    }

    Pos = Loc – Vector(Rot) * Dist; /*Instead of using FreeCamDistance here, which would cause the camera to jump by the entire increment, we use Dist, which increments in small steps to the desired value of FreeCamDistance using the Lerp function above*/
    // Setting the XY camera offset for shoulder view
    Pos.X += Offset*sin(-Rot.Yaw*pival*2/65536);
    Pos.Y += Offset*cos(Rot.Yaw*pival*2/65536);
    // @fixme, respect BlockingVolume.bBlockCamera=false

    //This determines if the camera will pass through a mesh by tracing a path to the view target.
    HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12));
    //This is where the location and rotation of the camera are actually set
    OutVT.POV.Location = (HitActor == none) ? Pos : HitLocation;
    OutVT.POV.Rotation = Rot;

    break; //This is where our code leaves the switch-case statement, preventing it from executing the commands intended for the FirstPerson case.

    case ‘FirstPerson’ : // Simple first person, view through viewtarget’s ‘eyes’
    default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    break;

    }
    }
    }

    if( !bDoNotApplyModifiers )
    {
    // Apply camera modifiers at the end (view shakes for example)

    ApplyCameraModifiers(DeltaTime, OutVT.POV);
    }
    //`log( WorldInfo.TimeSeconds @ GetFuncName() @ OutVT.Target @ OutVT.POV.Location @ OutVT.POV.Rotation @ OutVT.POV.FOV );
    }

    defaultproperties
    {
    FreeCamDistance = 256.f
    pival = 3.14159;
    }
    ==========================================================================
    RhoneGameInfo

    class RhoneGameInfo extends UTGame; //This line tells UDK that you want to inherit all of the functionality of GameInfo.uc, and add your own. The name after “class” must match the file name.

    defaultproperties //Self explanatory
    {
    bDelayedStart = false
    PlayerControllerClass=class’RhoneGame.RhonePlayerController’ //Setting the Player Controller to your custom script
    DefaultPawnClass=class’RhoneGame.RhonePawn’ //Setting the Pawn to your custom script
    }
    ==========================================================================
    RhonePawn.uc

    class RhonePawn extends UTPawn;

    var float CameraOffsetLength;

    var float GlobalCamZoom; /* Indexer value to allow camera memory of where the user last had his zoom set */

    /* The values that will actually be used in the camera calculation algorithm */
    var float CurrCamZoom; //The camera’s position on the X axis or Forward/Backward
    var float CurrYZoom; //Camera’s Left/Right position
    var float CurrFOV; // Camera’s FOV used for a nice zoom effect
    var float CurrZ; // the camera’s position on the Z axis or Up/Down
    /* Lerp values to allow smooth interpolation of the camera */
    var float TargetFOV;
    var float TargetCamZoom;
    var float TargetYZoom;
    var float TargetZ;

    /* Target values for where the camera should go when we shoulder/unshoulder the camera */
    var float ShoulderZoom;
    var float ShoulderYZoom;
    var float ShoulderFOV;
    var float ShoulderZ;
    var float NonShoulderZ;
    var float NonShoulderFOV;
    var float NonShoulderYZoom;
    /* Flag to indicate if the user zoomed in or not. */
    var bool bShoulderCam;

    var float CurrentCameraDistance, CurrentCameraOffsetLength;
    var Vector PawnEyeLocation;
    var Vector PlayerHitTarget;

    var bool bInvulnerable;
    var float InvulnerableTime;
    var bool bScoreDeaths;

    event Bump(Actor Other, PrimitiveComponent OtherComp, vector HitNormal)
    {
    if(RhoneEnemy(Other) != none && !bInvulnerable)
    {
    bInvulnerable = true;
    SetTimer(InvulnerableTime, false, ‘EndInvulnerable’);
    TakeDamage(RhoneEnemy(Other).BumpDamage, none, Location, vect(0,0,0), class’UTDmgType_LinkPlasma’);
    }
    }

    function EndInvulnerable()
    {
    bInvulnerable = false;
    }

    simulated function bool CalcCamera(float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV)
    {
    local vector CamStart, /*FirstHitLocation,*/ HitLocation, HitNormal, CamDir, X, Y, Z, end;
    local float DesiredCameraZOffset;
    local bool /*bInsideHero,*/ bObstructed;

    local float DesiredCameraDistance;
    local float CameraOffsetRatio;
    local vector tempCamStart, tempCamEnd;
    local Vector VectorX, VectorY, VectorZ;

    local Actor CamTrace;

    bObstructed = false;

    //Mesh.SetOwnerNoSee(false);

    // Handle the fixed camera
    if (bFixedView)
    {
    out_CamLoc = FixedViewLoc;
    out_CamRot = FixedViewRot;
    }

    if(bShoulderCam) // User has zoomed in, set our Lerp targets to where we’re zooming to.
    {
    TargetYZoom = ShoulderYZoom;
    TargetCamZoom = ShoulderZoom;
    TargetFOV = ShoulderFOV;
    TargetZ = ShoulderZ;
    }
    else // Default the Target, if the user was zoomed in, return the values back to normal otherwise do nothing
    {
    TargetYZoom = NonShoulderYZoom;
    TargetCamZoom = GlobalCamZoom;
    TargetFOV = NonShoulderFOV;
    TargetZ = NonShoulderZ;
    }

    if(CurrZ != TargetZ) // Lerp the Z-Axis if the value changed
    {
    CurrZ = Lerp(CurrZ, TargetZ, 0.1);
    }
    if(CurrFOV != TargetFOV) // Lerp the FOV for the zoom effect
    {
    CurrFOV = Lerp(CurrFOV, TargetFOV, 0.1);
    /* TODO: Change Controller to the name of your PlayerController Class */
    RhonePlayerController(Owner).SetFOV(CurrFOV);
    }
    if(CurrCamZoom != TargetCamZoom) // Lerp the Zoom for a steady zoom in/out effect
    {
    CurrCamZoom = Lerp(CurrCamZoom, TargetCamZoom, 0.1);
    }

    if(CurrYZoom != TargetYZoom) // Lerp the left/right movement of the camera when we zoom in to prevent model clipping
    {
    CurrYZoom = Lerp(CurrYZoom, TargetYZoom, 0.1);
    }

    ModifyRotForDebugFreeCam(out_CamRot);

    CamStart = Location;
    DesiredCameraZOffset = (Health > 0) ? GetCollisionRadius() * /*Default Value: 0.75*/ CurrZ : 0.f;
    CameraZOffset = (fDeltaTime < 0.2) ? DesiredCameraZOffset * 5 * fDeltaTime + (1 – 5*fDeltaTime) * CameraZOffset : DesiredCameraZOffset;

    CamStart.Z += CameraZOffset;
    GetAxes(out_CamRot, X, Y, Z);

    /*VectorX here you can implement camera zoom in/out or scaling or whatever you want to call it */
    VectorX = X * GetCollisionRadius() * CurrCamZoom; //this vector determine depth of camera, how far from character it will be
    VectorY = Y * GetCollisionRadius() * CurrYZoom; // this vector determine side of camera, negaive value pull character to left side, while positive to right side
    VectorZ = (GetCollisionRadius() /* FMax(0,(1.0-CamRotZ.Z))*/ * Z) * -1.55; //this value try to pull camera forward while pitching down, and back while pitching up, but pulling back seems to dont work
    CamDir = VectorX + VectorY + VectorZ;

    if ( (Health <= 0) || bFeigningDeath )
    {
    // adjust camera position to make sure it's not clipping into world
    //Note that you can still get clipping if FindSpot fails (happens rarely)
    FindSpot(GetCollisionExtent(),CamStart);
    }

    if (CurrentCameraScale CameraScale)
    {
    CurrentCameraScale = FMax(CameraScale, CurrentCameraScale – 5 * FMax(CameraScale – CurrentCameraScale, 0.3)*fDeltaTime);
    }
    if (CamDir.Z <= GetCollisionHeight())
    {
    CamDir *= square(cos(out_CamRot.Pitch * 0.000000958738)); // 0.0000958738 = 2*PI/65536
    }

    out_CamLoc = CamStart – CamDir;

    if (Trace(HitLocation, HitNormal, out_CamLoc, CamStart, false, vect(12,12,12)) != none)
    {
    out_CamLoc = HitLocation;
    bObstructed = true;
    }

    /* This code is from ActionGam, thanks for fall, for creating this.
    * It will determine back trace collision while closing to walls or sth like thaht*/
    if (Trace(HitLocation, HitNormal, out_CamLoc, CamStart, false, vect(12,12,12),,TRACEFLAG_Blocking) != none)
    {
    DesiredCameraDistance = VSize(HitLocation-CamStart);
    CurrentCameraDistance = (fDeltaTime < 0.5f) ? FClamp(DesiredCameraDistance * 2 * fDeltaTime + (1 – 2*fDeltaTime) * CurrentCameraDistance,0,DesiredCameraDistance) : DesiredCameraDistance;

    HitLocation = CamStart + Normal(HitLocation-CamStart) * CurrentCameraDistance;

    CameraOffsetRatio = CurrentCameraDistance/VSize(out_CamLoc – CamStart);
    out_CamLoc = HitLocation;
    bObstructed = true;
    }

    else
    {
    DesiredCameraDistance = VSize(out_CamLoc-CamStart);
    CurrentCameraDistance = (fDeltaTime < 0.5f) ? FClamp(DesiredCameraDistance * 2 * fDeltaTime + (1 – 2*fDeltaTime) * CurrentCameraDistance,0,DesiredCameraDistance) : DesiredCameraDistance;

    HitLocation = CamStart + Normal(out_CamLoc – CamStart) * CurrentCameraDistance;

    CameraOffsetRatio = CurrentCameraDistance/VSize(out_CamLoc – CamStart);
    out_CamLoc = HitLocation;
    }

    if (Trace(HitLocation, HitNormal, out_CamLoc, CamStart, false, vect(12,12,12)) != none)
    {
    out_CamLoc = HitLocation;
    return false;
    }

    /*Again thanks for fall, for this. It just inside character collision detection*/
    tempCamStart = CamStart;
    tempCamStart.Z = 0;
    tempCamEnd = out_CamLoc;
    tempCamEnd.Z = 0;

    end = out_CamLoc + Normal(vector(out_CamRot))*32768;
    CamTrace = Trace(HitLocation, HitNormal, end, out_CamLoc, false);

    PlayerHitTarget = HitLocation;

    PawnEyeLocation = Location + EyeHeight * vect(0,0,1);

    if(bObstructed && (VSize(tempCamEnd – tempCamStart) < CylinderComponent.CollisionRadius*1.25) && (out_CamLoc.ZLocation.Z-CylinderComponent.CollisionHeight))
    {
    SetHidden(true);
    }
    else
    SetHidden(false);

    return !bObstructed;
    }

    defaultproperties
    {
    bScoreDeaths=false
    bCanPickupInventory=True
    InvulnerableTime=0.6

    bShoulderCam = false;

    /*TODO: Modify camera zoom values to fit your tastes
    * Be sure to set CurrCamZoom/TargetCamZoom to the GlobalCamZoom to prevent the
    * camera from LERPing and giving a weird effect on game start */
    CurrCamZoom = 5.0
    TargetCamZoom = 5.0
    GlobalCamZoom = 5.0
    ShoulderZoom = 2.5

    /*TODO: Modify Left/Right values to fit your tastes
    * Set Curr/Target values to your default values to avoid Lerping without change
    */
    CurrYZoom=-0.5
    TargetYZoom=-0.5
    ShoulderYZoom=-1.0
    NonShoulderYZoom=-0.5
    /*TODO: Modify FOV values to fit your tastes
    * Set Curr/Target values to your default values to avoid Lerping without change
    */
    CurrFOV=90.0
    TargetFOV=90.0
    ShoulderFOV=45.0
    NonShoulderFOV=90.0
    /*TODO: Modify Z values to fit your tastes
    * Set Curr/Target values to your default values to avoid Lerping without change
    */
    CurrZ=0.75
    TargetZ=0.75
    ShoulderZ=0.50
    NonShoulderZ=0.75

    }
    ==========================================================================
    RhonePlayerController.uc

    class RhonePlayerController extends UTPlayerController;

    exec function NextWeapon()
    {
    if(!RhonePawn(Pawn).bShoulderCam)
    RhonePawn(Pawn).GlobalCamZoom += 1.0;
    }
    exec function PrevWeapon()
    {
    if(!RhonePawn(Pawn).bShoulderCam)
    RhonePawn(Pawn).GlobalCamZoom -= 1.0;
    }
    exec function ShoulderCam()//Set the camera into aim mode. Decrease FOV and such
    {
    RhonePawn(Pawn).bShoulderCam = true;
    }
    exec function ReturnCam()
    {
    RhonePawn(Pawn).bShoulderCam = false;
    }

    /**
    * Adjusts weapon aiming direction.
    * Gives controller a chance to modify the aiming of the pawn. For example aim error, auto aiming, adhesion, AI help…
    * Requested by weapon prior to firing.
    *
    * @param W, weapon about to fire
    * @param StartFireLoc, world location of weapon fire start trace, or projectile spawn loc.
    */

    //This function is required otherwise our aim will be off ever so slightly because we don’t account for the camera offset in calculation.
    function Rotator GetAdjustedAimFor( Weapon W, vector StartFireLoc )
    {
    local RhonePawn P;
    local Rotator R;
    local Vector V;
    P = RhonePawn(Pawn);
    // by default, return Rotation. This is the standard aim for controllers
    // see implementation for PlayerController.
    if ( Pawn != none )
    {
    // Gets the vector for our aim adjustment by taking the result of our HitLocation from running Trace() when our camera updates and subtracting from it our current location
    V = P.PlayerHitTarget – P.PawnEyeLocation;

    //Cast our Vector to a Rotator
    R = Rotator(V);

    //Return our adjusted aim Rotator
    return R;
    }
    return Rotation;
    }

    function MakeMeInvisible()
    {
    if(Pawn != none)
    Pawn.SetHidden(true);
    }

    reliable client function ClientSetHUD(class newHUDType)
    {
    if(myHUD != none)
    myHUD.Destroy();

    myHUD = spawn(class’RhoneHUD’, self);
    }

    exec function Upgrade()
    {
    if(Pawn != none && RWeapon(Pawn.Weapon) != none)
    RWeapon(Pawn.Weapon).UpgradeWeapon();
    }

    exec function StartFire( optional byte FireModeNum )
    {
    super.StartFire(FireModeNum);

    if(Pawn != none && UTWeap_RocketLauncher(Pawn.Weapon) != none)
    {
    Pawn.SetHidden(false);
    SetTimer(1, false, ‘MakeMeInvisible’);
    }
    }

    defaultproperties
    {
    CameraClass = class ‘RhoneGameCamera’ //Telling the player controller to use your custom camera script
    DefaultFOV=90.f //Telling the player controller what the default field of view (FOV) should be

    bBehindView=true //Required to route camera calculation to our portion of CalcCamera()
    }

  18. WOW took a while but i found the fix to get it running in the batch file. Just needed to add this to the GameInfo class.

    static event class SetGameType(string MapName, string Options, string Portal)
    {
    return class’RhoneGame.RhoneGameInfo’;
    }

    • Solved it just need to add this to GameInfo class for anybody else who has this trouble

      WOW took a while but i found the fix to get it running in the batch file. Just needed to add this to the GameInfo class.

      Code:
      static event class SetGameType(string MapName, string Options, string Portal)
      {
      return class’RhoneGame.RhoneGameInfo’;
      }

  19. Hello again Dave my man, I decided to go through your ‘UnrealScript Game Programming CookBook’, and am following your ‘Custom Camera System tutorials, but once again have a nice error ‘LOL’.

    Chapter 3!
    In this chapter, we will be covering the following recipes:
    Configuring the engine and editor for a custom camera
    Writing the TutorialCamera class
    Camera properties and archetypes
    Creating a first person camera
    Creating a third person camera
    Creating a side-scrolling camera
    Creating a top-down camera

    so I have followed what you have said so far up to the point of creating the Archtype, now when creating the archtype under RhonePackage.archetypes.Arc_RhoneGameCamera:

    1. Build is successful – 0 Errors, 2 Warnings

    Warning 2 Invalid property value in defaults: CameraProperties=RhoneCameraProperties’RhonePackage.archetypes.Arc_RhoneGameCamera’ C:UDKUDK-RhoneGameDevelopmentSrcRhoneGameClassesRhoneGameCamera.uc 84 1 RhoneGame

    Warning 1 ObjectProperty RhoneGame.RhoneGameCamera:CameraProperties: unresolved reference to ‘RhoneCameraProperties’RhonePackage.archetypes.Arc_RhoneGameCamera” C:UDKUDK-RhoneGameDevelopmentSrcRhoneGameClassesRhoneGameCamera.uc 84 1 RhoneGame
    So I assumed it was invalid due to the Archetype not being created in my custom level, so I have tried making the archetype following the exact instructions in the book but obviously changing to suit my game.

    CameraProperties=RhoneCameraProperties’RhonePackage.archetypes.Arc_RhoneGameCamera’

    now for some reason creating the archetype under these properties the archtype does not show up even under all assets, but when I create the archtype under

    RhoneGame.archetypes.Arc_RhoneGameCamera

    it creates the archtype but I do not get all the functionality of the Unrealscript and so so not have the tick box to turn the camera on in PIE and edit the properties on the fly.

    I will now post the code and you can go through and see if I have made any errors?!

    ==========================================================================

    class RhoneGameCamera extends Camera;

    // Reference to the camera properties
    var const RhoneCameraProperties CameraProperties;

    /** Lets us know that the class is being called, for debugging purposes */
    simulated event PostBeginPlay()
    {
    super.PostBeginPlay();
    `Log(“Rhone Camera up”);
    }

    /*****************************************************************
    Query ViewTarget and outputs Point Of View.
    *
    * @param OutVT ViewTarget to use.
    * @param DeltaTime Delta Time since last camera
    update in seconds
    *****************************************************************/
    function UpdateViewTarget (out TViewTarget OutVT, float DeltaTime)
    {
    local Pawn Pawn;
    local Vector V, PotentialCameraLocation, HitLocation,
    HitNormal;
    local Actor HitActor;

    /** If there is an interpolation, don’t update outgoing viewtarget */
    if (PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing)
    {
    return;
    }

    /** Our pawn will be where we are grabbing our perspective from */
    Pawn = Pawn(OutVT.Target);

    /** If our pawn is alive*/
    if (Pawn != None)
    {
    /** Start the camera location from a valid socket name, if set correctly in the camera properties */
    // (i.e. WeaponSocket)
    if (Pawn.Mesh != None && Pawn.Mesh.GetSocketByName(CameraProperties.PawnSocketName) != None)
    {
    Pawn.Mesh.GetSocketWorldLocationAndRotation(CameraProperties.PawnSocketName, OutVT.POV.Location, OutVT.POV.Rotation);
    }

    /** Otherwise grab it from the target eye view point */
    else
    {
    OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    }

    /** If the camera properties forces the camera to always use the target rotation, then extract it now */
    if (CameraProperties.UseTargetRotation)
    {
    OutVT.Target.GetActorEyesViewPoint(V, OutVT.POV.Rotation);
    }

    //CameraProperties.UseTargetRotation = false;

    /** Offset the camera */
    OutVT.POV.Rotation+=CameraProperties.CameraRotationOffset;

    /** Do the math for the potential camera location */
    PotentialCameraLocation=OutVT.POV.Location+ (CameraProperties.CameraOffset >> OutVT.POV.Rotation);

    /** Draw a trace to see if the potential camera location will work*/
    HitActor=Trace(HitLocation, HitNormal, PotentialCameraLocation, OutVT.POV.Location, true,,, TRACEFLAG_BULLET);

    /** Will the trace hit world geometry? If so then use the hit location and offset it by the hit normal */
    if (HitActor!=None&&HitActor.bWorldGeometry)
    {
    OutVT.POV.Location=HitLocation+HitNormal*16.f;
    }
    else
    {
    OutVT.POV.Location=PotentialCameraLocation;
    }
    }
    }

    defaultproperties
    {
    /** This sets our camera to use the settings we create in the editor */
    CameraProperties=RhoneCameraProperties’RhonePackage.archetypes.Arc_RhoneGameCamera’
    }

    ==========================================================================

    class RhoneCameraProperties extends Object
    /** We don’t want to clutter up the editor, so hide Object categories */
    HideCategories(Object);

    /** Camera offset to apply */
    var(Camera) const Vector CameraOffset;

    /** Camera rotational offset to apply */
    var(Camera) const Rotator CameraRotationOffset;

    /** Pawn socket to attach the camera to */
    var(Camera) const Name PawnSocketName;

    /** If true, then always use the target rotation */
    var(Camera) const bool UseTargetRotation;

    defaultproperties
    {

    }
    ==========================================================================

  20. Solved it bro, had to actually make the archetype of CameraProperties in the actor browser, not Camera as you stated lol. But all working so now I can continue with the FPS and Third Person etc…

    thanks bro brilliant book though πŸ™‚

  21. How do we get the code to go with the UnrealScript Game Programming cookbook as Packtpub says that there is no code with this book, although chapter 2 says there is lol

  22. how do I implement a first person style zoom to this? so that default is OverShoulderCam and when zoomed it goes to FirstPerson like looking down the barrel

    ==========================================================================

    class RhonePlayerController extends PlayerController;

    // Reference to the camera properties
    var const RhoneCameraProperties CameraProperties;

    /************************************************************************************
    * Rotator where the pawn will be aiming the weapon, forces the game to use the pawn’s
    * direction for aiming, not camera’s
    ************************************************************************************/
    function Rotator GetAdjustedAimFor(Weapon W, vector StartFireLoc)
    {
    return Pawn.GetBaseAimRotation();
    }

    /*************************************************************************************************************
    * Place the name of the camera you want to use in here. If you want to adjust it on the fly within the editor,
    * use the Archetype that we’ve created, so Class’RhoneGameCamera’.
    * Otherwise, enter the name of the class you’d like to use. i.e. ‘ThirdPersonCam’
    *************************************************************************************************************/

    defaultproperties
    {
    //Switch between the different styles of camera
    //CameraClass = Class’ThirdPersonCam’//Telling the player controller to use your custom camera script
    CameraClass = Class’OverShoulderCam’//Telling the player controller to use your custom camera script
    //CameraClass = Class’FirstPersonCam’//Telling the player controller to use your custom camera script
    }

    ============================================================================
    class RhonePawn extends UTPawn;

    //makes player temporarily invulnerable to the enemy attacks so life depletes slower
    var bool bInvulnerable;
    var float InvulnerableTime;
    var bool bScoreDeaths;

    //sprint speed and stamina variables
    var float SprintSpeed;
    var float WalkSpeed;

    var float Stamina;
    var float SprintTimer;
    var float SprintRecoverTimer;
    var float Empty;
    var bool bSprinting;

    event Bump(Actor Other, PrimitiveComponent OtherComp, vector HitNormal)
    {
    if(RhoneEnemy(Other) != none && !bInvulnerable)
    {
    bInvulnerable = true;
    SetTimer(InvulnerableTime, false, ‘EndInvulnerable’);
    TakeDamage(RhoneEnemy(Other).BumpDamage, none, Location, vect(0,0,0), class’UTDmgType_LinkPlasma’);
    }
    }

    function EndInvulnerable()
    {
    bInvulnerable = false;
    }

    exec function startSprint()
    {
    GroundSpeed = SprintSpeed;
    bSprinting = true;
    if(GroundSpeed == SprintSpeed)
    {
    StopFiring();
    SetTimer(SprintTimer, false, ‘EmptySprint’);
    }
    }

    exec function stopSprint()
    {
    GroundSpeed = WalkSpeed;
    }

    simulated function EmptySprint()
    {
    Stamina = Empty;
    GroundSpeed = WalkSpeed;
    bSprinting = true;
    SetTimer(SprintRecoverTimer, false, ‘ReplenishStamina’);
    }

    simulated function ReplenishStamina()
    {
    Stamina = 20.0;
    bSprinting = false;
    }

    simulated function PlayFootStepSound(int FootDown)
    {
    super.PlayFootStepSound(FootDown);
    }

    defaultproperties
    {
    //invulnerable
    bScoreDeaths=false
    bCanPickupInventory=True
    InvulnerableTime=0.6

    //sprint and stamina settings
    GroundSpeed=200.0
    AirSpeed=200.0

    WalkSpeed=220.0
    SprintSpeed=500.0
    SprintTimer=12.0
    SprintRecoverTimer=8.0
    Stamina=10.0
    Empty=1
    }
    ==========================================================================
    class RhoneGameCamera extends Camera;

    // Reference to the camera properties
    var const RhoneCameraProperties CameraProperties;

    /** Lets us know that the class is being called, for debugging purposes */
    simulated event PostBeginPlay()
    {
    super.PostBeginPlay();
    `Log(“Rhone Camera up”);
    }

    /********************************************************************************
    * Searches ViewTarget and outputs PoV
    *
    * @param OutVT ViewTarget we’ll be using
    * @param DeltaTime Delta Time since last cam update (in seconds)
    ********************************************************************************/
    function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
    {
    local Pawn Pawn;
    local Vector V, PreferredCamLoc, HitLoc, HitNorm;
    local Actor HitActor;

    // If we don’t have our CameraProperties class attached, then juse use Camera.UC’s default code
    if (CameraProperties == None)
    {
    Super.UpdateViewTarget(OutVT, DeltaTime);
    }

    // If there is an interpolation, don’t update outgoing viewtarget
    if (PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing)
    {
    return;
    }

    // Our pawn will be be where we are grabbing our perspective from
    Pawn = Pawn(OutVT.Target);
    // If our pawn is alive
    if (Pawn != None)
    {
    //Start the camera location from a valid socket name, if set correctly in the camera properties
    // (i.e. WeaponSocket)
    if (Pawn.Mesh != None && Pawn.Mesh.GetSocketByName(CameraProperties.PawnSocketName) != None)
    {
    Pawn.Mesh.GetSocketWorldLocationAndRotation(CameraProperties.PawnSocketName, OutVT.POV.Location, OutVT.POV.Rotation);
    }
    // Otherwise grab it from the target eye view point
    else
    {
    OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    }

    // If the camera properties forces the camera to always use the target rotation, then extract it now
    if (CameraProperties.UseTargetRotation)
    {
    OutVT.Target.GetActorEyesViewPoint(V, OutVT.POV.Rotation);
    }

    // Offset the cam
    OutVT.POV.Rotation += CameraProperties.CameraRotationOffset;

    // Do the math for the potential cam location
    PreferredCamLoc = OutVT.POV.Location + (CameraProperties.CameraOffset >> OutVT.POV.Rotation);

    // Draw a trace to see if the potential cam location will work
    HitActor = Trace(HitLoc, HitNorm, PreferredCamLoc, OutVT.POV.Location, true,,, TRACEFLAG_BULLET);

    // Will the trace hit world geometry? If so then use the hit location and offset it by the hit normal
    if (HitActor != None && HitActor.bWorldGeometry)
    {
    OutVT.POV.Location = HitLoc + HitNorm * 16.f;
    }
    else
    {
    OutVT.POV.Location = PreferredCamLoc;
    }
    }
    }

    defaultproperties
    {
    /** This sets our camera to use the settings we create in the editor */
    CameraProperties=RhoneCameraProperties’RhonePackage.Archetypes.Arc_RhoneGameCamera1′
    }
    ==========================================================================
    class RhoneCameraProperties extends Object
    /** We don’t want to clutter up the editor, so hide Object categories */
    HideCategories(Object);

    /** Camera offset to apply */
    var(Camera) const Vector CameraOffset;

    /** Camera rotational offset to apply */
    var(Camera) const Rotator CameraRotationOffset;

    /** Pawn socket to attach the camera to */
    var(Camera) const Name PawnSocketName;

    /** If true, then always use the target rotation */
    var(Camera) const bool UseTargetRotation;

    /** If true, then use the third person settings */
    var(Camera) const bool UseThirdPerson;

    defaultproperties
    {

    }
    ==========================================================================
    class FirstPersonCam extends Camera;

    //Hardcoded vector offset we will use, rather than tweaking values in the editor’s CameraProperties
    var const Vector CamOffset;
    //Hardcoded rotator offset we will use, rather than tweaking values in the editor’s CameraProperties
    var const Rotator CamOffsetRot;

    // Lets us know that the class is being called, for debugging purposes
    simulated event PostBeginPlay()
    {
    super.PostBeginPlay();
    `Log(“First Person Camera up”);
    }

    /**********************************************************************************
    * Search ViewTarget and outputs PoV
    *
    * @param OutVT ViewTarget we’l be using
    * @param DeltaTime Delta Time since last cam update (in sec)
    **********************************************************************************/
    function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
    {
    local Pawn Pawn;
    local Vector V, PreferredCamLoc, HitLoc, HitNorm;
    local Actor HitActor;

    // UpdateViewTarget for the camera class we’re extending from
    Super.UpdateViewTarget(OutVT, DeltaTime);

    // If there is an interpolation, don’t update outgoing viewtarget
    if (PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing)
    {
    return;
    }

    Pawn = Pawn(OutVT.Target);
    if (Pawn != None)
    {
    // To hide the third person mesh
    Pawn.SetHidden(true);

    /************************************************************************************************
    * If you know the name of the bone socket you want to use, then replace ‘WeaponPoint’ with yours.
    * Otherwise, just use the Pawn’s eye view point as your starting point
    *************************************************************************************************/
    //socket not found, use the other way of updating vectors
    if (Pawn.Mesh.GetSocketWorldLocationAndRotation(‘HeadShotGoreSocket’, OutVT.POV.Location, OutVT.POV.Rotation) == false)
    {
    //Start the camera location from the target eye view point
    OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    }

    // Force the cam to use the target’s rotation
    OutVT.Target.GetActorEyesViewPoint(V, OutVT.POV.Rotation);

    // Add the cam offset
    OutVT.POV.Rotation += CamOffsetRot;

    // Math for the potential camera location
    PreferredCamLoc = OutVT.POV.Location + (CamOffset >> OutVT.POV.Rotation);

    // Draw a trace to see if the pref camera location will work
    HitActor = Trace(HitLoc, HitNorm, PreferredCamLoc, OutVT.POV.Location, true,,, TRACEFLAG_BULLET);

    // Will the trace hit world geometry? If so then use the hit location and offset it by the hit normal
    if (HitActor != None && HitActor.bWorldGeometry)
    {
    OutVT.POV.Location = HitLoc + HitNorm * 16.f;
    }
    else
    {
    OutVT.POV.Location = PreferredCamLoc;
    }
    }
    }

    // Hard coded vector & rotator values for our camera
    defaultproperties
    {
    CamOffset=(x=+10,y=0,z=0)
    CamOffsetRot=(Pitch=0, Roll=0, Yaw=0)
    }

    /********************
    *****Reference*******
    *********************
    * 65536 = 360 degrees
    * 32768 = 180 degrees
    * 16384 = 90 degrees
    * 8192 = 45 degrees
    * 182 = 1 degree
    *********************/

    ==========================================================================
    class OverShoulderCam extends Camera;

    //Hardcoded vector offset we will use, rather than tweaking values in the editor’s CameraProperties
    var const Vector OSCamOffset;
    //Hardcoded rotator offset we will use, rather than tweaking values in the editor’s CameraProperties
    var const Rotator OSCamOffsetRotation;

    /**********************************************************************************
    * Query ViewTarget and outputs Point Of View.
    *
    * @param OutVT ViewTarget to use.
    * @param DeltaTime Delta Time since last camera update (in seconds)
    **********************************************************************************/
    function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
    {
    local Pawn Pawn;
    local Vector V, PotentialCameraLocation, HitLocation, HitNormal;
    local Actor HitActor;

    // UpdateViewTarget for the camera class we’re extending from
    Super.UpdateViewTarget(OutVT, DeltaTime);

    // If there is an interpolation, don’t update outgoing viewtarget
    if (PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing)
    {
    return;
    }

    Pawn = Pawn(OutVT.Target);
    if (Pawn != None)
    {
    // Hide the pawn’s first-person weapon
    if(Pawn.Weapon != none)
    {
    Pawn.Weapon.SetHidden(true);
    }

    /************************************************************************************************
    * If you know the name of the bone socket you want to use, then replace ‘WeaponPoint’ with yours.
    * Otherwise, just use the Pawn’s eye view point as your starting point
    *************************************************************************************************/
    //socket not found, use the other way of updating vectors
    if (Pawn.Mesh.GetSocketWorldLocationAndRotation(‘WeaponPoint’, OutVT.POV.Location, OutVT.POV.Rotation) == false)
    {
    //Start the camera location from the target eye view point
    OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    }

    // Force the camera to use the target’s rotation
    OutVT.Target.GetActorEyesViewPoint(V, OutVT.POV.Rotation);

    // Add the camera offset
    OutVT.POV.Rotation += OSCamOffsetRotation;

    // Math for the potential camera location
    PotentialCameraLocation = OutVT.POV.Location + (OSCamOffset >> OutVT.POV.Rotation);

    // Draw a trace to see if the potential camera location will work
    HitActor = Trace(HitLocation, HitNormal, PotentialCameraLocation, OutVT.POV.Location, true,,, TRACEFLAG_BULLET);

    // Will the trace hit world geometry? If so then use the hit location and offset it by the hit normal
    if (HitActor != None && HitActor.bWorldGeometry)
    {
    OutVT.POV.Location = HitLocation + HitNormal * 16.f;
    }
    else
    {
    OutVT.POV.Location = PotentialCameraLocation;
    }
    }
    }

    // Hardcoded vector & rotator values for our camera
    defaultproperties
    {
    OSCamOffset=(x=-60,y=20,z=25)
    OSCamOffsetRotation=(Pitch=-2048)
    }

    /********************
    *****Reference*******
    *********************
    * 65536 = 360 degrees
    * 32768 = 180 degrees
    * 16384 = 90 degrees
    * 8192 = 45 degrees
    * 182 = 1 degree
    *********************/

  23. So much to respond to. Please don’t drop the code in here guys, it makes it very difficult to load and read the page. Your best bet is to drop it in the forums, then put a link here so that we can all see it. The forum formats it better anyway.

    Here is the link to the code for the book.
    Code by chapter: http://sdrv.ms/Xc0L8x
    Entire code for the project: http://sdrv.ms/Xc0T8a
    Maps and packages: http://sdrv.ms/Xc0WRn

    Wow, that’s odd that I put the wrong reference in there, and that I told you to create an archetype for the camera properties, and not the camera. I apologize for that. If you point out exactly where it is, I can make the changes to the book, and have the publisher adjust it.

    • No no no Dave what you have wrote in chapter 3 under the first section creating the archetype so you can adjust settings on the fly, is : Camera = etc…

      But every time an archetype is created under camera it does not work an archetype can not be created! Once creating one from camera properties it works and imports all the game settings! Weird huh!

      Also I must say that your code in the files you sent quite significant differs in the book lol

      But in relation to my above comment do you know how I can implement a first person style zoom to your code from chapter 3 ? So say the over shoulder can is default and we want our pawn to zoom in almost as if he is looking down the barrel ?

  24. The book code and the included code will not be *identical* but they will operate exactly the same. I only have 3 weeks to build each chapter, so I did that, wrote the text, then had the opportunity to go back later on and refactor/clean up the code.

    As far as the zooming feature, your best bet is to look in the forums, as I haven’t done that before, and I’m really not too sure of how to implement it.

  25. Is there a particular location that the TutorialPackage *HAS* to be saved in?

    I keep getting invalid property value warnings when I compile scripts: CameraProperties=TutorialCameraProperties’TutorialPacakge.archetypes.Arc_TutorialCamera’

    When I create the archetype in the udk editor, I don’t see any of the expected variables from the TutorialCameraPropries script.

    I’ve attempted this countless times; truly lost.

Leave a Reply