Third-Person Camera/State Switcher for Camera (WORKING)

Discussions about Coding and Scripting
Post Reply
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Third-Person Camera/State Switcher for Camera (WORKING)

Post by ANUBITEK »

EDIT: This has been done now, so this post is now changing from a question to posting the script itself!

> RPG_Camera

Code: Select all

//=============================================================================
// RPG_Camera.
// Operates independently now
// There should only be one camera
//=============================================================================
class RPG_Camera expands Pawn;


//Some dummy Camera values that might be coded at a later date
enum ECamMode
{
    CM_Fixed, //Fixed camera, useful for putting the camera at a certain spot
    CM_TrackFixedXY, //Track player and rotate instead of moving
    CM_Track, //Track player
    CM_EventInterpolation, //Interpolate a path (one of these days...)
    CM_Unused1,
    CM_Unused2,
    CM_Unused3,
    CM_Unused4
};

//The visible properties are kept here to allow map save/loading as well as letting the mapper
//specify the initial camera mode without using a trigger
var() ECamMode CameraMode;
var PlayerPawn LocalPlayer;
var() float CamDistance;
var float TargetDistance;
//These already exist, putting these here for informative purposes
//var (Movement) rotator DesiredRotation;
//var (Movement) rotator RotationRate;

//Disabling some superclass functions
function ClientDying(name DamageType, vector HitLocation);
function ClientGameEnded();
function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, name damageType);
function Died(pawn Killer, name damageType, vector HitLocation);
event FellOutOfWorld();

//The () makes it appear as a selectable InitialState
state() Camera
{
    //This event is called by the player when viewing this actor in first person view
    event Tick( float DeltaTime )
    {
        local vector NewLoc;
        local int OldPitch;

        if ( LocalPlayer == none )
            return;
        switch CameraMode
        {
            case CM_Fixed:
                break;
            case CM_TrackFixedXY:
                OldPitch = DesiredRotation.Pitch; //Conserve DesiredRotation's pitch
                DesiredRotation = rotator( LocalPlayer.Location - Location); //Aim at local player
                DesiredRotation.Pitch = OldPitch; //Restore pitch
                NewLoc = Location; //Conserve location, but alter Z if necessar... useful for spiral stairs!
                NewLoc.Z = LocalPlayer.Location.Z - vector(DesiredRotation).Z * VSize(Location - LocalPlayer.Location);
                SetLocation( NewLoc );
                break;
            case CM_Track:
                if ( TargetDistance < CamDistance ) //Interpolate camera distance in a very arbitrary way
                    CamDistance = fMax( CamDistance - LocalPlayer.GroundSpeed * 0.5 * DeltaTime, TargetDistance);
                else if ( TargetDistance > CamDistance )
                    CamDistance = fMin( CamDistance + LocalPlayer.GroundSpeed * 0.5 * DeltaTime, TargetDistance);
                NewLoc = LocalPlayer.Location - vector(DesiredRotation) * CamDistance;
                SetLocation( NewLoc);
                break;
            default:
                break;
        }
    }
Begin:
    //Loop if no player
    if ( LocalPlayer == none && !FindLocalPlayer() )
    {
        Sleep(0.0);
        Goto('Begin');
    }
    SetPhysics( PHYS_Flying);
CheckViewTarget:
    LocalPlayer.ViewTarget = self;
    LocalPlayer.bBehindView = false;
}


//Unrealscript functions always have a return value, said value is zero'd before function call.
//Meaning, if we return nothing, the function still return False
function bool FindLocalPlayer()
{
    local PlayerPawn P;
    ForEach AllActors (class'PlayerPawn', P)
        if ( ViewPort(P.Player) != none )
        {
            LocalPlayer = P;
            return true;
        }
}


event PostBeginPlay()
{
    Super.PostBeginPlay();
    //The rotation the mapper uses will be the initial rotation
    DesiredRotation = Rotation;
    ViewRotation = Rotation;
    TargetDistance = CamDistance;
}
> RPG_CameraSwitcher

Code: Select all

//=============================================================================
// RPG_CameraSwitcher.
//
// Extra notes:
// Cannot be destroyed
// Operates on both server and client instances
//=============================================================================
class RPG_CameraSwitcher expands Triggers;

var RPG_Camera ActiveCamera;

enum ECamMode
{
    CM_Fixed,
    CM_TrackFixedXY,
    CM_Track,
    CM_EventInterpolation,
    CM_Unused1,
    CM_Unused2,
    CM_Unused3,
    CM_Unused4
};
var() ECamMode NewCameraMode;

var(Events) bool bOnlyLocalTrigger; //Event is only triggered on the local machine
//var(Events) name Event; //Left here for informative purposes, works like a normal trigger
var() bool bTriggerOnceOnly;
var() bool bSmoothTransition;
var() float NewDistance;
var() float SmoothFactor; //To be described later
var() rotator NewOrientation;
var() vector FixedCamPos; //For fixed or X,Y track mode, if Zero, use camera's current


