/** * Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. */ class UDKVehicleBase extends SVehicle abstract native notplaceable; /** If true the driver will be ejected if he leaves*/ var bool bShouldEject; cpptext { virtual UBOOL ReachedDesiredRotation(); } /** * Attach GameObject to mesh. * @param GameObj Game object to hold */ simulated event HoldGameObject(UDKCarriedObject GameObj); /** * Use the SwitchWeapon binding (number keys bound on keyboard by default) * to switch seats when in a multi-seat vehicle. */ simulated function SwitchWeapon(byte NewGroup) { ServerChangeSeat(NewGroup-1); } /** * Request change to adjacent vehicle seat */ simulated function AdjacentSeat(int Direction, Controller C) { ServerAdjacentSeat(Direction, C); } /** request change to adjacent vehicle seat */ reliable server function ServerAdjacentSeat(int Direction, Controller C); /** * Called when a client is requesting a seat change * * @network Server-Side */ reliable server function ServerChangeSeat(int RequestedSeat); /** * @Returns the scale factor to apply to damage affecting this vehicle */ function float GetDamageScaling() { if (Driver != None) { return (Driver.GetDamageScaling() * Super.GetDamageScaling()); } else { return Super.GetDamageScaling(); } } /** * @Returns true if the AI needs to turn towards a target */ function bool NeedToTurn(vector Targ) { local UDKWeapon VWeapon; // vehicles can have weapons that rotate independently of the vehicle, so check with the weapon instead VWeapon = UDKWeapon(Weapon); if (VWeapon != None) { return !VWeapon.IsAimCorrect(); } else { return Super.NeedToTurn(Targ); } } simulated function DrivingStatusChanged() { Super.DrivingStatusChanged(); if (!bDriving) { StopFiringWeapon(); } } function bool DriverEnter(Pawn P) { local AIController C; if (Super.DriverEnter(P)) { // update AI enemy foreach WorldInfo.AllControllers(class'AIController', C) { if (C.Enemy == P) { C.Enemy = self; } } return true; } else { return false; } } /** Stub: applies weapon effects based on the passed in bitfield */ simulated function ApplyWeaponEffects(int OverlayFlags, optional int SeatIndex); /** * Statistics gathering */ function name GetVehicleDrivingStatName() { local name VehicleStatName; VehicleStatName = name('DRIVING_'$Class.name); return VehicleStatName; } /** EjectDriver() throws the driver out at high velocity */ function EjectDriver() { local float Speed; local rotator ExitRotation; if ( Driver == None ) { return; } if ( PlayerController(Driver.Controller) != None ) { ExitRotation = Rotation; //rotator(Velocity); <-- this resulted in weirdness if ejecting from a stop. ExitRotation.Pitch = -8192; ExitRotation.Roll = 0.0; Driver.Controller.SetRotation(ExitRotation); Driver.Controller.ClientSetRotation(ExitRotation); } Speed = VSize(Velocity); if (Speed < 2600 && Speed > 0) { Driver.Velocity = -0.6 * (2600 - Speed) * Velocity/Speed; Driver.Velocity.Z = 600; } else { Driver.Velocity = vect(0,0,600); } if ( UDKPawn(Driver) != None ) { UDKPawn(Driver).CustomGravityScaling = 0.5; UDKPawn(Driver).bNotifyStopFalling = true; UDKPawn(Driver).MultiJumpRemaining = 0; } } simulated function DetachDriver(Pawn P) { local UDKPawn UTP; Super.DetachDriver(P); UTP = UDKPawn(P); if (UTP != None) { // Turn on cloth again UTP.Mesh.UpdateRBBonesFromSpaceBases(TRUE,TRUE); if (UTP.Mesh.PhysicsAssetInstance != None) { UTP.Mesh.PhysicsAssetInstance.SetAllBodiesFixed(TRUE); UTP.Mesh.PhysicsAssetInstance.SetFullAnimWeightBonesFixed(FALSE, UTP.Mesh); } UTP.Mesh.bUpdateKinematicBonesFromAnimation = UTP.default.Mesh.bUpdateKinematicBonesFromAnimation; UTP.SetWeaponAttachmentVisibility(true); UTP.SetHandIKEnabled(true); } } /** * AI - Returns the best firing mode for this weapon */ function byte ChooseFireMode() { if (UDKWeapon(Weapon) != None) { return UDKWeapon(Weapon).BestMode(); } return 0; } /** * AI - An AI controller wants to fire * * @Param bFinished unused */ function bool BotFire(bool bFinished) { local UDKBot Bot; Bot = UDKBot(Controller); if (Bot != None && Bot.ScriptedFireMode != 255) { StartFire(Bot.ScriptedFireMode); } else { StartFire(ChooseFireMode()); } return true; } /** * Shut down the weapon */ simulated function StopFiringWeapon() { if (Weapon != none) { Weapon.ForceEndFire(); } } /** * Called on both the server and owning client when the player leaves the vehicle. We want to make sure * any active weapon is shut down */ function DriverLeft() { local AIController C; // update AI enemy foreach WorldInfo.AllControllers(class'AIController', C) { if (C.Enemy == self) { C.Enemy = Driver; } } if (bShouldEject) { EjectDriver(); bShouldEject = false; // so next driver doesn't get ejected. } Super.DriverLeft(); } /** handles the driver pawn of the dead vehicle (decide whether to ragdoll it, etc) */ function HandleDeadVehicleDriver() { local Pawn OldDriver; local UDKVehicle VehicleBase; if (Driver != None) { VehicleBase = UDKVehicle(self); if ( VehicleBase == None ) VehicleBase = UDKVehicle(GetVehicleBase()); // if Driver wasn't visible in vehicle, destroy it if (VehicleBase != None && VehicleBase.bEjectKilledBodies && (WorldInfo.TimeSeconds - LastRenderTime < 1.0) && (bDriverIsVisible || ((WorldInfo.GetDetailMode() != DM_Low) && !WorldInfo.bDropDetail)) ) { // otherwise spawn dead physics body if (!bDriverIsVisible && PlaceExitingDriver()) { Driver.StopDriving(self); Driver.DrivenVehicle = self; } Driver.TearOffMomentum = Velocity * 0.25; Driver.SetOwner(None); Driver.Died(None, VehicleBase.GetRanOverDamageType(), Driver.Location); } else { OldDriver = Driver; Driver = None; OldDriver.DrivenVehicle = None; OldDriver.Destroy(); } } } defaultproperties { Begin Object Name=SVehicleMesh End Object SightRadius=12000.0 bCanBeAdheredTo=TRUE bCanBeFrictionedTo=TRUE }