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)