| Home Page | Recent Changes

Vehicles/Passengers

Much of this is experimental code and needs a custom Controller class. Tested in multiplayer, the camera of the Passengers has the message "viewing from ..." I’ll look into that later. If you have any problems with this code, you should contact me at sneakeye_@hotmail.com

MyVehicle

class MyVehicle extends KVehicle;

var()   int     MaxPassengers;  //Number of Passengers (without driver)
var Pawn        Passengers[10];
var Controller  PassengersControllers[10];

var()   bool        bAllowDriver;

function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, 
                        Vector momentum, class<DamageType> damageType)
{
    Local int i;

    Health -= Damage;

    // The vehicle is dead!
    if(Health <= 0)
    {
        if ( Controller != None )
        {
            if( Controller.bIsPlayer )
            {
                ClientKDriverLeave(PlayerController(Controller)); // Just to reset HUD etc.
                Controller.PawnDied(self); // This should unpossess the controller and let the player respawn
            }
            else
                Controller.Destroy();
        }
        for (i=0;i<MaxPassengers;i++)
        {
            if ( PassengersControllers[i] != None )
            {
                KPassengerLeave(True, MyPlayerController(PassengersControllers[i])); // Just to reset HUD etc.
                PassengersControllers[i].PawnDied(self); // This should unpossess the controller and let the player respawn
            }
        }

        Destroy(); // Destroy the vehicle itself (see Destroyed below)
    }

    //KAddImpulse(momentum, hitlocation);
}

simulated function Destroyed()
{
    local int i;
    // If there where passengers in the vehicle, destroy them too
    for (i=0;i<MaxPassengers;i++)
        if ( Passengers[i] != None )
            Passengers[i].Destroy();
    Super.Destroyed();
}

function TryToDrive(Pawn p)
{
    local Controller C;
    C = p.Controller;

    if ( (Driver == None) && (C != None) && C.bIsPlayer && !C.IsInState('PlayerDriving') && p.IsHumanControlled() && bAllowDriver)
    {
        KDriverEnter(p);
    }else if (C != None && C.IsA('MyPlayerController') && !C.IsInState('PlayerDriving') && p.IsHumanControlled()) {
        TryToPassenger(p);
    }
}

function KDriverEnter(Pawn p)
{
    Super.KDriverEnter(p);
    p.bHidden = True;
}

function bool KDriverLeave(bool bForceLeave)
{
    local Pawn OldDriver;

    OldDriver = Driver;

    // If we succesfully got out of the car, make driver visible again.
    if( Super.KDriverLeave(bForceLeave) )
    {
        OldDriver.bHidden = false;
        return true;
    }
    else
        return false;
}

function TryToPassenger(Pawn p)
{
    local int i;
    for(i=0;i<MaxPassengers;i++)
    {
        if (Passengers[i] == None)
        {
            KPassengerEnter(p, i);  //Enter passenger
            i = MaxPassengers;  //Make sure not added as another passenger
        }
    }
}

simulated function ClientKPassengerEnter(PlayerController pc)
{
    pc.myHUD.bCrosshairShow = false;
    pc.myHUD.bShowWeaponInfo = false;
    //pc.myHUD.bShowPersonalInfo = false;
    pc.myHUD.bShowPoints = false;

    pc.bBehindView = true;
    pc.bFixedCamera = false;
    pc.bFreeCamera = true;

    pc.SetRotation(rotator( vect(-1, 0, 0) >> Rotation ));
}

function KPassengerEnter(Pawn p, int i)
{
    local MyPlayerController pc;

    //log("KVehicle KDriverEnter");

    // Set pawns current controller to control the vehicle pawn instead
    Passengers[i] = p;

    // Move the driver into position, and attach to car.
    p.SetCollision(false, false, false);
    p.bCollideWorld = false;
    p.bPhysicsAnimUpdate = false;
    p.Velocity = vect(0,0,0);
    p.SetPhysics(PHYS_None);
    p.SetBase(self);

    pc = MyPlayerController(p.Controller);
    //pc.ClientSetBehindView(true);
    //pc.ClientSetFixedCamera(false);

    // Disconnect PlyaerController from Driver and connect to KVehicle.
    pc.Unpossess();
    Passengers[i].SetOwner(pc); // This keeps the driver relevant.
    pc.PossessPassenger(self);
    PassengersControllers[i] = pc;

    pc.ClientSetViewTarget(self); // Set playercontroller to view the vehicle

    // Change controller state to driver
    pc.GotoState('PlayerPassenger');

    ClientKPassengerEnter(pc);

    p.bHidden = True;
}

