310 lines
6.3 KiB
Ucode
310 lines
6.3 KiB
Ucode
/**
|
|
* 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
|
|
} |