function Touch( Actor Other)
{
    local Actor A;

    //This is the local player
    if ( PlayerPawn(Other) != none && ViewPort(PlayerPawn(Other).Player) != none )
    {
        //Trigger additional event if there's one
        if ( !bOnlyLocalTrigger )
            TriggerEvent( Event, self, Pawn(Other) );
        if ( HasActiveCamera() )
        {
            if ( NewCameraMode <= CM_TrackFixedXY && FixedCamPos != vect(0,0,0) ) //Move the camera if Fixed or TrackXY
                ActiveCamera.SetLocation( FixedCamPos);
            ActiveCamera.CameraMode = ECamMode(NewCameraMode);
            ActiveCamera.TargetDistance = NewDistance; //Linear distance interpolation
            ActiveCamera.DesiredRotation = NewOrientation; //Linear rotation interpolation (layer 1) towards this orientation
            if ( !bSmoothTransition )
            {
                ActiveCamera.SetRotation( ActiveCamera.DesiredRotation);
                ActiveCamera.ViewRotation = ActiveCamera.DesiredRotation;
                ActiveCamera.CamDistance = NewDistance;
            }
            if ( bOnlyLocalTrigger )
                TriggerEvent( Event, self, Pawn(Other) );
            if ( bTriggerOnceOnly )
                SetCollision( false);
            ActiveCamera.Tick( 0.0); //Force immediate camera update
        }
    }
}

//Sanity check and camera finder
function bool HasActiveCamera()
{
    if ( ActiveCamera != none )
        return true;
    //No camera, find it
    ForEach AllActors (class'RPG_Camera', ActiveCamera)
        return true;
}
SPECIAL THANKS TO UT99.ORG USER HIGOR FOR BASICALLY WRITING THESE TWO SCRIPTS PLUS TWO OTHERS FOR ME TO STUDY, EVERYONE SHOULD ALWAYS GIVE THEM MONEY ALWAYS FOREVER.

RPG_Camera is an offset pawn actor of any playerpawn (only appearing for individual local machines so each player pawn can have their own camera), it being where the player sees from. RPG_CameraSwitcher is intended to send signals to RPG_Camera, depending on whether or not the player is touching it (it is now a trigger. RPG_CameraHook actors change the state of RPG_Camera to make it either stay at a location and track the player, follow the player, or being fixed in one area). Do not intersect the RPG_CameraSwitcher collision radii as I don't think that they will function properly.
Last edited by ANUBITEK on Sat Feb 21, 2015 5:08 pm, edited 3 times in total.
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Need help: Third Person Camera + Actors Camera Snaps To

Post by Higor »

Relying on simple touch events is gonna mess the entire thing up, especially if you want two way support.
You might want to define volumes and have each point to a camera instead, detect when the local player comes it and set the main camera as viewtarget.

I DO think 227i has volume support, i'd need to double check...


EDIT:
Zones do fullfill that purpose as well, but you might want to reserve zones for mapping reasons (they're limited to 64)
User avatar
ANUBITEK
Adept
Posts: 261
Joined: Sun Dec 28, 2014 1:10 am
Location: Anubitek

Re: Need help: Third Person Camera + Actors Camera Snaps To

Post by ANUBITEK »

Higor wrote:You might want to define volumes
How would I go about doing this?
Higor wrote:[. . .] and have each point to a camera instead, detect when the local player comes it and set the main camera as viewtarget.
I'm not sure what you're describing here. Do you mean make it so every CameraHook has it's own camera, and the camera view switches to the camera that is attached to the actor, that has volume and activates when said actor detects a local player? Could you elaborate a bit more on this? I've recently been told that cameras cannot make standard actors into camera targets, so I'm really not sure how this would work.
Higor wrote:Zones do fullfill that purpose as well, but you might want to reserve zones for mapping reasons (they're limited to 64)
True dat.
<<| http://uncodex.ut-files.com/ |>>

Code reference for UGold, UT99, Unreal2, UT2k3, UT3
Additional Beyond Unreal Wiki Links
wiki.beyondunreal.com/Legacy:Console_Bar
wiki.beyondunreal.com/Exec_commands#Load
wiki.beyondunreal.com/Legacy:Exec_Directive#Loading_Other_Packages
wiki.beyondunreal.com/Legacy:Config_Vars_And_.Ini_Files
wiki.beyondunreal.com/Legacy:INT_File
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Need help: Third Person Camera + Actors Camera Snaps To

Post by Higor »

Ok, no volumes in 227, time to rethink.
You'd need 'enter' points and 'exit' points, and perhaps implement rotation interpolation in camers (to make them rotate in L shaped hallways).

If there's a point where the camera must 'change', add two big triggers that don't touch and cover the whole hallway, one trigger puts the camera in one state, the other in the other state, simulating a volume entry/exit point.
I suggest two ways of changing a camera:
- Smoothly rotate the camera (as mentioned for L shaped hallways)
- Change camera distance and orientation.
This way we don't define multiple camera actors, or even embed them into the map at all at a later stage (have the custom gametype spawn them).

So, we need custom triggers that describe the transition type (Intert, Instant), specify distance from player and the new orientation.
Start with this as template:

Code: Select all

class RPG_CameraSwitcher expands Triggers;

var float NewDistance;
var byte SmoothTransition;
var float SmoothFactor; //To be described later
var rotator NewOrientation;

//No code yet
Post Reply