simulated function ClientKPassengerLeave(PlayerController pc)
{
    //local vector exitLookDir;

    //log("Leave: "$pc.Pawn);

    pc.bBehindView = false;
    pc.bFixedCamera = true;
    pc.bFreeCamera = false;
    // This removes any 'roll' from the look direction.
    //exitLookDir = Vector(pc.Rotation);
    //pc.SetRotation(Rotator(exitLookDir));

    pc.myHUD.bCrosshairShow = pc.myHUD.default.bCrosshairShow;
    pc.myHUD.bShowWeaponInfo = pc.myHUD.default.bShowWeaponInfo;
    //pc.myHUD.bShowPersonalInfo = pc.myHUD.default.bShowPersonalInfo;
    pc.myHUD.bShowPoints = pc.myHUD.default.bShowPoints;

    // Reset the view-smoothing
    NextHistorySlot = 0;
    bHistoryWarmup = true;
}

// Called from the PlayerController when player wants to get out.
function bool KPassengerLeave(bool bForceLeave, MyPlayerController pc)
{
    local int i, PassengerNum;
    local bool havePlaced;
    local vector HitLocation, HitNormal, tryPlace;

    PassengerNum = -1;

    for (i=0;i<MaxPassengers;i++)
        if (PassengersControllers[i] == pc)
            PassengerNum = i;

    if(PassengerNum == -1)
        return false;

    // Before we can exit, we need to find a place to put the driver.
    // Iterate over array of possible exit locations.
    
    Passengers[PassengerNum].bCollideWorld = true;
    Passengers[PassengerNum].SetCollision(true, true, true);
    
    havePlaced = false;
    for(i=0; i < ExitPositions.Length && havePlaced == false; i++)
    {
        //Log("Trying Exit:"$i);
    
        tryPlace = Location + (ExitPositions[i] >> Rotation);
    
        // First, do a line check (stops us passing through things on exit).
        if( Trace(HitLocation, HitNormal, tryPlace, Location, false) != None )
            continue;
            
        // Then see if we can place the player there.
        if( !Passengers[PassengerNum].SetLocation(tryPlace) )
            continue;
        
        havePlaced = true;
        
        //Log("SUCCESS!");      
    }

    // If we could not find a place to put the driver, leave driver inside as before.
    if(!havePlaced && !bForceLeave)
    {
        Log("Could not place driver.");
    
        Passengers[PassengerNum].bCollideWorld = false;
        Passengers[PassengerNum].SetCollision(false, false, false);
    
        return false;
    }

    ClientKPassengerLeave(pc);

    // Reconnect PlayerController to Driver.
    pc.UnpossessPassenger();
    pc.Possess(Passengers[PassengerNum]);

    pc.ClientSetViewTarget(Passengers[PassengerNum]); // Set playercontroller to view the persone that got out

    PassengersControllers[PassengerNum] = None;

    Passengers[PassengerNum].PlayWaiting();
    Passengers[PassengerNum].bPhysicsAnimUpdate = Passengers[PassengerNum].Default.bPhysicsAnimUpdate;

    // Do stuff on client
    //pc.ClientSetBehindView(false);
    //pc.ClientSetFixedCamera(true);

    Passengers[PassengerNum].Acceleration = vect(0, 0, 24000);
    if (Passengers[PassengerNum].TouchingWaterVolume())
    {
        Passengers[PassengerNum].SetPhysics(PHYS_Swimming);
    }else{
        Passengers[PassengerNum].SetPhysics(PHYS_Falling);
    }
    Passengers[PassengerNum].SetBase(None);
    Passengers[PassengerNum].bHidden = False;

    // Car now has no Passenger[Num]
    Passengers[PassengerNum] = None;

    return true;
}

function PossessedByPassenger(Controller C)
{
    NetPriority = 3;

    if ( C.IsA('PlayerController') )
    {
        if ( Level.NetMode != NM_Standalone )
            RemoteRole = ROLE_AutonomousProxy;
        BecomeViewTarget();
    }
    else
        RemoteRole = Default.RemoteRole;

//  The real controller is already owner
//  SetOwner(C);    // for network replication
    Eyeheight = BaseEyeHeight;
    ChangeAnimation();
}

simulated event Tick(float deltaSeconds)
{
    local int i;

    if(bGetOut && ROLE==Role_Authority)
    {
        for(i=0;i<MaxPassengers;i++)
        if(Passengers[i] != None)
        {
            KPassengerLeave(false, MyPlayerController(PassengersControllers[i]));
        }
    }
    Super.Tick(deltaSeconds);
}

simulated function bool SpecialCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
{
    local vector CamLookAt, HitLocation, HitNormal;
    local int i, averageOver;

    ViewActor = self;
    CamLookAt = Location + (vect(-100, 0, 100) >> Rotation); 

    //////////////////////////////////////////////////////
    // Smooth lookat position over a few frames.
    CameraHistory[NextHistorySlot] = CamLookAt;
    NextHistorySlot++;

    if(bHistoryWarmup)
        averageOver = NextHistorySlot;
    else
        averageOver = FilterFrames;

    CamLookAt = vect(0, 0, 0);
    for(i=0; i<averageOver; i++)
        CamLookAt += CameraHistory[i];

    CamLookAt /= float(averageOver);

    if(NextHistorySlot == FilterFrames)
    {
        NextHistorySlot = 0;
        bHistoryWarmup=false;
    }
    //////////////////////////////////////////////////////

    CameraLocation = CamLookAt + (vect(-600, 0, 0) >> CameraRotation);

    if( Trace( HitLocation, HitNormal, CameraLocation, CamLookAt, false, vect(10, 10, 10) ) != None )
    {
        CameraLocation = HitLocation;
    }

    return true;
}

defaultproperties
{
    MaxPassengers = 1;
    bAllowDriver = True;
}

MyPlayerController

class MyPlayerController extends xPlayer;

simulated event Destroyed()
{
    local int i;
    local MyVehicle Vehicle;
    local Pawn Passenger;
    //Don't destroy driver if in vehicle, could also be passenger!
    if (Pawn != None)
    {
        if (Pawn.IsA('MyVehicle'))  //Now you've done it, your in a vehicle
        {
            Vehicle = MyVehicle(Pawn);
            for(i=0;i<Vehicle.MaxPassengers;i++)    //If find self in vehicle, throw out, and destroy the pawn.
                if (Vehicle.PassengersControllers[i] == Self)
                {
                    Passenger = Vehicle.Passengers[i];
                    Vehicle.KPassengerLeave(true, Self); // Force the driver out of the car
                    Passenger.Destroy();
                    Pawn = None;
                }
        }
    }
    Super.Destroyed();
}

// Possess a pawn
function PossessPassenger(MyVehicle aPawn)
{
    if ( PlayerReplicationInfo.bOnlySpectator )
        return;

    SetRotation(aPawn.Rotation);
    aPawn.PossessedByPassenger(self);
    Pawn = aPawn;
    Pawn.bStasis = false;
    PlayerReplicationInfo.bIsFemale = Pawn.bIsFemale;
    Restart();
}

// unpossessed a pawn (not because pawn was killed)
function UnPossessPassenger()
{
    if ( Pawn != None )
    {
        SetLocation(Pawn.Location);
        if ( Viewtarget == Pawn )
            SetViewTarget(self);
    }
    Pawn = None;
    GotoState('Spectating');
}

state PlayerPassenger
{
ignores SeePlayer, HearNoise, Bump;

    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {
    }

    exec function Fire(optional float F)
    {
    }

    exec function AltFire(optional float F)
    {
    }

    // Set the throttle, steering etc. for the vehicle based on the input provided
    function ProcessDrive(float InForward, float InStrafe, bool InJump)
    {
        local MyVehicle DrivenVehicle;

        DrivenVehicle = MyVehicle(Pawn);

        if(DrivenVehicle == None)
        {
            log("PlayerPassenger.PlayerMove: No Vehicle");
            return;
        }

        // check for 'jump' to throw the driver out.
        if(InJump && Role == ROLE_Authority)
        {
            Log("Passenger tries to leave");
            DrivenVehicle.KPassengerLeave(False, Self);
            return;
        }
    }

    function PlayerMove( float DeltaTime )
    {
        local KVehicle DrivenVehicle;

        // Only servers can actually do the driving logic.
        if(Role < ROLE_Authority)
            ServerDrive(aForward, aStrafe, bPressedJump);
        else
            ProcessDrive(aForward, aStrafe, bPressedJump);

        // If the vehicle is being controlled here - set replicated variables.
        DrivenVehicle = KVehicle(Pawn);

        // update 'looking' rotation - no affect on driving
        UpdateRotation(DeltaTime, 2);
    }

    function BeginState()
    {
        CleanOutSavedMoves();
    }

    function EndState()
    {
        CleanOutSavedMoves();
    }
}

Discussion

mosquito What does the second one do? I looks like an extendion of the first

Highlander: First one is the actual code for the vehicle, second one looks like it handles the players inside the vehicle. (new controller class)


Category Custom Class

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In