Files
GTASource/game/Vehicles/vehicle.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

3469 lines
146 KiB
C++

// Title : Vehicle.h
// Author : Richard Jobling/William Henderson
// Started : 25/08/99
//
//
//
//
#ifndef _VEHICLE_H_
#define _VEHICLE_H_
// Rage headers
#include "fragment/cache.h"
#include "fragment/type.h"
#include "fwmaths/random.h"
#include "fwanimation/animdirector.h"
// Framework headers
#include "fwmaths/vector.h"
#include "fwtl/pool.h"
#include "fwvehicleai/pathfindtypes.h"
#include "entity/extensionlist.h"
// Game headers
#include "ai/spatialarray.h"
#include "audio/vehicleaudioentity.h"
#include "Debug/DebugDrawStore.h"
#include "game/ModelIndices.h"
#include "modelinfo/VehicleModelInfo.h"
#include "modelinfo/VehicleModelInfoFlags.h"
#include "modelinfo/VehicleModelInfoVariation.h"
#include "modelinfo/VehicleModelInfoFlags.h"
#include "Pathserver/PathServer_DataTypes.h"
#include "physics/gtaInst.h"
#include "renderer/HierarchyIds.h"
#include "renderer/lights/lights.h"
#include "renderer/Entities/VehicleDrawHandler.h"
#include "scene/physical.h"
#include "scene/ContinuityMgr.h"
#include "vehicleAI/VehicleAILod.h"
#include "vehicles/AnchorHelper.h"
#include "vehicles/componentReserve.h"
#include "vehicles/door.h"
#include "vehicles/handlingMgr.h"
#include "vehicles/transmission.h"
#include "vehicles/vehicleDamage.h"
#include "vehicles/VehicleDefines.h"
#include "vehicles/VehicleFlags.h"
#include "vehicles/vehicleLightSwitch.h"
#include "vehicles/wheel.h"
#include "weapons/weaponTypes.h"
#include "system/poolallocator.h"
#include "System/PadGestures.h" // for define
#define MAX_CARGO_VEHICLES 6
#define MAX_NUM_COVER_DOORS 4
#define VEH_WINDOW_STATE_DIRTY -2
class CAmbientModelVariations;
class CAmbientModelSetFilter;
class CFire;
class CPed;
class CWheel;
class CAnimPlayer;
class CControl;
class CMoveVehicle;
class CCustomShaderEffectVehicle;
class CPropeller;
class CVehicleGadget;
class CVehicleWeaponMgr;
class CVehicleSeatAnimInfo;
class CVehicleEntryPointAnimInfo;
class CVehicleIntelligence;
class CTaskManager;
class CTrailer;
struct vehicleLightSettings;
class CStoredVehicleVariations;
struct ConfigLightSettings;
class CoronaAndLightList;
class CBoatHandling;
class CVehicleWeaponBattery;
namespace rage
{
class fwPtrList;
struct grcTextureLock;
}
#if !__FINAL
#define DEBUG_VEH_NAME_STRING_LENGTH (16)
#endif
class CVisualSettings;
class CSubmarineHandling;
class CVehControls
{
public:
CVehControls()
:
m_steerAngle (0.0f),
m_secondSteerAngle (0.0f),
m_throttle (0.0f),
m_brake (0.0f),
m_handBrake (true),
m_nitrous (false),
m_KERS (false)
{;}
void Copy(const CVehControls& rOther)
{
m_steerAngle = rOther.m_steerAngle;
m_secondSteerAngle = rOther.m_secondSteerAngle;
m_throttle = rOther.m_throttle;
m_brake = rOther.m_brake;
m_handBrake = rOther.m_handBrake;
m_nitrous = rOther.m_nitrous;
m_KERS = rOther.m_KERS;
}
void Reset()
{
m_steerAngle = 0.0f;
m_secondSteerAngle = 0.0f;
m_throttle = 0.0f;
m_brake = 0.0f;
m_handBrake = true;
m_nitrous = false;
m_KERS = false;
}
inline void SetSteerAngle (float val) {Assertf(val == val, "Provided steer Angle is NaN"); m_steerAngle = val;}
float GetSteerAngle (void) const {return m_steerAngle;}
void SetSecondSteerAngle (float val) {m_secondSteerAngle = val;}
float GetSecondSteerAngle (void) const {return m_secondSteerAngle;}
void SetThrottle (float val) {Assertf(m_throttle >= -1.0f && m_throttle <= 1.0f, "Throttle out of range (%f)", m_throttle); Assertf(val >= -1.0f && val <= 1.0f, "Throttle out of range (%f)", val); m_throttle = val;}
float GetThrottle (void) const {return m_throttle;}
void SetBrake (float val) {Assertf(m_brake >=0.0f && m_brake <= 1.0f, "Brake out of range (%f)", m_brake); Assertf(val >=0.0f && val <= 1.0f, "Brake out of range (%f)", val); m_brake = val;}
float GetBrake (void) const {return m_brake;}
void SetHandBrake (bool val) {m_handBrake = val;}
bool GetHandBrake (void) const {return m_handBrake;}
void SetNitrous (bool val) {m_nitrous = val;}
bool GetNitrous (void) const {return m_nitrous;}
void SetKERS (bool val) {m_KERS = val;}
bool GetKERS (void) const {return m_KERS;}
float m_steerAngle;
float m_secondSteerAngle; // used for steering 2nd set of wheels or elevators etc..
float m_throttle;
float m_brake;
bool m_handBrake;
bool m_nitrous;
bool m_KERS;
};
enum eVehicleTwinHeadLightMode
{
VTHL_MODE_SINGLE = 0,
VTHL_MODE_SINGLE_TEXTURED,
VTHL_MODE_SINGLE_WITH_FAKE_SPLIT,
VTHL_MODE_2_LIGHTS,
VTHL_MODE_SINGLE_TEXTURED_WITH_FAKE_SPLIT,
VTHL_MODE_2_LIGHTS_TEXTURED,
VTHL_NUM_MODES
};
enum eVehicleTwinTailLightMode
{
VTTL_MODE_SINGLE = 0,
VTTL_MODE_SINGLE_FILLER_ONLY,
VTTL_MODE_SINGLE_WITH_FAKE_SPLIT,
VTTL_NUM_MODES
};
class CHeadlightTuningData
{
public:
#if __BANK
static void SetupHeadlightTuningBank(bkBank& bank);
#endif // __DEV
static float ms_globalHeadlightIntensityMult;
static float ms_globalHeadlightDistMult;
static float ms_globalConeInnerAngleMod;
static float ms_globalConeOuterAngleMod;
static float ms_globalOnlyOneLightMod;
static float ms_globalFake2LightAngleMod;
static float ms_globalFake2LightsDisplacementMod;
static float ms_globalFake2LightAngleModSubmarine;
static float ms_globalFake2LightsDisplacementModSubmarine;
static bool ms_useFullBeamOrDippedBeamMods;
static float ms_fullBeamHeadlightIntensityMult;
static float ms_fullBeamHeadlightDistMult;
static float ms_fullBeamHeadlightCoronaIntensityMult;
static float ms_fullBeamHeadlightCoronaSizeMult;
static float ms_aimFullBeamMod;
static float ms_aimDippedBeamMod;
static bool ms_makeHeadlightsCastFurtherForPlayer;
static float ms_playerHeadlightIntensityMult;
static float ms_playerHeadlightDistMult;
static float ms_playerHeadlightExponentMult;
static float ms_aimFullBeamAngle;
static float ms_aimDippedBeamAngle;
//Volume lights
static float ms_volumeIntensityScale;
static float ms_volumeSizeScale;
static Color32 ms_outerVolumeColor;
static float ms_outerVolumeIntensity;
static float ms_outerVolumeFallOffExponent;
static eVehicleTwinHeadLightMode ms_VehicleTwinHeadLightMode;
static eVehicleTwinTailLightMode ms_VehicleTwinTailLightMode;
#if __BANK
static u8 ms_ForceHeadlightShadows;
static bool ms_useVehicleLodDist;
static bool ms_globalForceRecessedCorona;
#endif // __BANK
static void Set(const CVisualSettings& visualSettings);
};
class CNeonTuningData
{
public:
#if __BANK
static void SetupNeonTuningBank(bkBank& bank);
#endif // __BANK
static float ms_globalNeonIntensity;
static float ms_globalNeonRadius;
static float ms_globalNeonRadiusFallOffExponent;
static float ms_globalNeonCapsuleExtentSides;
static float ms_globalNeonCapsuleExtentFrontBack;
static float ms_globalNeonClipPlaneHeight;
static float ms_globalNeonBikeClipPlaneHeight;
static Color32 ms_defaultNeonColor;
#if __BANK
static bool ms_neonsForcedOn;
#endif // __BANK
static void Set(const CVisualSettings& visualSettings);
};
#if __BANK
extern void SetupVehicleBank(bkBank& bank);
#endif // __BANK
enum eVehicleLodState {
VLS_HD_NA = 0, // - cannot go into HD at all
VLS_HD_NONE = 1, // - no HD resources currently Loaded
VLS_HD_REQUESTED = 2, // - HD resource requests are in flight
VLS_HD_AVAILABLE = 3, // - HD resources available & can be used
VLS_HD_REMOVING = 4 // - HD not available & scheduled for removal
};
class CSeaPlaneExtension : public fwExtension
{
public:
EXTENSIONID_DECL(CSeaPlaneExtension, fwExtension);
CSeaPlaneExtension();
~CSeaPlaneExtension() {}
CAnchorHelper& GetAnchorHelper() { return m_AnchorHelper; }
protected:
CAnchorHelper m_AnchorHelper;
public:
struct CSeaPlaneFlags
{
u8 bSinksWhenDestroyed : 1;
};
CSeaPlaneFlags m_nFlags;
float m_fTimeOnWater;
};
enum eBobbleHeadType {
BHT_START = 0,
BHT_HEAD = BHT_START,
BHT_HAND,
BHT_ENGINE,
BHT_MISC_1,
BHT_MISC_2,
BHT_MISC_3,
BHT_MISC_4,
BHT_MISC_5,
BHT_MISC_6,
BHT_MISC_7,
BHT_MISC_8,
BHT_MAX
};
#define MAX_NUM_BOBBLE_HEADS (8)
class CBobbleHead
{
public:
CBobbleHead() : m_vehicle( NULL ), m_bobbleHeadVelocity( V_ZERO ), m_bobbleHeadVehiclePrevVelocity( V_ZERO ), m_bobbleHeadPrevDistance( V_ZERO ), m_bobbleHeadDistance( FLT_MAX ) {}
void Reset();
void Update();
CVehicle* GetVehicle() { return m_vehicle; }
void SetVehicle( CVehicle* pVehicle ) { m_vehicle = pVehicle; }
eBobbleHeadType GetType() { return m_type; }
void SetType( eBobbleHeadType type ) { m_type = type; }
float GetDistanceFromPlayer() { return m_bobbleHeadDistance; }
void SetVelocity( Vec3V& velocity ) { m_bobbleHeadVelocity = velocity; }
private:
eHierarchyId GetBoneIdFromType();
Vec3V m_bobbleHeadVelocity;
Vec3V m_bobbleHeadVehiclePrevVelocity;
Vec3V m_bobbleHeadPrevDistance;
float m_bobbleHeadDistance;
CVehicle* m_vehicle;
eBobbleHeadType m_type;
static Vec3V ms_bobbleHeadStiffness;
static ScalarV ms_bobbleHeadMass;
static ScalarV ms_bobbleHeadMassInv;
static Vec3V ms_bobbleHeadDamping;
static Vec3V ms_bobbleHeadLimits;
static Vec3V ms_bobbleArmStiffness;
static ScalarV ms_bobbleArmMass;
static ScalarV ms_bobbleArmMassInv;
static Vec3V ms_bobbleArmDamping;
static Vec3V ms_bobbleArmLimits;
static Vec3V ms_bobbleEngineStiffness;
static ScalarV ms_bobbleEngineMass;
static ScalarV ms_bobbleEngineMassInv;
static Vec3V ms_bobbleEngineDamping;
static Vec3V ms_bobbleEngineLimits;
};
class CWeaponBlade
{
public:
CWeaponBlade() : m_currentRPM( 0.0f ), m_mass( 0.0f ), m_bladeAngle( 0.0f ), m_fragChild( -1 ), m_modBone( -1 ), m_fastBone( -1 ) {}
void Init( int modBone, int fastBone, int fragChild, eRotationAxis rotationAxis, float maxRotationSpeed, float mass );
void Reset(){};
void Update( CVehicle* parentVehicle );
bool ApplyImpacts( CVehicle* parentVehicle, CEntity* otherEntity, Vec3V myNormal, Vec3V myPosition, Vec3V otherPosition, int bladeIndex, int hitComponent, int otherComponent );
void ApplyWheelImpact( CVehicle* parentVehicle, CWheel* wheel, int hitComponent );
void SetRpmToMax() { m_currentRPM = m_maxRPM; }
void UpdateBladeRpmWhenEngineSetToOff();
float GetCurrentRPM() const { return m_currentRPM; }
int GetModBone() const { return m_modBone; }
int GetFastBone() const { return m_fastBone; }
int GetFragChild() { return m_fragChild; }
static bool ms_bDisableRetractingWeaponBlades;
private:
float m_currentRPM;
float m_mass;
float m_bladeAngle;
float m_maxRPM;
int m_fragChild;
int m_modBone;
int m_fastBone;
eRotationAxis m_rotationAxis;
};
struct ScriptOverridesNitrous
{
bool isOverrideActive;
float durationModifier;
float powerModifier;
float rechargeRateModifier;
bool disableDefaultSound;
void Init()
{
isOverrideActive = false;
durationModifier = 0.0f;
powerModifier = 0.0f;
rechargeRateModifier = 0.0f;
disableDefaultSound = false;
}
};
#define VEHICLE_REAR_DOOR_BLOWN_DOOR_FLAGS (CCarDoor::DRIVEN_NORESET | CCarDoor::RELEASE_AFTER_DRIVEN | CCarDoor::DRIVEN_SPECIAL)
class CVehicle : public CPhysical
{
DECLARE_RTTI_DERIVED_CLASS(CVehicle, CPhysical);
friend struct CVehicleOffsetInfo;
protected:
// This is PROTECTED as we can't create a base CVehicle instance
explicit CVehicle(const eEntityOwnedBy ownedBy, u32 popType, VehicleType vehType);
friend class CVehicleFactory;
public:
#if DEBUG_DRAW
static CDebugDrawStore ms_debugDraw;
#endif
static const float sm_fInvalidPlaceOnRoadHeight;
static float sm_fDoorPushMassScale;
static bool sm_bCanForceCarRecordingToDummy;
static bool sm_bForceRecordedVehicleToBeInactive;
static bool sm_bForceRecordedVehicleToBeActive;
static bool sm_bSlipstreamingEnabled;
~CVehicle();
REGISTER_POOL_ALLOCATOR(CVehicle, false);
virtual void SetModelId(fwModelId modelId);
virtual void DeleteDrawable();
virtual CDynamicEntity* GetProcessControlOrderParent() const;
virtual ePrerenderStatus PreRender(const bool bIsVisibleInMainViewport = true);
virtual void PreRender2(const bool bIsVisibleInMainViewport = true);
virtual void ProcessPrePhysics();
virtual fwDrawData* AllocateDrawHandler(rmcDrawable* pDrawable);
#if !__SPU
virtual fwMove *CreateMoveObject();
virtual const fwMvNetworkDefId &GetAnimNetworkMoveInfo() const;
#endif // !__SPU
#if !__NO_OUTPUT
static void PrintSkeletonData();
#endif
virtual bool CanBeDeleted(void) const { return CanBeDeletedSpecial(true); }
virtual void StartAnimUpdate(float fTimeStep);
virtual void StartAnimUpdateAfterCamera(float fTimeStep);
bool CanBeDeletedNetwork(const bool bLogClearCarFromAreaFailures = false) const;
bool CanBeDeletedSpecial(bool bTakeAccountOfMissionPopType, bool bDoNetworkChecks = true, bool bCheckForPedsEnteringAndExiting = true, bool bCheckPedStates = true, bool bCheckInterestingVehicles = true, bool bAllowCopRemovalWithWantedLevel = false, const bool bReturnCarsContainingAPlayer = false, const bool bAllowRemovalOfCarsInGarage = false, const bool bLogClearCarFromAreaFailures = false) const;
virtual void FlagToDestroyWhenNextProcessed(void);
inline CVehicleModelInfo* GetVehicleModelInfo() const {return (CVehicleModelInfo*)GetBaseModelInfo();}
inline CComponentReservationManager* GetComponentReservationMgr() {return &m_ComponentReservationMgr;}
inline const CComponentReservationManager* GetComponentReservationMgr() const {return &m_ComponentReservationMgr;}
CVehicleVariationInstance& GetVariationInstance() { return GetVehicleDrawHandler().GetVariationInstance(); }
const CVehicleVariationInstance& GetVariationInstance() const{ return GetVehicleDrawHandler().GetVariationInstance(); }
void SetVariationInstance(const CStoredVehicleVariations& storedVariation);
bool IsModded() const { return GetVariationInstance().GetNumMods() > 0; }
void GetExhaustMatrix(eHierarchyId exhaustId, Mat34V_InOut mat, s32& boneIndex) const;
bool GetExhaustMatrixFromBoneIndex(Mat34V_InOut mat, s32 boneIndex) const;
bool GetThrustMatrixFromBoneIndex(Mat34V_InOut mat, s32 boneIndex) const;
void GetExtraLightMatrix(eHierarchyId extraLightId, Mat34V_InOut mat, s32& boneIndex, const char** boneName) const;
void GetExtraLightMatrix(const crSkeleton *skeleton, eHierarchyId extraLightId, Mat34V_InOut mat, s32& boneIndex) const;
int GetExtraLightPosition(eHierarchyId extraLightId, Vector3& vecResult) const;
bool AllowBonnetSlide() const;
virtual void GetGlobalMtx(int boneIdx, Matrix34& matrix) const;
// Get the lock on position for this vehicle
virtual void GetLockOnTargetAimAtPos( Vector3& aimAtPos) const;
bool HasExtraLights() const;
bool HasNeons() const;
bool HasDoubleExtraLights() const;
void PartHasBrokenOff(eHierarchyId id);
bool CanCreateBrokenPart();
static void ClearLastBrokenOffPart() { ms_slotTurnedOff = -1; ms_boneTurnedOff = -1; }
static s8 GetLastBrokenOffPart() { return ms_slotTurnedOff; }
void SetWheelBroken(u32 wheelIndex);
const bool GetWheelBroken(u32 wheelIndex) const;
const u32 GetWheelBrokenIndex() const { return m_wheelBrokenIndex; }
void ResetWheelBroken() { m_wheelBrokenIndex = 0; }
void TriggerHydraulicBounceSound();
void TriggerHydraulicActivationSound();
void TriggerHydraulicDeactivationSound();
void SetFlashLocallyDuringRespotting(bool shouldFlash) { m_bFlashLocallyDuringRespotting = shouldFlash; }
bool GetFlashRemotelyDuringRespotting() { return m_bFlashRemotelyDuringRespotting; }
void SetFlashRemotelyDuringRespotting(bool shouldFlash) { m_bFlashRemotelyDuringRespotting = shouldFlash; }
void SetTopSpeedPercentage(float topSpeedPercent) { m_VehicleTopSpeedPercent = topSpeedPercent; }
float GetTopSpeedPercentage() { return m_VehicleTopSpeedPercent; }
void SetOverrideArriveDistForVehPersuitAttack(float topSpeedPercent) { m_fOverrideArriveDistForVehPersuitAttack = topSpeedPercent; }
float GetOverrideArriveDistForVehPersuitAttack() const { return m_fOverrideArriveDistForVehPersuitAttack; }
float GetTargetGravityScale() { return m_targetGravityScale; }
float GetCachedStickY() { return m_cachedStickYfromNetwork; }
void SetTargetGravityScale(float val) { m_targetGravityScale = val; }
void SetCachedStickY(float val) { m_cachedStickYfromNetwork = val; }
void SetHoverModeWingRatio(float val) { m_currentWingRatio = val; }
//////////////////////////////////////////////////////////////////////////
// Position
virtual void Teleport(const Vector3& vecSetCoors, float fSetHeading=-10.0f, bool bCalledByPedTask=false, bool bTriggerPortalRescan = true, bool bCalledByPedTask2 = false, bool bWarp=true, bool bKeepRagdoll = false, bool bResetPlants=true);
void TeleportWithoutUpdateGadgets(const Vector3& vecSetCoors, float fSetHeading, bool bTriggerPortalRescan, bool bWarp);
void ResetAfterTeleport();//called inside teleport
void UpdateGadgetsAfterTeleport( const Matrix34 &matOld, bool bDetachFromParent = true, bool bUpdateTrailer = true, bool bUpdateTrailerParent = true, bool translateOnly = false);
void UpdateAttachedClonePedsAfterWarp();
void UpdateInertiasAfterTeleport();
void UpdateAfterCutsceneMovement();
Vec3V_Out GetVehiclePosition() const { return GetMatrixRef().GetCol3(); }
Vec3V_Out GetVehicleForwardDirection() const { return GetMatrixRef().GetCol1(); }
Vec3V_Out GetVehicleUpDirection() const { return GetMatrixRef().GetCol2(); }
Vec3V_Out GetVehicleRightDirection() const { return GetMatrixRef().GetCol0(); }
Vec3V_ConstRef GetVehicleForwardDirectionRef() const { return GetMatrixRef().GetCol1ConstRef(); }
// Accessors that can be overridden to provide different information under for different circumstances
virtual Vec3V_Out GetVehiclePositionForDriving() const { return GetVehiclePosition(); }
virtual Vec3V_Out GetVehicleForwardDirectionForDriving() const { return GetVehicleForwardDirection(); }
virtual Vec3V_Out GetVehicleRightDirectionForDriving() const { return GetVehicleRightDirection(); }
virtual Vec3V_ConstRef GetVehicleForwardDirectionForDrivingRef() const { return GetVehicleForwardDirectionRef(); }
//////////////////////////////////////////////////////////////////////////
// Base accessors
VehicleType GetVehicleType() const {Assertf((m_vehicleType > VEHICLE_TYPE_NONE) && (m_vehicleType < VEHICLE_TYPE_NUM), "Bad vehicle type on '%s'", GetModelName()); return m_vehicleType;}
#if RSG_BANK
const char* GetVehicleTypeString(VehicleType vehicleType) const;
#endif
// Some useful queries for casting
// Lets you easily figure out what the base class might be to avoid long 'if' statements
bool GetIsAircraft() const { return (GetIsRotaryAircraft() || GetVehicleType() == VEHICLE_TYPE_PLANE);}
bool GetIsRotaryAircraft() const { return (GetVehicleType() >= VEHICLE_TYPE_HELI && GetVehicleType() <= VEHICLE_TYPE_AUTOGYRO);}
bool GetIsAquatic() const {return InheritsFromBoat() || InheritsFromSubmarine() || InheritsFromSubmarineCar() || InheritsFromAmphibiousAutomobile();}
bool GetIsAquaticMode() const {return InheritsFromBoat() || InheritsFromSubmarine() || IsInSubmarineMode();}
bool GetIsLandVehicle() const {return !GetIsAquatic() && !GetIsAircraft();}
bool GetIsHeli() const { return GetVehicleType() == VEHICLE_TYPE_HELI; }
virtual bool GetHoverMode() const { return false; }
virtual bool IsInSubmarineMode() const { return false; }
bool GetIsSmallDoubleSidedAccessVehicle() const
{
return InheritsFromBike() || InheritsFromQuadBike() || GetIsJetSki() || InheritsFromAmphibiousQuadBike();
}
bool GetIsJetSki() const;
bool IsBikeOrQuad() const { return (GetVehicleType() == VEHICLE_TYPE_BIKE || GetVehicleType() == VEHICLE_TYPE_QUADBIKE || GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_QUADBIKE); }
// Remember aircraft inherit from CAutomobile!
bool InheritsFromAutomobile() const {return (GetVehicleType() >= VEHICLE_TYPE_CAR && GetVehicleType() <= VEHICLE_TYPE_AUTOGYRO);}
bool InheritsFromBoat() const { return (GetVehicleType() == VEHICLE_TYPE_BOAT); }
bool InheritsFromAmphibiousAutomobile() const { return (GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_AUTOMOBILE || GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_QUADBIKE ); }
bool InheritsFromBike() const { return (GetVehicleType() >= VEHICLE_TYPE_BIKE && GetVehicleType() <= VEHICLE_TYPE_BICYCLE); }
bool InheritsFromBicycle() const { return GetVehicleType() == VEHICLE_TYPE_BICYCLE; }
bool InheritsFromTrain() const { return (GetVehicleType() == VEHICLE_TYPE_TRAIN); }
bool InheritsFromHeli() const { return (GetVehicleType() >= VEHICLE_TYPE_HELI && GetVehicleType() <= VEHICLE_TYPE_BLIMP) ; }
bool InheritsFromAutogyro() const { return (GetVehicleType() == VEHICLE_TYPE_AUTOGYRO) ; }
bool InheritsFromBlimp() const { return (GetVehicleType() == VEHICLE_TYPE_BLIMP) ; }
bool InheritsFromPlane() const { return (GetVehicleType() == VEHICLE_TYPE_PLANE) ; }
bool InheritsFromSubmarine() const { return (GetVehicleType() == VEHICLE_TYPE_SUBMARINE) ; }
bool InheritsFromTrailer() const { return (GetVehicleType() == VEHICLE_TYPE_TRAILER) ; }
bool InheritsFromQuadBike() const { return (GetVehicleType() == VEHICLE_TYPE_QUADBIKE) ; }
bool InheritsFromAmphibiousQuadBike() const { return (GetVehicleType() == VEHICLE_TYPE_AMPHIBIOUS_QUADBIKE) ; }
bool InheritsFromDraftVeh() const { return (GetVehicleType() == VEHICLE_TYPE_DRAFT); }
bool InheritsFromSubmarineCar() const { return (GetVehicleType() == VEHICLE_TYPE_SUBMARINECAR); }
bool IsTrailerSmall2() const { return InheritsFromTrailer() && MI_TRAILER_TRAILERSMALL2.IsValid() && GetModelIndex() == MI_TRAILER_TRAILERSMALL2; }
virtual void PopTypeSet(ePopType newPopType);// Does some pop count tracking...
CMoveVehicle &GetMoveVehicle() { Assert(GetAnimDirector()); return (CMoveVehicle&) (GetAnimDirector()->GetMove()); }
const CMoveVehicle &GetMoveVehicle() const { Assert(GetAnimDirector()); return (const CMoveVehicle&) (GetAnimDirector()->GetMove()); }
void ForcePostCameraAnimUpdate(bool bForce, bool bUseZeroTimestep)
{
if (bUseZeroTimestep)
{
m_nVehicleFlags.bForcePostCameraAnimUpdateUseZeroTimeStep = bForce ? 1 : 0;
}
else
{
m_nVehicleFlags.bForcePostCameraAnimUpdate = bForce ? 1 : 0;
}
}
bool GetWillEngineStart() const { return !m_nVehicleFlags.bEngineWontStart; }
bool GetActiveForPedNavitation() const { return m_nVehicleFlags.bActiveForPedNavigation; }
void SetActiveForPedNavitation(bool b) { m_nVehicleFlags.bActiveForPedNavigation = b; }
// Access/Mutate whether the vehicle has generated cover points
bool GetHasGeneratedCover() const { return m_nVehicleFlags.bHasGeneratedCover; }
void SetHasGeneratedCover(bool bGeneratedCover) { m_nVehicleFlags.bHasGeneratedCover = bGeneratedCover; }
// Get the last cover orientation
CoverOrientation GetCoverOrientation() const { return m_eLastCoverOrientation; }
void SetCoverOrientation(CoverOrientation eOrientation ) { m_eLastCoverOrientation = eOrientation; }
// Access/Mutate the position at last cover generation
const Vector3& GetLastCoverPosition() const { return m_vLastCoverPosition; }
void SetLastCoverPosition(const Vector3& vPosition) { m_vLastCoverPosition = vPosition; }
// Access/Mutate the forward direction at last cover generation
const Vector3& GetLastCoverForwardDirection() const { return m_vLastCoverForwardDirection; }
void SetLastCoverForwardDirection(const Vector3& vDirection) { m_vLastCoverForwardDirection = vDirection; }
// Access/Mutate the door intact status at last cover generation
bool GetLastCoverDoorIntactStatus(int i) const { if(AssertVerify(i >= 0 && i < MAX_NUM_COVER_DOORS)){ return m_bLastCoverDoorIntactList[i]; } return false;}
void SetLastCoverDoorIntactStatus(int i, bool bStatus) { if(AssertVerify(i >= 0 && i < MAX_NUM_COVER_DOORS)){ m_bLastCoverDoorIntactList[i] = bStatus; } }
// Access/Mutate the door ratio at last cover generation
float GetLastCoverDoorRatio(int i) const { if(AssertVerify(i >= 0 && i < MAX_NUM_COVER_DOORS)){ return m_fLastCoverDoorRatioList[i]; } return 0.0f;}
void SetLastCoverDoorRatio(int i, float fRatio) { if(AssertVerify(i >= 0 && i < MAX_NUM_COVER_DOORS)){ m_fLastCoverDoorRatioList[i] = fRatio; } }
//////////////////////////////////////////////////////////////////////////
// Flags (probably want to move elsewhere
bool GetCheatFlag(u32 nFlag) const {return (m_nVehicleCheats & nFlag) != 0;}
void SetCheatFlag(u32 nFlag) {m_nVehicleCheats |= nFlag;}
void ClearCheatFlag(u32 nFlag) {m_nVehicleCheats &= ~nFlag;}
void SetCheatFlags(u32 nFlags) {m_nVehicleCheats = nFlags;}
float GetCheatPowerIncrease() const { return m_fCheatPowerIncrease; }
void SetCheatPowerIncrease(float val) { m_fCheatPowerIncrease = val; }
bool UsesSiren(void) const { return m_nVehicleFlags.bHasSiren; }
bool UsesTandemSeating() const {return (pHandling->mFlags &MF_TANDEM_SEATING) != 0;}
void SetScriptMutedSirens(bool bMutedSirens) { m_nVehicleFlags.SetSirenMutedByScript(bMutedSirens); }
void SetHasGlowingBrakes(bool bNewHasGlowingBrakes) { m_nVehicleFlags.bHasGlowingBrakes = bNewHasGlowingBrakes; }
bool GetHasGlowingBrakes() const { return (m_nVehicleFlags.bHasGlowingBrakes); }
inline bool IsLawEnforcementVehicle() const { return (m_nVehicleFlags.bIsLawEnforcementVehicle); }
inline bool IsLawEnforcementCar() const { return (m_nVehicleFlags.bIsLawEnforcementCar); }
static bool IsLawEnforcementVehicleModelId(fwModelId modelId);
static bool IsLawEnforcementCarModelId(fwModelId modelId);
static bool IsTaxiModelId(fwModelId modelId);
static bool IsBusModelId(fwModelId modelId);
static bool IsTractorModelId(fwModelId modelId);
static bool IsMowerModelId(fwModelId modelId);
bool HasBulletResistantGlass() const;
bool HasIncreasedRammingForce();
bool HasIncreasedRammingForceVsAllVehicles();
float GetIncreasedRammingForceScale() { return pHandling->GetCarHandlingData() ? pHandling->GetCarHandlingData()->m_fIncreasedRammingForceScale : 1.0f; }
bool HasRammingScoop() const;
bool HasRamp() const;
bool HasSuperBrakes() const;
bool IsTunerVehicle() const;
bool IsTank() const;
bool IsTaxi() const;
bool IsTrike() const;
bool IsReverseTrike() const;
bool FleesFromCombat() const;
bool ReportCrimeIfStandingOn() const { return m_nVehicleFlags.bReportCrimeIfStandingOn; }
void SetIsScheduled(bool bIsScheduled) { m_nVehicleFlags.bScheduledForCreation = bIsScheduled; }
bool GetIsScheduled() const { return m_nVehicleFlags.bScheduledForCreation; }
const CAIHandlingInfo* GetAIHandlingInfo() const;
// LOD-related flags
bool GetFlagLodFarFromPopCenter() const { return m_nVehicleFlags.bLodFarFromPopCenter; }
bool GetFlagSuperDummyWheelCompressionSet() const { return m_nVehicleFlags.bLodSuperDummyWheelCompressionSet; }
void SetFlagSuperDummyWheelCompressionSet(bool bIsSet) { m_nVehicleFlags.bLodSuperDummyWheelCompressionSet = bIsSet; }
//////////////////////////////////////////////////////////////////////////
// Process functions
virtual bool RequiresProcessControl() const {return true;}
virtual bool WantsToBeAwake();
bool ForceNoSleep();
bool ProcessIsAsleep();
void ProcessPlayerControlInputsForBrakeAndGasPedal(CControl* pControl, bool bForceBrake);
virtual bool ProcessControl();
virtual void DoProcessControl(bool fullUpdate, float fFullUpdateTimeStep);
virtual void DoProcessControl_OnDeferredTaskCompletion(bool fullUpdate, float fFullUpdateTimeStep);
bool ProcessRumble(const CWheel* const * wheels, s32 numWheels, float velocity);
#if HAS_TRIGGER_RUMBLE
void ProcessTriggerRumble( const CWheel* const * wheels, s32 numWheels, float velocity, phMaterialMgr::Id padRumbleMaterialId, u32 padNextRumbleTime );
#endif // #if HAS_TRIGGER_RUMBLE
void ProcessRespotCounter(float fTimeStep);
void UpdateDoorsForNavigation();
#if __BANK
virtual void RenderDebug(void) const;
void RenderDebugBoneInfo(void) const;
void InitDebugName();
static void ToggleScriptedAutopilot();
#endif // __DEV
//////////////////////////////////////////////////////////////////////////
// Controls
void SetSteerAngle (float fAngle) {m_vehControls.SetSteerAngle(fAngle);};
float GetSteerAngle (void) const {return m_vehControls.GetSteerAngle();}
void SetSecondSteerAngle (float fAngle) {m_vehControls.SetSecondSteerAngle(fAngle);} // 4wheel steer. need to store variable separately so we can smooth the transition on and off
float GetSecondSteerAngle (void) const {return m_vehControls.GetSecondSteerAngle();}
void SetThrottle (float fPedal) {m_vehControls.SetThrottle(fPedal);}
float GetThrottle (void) const
{
if( pHandling->GetCarHandlingData() &&
pHandling->GetCarHandlingData()->aFlags & CF_ALLOW_TURN_ON_SPOT &&
m_vehControls.GetThrottle() >= 0.0f &&
Abs( m_vehControls.GetSteerAngle() ) > 0.1f )
{
float throttle = Clamp( m_vehControls.GetThrottle() + ( ( 1.0f - m_vehControls.GetThrottle() ) * ( Abs( m_vehControls.GetSteerAngle() ) ) ), -1.0f, 1.0f );
return throttle;
}
return m_vehControls.GetThrottle();
}
void SetBrake (float fPedal) {m_vehControls.SetBrake(fPedal);}
float GetBrake (void) const {return m_vehControls.GetBrake();}
bool GetHandBrake (void) const {return m_vehControls.GetHandBrake();}
void SetHandBrake (bool bHandBrake) { if(!GetHandBrake() && bHandBrake) m_uHandbrakeOnTime = fwTimer::GetTimeInMilliseconds();
m_vehControls.SetHandBrake(bHandBrake); }
void SetNitrous ( bool bNitrous ) { m_vehControls.SetNitrous( bNitrous ); }
void ToggleNitrous () { m_vehControls.SetNitrous( !m_vehControls.GetNitrous() ); }
bool GetNitrousActive (void) const { return m_nitrousActive; }
void SetNitrousActive ( bool active ) { m_nitrousActive = active; }
void SetKERS ( bool bKERS ) { m_vehControls.SetKERS( bKERS ); }
void ToggleKERS () { m_vehControls.SetKERS( !m_vehControls.GetKERS() ); }
bool GetKERSActive (void) const { return m_vehControls.GetKERS(); }
bool GetIsHandBrakePressed(const CControl* pControl) const;
virtual float GetSteerRatioForAnim() { return (m_vehControls.m_steerAngle / pHandling->m_fSteeringLock); } // overridden for bikes atm
//////////////////////////////////////////////////////////////////////////
// Physics
virtual int InitPhys();
virtual void InitCompositeBound();
virtual void InitDummyInst() { }
virtual void RemoveDummyInst();
virtual bool UsesDummyPhysics(const eVehicleDummyMode vdm) const;
virtual void RemovePhysics();
void UpdateCollisionOnPartBrokenOff(int componentIndex, fragInst* newFragInst);
virtual bool HasDummyConstraint() const {return false;}
virtual void ChangeDummyConstraints(const eVehicleDummyMode UNUSED_PARAM(dummyMode), bool UNUSED_PARAM(bIsStatic)) { }
virtual void UpdateDummyConstraints(const Vec3V * UNUSED_PARAM(pDistanceConstraintPos)=NULL, const float * UNUSED_PARAM(pDistanceConstraintMaxLength)=NULL) { }
void HandleDummyProbesBottomingOut(const WorldProbe::CShapeTestResults & dummyProbeResults);
virtual void ProcessTimeStartedFailingRealConversion() {}
virtual void ResetRealConversionFailedData() {}
virtual bool HasShrunkDummyConstraintsAsMuchAsPossible() const {return false;}
void SetGravityForWheellIntegrator(float fGravity);
float GetGravityForWheellIntegrator(){return m_fGravityForWheelIntegrator;}
// PURPOSE: Make sure that the next call to CAutomobile::UpdateAirResistance() sets up the damping parameters properly.
// NOTES: Should be called if m_fDragCoeff is changed, or if the damping parameters need to get updated
// for example because we have a new instance or something like that.
void RefreshAirResistance() { m_AirResistanceState = 0; }
phInstGta* GetDummyInst() { return m_pDummyInst; }
const phInstGta* GetDummyInst() const { return m_pDummyInst; }
bool HasDummyBound() const { return m_nVehicleFlags.bHasDummyBound; }
void SetDummyMtlId(phMaterialMgr::Id mtlId) {m_dummyMtlId = mtlId;}
phMaterialMgr::Id GetDummyMtlId() const {return m_dummyMtlId;}
inline fragInstGta* GetVehicleFragInst() const {return m_pVehicleFragInst;}
fragInst** GetVehicleFragInstPointerAddress(){return reinterpret_cast<fragInst**>(&m_pVehicleFragInst);} //used to tell the SPU the offset in the class
virtual fragInst* GetFragInst() const { return reinterpret_cast<fragInst*>(m_pVehicleFragInst); }
private:
#if __BANK
static bool sm_PreComputeImpacts;
#endif
public:
virtual ePhysicsResult ProcessPhysics(float UNUSED_PARAM(fTimeStep), bool UNUSED_PARAM(bCanPostpone), int UNUSED_PARAM(nTimeSlice));
virtual bool ProcessShouldFindImpactsWithPhysical(const phInst* pOtherInst) const;
virtual void ProcessPreComputeImpacts(phContactIterator impacts);
void ProcessPreComputeImpactsSuperDummyCar(phContactIterator& impacts);
virtual void ProcessPostPhysics();
virtual bool TestNoCollision(const phInst *pOtherInst);
void ProcessLowLODAudioRequirements(float fTimeStep);
void FixStuckInGeometry(phCachedContactIterator& iterator);
bool CloneBounds();
void HandleDeactivateForPlayback();
PPUVIRTUAL void LosingFragCacheEntry();
PPUVIRTUAL void OnActivate(phInst* pInst, phInst* pOtherInst);
PPUVIRTUAL void OnDeactivate(phInst* pInst);
virtual void DeActivatePhysics();
virtual void UpdateEntityFromPhysics(phInst *pInst, int nLoop);
virtual void UpdatePhysicsFromEntity(bool bWarp=false);
virtual bool ShouldLoadCollision() const { return !(m_nPhysicalFlags.bDontLoadCollision || IsDummy()); }
virtual void ProcessCollision(
phInst const * myInst,
CEntity* pHitEnt,
phInst const * hitInst,
const Vector3& vMyHitPos,
const Vector3& vOtherHitPos,
float fImpulseMag,
const Vector3& vMyNormal,
int iMyComponent,
int iOtherComponent,
phMaterialMgr::Id iOtherMaterial,
bool bIsPositiveDepth,
bool bIsNewContact);
// returns true if bits of the vehicle can break off as fragments
bool CarPartsCanBreakOff() const;
// PURPOSE: To check if a vehicle should be orientated up for
// ped entry. For example, a bike might be in a bad state to
// play the enter anim, so it's best to re-orientate it and then
// play the anim.
// PARAMS:
// - pVehicle: Vehicle to check if should be orientated up.
// RETURNS: It should return true if the vehicle should be orientated up.
// By default it returns false.
virtual bool ShouldOrientateVehicleUpForPedEntry(const CPed* UNUSED_PARAM(pPed)) const { return false; }
virtual const Vector3& GetVelocity() const;
virtual const Vector3& GetAngVelocity() const;
Vector3 GetVelocityIncludingReferenceFrame() const;
Vector3 GetReferenceFrameVelocity() const;
Vector3 GetRelativeVelocity(const CPed& rPed) const;
virtual void SetVelocity(const Vector3& vel);
virtual void SetAngVelocity(const Vector3& vecTurnSpeed);
void SetInactivePlaybackVelocity(const Vector3& vel);
void SetInactivePlaybackAngVelocity(const Vector3& angVel);
// internal forces that are applied within the wheel integrator
void ApplyInternalForceCg(const Vector3& vecForce);
void ApplyInternalTorque(const Vector3& vecTorque);
void ApplyInternalTorque(const Vector3& vecForce, const Vector3& vecOffset);
// PURPOSE: Apply the given torque and apply the necessary force to result in rotation about the given world position.
void ApplyInternalTorqueAndForce(const Vector3& vecTorque, const Vector3& vecWorldPosition);
// We sum the drag we wish to apply for each contact with a foliage bound and then apply a single force later so that
// we have control over the total drag force. Called from PreComputeImpacts() on the low LOD chassis bound if available.
void AddToFoliageDrag(const int nComponent, const Vector3& vImpactPosition, const Vector3& vCentreOfFoliageBound, const float fRadiusOfFoliageBound);
// Apply the drag force for this time step when driving through plants with GTA_TYPE_FOLIAGE set (the shrubbery!) with clamping.
void ApplyFoliageDrag();
void ApplyWindDisturbance();
void AutoLevelAndHeading( float fInAirSteerMult, bool bAdjustRoll = false, bool bAdjustHeading = true );
// flying stuff
float HeightAboveCeiling(float Height) const;
// Fixed waiting for collision update
virtual bool ShouldFixIfNoCollisionLoadedAroundPosition();
virtual void OnFixIfNoCollisionLoadedAroundPosition(bool bFix);
virtual bool IsCollisionLoadedAroundPosition();
bool CanPedsStandOnTop() const;
bool ShouldExplodeOnContact() const { return GetVehicleModelInfo()->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_EXPLODE_ON_CONTACT); }
bool DisableExplodeOnContact() const { return m_nVehicleFlags.bDisableExplodeOnContact; }
bool SprayPetrolBeforeExplosion() const { return GetVehicleModelInfo()->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_SPRAY_PETROL_BEFORE_EXPLOSION); }
u32 GetExplosionDelay(bool bDelayedExplosion) const { return bDelayedExplosion ? (u32)(fwRandom::GetRandomNumberInRange(CVehicle::ms_fVehicleExplosionDelayMin, CVehicle::ms_fVehicleExplosionDelayMax) * 1000.0f): 0; }
// Utility function which performs a shape test in the physics level using the vehicle's collision bound as a probe object.
static int TestVehicleBoundForCollision(
const Matrix34* pMatrix,
const CVehicle* pVehicle, u32 nModelIndex=fwModelId::MI_INVALID,
const CEntity** pExceptions=NULL, int nNumExceptions=0,
WorldProbe::CShapeTestResults* pBoundTestResults=NULL,
u32 includeFlags=INCLUDE_FLAGS_ALL,
bool bUseBoxBound = false,
bool bDoHeightFixup = true);
// Function to check if we should disable an impact between a ped and the vehicle they're exiting
static bool ShouldDisableImpactForPedExitingVehicle(const CPed& rPed, const CVehicle& rVeh, s32 iImpactComponentIndex);
static eHierarchyId GetDoorHierachyIdFromImpact(const CVehicle& rVeh, s32 iImpactComponentIndex);
static bool GetMinMaxBoundsFromDummyVehicleBound(const CVehicle& vehicle, Vec3V_Ref vMin, Vec3V_Ref vMax);
// B*1935020: Calculates a bounding box that takes into account mod kit parts and ignores doors to provide a base size for the vehicle that is more accurate to its current state than the entity AABB or modelinfo bounds size.
const void GetApproximateSize(Vector3 &vecBBoxMin, Vector3 &vecBBoxMax) const;
enum eVehicleOrientation
{
VO_Upright,
VO_UpsideDown,
VO_OnSide
};
static eVehicleOrientation GetVehicleOrientation(const CVehicle& rVeh);
// glider functions
enum EGliderState
{
NOT_GLIDING,
DEPLOYING_WINGS,
GLIDING,
RETRACTING_WINGS,
GLIDER_STATE_MAX
};
EGliderState GetGliderState() const { return m_gliderState; }
virtual void ProcessOtherAttachments();
float CalculateInvMassScale(float fVehicleSpeed, bool bIsOtherInstanceFirst, const CVehicle& rOtherVehicle) const;
void UpdateSlipStreamTimer(float fTimeStep);
void UpdateProducingSlipStreamTimer(float fTimeStep);
float GetSlipStreamEffect() const;
float GetTimeInSlipStream() const { return m_fTimeInSlipStream; }
virtual bool CanStraddlePortals() const { return true; }
static bool UseHardRevLimitFlag(CHandlingData* pHandling, bool bIsTunerVehicle, bool bIsCurrentGearTopGear )
{
FastAssert(pHandling);
bool bHasHardRevLimitFlag = pHandling->GetCarHandlingData() && (pHandling->GetCarHandlingData()->aFlags & CF_HARD_REV_LIMIT);
if( bHasHardRevLimitFlag && bIsTunerVehicle )
{
if( !bIsCurrentGearTopGear )
{
bHasHardRevLimitFlag = false;
}
}
return bHasHardRevLimitFlag;
}
static bool HasHoldGearWheelSpinFlag(CHandlingData* phandling, CVehicle* pParentVehicle)
{
FastAssert(phandling);
FastAssert(pParentVehicle);
bool bHasHoldGearWheelSpinFlag = phandling->GetCarHandlingData() && (phandling->GetCarHandlingData()->aFlags & CF_HOLD_GEAR_WITH_WHEELSPIN );
if(bHasHoldGearWheelSpinFlag && pParentVehicle->m_bDriftTyres )
{
bHasHoldGearWheelSpinFlag = false;
}
return bHasHoldGearWheelSpinFlag;
}
#if GPU_DAMAGE_WRITE_ENABLED
void SetDamageUpdatedByGPU(bool bDamageWasUpdatedByGPU, bool bEnableDamage);
bool WasDamageUpdatedByGPU() const { return m_bDamageWasUpdatedByGPU; }
void HandleDamageUpdatedByGPU();
virtual void PostBoundDeformationUpdate();
virtual bool HasBoundUpdatePending() const;
#endif
//////////////////////////////////////////////////////////////////////////
// Population and Dummy mode conversion management support.
void DelayedRemovalTimeReset (u32 extraTimeMs = 0);
void SetDelayedRemovalTime (u32 time)
{
// Store the current time.
m_delayedRemovalResetTimeMs = fwTimer::GetTimeInMilliseconds();
m_delayedRemovalAmountMs = time;
}
bool DelayedRemovalTimeHasPassed (float removalTimeScale = 1.0f, u32 removalTimeExtraMs = 0) const;
float DelayedRemovalTimeGetPortion (float removalTimeScale = 1.0f) const;
u32 GetTimeLastVisible() const { return m_iTimeLastVisible; }
u32 GetNumVisiblePixels() const { return m_nNumPixelsVisible; }
bool OffScreenRemovalTimeHasPassed(s32& timeRemaining, float removalTimeScale = 1.0f) const;
bool IsDummy() const { return m_vehicleAiLod.IsLodFlagSet(CVehicleAILod::AL_LodDummy | CVehicleAILod::AL_LodSuperDummy); }
bool IsSuperDummy() const { return (m_vehicleAiLod.IsLodFlagSet(CVehicleAILod::AL_LodSuperDummy)); }
bool ShouldAlwaysTryToBeReal() const;
bool ShouldTryToUseVirtualJunctionHeightmaps() const {return IsDummy(); }
eVehicleDummyMode ProcessOverriddenDummyMode(eVehicleDummyMode desiredDummyMode);
eVehicleDummyMode GetOverriddenDummyMode(eVehicleDummyMode desiredDummyMode, bool &zeroVelocitiesOut);
bool ProcessHaveDummyConstraintsChanged(ScalarV exceedLimit, bool failOnNoConstraints) const;
virtual bool GetCanMakeIntoDummy(eVehicleDummyMode dummyMode);
virtual bool TryToMakeIntoDummy(eVehicleDummyMode dummyMode, bool bSkipClearanceTest=false);
virtual bool TryToMakeFromDummy(const bool bSkipClearanceTest=false);
bool TryToMakeFromDummyIncludingParents(const bool bSkipClearanceTest=false);
bool TestForDummyInstClearance() const;
bool ConsiderParkedForLodPurposes() const
{
return (PopTypeGet() == POPTYPE_RANDOM_PARKED) && !m_nVehicleFlags.bHasParentVehicle && !InheritsFromTrailer();
}
bool IsParkedSuperDummy() const
{
return IsSuperDummy() && ConsiderParkedForLodPurposes();
}
bool ShouldSkipUpdatesInTimeslicedLod() const { return m_nVehicleFlags.bLodShouldSkipUpdatesInTimeslicedLod; }
void IncrementNumTimeslicedUpdatesSkipped() { ++m_iNumTimeslicedUpdatesSkipped; }
void ResetNumTimeslicedUpdatesSkipped() { m_iNumTimeslicedUpdatesSkipped = 0; }
virtual void SwitchToDummyPhysics(const eVehicleDummyMode prevMode);
virtual void SwitchToSuperDummyPhysics(const eVehicleDummyMode prevMode);
virtual void SwitchToFullFragmentPhysics(const eVehicleDummyMode prevMode);
// PURPOSE: Called to switch gravity off for the specified phys inst
void SetNoGravity(phInst *physInst, bool noGravity);
void UpdateFlagsForTimeslicedLod();
// PURPOSE: Called when switching to timesliced updates (AL_LodTimeslicing is set).
void SwitchAwayFromTimeslicedLod();
// PURPOSE: Called when switching out of timesliced updates (AL_LodTimeslicing is cleared).
void SwitchToTimeslicedLod();
void ProcessInterpolation(bool fullUpdate, float fFullUpdateTimeStep);
// PURPOSE: Interpolate the position of the vehicle towards a target, during timesliced LOD.
void ProcessInterpolationForTimeslicedLod();
// PURPOSE: Set a new target position and orientation to use as an interpolation target
// during timesliced updates. If updates continue, the vehicle should be at the
// target after the specified time has elapsed.
void SetInterpolationTargetAndTime(Vec3V_In posV, QuatV_In orientationV, ScalarV_In timeToInterpolateV)
{
Vec4V posAndTimeV(posV);
posAndTimeV.SetW(timeToInterpolateV);
m_InterpolationTargetAndTime = posAndTimeV;
m_InterpolationTargetOrientation = orientationV;
// When we set a new target, clear out the previously stored current orientation, forcing
// it to get recomputed. This simplifies things because we don't have to worry about using
// some old value.
m_InterpolationCurrentOrientation.ZeroComponents();
}
// PURPOSE: Clear any interpolation target set by SetInterpolationTargetAndTime().
void ClearInterpolationTargetAndTime()
{
m_InterpolationTargetAndTime.ZeroComponents();
// Could clear m_InterpolationTargetOrientation too here, but it shouldn't be necessary - the important
// part is that the time component (W in m_InterpolationTargetAndTime) is zero.
// Clear the current orientation too, so we don't accidentally reuse some old value.
m_InterpolationCurrentOrientation.ZeroComponents();
}
Vec4V_Out GetInterpolationTargetAndTime() const { return m_InterpolationTargetAndTime; }
QuatV_Out GetInterpolationTargetOrientation() const { return m_InterpolationTargetOrientation; }
// PURPOSE: Compute a new interpolation target by extrapolating the current velocity,
// and optionally applying some dampening to gradually slow down.
// PARAMS: allowSpeedReduction - If true, allow the speed to be dampened.
void SetInterpolationTargetFromExtrapolatedVelocity(bool allowSpeedReduction);
// PURPOSE: Call SetSuperDummyVelocity(), with a velocity computed from the vehicle's current position and its interpolation target.
void SetSuperDummyVelocityFromInterpolationTarget();
bool ProcessSuperDummy(float fUpdateTime, bool bAttachPhase = false);
bool TryToDeactivateSuperDummy();
bool DoBoundingBoxIntersectionTest(s32 iArchtypeFlags, int iNumExpections = 0, const CEntity ** pIntersectionException = NULL, const bool bDoHeightFixup = true, float* fIntersectDepth = NULL, Matrix34* pTestMatrix = NULL) const;
void LerpCloneSuperDummyMatrix(Matrix34 &matrix);
#if __BANK
void SetNonConversionReason(const char* val) const { m_pNonConversionReasonString = val; }
const char* GetNonConversionReason() const { return m_pNonConversionReasonString; }
void SetLastVehPopRemovalFailReason(const char *reason) const;
const char *GetLastVehPopRemovalFailReason() const { return m_pLastVehPopRemovalFailReason; }
unsigned GetLastVehPopRemovalFailFrame() const { return m_iLastVehPopRemovalFailFrame; }
#endif // __BANK
// Move a dummy vehicle so that it isn't intersecting a ground surface
void FixupIntersectionWithWheelSurface(WorldProbe::CShapeTestResults& testResults);
// Pretend occupant management support.
virtual bool CanSetUpWithPretendOccupants() const;
virtual void SetUpWithPretendOccupants();
virtual bool IsUsingPretendOccupants() const;
virtual bool TryToMakePedsIntoPretendOccupants();
bool HasNetworkClonedOccupant();
void RemoveAllOccupants();
bool TryToMakePedsFromPretendOccupants(bool onlyAddDriver = false, const int* in_pMaxNumPedsToMakeReal = NULL, const CAmbientModelSetFilter * pModelsFilter = NULL);
void TryToGiveEventReponseTaskToOccupant(CPed* pPed);
void SetStartNodes(const CNodeAddress &from, const CNodeAddress &to, s16 link, s8 lane)
{
m_StartNodes[0] = from;
m_StartNodes[1] = to;
m_StartLink = link;
m_StartLane = lane;
}
void GetStartNodes(CNodeAddress &rFrom, CNodeAddress &rTo, s16 &rLink, s8 &rLane) const
{
rFrom = m_StartNodes[0];
rTo = m_StartNodes[1];
rLink = m_StartLink;
rLane = m_StartLane;
}
void ClearStartNodes()
{
m_StartNodes[0].SetEmpty();
m_StartNodes[1].SetEmpty();
m_StartLink = -1;
m_StartLane = -1;
}
bool HasStartNodes() const
{
return !m_StartNodes[0].IsEmpty();
}
// Default task
void GiveDefaultTask();
//////////////////////////////////////////////////////////////////////////
// AI
void InitAi();
void PostCreationAiUpdate();
void ProcessIntelligence(bool fullUpdate, float fFullUpdateTimeStep);
void ProcessPostCamera();
void ForcePostCameraAiUpdate(bool bForce) { m_nVehicleFlags.bForcePostCameraAiSecondaryTaskUpdate = bForce; }
CVehicleIntelligence *GetIntelligence() const {return m_pIntelligence;}
void WeAreBlockingSomeone();
bool ShouldBeRemovedByAmbientPed() const;
bool HasCarStoppedBecauseOfLight(bool bLookFurther = false) const; // function itself is in pathfind.cpp
void UpdateJunctions(); // Add vehicle to the junction it is next to encounter.
void SetHandlingCheatValuesForPoliceCarInPursuit(bool bCheat);
void UpdateInSlownessZone(); // Works out whether this vehicle is in a slowness zone.
void SetDrivenDangerouslyThisUpdate(bool val) { m_nVehicleFlags.bDrivenDangerouslyThisUpdate = val; }
float GetDrivenDangerouslyTime() const { return m_fDrivenDangerouslyTime; }
void SetDrivenDangerouslyExtremeThisUpdate() { m_nVehicleFlags.bDrivenDangerouslyExtreme = true; }
void UpdateDangerousDriverEvents(float fTimeStep); // Update timer and generate shocking events
void GiveWarning();// Flash the headlights, etc.
CTaskManager *GetTaskManager();
// Vehicle lodding control class (this is AI/physics LOD, not rendering LOD)
const CVehicleAILod& GetVehicleAiLod() const { return m_vehicleAiLod; }
CVehicleAILod& GetVehicleAiLod() { return m_vehicleAiLod; }
void SelectAppropriateGearForSpeed();
void SetPlayerDriveTask(CPed *pPed);
void CacheAiData();
void InvalidateCachedAiData();
Vector3 GetAiVelocity() const { Assertf(IsFiniteAll(m_CachedAiData.m_VelocityAndXYSpeed), "Cached Vehicle AI Velocity is invalid."); return VEC3V_TO_VECTOR3(m_CachedAiData.m_VelocityAndXYSpeed.GetXYZ()); }
const Vec3V& GetAiVelocityConstRef() const { return RCC_VEC3V(RCC_VECTOR3(m_CachedAiData.m_VelocityAndXYSpeed)); /* using a double cast here because we currently don't have a direct conversion from const Vec4V& to const Vec3V& */ }
float GetAiXYSpeed() const { Assertf(IsFiniteAll(m_CachedAiData.m_VelocityAndXYSpeed), "Cached Vehicle AI XY speed is invalid."); return m_CachedAiData.m_VelocityAndXYSpeed.GetWf(); }
bool IsCachedAiDataValid() const { return IsFiniteAll(m_CachedAiData.m_VelocityAndXYSpeed); }
// Used to check if certain shocking events (horn sounded, mad driver) should be allowed to be generated.
bool ShouldGenerateMinorShockingEvent() const;
// Right now just the tank is considered dangerous like this, but it could be a model info flag if necessary.
bool GetIsConsideredDangerousForShockingEvents() const { return IsTank(); }
CVehicle* GetVehicleDrivingOn() const;
// PURPOSE: Prefetch the memory where the pointer to the matrix is stored - not the matrix itself.
void PrefetchPtrToMatrix() const { PrefetchDC(&m_MatrixTransformPtr); }
// PURPOSE: Prefetch the memory where the pointer to the model info is stored - not the model info itself.
void PrefetchPtrToModelInfo() const { PrefetchDC(&m_pArchetype); }
virtual bool GetBurnoutMode() const { return false; }
bool GetBlockingOfNonTemporaryEvents() const { return (GetBlockingOfNonTemporaryEventsThisFrame()); }
bool GetBlockingOfNonTemporaryEventsThisFrame() const;
bool GetIsUsingScriptAutoPilot() const;
#if __ASSERT
void VerifyCache();
#endif
//////////////////////////////////////////////////////////////////////////
// Occupants
CPed *PickRandomPassenger();
bool PickRandomPassengers(int iNumToPick, atArray<int>& aiSeatIndecesOut);
CPed *GetPedInSeat(int iSeat) const;
// Get Whether the vehicle has any occupants in the vehicle ped spawn queue
bool HasScheduledOccupants() const { return m_SeatManager.GetNumScheduledOccupants() > 0;}
// Let the vehicle know that it has a ped waiting to be spawned
void AddScheduledOccupant() { m_SeatManager.AddScheduledOccupant(); }
// Let the vehicle know that a waiting ped has been spawned
void RemoveScheduledOccupant() { m_SeatManager.RemoveScheduledOccupant(); }
bool ContainsPlayer() const { return m_SeatManager.GetNumPlayers() > 0; }
bool IsDriverAPlayer() const;
bool ContainsLocalPlayer( ) const;
bool ContainsPed(const CPed* pPed) const;
s32 GetNumberOfPassenger() const;
bool HasMissionCharsInIt() const;
bool HasPedsInIt() const;
bool HasAlivePedsInIt() const;
bool HasAliveLawPedsInIt() const;
bool HasAliveVictimInIt() const;
void KillPedsInVehicle(CEntity *pCulprit, u32 weaponHash);
void KillPedsGettingInVehicle(CEntity *pCulprit);
bool ShufflePassengersToMakeSpace();
bool CanBeDriven() const;
// apparently this is used to flag occupants of cop veh to not fly through the windscreen when player has a wanted level > 1
void EveryoneInsideWillFlyThroughWindscreen(bool bSetVal);
// Seats with collision are used for open top vehicles to knock peds off
void ProcessSeatCollisionFlags();
void ProcessSeatCollisionBound(bool bReset = false);
bool IsInDriveableState() const;
bool IsInEnterableState(bool bIgnoreSideTest = false) const;
//////////////////////////////////////////////////////////////////////////
// Get in/out
bool CanPedEnterCar(const CPed *pEnteringPed) const;
virtual bool CanPedStepOutCar(const CPed* pPed, bool bIgnoreSpeedCheck = false, bool bDoGroundCheckForHelis = false) const;
virtual bool CanPedJumpOutCar(CPed* pPed, bool bForceSpeedCheck = false) const;
bool CanPedExitCar();
virtual bool UseBikeGetOn() const {return false;}
void SetCarDoorLocks(eCarLockState NewLockState);
void SetRemoteCarDoorLocks(eCarLockState NewLockState);
bool CanPedOpenLocks(const CPed *pEnteringPed) const;
eCarLockState GetCarDoorLocks() const {return m_eDoorLockState;}
void ResetCarDoorKnockedOpenStatus();
// entry position and attachment matrix calculations
void GetVehicleGetInOffset(Vector3& vOffset, float& fHeadingRotation, int iEntryPointIndex) const;
void GetSeatAttachmentOffsets(Vector3& vTransOffset, Quaternion& qRotOffset, s32 iSeatIndex) const;
//
// Accessor functions for the entry/exit points
const CEntryExitPoint* GetEntryExitPoint(s32 i) const;
s32 GetEntryExitPointIndex(const CEntryExitPoint* pEntryExitPoint) const;
// Returns the entry point position
s32 GetNumberEntryExitPoints() const;
bool IsEntryPointIndexValid(s32 i) const;
static float GetDoorRatioToConsiderDoorOpen(const CVehicle& rVeh, bool bIsCombatEntry);
static bool IsEntryPointClearForPed(const CVehicle& vehicle, const CPed& ped, s32 iEntryPoint, const Vector3* pvPosModifier = NULL, bool bDoCapsuleTest = false);
static bool IsDoorClearForPed(const Vector3& vEntryPosition, const CVehicle& vehicle, const CPed& ped, s32 iEntryPoint);
bool HasWaterEntry() const;
//////////////////////////////////////////////////////////////////////////
// Wheels, doors and roof
// Virtual wheel stuff
virtual void InitWheels(){;}
virtual void SetupWheels(const void* UNUSED_PARAM(damageTexture)){;}
virtual bool IsInAir(bool UNUSED_PARAM(bCheckForZeroVelocity) = true) const {return false;}
virtual bool HasLandedStably() const;
int GetNumWheels() const { return m_nNumWheels; }
__forceinline CWheel* GetWheel(int i) { if(i < m_nNumWheels) return m_ppWheels[i]; else return NULL; }
__forceinline const CWheel* GetWheel(int i) const { if(i < m_nNumWheels) return m_ppWheels[i]; else return NULL; }
CWheel* GetWheelFromId(eHierarchyId nId);
const CWheel* GetWheelFromId(eHierarchyId nId) const;
const u32 GetWheelIndexFromId(eHierarchyId nId) const;
int GetNumContactWheels() const; // More expensive than HasContactWheels(), use only if necessary.
bool HasContactWheels() const;
bool IsWheelContactPhysicalMoving() const;
void ResetSuspension();
void TeleportWheels();
CWheel * const * GetWheels() { return m_ppWheels; }
const CWheel * const * GetWheels() const { return m_ppWheels; }
bool GetAreWheelsJustProbes() const { return m_WheelsAreJustProbes; }
void InitialiseWeaponBlades();
void InitialiseWeaponBladeCollision( int bladeMod, int bladeIndex );
void InitialiseSpikeCollision();
void InitialiseRammingScoops();
void InitialiseRamps();
void InitialiseRammingBars();
int GetNumRammingScoopBones() const;
int GetNumFrontSpikeBones() const;
int GetNumRampBones() const;
int GetNumRammingBarBones() const;
// Virtual door stuff
virtual void InitDoors();
int GetNumDoors() const { return m_nNumDoors; }
CCarDoor* GetDoor(int i) { if(i < m_nNumDoors) return &m_pDoors[i]; else return NULL; }
const CCarDoor* GetDoor(int i) const { if(i < m_nNumDoors) return &m_pDoors[i]; else return NULL; }
CCarDoor* GetDoorFromId(eHierarchyId nId);
const CCarDoor* GetDoorFromId(eHierarchyId nId) const;
CCarDoor* GetDoorFromBoneIndex(int iBoneIndex);
const CCarDoor* GetDoorFromBoneIndex(int iBoneIndex) const;
CCarDoor* GetSecondDoorFromEntryPointIndex(s32 iEntryPointIndex);
const CCarDoor* GetSecondDoorFromEntryPointIndex(s32 iEntryPointIndex) const { return const_cast<CVehicle*>(this)->GetSecondDoorFromEntryPointIndex(iEntryPointIndex); }
CCarDoor* GetArticulatedDoorFromComponent(int componentIndex);
bool CanDoorsBeDamaged(void) const;
eCarLockState GetDoorLockStateFromDoorIndex(int i) const;
eCarLockState GetDoorLockStateFromEntryPoint(int i) const;
eCarLockState GetDoorLockStateFromSeatIndex(int i) const;
void SetDoorLockStateFromDoorIndex(int i, eCarLockState eState);
void SetDoorLockStateFromDoorID(eHierarchyId eDoorID, eCarLockState eState);
void SetDoorLockStateFromEntryPoint(int i, eCarLockState eState);
void SetDoorLockStateFromSeatIndex(int i, eCarLockState eState);
bool IsPedUsingDoor();
bool IsPedUsingDoor( CCarDoor* pDoor );
const bool GetRemoteDriverDoorClosing() const { return m_remoteDriverDoorClosing; }
void SetRemoteDriverDoorClosing(bool value) { m_remoteDriverDoorClosing = value; }
bool DoesVehicleHaveAConvertibleRoofAnimation() const;
bool DoesVehicleHaveATransformAnimation() const;
s32 GetConvertibleRoofState() const;
float GetConvertibleRoofProgress() const;
bool IsDoingInstantRoofTransition() const;
void LowerConvertibleRoof(bool bInstantlyLowerRoof);
void RaiseConvertibleRoof(bool bInstantlyRaiseRoof);
bool ShouldLowerConvertibleRoof() const;
void ToggleRoofCollision(bool bSwitchOn);
void TransformToSubmarine( bool bInstantlyTransform );
void TransformToCar( bool bInstantlyTransform );
void PreventSubmarineCarTransform(bool prevent) { m_bSubmarineCarTransformPrevented = prevent; }
s32 GetTransformationState() const;
void SetTransformRateForCurrentAnimation(float fRate);
s32 GetSeatIndexFromDoor(const CCarDoor* pDoor) const;
//////////////////////////////////////////////////////////////////////////
// Bones and components
inline int GetBoneIndex(eHierarchyId nComponent) const {return GetVehicleModelInfo()->GetBoneIndex(nComponent);}
inline bool HasComponent(eHierarchyId nComponent) const {return GetVehicleModelInfo()->GetBoneIndex(nComponent)!=-1;}
bool GetDefaultBonePositionForSetup(eHierarchyId nComponent, Vector3& vecResult) const;
bool GetDefaultBoneRotationForSetup(eHierarchyId nComponent, Quaternion& quatResult) const;
void GetDefaultBonePosition(s32 boneIndex, Vector3& vecResult) const;
void GetDefaultBoneRotation(s32 boneIndex, Quaternion& quatResult) const;
void GetDefaultBonePositionSimple(s32 boneIndex, Vector3& vecResult) const;
const char* GetHierarchyName(eHierarchyId nId) const;
void SetComponentRotation(eHierarchyId compId, eRotationAxis nAxis, float fAngle, bool bSetRotate=true, Vector3* pVecRotateAboutOffset=NULL, Vector3* pVecShiftPos=NULL);
void SetComponentRotation(eHierarchyId compId, const Quaternion& q, bool bSetRotate=true, Vector3* pVecRotateAboutOffset=NULL, Vector3* pVecShiftPos=NULL);
void SetBoneRotation(int nBoneIndex, eRotationAxis nAxis, float fAngle, bool bSetRotate=true, Vector3* pVecRotateAboutOffset=NULL, Vector3* pVecShiftPos=NULL);
void SetBoneRotation(int nBoneIndex, const Quaternion& q, bool bSetRotate=true, Vector3* pVecRotateAboutOffset=NULL, Vector3* pVecShiftPos=NULL);
void SetTransmissionRotation(eHierarchyId compId, eHierarchyId wheelIdL, eHierarchyId wheelIdR);
void SetTransmissionRotationForTrike(eHierarchyId compId, eHierarchyId wheelIdL);
void SetSuspensionTransformation(eHierarchyId compId, eHierarchyId wheelId, SuspensionType nType, const Vec3V *pDeformation = NULL);
void UpdateLinkAttachmentMatricesRecursive( phBoundComposite* pBoundComp, fragTypeGroup* pGroup );
// Extra component stuff (e.g hoods on convertibles, rubbish in veh, stuff on the back of trucks)
void InitExtraFlags(u32 nExtraCommands);
void InitFragmentExtras();
void InitLightExtras();
void InitAllExtras();
void TurnOffExtra(eHierarchyId nId, bool bTurnOff);
bool GetIsExtraOn(eHierarchyId nId) const;
inline bool GetDoesExtraExist(eHierarchyId nId) const {return HasComponent(nId);}
bool HasFragmentComponent(eHierarchyId hierarchyId) const;
int GetFragmentComponentIndex(eHierarchyId hierarchyId) const; // Returns a valid component index only if the component still exists
void RemoveFragmentComponent(eHierarchyId hierarchyId);
void UpdateExtras();
bool CarHasRoof(bool bCheckForRoofDown = false) const;
bool HasRaisedRoof() const;
bool IsGangCar() const;
bool IsPersonalVehicle();
bool IsPersonalOperationsVehicle();
int GetPersonalVehicleOwnerId();
void DeployFoldingWings(bool bDeploy, bool bInstant);
bool GetAreFoldingWingsDeployed() const;
//Make sure if a remote driver is driving your vehicle that
// he gets charged with the correct insurance amount.
CPed* GetVehicleWasSunkByAPlayerPed();
#if !__FINAL
bool IsLocalPersonalVehicle();
bool IsRemotePersonalVehicle();
#endif
// the following function is only really valid for cars/bikes and is redefined there,
// but the colbox limit should be approx ok for other vehicles
virtual float GetHeightAboveRoad() const { return -1.0f * GetBaseModelInfo()->GetBoundingBoxMin().z; }
const CBoardingPoints * GetBoardingPoints() const;
bool GetClosestBoardingPoint(const Vector3 & vWorldSpaceInputPos, CBoardingPoint & boardingPointLocalSpace) const;
// Sets the composite bounding box to the maximum extents possible due to wheel movement
void CalculateNonArticulatedMaximumExtents(bool bDontSweepWheels = false);
bool IsColliderArticulated() const;
virtual inline bool IsPropeller(int UNUSED_PARAM(nComponent)) const {return false;}
virtual inline bool ShouldKeepRotorInCenter(CPropeller *UNUSED_PARAM(pPropeller)) const {return false;}
void RequestDials(const bool overriden = false);
static bool DialsOverriddenByScript(void) {return ms_bDialsScriptOveridden;}
static void ResetDialsOverriddenByScript(void) {ms_bDialsScriptOveridden = false;}
//////////////////////////////////////////////////////////////////////////
// Rendering and Fx//
CVehicleDrawHandler& GetVehicleDrawHandler() {return reinterpret_cast<CVehicleDrawHandler&>(GetDrawHandler());}
const CVehicleDrawHandler& GetVehicleDrawHandler() const {return reinterpret_cast<CVehicleDrawHandler&>(GetDrawHandler());}
// 16 levels allowed: 0.0f=full clean, 7.0f=medium dirty, 15.0f=full dirty, etc.
inline void SetBodyDirtLevel(float d) { m_fBodyDirtLevel = d;}
inline float GetBodyDirtLevel() const { return m_fBodyDirtLevel; }
inline void SetBodyDirtColor(Color32 c) { m_bodyDirtColor = c; }
inline Color32 GetBodyDirtColor() const { return m_bodyDirtColor; }
// returns u8 number 0-15:
inline u8 GetBodyDirtLevelUInt8() { return static_cast<u8>( static_cast<u32>(GetBodyDirtLevel())&0x0F ); }
void ProcessDirtLevel();
// access to vehicle body colours:
inline u8 GetBodyColour1() const { return GetVehicleDrawHandler().GetVariationInstance().GetColor1(); }
inline u8 GetBodyColour2() const { return GetVehicleDrawHandler().GetVariationInstance().GetColor2(); }
inline u8 GetBodyColour3() const { return GetVehicleDrawHandler().GetVariationInstance().GetColor3(); }
inline u8 GetBodyColour4() const { return GetVehicleDrawHandler().GetVariationInstance().GetColor4(); }
inline u8 GetBodyColour5() const { return GetVehicleDrawHandler().GetVariationInstance().GetColor5(); }
inline u8 GetBodyColour6() const { return GetVehicleDrawHandler().GetVariationInstance().GetColor6(); }
inline void SetBodyColour1(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetColor1(c); }
inline void SetBodyColour2(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetColor2(c); }
inline void SetBodyColour3(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetColor3(c); }
inline void SetBodyColour4(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetColor4(c); }
inline void SetBodyColour5(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetColor5(c); }
inline void SetBodyColour6(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetColor6(c); }
s32 GetLiveryId() const;
void SetLiveryId(s32 id);
void SetLiveryModFrag(strLocalIndex fragSlotIdx);
s32 GetLivery2Id() const;
void SetLivery2Id(s32 id2);
void UpdateBodyColourRemapping(bool repainted = true); // updates body colours with shaders
// Access to neon colours / on/off flags
inline Color32 GetNeonColour() const { return GetVariationInstance().GetNeonColour(); }
inline void SetNeonColour(Color32 c) { GetVariationInstance().SetNeonColour(c); }
inline bool IsNeonLOn() const { return GetVariationInstance().IsNeonLOn(); }
inline void SetNeonLOn(bool on) { GetVariationInstance().SetNeonLOn(on); }
inline bool IsNeonROn() const { return GetVariationInstance().IsNeonROn(); }
inline void SetNeonROn(bool on) { GetVariationInstance().SetNeonROn(on); }
inline bool IsNeonFOn() const { return GetVariationInstance().IsNeonFOn(); }
inline void SetNeonFOn(bool on) { GetVariationInstance().SetNeonFOn(on); }
inline bool IsNeonBOn() const { return GetVariationInstance().IsNeonBOn(); }
inline void SetNeonBOn(bool on) { GetVariationInstance().SetNeonBOn(on); }
inline void SetXenonLightColor(u8 c) { GetVehicleDrawHandler().GetVariationInstance().SetXenonLightColor(c); }
inline u8 GetXenonLightColor() const { return GetVehicleDrawHandler().GetVariationInstance().GetXenonLightColor(); }
bool IsAirExplosion(const Vector3& expPos);
bool IsCamInsideVehicleInterior();
// HD drawing
static int ms_maxHdVehiclesInSp;
static int ms_maxHdVehiclesInMp;
static float ms_afVehicleHdDistanceMP[CContinuityState::SCENE_STREAMING_PRESSURE_TOTAL];
static float ms_afVehicleHdDistanceSP[CContinuityState::SCENE_STREAMING_PRESSURE_TOTAL];
static void RetrieveAndCacheCloudTunables();
void GetHDModeRequests(bool &requestDraw, bool & requestStream); // Tells you whether we should draw based on distance
virtual void Update_HD_Models(); // handle requests for high detail models
virtual inline bool GetIsCurrentlyHD() const { return (m_vehicleLodState == VLS_HD_AVAILABLE); }
void SetVehicleLodState(eVehicleLodState state) { m_vehicleLodState = state; }
eVehicleLodState GetVehicleLodState() { return(m_vehicleLodState); }
void SetRespotCounter(u32 counter); // when veh gets re-spotted in a network game, want to disable collisions with other network vehicles
u16 GetRespotCounter() { return m_nNetworkRespotCounter; }
bool IsBeingRespotted() const { return m_nNetworkRespotCounter > 0; }
bool IsRunningSecondaryRespotCounter() const { return m_uSecondaryRespotOverrideTimeout > 0; }
void ResetRespotCounter(bool bForceResetDamagedByAnything = true);
bool ShouldPreRenderBeyondSmallRadius() const;
void ResetSkeletonForMods();
// Short-hand for checking if the jumping car flag is set
bool HasJump();
float GetJumpForceModifier();
// Short-hand for checking if the rocket car flag is set
bool HasRocketBoost();
bool HasNitrousBoost();
bool HasSideShunt() const;
float GetNitrousPowerModifier();
float GetNitrousDurationModifier();
float GetNitrousRechargeModifier();
bool IsRocketBoosting() const { return m_bIsRocketBoosting; }
void SetRocketBoosting(bool bNewValue);
void SetRocketBoostedFromNetwork() { m_bRocketBoostedFromNetwork = true; }
void SetRocketBoostedStoppedFromNetwork() { m_bRocketBoostedStoppedFromNetwork = true; }
f32 GetRocketBoostRemaining() const { return m_fRocketBoostRemaining; }
void SetRocketBoostRemaining(f32 f) { m_fRocketBoostRemaining = f; }
f32 GetRocketBoostCapacity() const { return pHandling->m_fRocketBoostCapacity * ( InheritsFromPlane() ? ( 1.0f + (ms_fRocketBoostMaxIncrease * GetVariationInstance().GetGearboxModifier() * 0.01f ) ) : 1.0f ); }
void SetRocketBoostRechargeRate(float fNewValue) { m_fRocketBoostRechargeRate = fNewValue; }
float GetRocketBoostRechargeRate() { return m_fRocketBoostRechargeRate; }
// Short-hand for checking if the parachute car flag is set
bool HasParachute() { return GetVehicleModelInfo()->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_HAS_PARACHUTE); }
bool HasGlider() const { return GetVehicleModelInfo()->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_HAS_GLIDER); }
float GetGliderDeployedRatio() { return m_wingDeployedRatio; }
float GetGliderNormaliseDeployedRatio() const;
float GetSpecialFlightModeRatio() const;
void ApplyParachuteStabilisation( Vector3& vStabilisationAxis, float fAngle, float fMaxTorque = 0.0f, float pitchStabilisationMult = sfPitchStabilisationMult, float rollStabilisationMult = sfRollStabilisationMult );
void ApplyHoverModeStabilisation( Vector3& vDesiredUp, float normalisedDeployedRatio );
void ApplyHoverModeThrust( CSpecialFlightHandlingData* flightHandling, Vector3 thrustDirection, float fTimeStep, float normalisedDeployedRatio, float forwardVelocity, float normalisedForwardVelocity, float fThrottle, float fStickY, float fStickX, bool strafeMode );
int CalculateWheelHoverForce( CWheel* wheel, Vector3& wheelForce, Vector3& upVec, float normalisedForwardVelocity, float normalisedDeployedRatio, float fStickY, float invTimeStep, int sampleIndex, bool worksUpsideDown );
void UpdateHoverModeBones();
Vector3 CalculateGroundHeight( float rightOffset, float forwardOffset, float probeLength );
Vector3 CalculateDesiredUp( float normalisedDeployedRatio, float normalisedForwardVelocity, float fStickX, float fStickY );
void ApplyLowSpeedMovement( float normalisedDeployedRatio, float normalisedVelocity, bool anchorPosition );
virtual CTransmission* GetSecondTransmission() { return NULL; }
bool IsPlaceOnRoadHeightOverriden() { return m_fOverridenPlaceOnRoadHeight != sm_fInvalidPlaceOnRoadHeight; }
float GetOverridenPlaceOnRoadHeight() { return m_fOverridenPlaceOnRoadHeight; }
void SetOverridenPlaceOnRoadHeight(float fHeight) { m_fOverridenPlaceOnRoadHeight = fHeight; }
void ResetOverridenPlaceOnRoadHeight() { m_fOverridenPlaceOnRoadHeight = sm_fInvalidPlaceOnRoadHeight; }
bool GetHomingCanLockOnToObjects() const { return m_bHomingCanLockOnToObjects; }
void SetHomingCanLockOnToObjects(bool bValue) { m_bHomingCanLockOnToObjects = bValue; }
void SetScriptMaxSpeed( float maxSpeed ) { m_scriptMaxSpeed = maxSpeed; }
float GetScriptMaxSpeed() { return m_scriptMaxSpeed; }
bool IsShuntModifierActive() const { return m_shuntModifierActive; }
//////////////////////////////////////////////////////////////////////////
// Lights
public:
enum eHeadlightCoverState
{
LIGHTCOVER_CLOSED = 0,
LIGHTCOVER_OPEN,
LIGHTCOVER_OPENING,
LIGHTCOVER_CLOSING,
};
eHeadlightCoverState GetHeadlightCoverState() { return m_lightCoverState; }
protected:
eHeadlightCoverState m_lightCoverState;
float m_lightCoverOpenRatio;
void ProcessLightCovers();
bool ShouldLightsBeOn() const;
void UpdateLightsOnFlag();
public:
bool GetVehicleLightsStatus();
bool UpdateVehicleLightOverrideStatus();
bool GetFullBeamStatus();
void CalculateInitialLightStateBasedOnClock();
void UpdateLightRandomisation();
void DoVehicleLights(u32 nLightFlags, Vec4V_In ambientVolumeParams = Vec4V(V_ZERO_WONE));
void ProcessIndicators(bool &bTurningLeft, bool &bTurningRight, bool bForcedOn);
void DoAdditionalLightsEffect(s32 lightId, float fade, const ConfigLightSettings* lightConfig, fwInteriorLocation interiorLoc, bool restrictRadius, CoronaAndLightList& coronaAndLightList);
void DoVehicleLightsAsync(const Matrix34 &matVehicle, u32 nLightFlags, Vec4V_In ambientVolumeParams, const fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
#if ENABLE_FRAG_OPTIMIZATION
void DoHeadLightsEffect(bool leftOn, bool rightOn, s32 boneIdLeft, s32 boneIdRight, float fade, float daynightFade, float coronaFade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, bool bExtraBright, bool noLight, const vehicleLightSettings *settings, float intensityMultiplierHeadLeft, float intensityMultiplierHeadRight, fwInteriorLocation interiorLoc, bool useVolumetricLights, bool forceLowResVolumetricLights, bool reduceHeadlightCoronas, CoronaAndLightList& coronaAndLightList );
void DoExtraLightsEffect(s32 boneId1, s32 boneId2, s32 boneId3, s32 boneId4, bool On1, bool On2, bool On3, bool On4,bool doLight, float fade, float daynightFade, float coronaFade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, const vehicleLightSettings *settings, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList );
void DoIndicatorLightEffect(s32 boneId, float fade, float daynightFade, float coronaFade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, const vehicleLightSettings *settings, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoTailLightsEffect(s32 boneIdLeft, s32 boneIdMiddle, s32 boneIdRight, bool leftOn, bool middleOn, bool rightOn, float fade, float daynightFade, float coronaFade, bool noCorona, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, bool isBrakes, const vehicleLightSettings *settings, float intensityMultiplierTailLeft, float intensityMultiplierTailRight, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoReversingLightsEffect(s32 boneIdLeft, s32 boneIdRight, bool leftOn, bool rightOn, float fade, float daynightFade, float coronaFade, bool noCorona, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, const vehicleLightSettings *settings, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoInteriorLightEffect(s32 boneId, float fade, CVehicleModelInfo* pModelInfo, fwInteriorLocation interiorLoc, bool isHeli = false);
void DoInteriorLightEffect(s32 boneId, float fade, CVehicleModelInfo* pModelInfo, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList, bool isHeli = false);
void DoTaxiLightEffect(float fade, float daynightFade, CVehicleModelInfo* pModelInfo, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoNeonLightEffect(u32 neonFlags, float fade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, fwInteriorLocation interiorLocation, CoronaAndLightList& coronaAndLightList);
void DoSirenLightsEffect(float fade, float daynightFade, float coronaFade, bool noActualLights, const CVehicleModelInfo* const pModelInfo, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
#else
void DoHeadLightsEffect(bool leftOn, bool rightOn, s32 boneIdLeft, s32 boneIdRight, float fade, float daynightFade, float coronaFade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, bool bExtraBright, bool noLight, const vehicleLightSettings *settings, float intensityMultiplierHeadLeft, float intensityMultiplierHeadRight, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, bool useVolumetricLights, bool forceLowResVolumetricLights, bool reduceHeadlightCoronas, CoronaAndLightList& coronaAndLightList );
void DoExtraLightsEffect(s32 boneId1, s32 boneId2, s32 boneId3, s32 boneId4, bool On1, bool On2, bool On3, bool On4,bool doLight, float fade, float daynightFade, float coronaFade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, const vehicleLightSettings *settings, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList );
void DoIndicatorLightEffect(s32 boneId, float fade, float daynightFade, float coronaFade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, const vehicleLightSettings *settings, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoTailLightsEffect(s32 boneIdLeft, s32 boneIdMiddle, s32 boneIdRight, bool leftOn, bool middleOn, bool rightOn, float fade, float daynightFade, float coronaFade, bool noCorona, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, bool isBrakes, const vehicleLightSettings *settings, float intensityMultiplierTailLeft, float intensityMultiplierTailRight, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoReversingLightsEffect(s32 boneIdLeft, s32 boneIdRight, bool leftOn, bool rightOn, float fade, float daynightFade, float coronaFade, bool noCorona, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, const vehicleLightSettings *settings, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoInteriorLightEffect(s32 boneId, float fade, CVehicleModelInfo* pModelInfo, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, bool isHeli = false);
void DoInteriorLightEffect(s32 boneId, float fade, CVehicleModelInfo* pModelInfo, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList, bool isHeli = false);
void DoTaxiLightEffect(float fade, float daynightFade, CVehicleModelInfo* pModelInfo, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
void DoNeonLightEffect(u32 neonFlags, float fade, CVehicleModelInfo* pModelInfo, const Matrix34 &matVehicle, crSkeleton *pSkeleton, fwInteriorLocation interiorLocation, CoronaAndLightList& coronaAndLightList);
void DoSirenLightsEffect(float fade, float daynightFade, float coronaFade, bool noActualLights, const CVehicleModelInfo* const pModelInfo, crSkeleton *pSkeleton, fwInteriorLocation interiorLoc, CoronaAndLightList& coronaAndLightList);
#endif
static inline float CalculateVehicleDaylightFade()
{
// One bit per hour, we wants veh lights from 19 till 6
// 0000000000111111111122222
// 0123456789012345678901234
//const int vehTimeFlags = 0b111110000000000000111111; since only SN/gcc support this notation, let's have an hex value instead.
const int vehTimeFlags = 0xF8003F;
return Lights::CalculateTimeFade(vehTimeFlags);
}
void DoVehicleLightsNoLights();
void SetHazardLights(bool set) { m_nVehicleFlags.bHazardLights = set; }
void SetIndicatorLights(bool set) { m_nVehicleFlags.bIndicatorLights = set; }
void SetInteriorLight(bool set) { m_nVehicleFlags.bInteriorLightOn = set; }
void SetForceInteriorLight(bool force) { m_bInteriorLightForceOn = force; }
void TurnSirenOn(bool on, bool randomDelay = true);
//////////////////////////////////////////////////////////////////////////
// Damage
inline CVehicleDamage* GetVehicleDamage() {return &m_VehicleDamage;}
inline const CVehicleDamage* GetVehicleDamage() const {return &m_VehicleDamage;}
bool HasInfiniteFuel() const;
float GetFuelConsumptionRate() const;
virtual void BlowUpCar(CEntity* UNUSED_PARAM(pCulprit), bool UNUSED_PARAM(bInACutscene)=false, bool UNUSED_PARAM(bAddExplosion)=true, bool UNUSED_PARAM(bNetCall)=false, u32 UNUSED_PARAM(weaponHash) = WEAPONTYPE_EXPLOSION, bool UNUSED_PARAM(bDelayedExplosion) = false);
virtual void AddVehicleExplosion(CEntity *pCulprit, bool bInACutscene, bool bDelayedExplosion);
virtual const eHierarchyId* GetExtraBonesToDeform(int& extraBoneCount) { extraBoneCount = 0; return NULL; }
void MakeRealOrFixForExplosion();
virtual void Fix(bool resetFrag = true, bool allowNetwork = false);
virtual void SetupDamageAfterLoad() {;}
virtual void ApplyDeformationToBones(const void* UNUSED_PARAM(basePtr)) {;}
void FixVehicleDeformation() { m_VehicleDamage.FixVehicleDeformation(); }
bool IsUpsideDown() const;
bool IsOnItsSide() const;
bool IsRightWayUp() const;
void SetCanBeDamaged(bool DamageFlag) { m_nPhysicalFlags.bNotDamagedByAnything = !DamageFlag; }
void ExtinguishCarFire(bool finishPtFx=false, bool bClampVehicleHealth = true);
void ClearCulpritFromCarFires(const CEntity* pCulprit);
bool CanLeakPetrol() const;
bool HasScriptForcedLeakingOff() const;
bool HasScriptForcedLeakingOn() const;
bool CanLeakOil() const;
bool IsLeakingPetrol() const;
bool IsLeakingOil() const;
bool CanEngineDegrade() const;
bool IsOnFire() const;
bool AreTyresDamaged() const;
bool IsSuspensionDamaged() const;
bool IsLeftHeadLightDamaged() const { return m_VehicleDamage.GetLightState(VEH_HEADLIGHT_L); }
bool IsRightHeadLightDamaged() const { return m_VehicleDamage.GetLightState(VEH_HEADLIGHT_R); }
bool AreBothHeadLightsDamaged() const { return IsLeftHeadLightDamaged() && IsRightHeadLightDamaged(); }
int GetNumberOfDamagedHeadlights() const
{
int count = IsLeftHeadLightDamaged() ? 1 : 0;
if (IsRightHeadLightDamaged())
{
++count;
}
return count;
}
u8 GetNumFlatTires() const;
virtual void NotifyWheelPopped(CWheel *UNUSED_PARAM(pWheel)) {}
void FlagWheelsWithDeformationImpact(Vec3V_In damageOffset, ScalarV_In damageRadius);
Vec3V_Out GetWindowNormalForSmash(eHierarchyId windowId) const;
void SmashWindow(eHierarchyId iWindowHierarchy, float force, bool bIgnoreCracks = false, bool bDetachAll = false);
void FixWindow(eHierarchyId iWindowHierarchy);
bool HasWindow(eHierarchyId iWindowHierarchy) const;
bool HasWindowToSmash(eHierarchyId iWindowHierarchy, bool bIgnoreCracks = false) const;
bool HasAnyWindowsToSmash() const;
void DeleteWindow(eHierarchyId iWindowHierarchy);
void SetWindowComponentDirty(eHierarchyId id ) {Assert(id >= VEH_FIRST_WINDOW && id <= VEH_LAST_WINDOW);m_iWindowComponent[id - VEH_FIRST_WINDOW] = VEH_WINDOW_STATE_DIRTY;}
void SetAllWindowComponentsDirty(){ for (u32 i=VEH_FIRST_WINDOW; i<=VEH_LAST_WINDOW; ++i) m_iWindowComponent[i - VEH_FIRST_WINDOW] = VEH_WINDOW_STATE_DIRTY;}
void CacheSmashableWindows();
static eHierarchyId GetWindowIdFromDoor(eHierarchyId doorId);
static eHierarchyId GetDoorIdFromWindow(eHierarchyId windowId);
bool IsWindowDown(eHierarchyId eWindowId) const;
void RolldownWindows();
void RolldownWindow(eHierarchyId iWindowHierarchy, bool bCalledFromPreRender=false);
void RollupWindows(bool bSkeletonReset = true);
void RollWindowUp(eHierarchyId iWindowHierarchy);
bool IsAlarmActivated() const {return (CarAlarmState && CarAlarmState!=CAR_ALARM_SET && GetStatus()!=STATUS_WRECKED);};
void SetCarAlarm(bool set) { if(set) CarAlarmState = CAR_ALARM_SET; else CarAlarmState = CAR_ALARM_NONE;}
#if GTA_REPLAY
bool IsReplayOverrideWheelsRot() const { return m_replayOverrideWheelsRot; }
void SetIsReplayOverrideWheelsRot(bool overRot) { m_replayOverrideWheelsRot = overRot;}
void SetCarAlarmState(u16 state) { CarAlarmState = state; }
void IncreaseNumAppliedVehicleDamage(void) { m_appliedVehicleDamage++; }
u8 GetNumAppliedVehicleDamage(void) { return m_appliedVehicleDamage; }
void SetNumAppliedVehicleDamage(const u8 s) { m_appliedVehicleDamage = s; }
void ResetNumAppliedVehicleDamage(void) { m_appliedVehicleDamage=0; }
#endif // GTA_REPLAY
void ProcessCarAlarm(const float fFullUpdateTimeStep);
bool TriggerCarAlarm();
void SetIsWrecked();
virtual void SetIsAbandoned(const CPed *pOriginalDriver = NULL);
virtual void SetIsOutOfControl();
void SetIsPlayerDisabled();
bool TestExplosionPosAndBlowRearDoorsopen(const Vector3& vExplosionPos );
struct DestructionInfo
{
void Clear()
{
m_Source = NULL;
m_Weapon = 0;
m_Time = 0;
}
RegdEnt m_Source;
u32 m_Weapon;
u32 m_Time;
};
void ClearDestructionInfo() { m_DestructionInfo.Clear(); }
CEntity* GetSourceOfDestruction() const { return m_DestructionInfo.m_Source; }
void SetSourceOfDestruction(CEntity* pSource) { m_DestructionInfo.m_Source = pSource; }
u32 GetCauseOfDestruction() const { return m_DestructionInfo.m_Weapon; }
void SetCauseOfDestruction(const u32 uWeapon) { m_DestructionInfo.m_Weapon = uWeapon; }
u32 GetTimeOfDestruction() const { return m_DestructionInfo.m_Time; }
void SetTimeOfDestruction() { SetTimeOfDestruction(fwTimer::GetTimeInMilliseconds()); }
void SetTimeOfDestruction(const u32 uTime) { m_DestructionInfo.m_Time = uTime; }
void SetDestructionInfo(CEntity* pSource, const u32 uWeapon);
bool CalculateTimeUntilExplosion(float& fTime) const;
//These are the damaged bounds (if damaged), otherwise the VEH_CHASSIS bounds or overall vehicle bounds
Vector3 GetChassisBoundMin(bool includeDamage = false) const;
Vector3 GetChassisBoundMax(bool includeDamage = false) const;
//////////////////////////////////////////////////////////////////////////
// Audio
audVehicleAudioEntity* GetVehicleAudioEntity() { return(m_VehicleAudioEntity); }
const audVehicleAudioEntity* GetVehicleAudioEntity() const { return(m_VehicleAudioEntity); }
audPlaceableTracker *GetPlaceableTracker() { return &m_PlaceableTracker; }
const audPlaceableTracker *GetPlaceableTracker() const { return &m_PlaceableTracker; }
void ProcessSirenAndHorn(bool bHornAvailable);
void StopHorn();
bool IsHornOn() const;
// Functions having to do with the engine temperature and starting
bool IsEngineOn() const { return m_nVehicleFlags.bEngineOn; }
void SwitchEngineOn(bool bNoDelay = false, bool bNetCheck = true, bool forceFail = false);
void SwitchEngineOff(bool bNetCheck = true);
void UpdateEngineTemperature(float fTimeStep);
void SetRandomEngineTemperature(float value = fwRandom::GetRandomNumberInRange(0.0f, 1.0f));
float ComputeEngineWontStartProbability();
//Check if this vehicle can add an event for peds to comment on it.
void AddCommentOnVehicleEvent();
//////////////////////////////////////////////////////////////////////////
// Vehicle Gadgets (weapons etc)
const CVehicleWeaponMgr* GetVehicleWeaponMgr() const { return m_pVehicleWeaponMgr; }
CVehicleWeaponMgr* GetVehicleWeaponMgr() { return m_pVehicleWeaponMgr; }
void CreateVehicleWeaponMgr();
void DestroyVehicleWeaponWhenInactive() { m_destroyWeaponMgr = true; };
void DestroyVehicleWeaponMgr();
void RecreateVehicleWeaponMgr() { DestroyVehicleWeaponMgr(); CreateVehicleWeaponMgr(); }
void SetupWeaponModCollision();
void InitialiseSeatCollision( phBoundComposite* pBoundComp );
//Function to see if a specific vehicle seat has any turrets or weapons associated with it
bool GetSeatHasWeaponsOrTurrets(s32 seatIndex) const;
void AddVehicleGadget(CVehicleGadget* pGadget);
CVehicleGadget* GetVehicleGadget(int iGadgetIndex) const;
int GetNumberOfVehicleGadgets() const {return m_pVehicleGadgets.size();}
int GetGadgetEntities(int entityListSize, const CEntity ** entityListOut) const;
void UpdateUserEmissiveMultiplier(bool bNewEngineOnValue, bool bOldEngineOnValue);
// Allow script to set an ammo limit for a particular vehicle weapon index
void SetRestrictedAmmoCount(s32 iWeaponIndex, s32 iAmmoCount) {vehicleAssert(iWeaponIndex >= 0 && iWeaponIndex < MAX_NUM_VEHICLE_WEAPONS); m_iRestrictedAmmoCount[iWeaponIndex] = iAmmoCount;}
s32 GetRestrictedAmmoCount(s32 iWeaponIndex) const {vehicleAssert(iWeaponIndex >= 0 && iWeaponIndex < MAX_NUM_VEHICLE_WEAPONS); return m_iRestrictedAmmoCount[iWeaponIndex];}
void ReduceRestrictedAmmoCount(s32 iWeaponIndex) {vehicleAssert(iWeaponIndex >= 0 && iWeaponIndex < MAX_NUM_VEHICLE_WEAPONS); m_iRestrictedAmmoCount[iWeaponIndex]--;}
// Network-synced ammo counts for bombs and countermeasures (can't be tied to a specific player)
void SetBombAmmoCount(s32 iAmmoCount) { m_iBombAmmoCount = iAmmoCount; }
s32 GetBombAmmoCount() const { return m_iBombAmmoCount; }
void SetCountermeasureAmmoCount(s32 iAmmoCount) { m_iCountermeasureAmmoCount = iAmmoCount; }
s32 GetCountermeasureAmmoCount() const { return m_iCountermeasureAmmoCount; }
//////////////////////////////////////////////////////////////////////////
// Script
virtual void SetupMissionState();
virtual void CleanupMissionState();
//////////////////////////////////////////////////////////////////////////
// Misc
inline bool IsRunningCarRecording() const { return m_nVehicleFlags.bIsInRecording; }
bool CanBeInactiveDuringRecording() const;
inline bool IsInactiveForRecording() const { return m_nVehicleFlags.bIsInRecording && m_nVehicleFlags.bIsDeactivatedByPlayback; }
virtual bool TreatAsOnFootForGarages() const {return false;} // bmx will be treated as on foot in the garage code for some reason?
void DisableWheelCollisions(bool bDisableCameraCollision = false);
void EnableWheelCollisions();
void SetupWheelCollisions(phBoundComposite * pVehCompositeBound);
void FreezeAllTurretJoints( gtaFragType* type, bool freeze );
void FreezeAllJoints( gtaFragType* type );
void Freeze1DofJointInCurrentPosition(fragInstGta* pFragInst, int iChildIndex);
void Freeze1DofJointInCurrentPosition(fragInstGta* pFragInst, int typeComponentIndex, bool freeze);
// just have an empty function so it can be called from vehicle pointers
virtual void PlayCarHorn(bool UNUSED_PARAM(bOneShot), u32 UNUSED_PARAM( hornTypeHash )= 0 ) {};
bool PlaceOnRoadAdjust(bool bJustSetCompression = false, float hightSampleRangeUp = PLACEONROAD_DEFAULTHEIGHTUP ) {return PlaceOnRoadAdjust(hightSampleRangeUp,PLACEONROAD_DEFAULTHEIGHTDOWN, bJustSetCompression);}
bool PlaceOnRoadAdjust(float HeightSampleRangeUp, float HeightSampleRangeDown, bool bJustSetCompression = false);
//bool IsInTunnel() const;
inline TDynamicObjectIndex GetPathServerDynamicObjectIndex() const { return m_iPathServerDynObjId; }
inline void SetPathServerDynamicObjectIndex(const TDynamicObjectIndex i) { m_iPathServerDynObjId = i; }
// Targeting
virtual float GetLockOnTargetableDistance() const { return m_fTargetableDistance; }
virtual void SetLockOnTargetableDistance(float fTargetableDistance) { m_fTargetableDistance = fTargetableDistance; }
virtual void SetHomingLockOnState(CEntity::eHomingLockOnState state);
CEntity::eHomingLockOnState GetHomingLockOnState() const { return m_eHomingLockOnState; }
CEntity::eHomingLockOnState GetHomingLockedOntoState() const { return m_eHomingLockedOntoState; }
virtual void SetHomingProjectileDistance( float fHomingProjectileDistance );
float GetHomingProjectileDistance() const { return m_fHomingProjectileDistance; }
void SetLockOnTarget(CPhysical *pTarget) { m_pLockOnTarget = pTarget; }
CPhysical *GetLockOnTarget() const { return m_pLockOnTarget; }
void UpdateHomingLockedOntoState(CEntity::eHomingLockOnState state);
void UpdateLockOnStatus();
void SetLastTimeHomedAt(u32 time) { m_uLastTimeHomedAt = time; }
u32 GetLastTimeHomedAt() const { return m_uLastTimeHomedAt; }
static const u32 MAX_NUM_EXCLUSIVE_DRIVERS = 2;
void SetExclusiveDriverPed(CPed *pPed, s32 i=0);
CPed * GetExclusiveDriverPed(s32 i=0) const { Assert(i<MAX_NUM_EXCLUSIVE_DRIVERS); return m_pExclusiveDriverPeds[i]; }
bool IsAnExclusiveDriverPedOrOpenSeat(const CPed* ped ) const;
bool IsAnExclusiveDriverPed(const CPed* ped) const;
bool HasAnExclusiveDriver() const;
bool HasExpandedMods();
float GetBrakeForce( bool includeModifier = false ) const;
// Event Generation Helpers
bool ShouldAlertNearbyWhenVehicleIsEntered() const { return m_nVehicleFlags.bAlertWhenEntered; }
void SetShouldAlertNearbyWhenVehicleIsEntered(bool bSet) { m_nVehicleFlags.bAlertWhenEntered = bSet; }
bool ShouldGenerateEngineShockingEvents() const { return m_nVehicleFlags.bGeneratesEngineShockingEvents; }
void SetShouldGenerateEngineShockingEvents(bool bSet) { m_nVehicleFlags.bGeneratesEngineShockingEvents = bSet; }
const Vector3& GetInternalForce() { return m_vecInternalForce; }
const Vector3& GetInternalTorque() { return m_vecInternalTorque; }
#if !__FINAL
void SetDebugName(const char* strName);
virtual const char* GetDebugName() const;
#endif
void SetNeonSuppressionState(bool val) { m_bSuppressNeons = val; }
bool GetNeonSuppressionState() const { return m_bSuppressNeons; }
//////////////////////////////////////////////////////////////////////////
// Attachments
// Returns the physical attachment parent if it is a vehicle.
CVehicle* GetAttachParentVehicle() const;
// Returns the dummy attached parent or physical attachment parent if it is a vehicle
CVehicle* GetAttachParentVehicleDummyOrPhysical() const;
// Trailers
bool HasTrailer() const { return (GetAttachedTrailer() != NULL) || HasDummyAttachmentChildren(); }
CTrailer* GetAttachedTrailer() const;
CTrailer* GetAttachedTrailerOrDummyTrailer() const;
CTrailer* GetParentTrailer() const { return m_parentTrailer; }
void SetParentTrailer(CTrailer* trailer) { m_parentTrailer = trailer; }
static bool IsEntityAttachedToTrailer(const CEntity* pEntity);
void SetIsCargoVehicle(bool isCargoVehicle);
float GetParentTrailerAttachStrength() const {return m_fParentTrailerAttachStrength;}
Vector3::Return GetParentTrailerEntity1Offset() const {return m_vParentTrailerEntity1Offset;}
Vector3::Return GetParentTrailerEntity2Offset() const {return m_vParentTrailerEntity2Offset;}
Quaternion GetParentTrailerEntityRotation() const {return m_qParentTrailerEntityRotation;}
void SetParentTrailerAttachStrength(float fStrength) {m_fParentTrailerAttachStrength = fStrength;}
void SetParentTrailerEntity1Offset(const Vector3& vOffset) {m_vParentTrailerEntity1Offset = vOffset;}
void SetParentTrailerEntity2Offset(const Vector3& vOffset) {m_vParentTrailerEntity2Offset = vOffset;}
void SetParentTrailerEntityRotation(const Quaternion& qRot) {m_qParentTrailerEntityRotation = qRot;}
// Dummy attachment accessors
CVehicle * GetDummyAttachmentParent() const { return m_DummyAttachmentParent; }
CVehicle* GetDummyAttachmentChild(const int index) const { return m_DummyAttachmentChildren[index]; }
int GetMaxNumDummyAttachmentChildren() const {return m_DummyAttachmentChildren.GetMaxCount();}
bool HasDummyAttachmentChildren() const { return m_nDummyAttachmentChildren>0; }
int FindDummyAttachmentChild(const CVehicle* const pVehicle);
// Dummy attachment modifiers
int DummyAttachChild(CVehicle & vehChild);
void DummyDetachChild(const CVehicle * pChildVehicle);
void DummyDetachChild(int iChildSlot);
void DummyDetachAllChildren();
void InitDummyAttachmentChildren();
//Tow truck
const CEntity* GetEntityBeingTowed() const;
void DetachFromParentVehicleGadget();
bool GetIsBeingTowed() const;
bool GetIsTowing() const;
bool HasTowingGadget() const;
//Submarine / Submarine car
virtual CSubmarineHandling* GetSubHandling() { return NULL; }
virtual const CSubmarineHandling* GetSubHandling() const { return NULL; }
virtual CBoatHandling* GetBoatHandling() { return NULL; }
virtual const CBoatHandling* GetBoatHandling() const { return NULL; }
//////////////////////////////////////////////////////////////////////////
// Special ability code
void ProcessSlowMotionSpecialAbilityPrePhysics(const CPed *pDriver);
void ProcessSlowMotionSpecialAbilityPostPhysics();
void ProcessSlowMotionVehiclePrePhysics(const float fFxStrength);
void SetFullThrottleTime(u32 iDurationMs) { m_iFullThrottleRecoveryTime = NetworkInterface::GetNetworkTime() + iDurationMs; }
bool IsFullThrottleActive() { return m_bFullThrottleActive; }
static float ms_fBrakeVarianceMaxModifier;
static float ms_fEngineVarianceMaxModifier;
static float ms_fThrustDropOffVarianceMaxModifier;
static float ms_fSuspensionVarianceMaxModifier;
static float ms_fGearboxClutchSpeedVarianceMaxModifier;
static float ms_fHydraulicVarianceUpperBoundMaxModifier;
static float ms_fHydraulicVarianceLowerBoundMaxModifier;
static float ms_fHydraulicVarianceUpperBoundMinModifier;
static float ms_fHydraulicVarianceLowerBoundMinModifier;
static float ms_fHydraulicRateMax;
static float ms_fHydraulicRateMin;
static float ms_fPlaneHandlingVarianceMaxModifier;
static float ms_fRocketBoostMaxIncrease;
void SetIsInPopulationCache(bool val) { m_nVehicleFlags.bIsInPopulationCache = val; }
bool GetIsInPopulationCache() const { return m_nVehicleFlags.bIsInPopulationCache; }
bool GetHavePartsBrokenOff() const { return m_nVehicleFlags.bPartsBrokenOff; }
void SetHavePartsBrokenOff(bool val) { m_nVehicleFlags.bPartsBrokenOff = val; }
bool GetHasBeenRepainted() const { return m_nVehicleFlags.bHasBeenRepainted; }
void SetHasBeenRepainted(bool val) { m_nVehicleFlags.bHasBeenRepainted = val; }
float GetLodMultiplier() const { return m_fLodMult; }
void SetLodMultiplier(float multiplier) { m_fLodMult = multiplier; }
s8 GetClampedRenderLod() const { return m_clampedRenderLod; }
void SetClampedRenderLod(s8 lod) { m_clampedRenderLod = lod; }
bool IsForcedHd() const { return m_nVehicleFlags.bForceHd; }
void SetForceHd(bool val) { m_nVehicleFlags.bForceHd = val; }
void SetScriptForceHd(bool val) { m_nVehicleFlags.bScriptForceHd = val; }
bool GetScriptForceHd() { return m_nVehicleFlags.bScriptForceHd; }
bool CanSaveInGarage() const { return m_nVehicleFlags.bCanSaveInGarage; }
void SetCanSaveInGarage(bool val) { m_nVehicleFlags.bCanSaveInGarage = val; }
void SetAnimateWheels(bool val) { m_nVehicleFlags.bAnimateWheels = val; }
bool GetAnimateWheels() const { return m_nVehicleFlags.bAnimateWheels; }
void SetAnimatePropellers(bool val) { m_nVehicleFlags.bAnimatePropellers = val; }
bool GetAnimatePropellers() const { return m_nVehicleFlags.bAnimatePropellers; }
void SetClearWaitingOnCollisionOnPlayerEnter( bool val ) { m_bClearWaitingOnCollisionOnPlayerEnter = val; }
bool GetClearWaitingOnCollisionOnPlayerEnter() { return m_bClearWaitingOnCollisionOnPlayerEnter; }
protected:
// Used in wheel setup to calculate the offset of iCurrentWheel relative to iFrontId and iRearId
// Returns a value between -1.0f and 1.0f
// 1.0f = front of car
// -1.0f = rear of car
// 0.0f = exact centre
float CalcFrontRearSelector(eHierarchyId iCurrentWheel, eHierarchyId iFrontId, eHierarchyId iRearId);
SuspensionType GetSuspensionType(bool bRearSuspension) const;
virtual bool PlaceOnRoadAdjustInternal(float UNUSED_PARAM(HeightSampleRangeUp), float UNUSED_PARAM(HeightSampleRangeDown), bool UNUSED_PARAM(bJustSetCompression)) { return false; }
virtual u32 GetMainSceneUpdateFlag() const;
virtual u32 GetStartAnimSceneUpdateFlag() const;
// Used to toggle wheel contact on and off
void SetEnableWheelContacts(bool enableContacts);
// Finding wheels by ID
void InitCacheWheelsById();
void ClearCacheWheelsById();
CWheel* GetWheelFromIdFromArray(eHierarchyId nId);
const CWheel* GetWheelFromIdFromArray(eHierarchyId nId) const;
bool GetHasLandingGear();
#if __WIN32PC
virtual void ProcessForceFeedback();
#endif // __WIN32PC
void ProcessVehicleCollision(CVehicle* pOtherVehicle);
//////////////////////////////////////////////////////////////////////////
// Seat interface
public:
const CSeatManager* GetSeatManager() const {return &m_SeatManager;}
// Quick accessors to the seat animation info
// Because they are used all over
const CVehicleSeatAnimInfo* GetSeatAnimationInfo(const CPed* pPed) const;
const CVehicleSeatAnimInfo* GetSeatAnimationInfo(s32 iSeatIndex) const;
const CVehicleSeatInfo* GetSeatInfo(const CPed* pPed) const;
const CVehicleSeatInfo* GetSeatInfo(s32 iSeatIndex) const;
const CVehicleEntryPointAnimInfo* GetEntryAnimInfo(s32 iEntryPointIndex) const;
const CVehicleEntryPointInfo* GetEntryInfo(s32 iEntryPointIndex) const;
const CVehicleLayoutInfo* GetLayoutInfo() const;
const CPOVTuningInfo* GetPOVTuningInfo() const;
const CVehicleCoverBoundOffsetInfo* GetVehicleCoverBoundOffsetInfo() const;
void ResetSeatManagerForReuse();
void ResetExclusiveDriverForReuse();
bool IsSeatIndexValid(s32 iSeatIndex) const { return iSeatIndex >= 0 && iSeatIndex < m_SeatManager.GetMaxSeats(); }
bool IsEntryIndexValid(s32 iEntryIndex) const;
// Do we have at least one entry we can use to get to this seat
bool CanSeatBeAccessedViaAnEntryPoint(s32 iSeatIndex) const;
CSeatAccessor::SeatAccessType GetSeatAccessType(s32 iSeatIndex) const;
bool IsTurretSeat(s32 iSeatIndex) const;
s32 GetFirstTurretSeat() const;
s32 GetDriverSeat() const;
__forceinline CPed* GetDriver() const { return m_SeatManager.GetDriver(); }
CPed* GetLastDriver() const;
void SetLastDriverFromNetwork(CPed *pPed) { m_SeatManager.SetLastDriverFromNetwork(pPed); }
// Add ped in the given seat
bool AddPedInSeat(CPed *pPed, s32 iSeat, bool bTestConversionCollision = true, bool bShouldApplyForce = true);
// Remove the ped from the seat
void RemovePedFromSeat(CPed *pPed, bool bChangeCarStatus = true, bool bDestroyWeaponMgr = true);
// Notify that a ped in this vehicle has changed into / from a player
void ChangePedsPlayerStatus(const CPed &pPed, bool bBecomingPlayer) { m_SeatManager.ChangePedsPlayerStatus(pPed,bBecomingPlayer); }
s32 GetDirectEntryPointIndexForPed(const CPed* pPed) const;
s32 GetDirectEntryPointIndexForSeat(s32 iSeat) const;
s32 GetIndirectEntryPointIndexForSeat(s32 iSeat) const;
s32 ChooseAppropriateJumpOutDirectEntryPointIndexForTurretDirection(s32 iSeat) const;
s32 ChooseAppropriateEntryPointForOnBoardJack(const CPed& rPed, s32 iSeat) const;
s32 FindSeatIndexForFirstHatchEntryPoint() const;
// For allowing scripts to control whether peds should fall off bikes / quads after a hard fall.
void SetAllowKnockOffVehicleForLargeVertVel(bool bValue) { m_nVehicleFlags.bAllowKnockOffVehicleForLargeVertVel = bValue; }
void SetVelocityThresholdBeforeKnockOffVehicle(float fValue) { m_fVerticalVelocityToKnockOffThisBike = fValue; }
float GetVelocityThresholdBeforeKnockOffVehicle() const { return m_fVerticalVelocityToKnockOffThisBike; }
const Vector3 & GetSuperDummyVelocity() const { return m_vSuperDummyVelocity; }
void SetSuperDummyVelocity(const Vector3& vVelocity);
void SetVelocityFromSuperDummyVelocity();
void RestoreVelocityFromInactivePlayback();
void SetForwardSpeed(float fSpeed);
void SetForwardSpeedXY( float fSpeed );
void SetSpeedToRestoreAfterFix(float fSpeed) { m_fSpeedToRestoreAfterFix = fSpeed; };
u8 GetNumInternalWindshieldHits() const {return m_nNumInternalWindshieldHits;}
void AddInternalWindshieldHit() {m_nNumInternalWindshieldHits++;}
u8 GetNumInternalWindshieldRearHits() const {return m_nNumInternalWindshieldRearHits;}
void AddInternalWindshieldRearHit() {m_nNumInternalWindshieldRearHits++;}
bool GetIsShelteredFromRain();
bool HasCollisionLoadedAroundVehicle();
// Legacy
// Gets max number of passengers for the vehicle
s32 GetMaxPassengers() const {return m_SeatManager.GetMaxSeats() > 0 ? m_SeatManager.GetMaxSeats()-1 : 0; }
// Add driver/passenger if one doesn't exist
CPed* SetUpDriver(bool bUseExistingNodes = false, bool canLeaveVehicle = true, u32 desiredModel = fwModelId::MI_INVALID, const CAmbientModelVariations* variations = NULL);
CPed* SetupPassenger(s32 seat_num, bool canLeaveVehicle = true, u32 desiredModel = fwModelId::MI_INVALID, const CAmbientModelVariations* variations = NULL);
// Swat Specific Setup
CPed* SetUpSwatDriver(bool bUseExistingNodes = false, bool canLeaveVehicle = true, u32 desiredModel = fwModelId::MI_INVALID);
CPed* SetupSwatPassenger(s32 seat_num, bool canLeaveVehicle = true, u32 desiredModel = fwModelId::MI_INVALID);
bool IsDriver(const CPed* pPed) const;
bool IsDriver(u32 iModelIndex) const;
// Animation
void InitAnimLazy();
void SetDriveMusclesToAnimation(bool bDriveMuscles) {m_nVehicleFlags.bDriveMusclesToAnim = bDriveMuscles;}
void NotifyPassengersOfRadioTrackChange();
bool GetHasBeenSeen() {return m_nVehicleFlags.bHasBeenSeen;}
bool GetIsInReusePool() const { return m_nVehicleFlags.bIsInVehicleReusePool; }
void SetIsInReusePool(bool isInReuse) { m_nVehicleFlags.bIsInVehicleReusePool = isInReuse;}
#if __BANK
bool GetWasReused() const { return m_nVehicleFlags.bWasReused; }
void SetWasReused(bool reused) { m_nVehicleFlags.bWasReused = reused;}
void LogPretendOccupantsFail() const;
void DrawDownforceDebug();
void DrawQADebug();
#endif // __BANK
u32 GetNpcHashForDriver(u32 driverModelIndex) const;
const Vector3& GetParentCargenPos() const { return m_parentCargenPos; }
void SetParentCargenPos(const Vector3& pos) { m_parentCargenPos = pos; }
#if ENABLE_FRAG_OPTIMIZATION
bool GetHasFragCacheEntry() const { return m_nVehicleFlags.bHasFragCacheEntry; }
void TryToReleaseFragCacheEntry();
void GiveFragCacheEntry(bool lock = false);
#endif
#if __ASSERT
bool IsVehicleAllowedInMultiplayer() const;
#endif /* __ASSERT */
static bool IsTypeAllowedInMP(u32);
bool GetNoDamageFromExplosionsOwnedByDriver() const { return m_bNoDamageFromExplosionsOwnedByDriver; }
void SetNoDamageFromExplosionsOwnedByDriver(bool bNoDamage) { m_bNoDamageFromExplosionsOwnedByDriver = bNoDamage; }
// B*2425992: Vehicle occupants will take explosive damage even if the vehicle is flagged as not damaged by anything/explosion proof.
bool GetVehicleOccupantsTakeExplosiveDamage() const { return m_bVehicleOccupantsTakeExplosiveDamage; }
void SetVehicleOccupantsTakeExplosiveDamage(bool bVehOccupantsTakeExplosiveDamage) { m_bVehicleOccupantsTakeExplosiveDamage = bVehOccupantsTakeExplosiveDamage; }
bool GetCanEjectPassengersIfLocked() const { return m_bCanEjectPassengersIfLocked; }
void SetCanEjectPassengersIfLocked(bool bCanEjectPassengersIfLocked) { m_bCanEjectPassengersIfLocked = bCanEjectPassengersIfLocked; }
bool GetVehicleAllowHomingMissleLockOnSynced() const { return m_bAllowHomingMissleLockOnSynced; }
void SetVehicleAllowHomingMissleLockOnSynced(bool bAllowHomingMissleLockOn) { m_bAllowHomingMissleLockOnSynced = bAllowHomingMissleLockOn; }
// Allow script to disable the damage reduction multiplier we apply in MP when attacking a vehicle containing a player
bool GetUseMPDamageMultiplierForPlayerVehicle() const { return m_bUseMPDamageMultiplierForPlayerVehicle; }
void SetUseMPDamageMultiplierForPlayerVehicle(bool bUseMultiplier) { m_bUseMPDamageMultiplierForPlayerVehicle = bUseMultiplier; }
// Allow script force a vehicle to explode when hitting zero body health with explosive damage (used in CVehicleDamage::ApplyDamageToBody).
bool GetShouldVehicleExplodesOnExplosionDamageAtZeroBodyHealth() const { return m_bShouldVehicleExplodesOnExplosionDamageAtZeroBodyHealth; }
void SetShouldVehicleExplodesOnExplosionDamageAtZeroBodyHealth(bool bShouldExplode) { m_bShouldVehicleExplodesOnExplosionDamageAtZeroBodyHealth = bShouldExplode; }
bool IsEnteringInsideOrExiting();
void AddLight(eLightType type, s32 boneIdx, const ConfigLightSettings &lightParam, float distFade);
float GetSlowDownBoostDuration(){ return m_fSlowdownDuration; }
float GetBoostAmount(){ return mf_BoostAmount; }
float GetSpeedUpBoostDuration(){ return mf_BoostAppliedTimer; }
void SetBeastVehicle( bool beastVehicle ) { m_BeastVehicle = beastVehicle; }
bool GetIsBeastVehicle(){ return m_BeastVehicle; }
void SetRampOrRammingAllowed( bool rampOrRammingAllowed ) { m_RampOrRammingAllowed = rampOrRammingAllowed; }
bool GetRampOrRammingAllowed() { return m_RampOrRammingAllowed; }
void SetEasyToLand( bool easyToLand ) { m_easyToLand = easyToLand; }
void SetScriptRammingImpulseScale( float scale ) { m_ScriptRampImpulseScale = scale; }
float GetScriptRammingImpulseScale() { return m_ScriptRampImpulseScale; }
void InitialiseModCollision();
void SetParachuteModelOverride( u32 uModelHash ) { m_ParachuteModelHash = uModelHash; }
u32 GetParachuteModelOverride() { return m_ParachuteModelHash; }
//////////////////////////////////////////////////////////////////////////
// Emblem material interface.
void SetEmblemMaterialGroup(bool isLocalPlayer) const { m_EmblemMaterialGroup = isLocalPlayer ? 1 : 0; }
void ClearEmblemMaterialGroup() const { m_EmblemMaterialGroup = 0; }
bool IsLocalPlayerEmblemMaterialGroup() const { return m_EmblemMaterialGroup == 1; }
//////////////////////////////////////////////////////////////////////////
bool ProcessBoostPadImpact( phCachedContactIterator& impacts, CEntity* pOtherEntity );
void UpdateWeaponBones(const CVehicleWeaponBattery* pBattery, const int* weaponBoneIndex, bool bScaleIndividualWeaponBones = false, bool bRotateGrillBone = false, float hiddenOffset = 0.11f, float fGrillOpenOffset = 0.07f, float fRackOpenOffset = 0.1f, float fGrillOpenRotation = 28.0f);
void UpdateWeaponBatteryBones();
void UpdateMissileFlapBonesOld(CVehicleWeaponBattery* pBattery, s32 iBatteryAmmo);
void UpdateMissileFlapBones(CVehicleWeaponBattery* pBattery);
void UpdateMissileBatteryState(CVehicleWeaponBattery* pBattery, s32 iLastFiredMissile);
float UpdateMissileFlapStateAndGetDesiredRotation(s32 i, s32 iLastFiredMissile, float fullyOpenFlapRotation, float openingRotation, float closingRotation, CVehicleWeaponBattery* pBattery);
// static vehicle functions
public:
static void InitSystem();
static void ShutdownSystem();
// a static version of GetHeightAboveRoad so we can calculate the vehicle's matrix on the road before it's actually created
static void CalculateHeightsAboveRoad(fwModelId, float *pFrontHeight, float *pRearHeight);
static void UpdateVisualDataSettings();
static void StartAiUpdate(CVehicle* pVehicle);
static void StartAiUpdate();
static void PreGameWorldAiUpdate(CVehicle* pVehicle, const bool bFullUpdate);
static void PreGameWorldAiUpdate();
static void FinishAiUpdate(CVehicle* pVehicle, const bool bFullUpdate);
static void FinishAiUpdate();
static void UpdateLightsOnFlagsForAllVehicles();
static void ProcessAfterCameraUpdate();
static void ProcessPostVisibility();
void UpdateInSpatialArray();
static CVehicle* GetVehicleFromSpatialArrayNode(CSpatialArrayNode* node)
{
return reinterpret_cast<CVehicle*>( reinterpret_cast<char*>(node) - OffsetOf(CVehicle, m_spatialArrayNode) );
}
static const CVehicle* GetVehicleFromSpatialArrayNode(const CSpatialArrayNode* node)
{
return reinterpret_cast<const CVehicle*>( reinterpret_cast<const char*>(node) - OffsetOf(CVehicle, m_spatialArrayNode) );
}
CSpatialArrayNode& GetSpatialArrayNode() { return m_spatialArrayNode; }
const CSpatialArrayNode& GetSpatialArrayNode() const { return m_spatialArrayNode; }
static CSpatialArray& GetSpatialArray() { return *ms_spatialArray; }
static void SetLightsCutoffDistanceTweak(float tweak) { ms_fLightCutoffDistanceTweak = tweak; }
static float GetLightsCutoffDistanceTweak() { return ms_fLightCutoffDistanceTweak; }
static void RequestHdForVehicle(CVehicle* veh) { ms_requestedHdVeh = veh; ms_lastTimeRequestedHd = fwTimer::GetTimeInMilliseconds(); }
#if __DEV
static void PoolFullCallback(void* pItem);
#endif // __DEV
static bool TooManyVehicleBreaksRecently() { return ms_VehicleBreaksPerSecond >= ms_MaxVehicleBreaksPerSecond; }
static float GetNumVehicleBreaksPerSecond() { return ms_VehicleBreaksPerSecond; }
static void RegisterVehicleBreak();
static void UpdateVehicleBreaksPerSecond();
static float GetDayNightFade();
static float GetLightOffValue(s32 light, float dayNightFade);
static void SetCanEnterLockedForSpecialEditionVehicles(bool bCanEnter) { ms_CanEnterLockedForSpecialEditionVehicles = bCanEnter; }
static bool GetCanEnterLockedForSpecialEditionVehicles() { return ms_CanEnterLockedForSpecialEditionVehicles; }
static void SetDisableHDVehicles(bool disableHDVehicles = true) { ms_DisableHDVehicles = disableHDVehicles; }
static bool GetConsumePetrol() { return m_consumePetrol; }
static void SetConsumePetrol(bool value) { m_consumePetrol = value; }
static bool IsInsideVehicleModeEnabled() { return (ms_insideVehicleMode > 0); }
static bool IsInsideSpecificVehicleModeEnabled(u32 vehicleHash) { return (ms_insideVehicleMode == vehicleHash); }
static void SetBobbleHeadVelocity( Vec3V& velocity );
void ProcessBoostPhysics( float fTimeStep );
float GetSideShuntForce() const { return m_sideShuntForce; }
//float GetForwardShuntForce() const { return m_fowardShuntForce; }
bool GetHitBySideShunt() const { return m_hitBySideShunt; }
CVehicle* GetLastSideShuntVehicle() const { return m_lastSideShuntVehicle; }
void SetHitBySideShunt( bool hit, CVehicle* sideShuntVehicle ) { m_hitBySideShunt = hit; m_lastSideShuntVehicle = sideShuntVehicle; }
bool GetHitByWeaponBlade() const { return m_hitByWeaponBlade; }
void SetHitByWeaponBlade( bool hit ) { m_hitByWeaponBlade = hit; }
CWeaponBlade& GetWeaponBlade(int bladeIdx) { return m_weaponBlades[bladeIdx]; }
void SetOverrideNitrousLevel(bool overrideNitrous);
void SetOverrideNitrousLevel(bool overrideNitrous, float durationModOverride, float powerModOverride, float rechargeRateModOverride, bool disableDefaultSound = false);
bool GetOverrideNitrousLevel() { return m_scriptOverridesNitrous.isOverrideActive; }
bool GetOverrideNitrousSound() { return m_scriptOverridesNitrous.disableDefaultSound; }
void FullyChargeNitrous();
void ClearNitrous();
int GetNumWeaponBlades() { return m_numWeaponBlades; }
void ApplyWeaponBladeWheelImpacts( CWheel* wheel, int hitComponent );
void DetachTombstone();
void HideTombstone( bool hide );
bool HasTombstone() const;
protected:
bool IsAnimated();
void ProcessRocketBoost();
bool CanToggleRocketBoost();
u32 GetBoostToggleTime() {return m_boostToggledTime;}
private:
static void CalculateRumbleFrequencies( s32& freq0, s32& freq1, phRumbleProfile* rumbleProfile, float rumbleMult, float velFreqScale, float velModifier, bool bIgnoreVelocityForRumble );
void UpdateBobbleHead( int boneIndex, eBobbleHeadType type );
static CBobbleHead* GetBobbleHead( CVehicle* pVehicle, eBobbleHeadType type );
static CBobbleHead* AddBobbleHead( CVehicle* pVehicle, eBobbleHeadType type );
void ApplyBeastModeToImpacts( phCachedContactIterator& impacts );
CVehicle* FindRammingScoopVehicle( phCachedContactIterator& impacts );
void ApplyRammingScoopToImpact( CVehicle* pOtherVehicle, phCachedContactIterator& impacts );
void ApplyRammingBarToImpact( CPhysical* pOtherEntity, phCachedContactIterator& impacts );
void UpdateInvMassForRammingBarImpacts( phCachedContactIterator& impacts );
CVehicle* FindRampVehicle( phCachedContactIterator& impacts );
void ModifyPedImpacts( phCachedContactIterator& impacts );
bool ShouldApplyRampToImpact( CVehicle* pRampCar, CVehicle* pOtherVehicle, Vec3V& rampCarNormal );
void ApplyRampToImpacts( CVehicle* pOtherVehicle, phCachedContactIterator& impacts );
void ProcessBoostVFX();
void ProcessRamBarVFX();
void ProcessWeapons();
void ProcessNitrousControl();
void UpdateBladeRpmOnEngineOff();
void ApplySpikeImpacts( phCachedContactIterator& impacts, CEntity* otherEntity );
void ApplySpikeDamageToPed( CPed* pPed, Vec3V& pedNormal, float vehicleVelocity );
void ApplySpikeDamageToVehicle( CVehicle* pOtherVehicle, int otherComponent, Vec3V& normal, float vehicleVelocity );
void ProcessCarJump();
void ProcessVehiclePumpedUpJump( float fTimeStep );
void ProcessTombstone();
CVehicle* CheckForSideShuntImpact( phCachedContactIterator& impacts, CVehicle* otherVehicle );
// Rocket boost //////////////////////////////
// Boost state flag
bool m_bIsRocketBoosting;
bool m_bRocketBoostedFromNetwork;
bool m_bRocketBoostedStoppedFromNetwork;
bool m_bCanRechargeRocketBoost;
bool m_bTriggerRefillBoostEffect;
bool m_bHasRocketBoostFXStarted;
// Remaining boost
float m_fRocketBoostRemaining;
// Rocket boost recharge rate
float m_fRocketBoostRechargeRate;
u32 m_boostToggledTime;
// End Rocket boost //////////////////////////
bool m_nitrousActive;
ScriptOverridesNitrous m_scriptOverridesNitrous;
// Place on road probe heights ///////////////
float m_fOverridenPlaceOnRoadHeight;
bool m_bHomingCanLockOnToObjects; // Flags whether the vehicle weapons can lock on to script flagged objects
// parachute params
u32 m_ParachuteModelHash;
void ProcessGlider();
void UpdateWingBones( float targetRatio, bool instant );
void ProcessGliderPhysics( float fTimeStep );
void ProcessHoverMode( float fTimeStep, float normalisedDeployedRatio, CSpecialFlightHandlingData* flightHandling, float fStickX, float fStickY );
void ProcessSpecialFlightMode();
void ProcessOutriggers();
void ProcessArenaMode();
void UpdateSideShunt( float fTimeStep );
void UpdateOutriggers( float fTimeStep );
EGliderState m_gliderState;
float m_wingDeployedRatio;
float m_specialFlightModeTargetRatio;
float m_targetGravityScale;
float m_previousNormalisedVelocity;
float m_previousThrottle;
float m_cachedStickYfromNetwork;
float m_currentWingRatio;
float m_scriptMaxSpeed;
bool m_disableHoverModeFlight;
bool m_destroyWeaponMgr;
bool m_hoveringCloseToGround;
bool m_forceFixLinkMatrices;
protected:
bool ProcessFoliageImpact( phInst* otherInstance, Vec3V myPosition, int myComponent, int otherComponent, int otherElement );
void ForceUpdateLinkMatrices();
float m_sideShuntForce;
// float m_fowardShuntForce;
float m_nozzleAngle;
float m_specialFlightModeRatio;
float m_outriggerRatio;
RegdVeh m_lastSideShuntVehicle;
bool m_deployOutriggers;
bool m_hitBySideShunt;
bool m_shuntModifierActive;
bool m_hitByWeaponBlade;
public:
void StartGliding();
void FinishGliding();
void StartGlidingInstant();
void FinishGlidingInstant();
void SetDisableHoverModeFlight( bool disable ) { m_disableHoverModeFlight = disable; }
bool GetDisableHoverModeFlight() const { return m_disableHoverModeFlight; }
bool GetAreOutriggersFullyDeployed() const { return m_outriggerRatio == 1.0f; }
float GetOutriggerDeployRatio() const { return m_outriggerRatio; }
void SetDeployOutriggers( bool deploy );
bool GetAreOutriggersBeingDeployed() const { return m_deployOutriggers; }
bool HoveringCloseToGround() const { return m_hoveringCloseToGround; }
void SetFixLinkMatrices() { m_forceFixLinkMatrices = true; }
void SetShuntLeftFromNetwork() { m_sideShuntForce = -SIDE_SHUNT_DURATION; m_VehicleAudioEntity->TriggerSideShunt(); }
void SetShuntRightFromNetwork() { m_sideShuntForce = SIDE_SHUNT_DURATION; m_VehicleAudioEntity->TriggerSideShunt(); }
// Car jump //////////////////////////////////////
// Available jump states
enum ECarJumpState
{
NOT_JUMPING,
JUMPING,
IN_AIR_STABILISATION,
//FORWARD_JUMP,
//BACKWARDS_JUMP,
HOVER_CAR_END
};
private:
// Tracks the current state of the jump
ECarJumpState m_carJumpState;
// Flag accessible to the world to start/cancel jump
bool m_bDoingJump;
//bool m_bDoingForwardJump;
// Timer used for transitioning between jump states
float m_fCarJumpTimer;
// Ground normal for measuring angles to stabilise vehicle mid-jump
Vector3 m_vCarJumpGroundNormal;
public:
// Jump recharge time
static bank_float ms_fJumpRechargeTime;
ECarJumpState GetJumpState() { return m_carJumpState; }
void SetJumpState( ECarJumpState jumpState ) { m_carJumpState = jumpState; }
// Car jump state accessor/mutator
bool GetIsDoingJump() { return m_bDoingJump; }
void SetIsDoingJump( bool bNewValue ) { m_bDoingJump = bNewValue; }
//void SetIsDoingForwardJump( bool bNewValue ) { m_bDoingForwardJump = bNewValue; }
//bool GetIsDoingForwardJump() { return m_bDoingForwardJump; }
bool CanTriggerForwardJump();
bool IsJumpFullyCharged() const { return m_fJumpRechargeTimer >= ms_fJumpRechargeTime; }
f32 GetJumpRechargeFraction() const { return Clamp( m_fJumpRechargeTimer / ms_fJumpRechargeTime, 0.f, 1.0f ); }
void SetDoHigherJump( bool bNewValue ) { m_bDoHigherJump = bNewValue; }
void SetJumpRechargeTimer( f32 recharge ) { m_fJumpRechargeTimer = recharge; }
f32 GetJumpRechargeTimer() { return m_fJumpRechargeTimer; }
void RechargeJumpTimer() { m_fJumpRechargeTimer = ms_fJumpRechargeTime; }
// Updates the recharge bar on the jumping car
void UpdateJumpingCarRechargeTimer();
CObject* GetDetachedTombStone() { return m_detachedTombstone; }
const CObject* GetDetachedTombStone() const { return m_detachedTombstone; }
private:
// Jump recharge timer
float m_fJumpRechargeTimer;
// Extra jump strength, to be set by script and used on missions
bool m_bDoHigherJump;
// End car jump //////////////////////////////////
public:
void TriggerPumpedUpJump( float fHeightScale );
// NEW JUMP FOR COPS AND CROOKS PUMPED UP ABILITY
// Available jump states
enum EPumpedUpJumpState
{
PUMPED_UP_JUMP_IDLE,
PUMPED_UP_JUMP_BEGIN,
PUMPED_UP_JUMP_COMPRESS_SUSPENSION = PUMPED_UP_JUMP_BEGIN,
PUMPED_UP_JUMP_EXTEND_SUSPENSION,
PUMPED_UP_JUMP_ACCELERATE, // might not need this state
PUMPED_UP_JUMP_END,
};
private:
EPumpedUpJumpState m_pumpedUpJumpState;
float m_fInitialSuspensionRaiseRate;
float m_fPumpedUpJumpTimer;
float m_fJumpHeightScale;
//////////////////////////////////////////////////////////////////////////
// Member variables
public:
// PURPOSE: Timesliced update interpolation target position (XYZ) and time (W) in seconds to get there.
Vec4V m_InterpolationTargetAndTime;
// PURPOSE: Timesliced update interpolation target orientation, as a quaternion.
QuatV m_InterpolationTargetOrientation;
// PURPOSE: When interpolating in timesliced mode, this is the current orientation,
// stored off so we don't have to recompute it from the matrix.
QuatV m_InterpolationCurrentOrientation;
//these are used to re-create trailer attachments
//when converting from superdummy mode
Vector3 m_vParentTrailerEntity1Offset;
Vector3 m_vParentTrailerEntity2Offset;
Quaternion m_qParentTrailerEntityRotation;
CVehicleDamage m_VehicleDamage;
CTransmission m_Transmission;
CHandlingData* pHandling;
CVehicleFlags m_nVehicleFlags;
// PURPOSE: Time passed since the last full AI update, in seconds. Used to compute
// the proper update time step during AI timeslicing.
float m_fTimeSinceLastAiUpdate;
u32 m_iNumTimeslicedUpdatesSkipped;
audVehicleAudioEntity* m_VehicleAudioEntity;
audPlaceableTracker m_PlaceableTracker;
fragInstGta* m_pVehicleFragInst;
phInstGta* m_pDummyInst;
float m_fParentTrailerAttachStrength;
float m_fSteerInput; // input from controller
float m_fSteerInputBias;// the amount by which the input from controller is biased (to be used by script to modify the controls)
CVehControls m_vehControls;
u32 m_uHandbrakeOnTime; // When was the handbrake pressed. Used to envelope handbrake after press
bool m_bInvertControls;
// population / creation / dummy
s16 m_CarGenThatCreatedUs;
s16 m_ExtendedRemovalRange;
u32 m_TimeOfCreation; // GetTimeInMilliseconds when this vehicle was created.
//CVehicle* m_pNextVehOnSamePathLink;
u32 m_delayedRemovalResetTimeMs;
u32 m_delayedRemovalAmountMs;
u32 m_LastTimeWeHadADriver; // Can be used to remove certain vehicles if they haven't had a driver for a while. (0 Means:never had a driver at all)
u32 m_dummyConvertAttemptTimeMs;
u32 m_realConvertAttemptTimeMs;
u32 m_nRealVehicleIncludeFlags;
u32 m_nCloneFlaggedForWreckedOrEmptyDeletionTime;
// rendering / effects
s32 m_Swankness;
float m_fBodyDirtLevel; // Dirt level of vehicle body texture: 0.0f=fully clean, 15.0f=maximum dirt visible, it may be altered at any time while vehicle's cycle of lige
Color32 m_bodyDirtColor;
// lights
CVehicleLightSwitch m_VehicleLightSwitch;
u32 m_FlashHeadLights; // Time at which we will stop flashing our headlights.
u32 m_TimeFullBeamSwitchedOn; // When were the beam lights switched on.
u32 m_KeepLightsOnForWeatherTime;
float m_HeadlightMultiplier;
u8 m_OverrideLights : 3; // uses enum NO_CAR_LIGHT_OVERRIDE, FORCE_CAR_LIGHTS_OFF, FORCE_CAR_LIGHTS_ON, SET_CAR_LIGHTS_OFF, SET_CAR_LIGHTS_ON
u8 m_HeadlightShadows : 2; // uses bit flags HEADLIGHTS_CAST_DYNAMIC_SHADOWS, HEADLIGHTS_CAST_STATIC_SHADOWS, HEADLIGHTS_CAST_FULL_SHADOWS
u8 m_AmbientScaleOverriden : 1;
u8 m_bInteriorLightForceOn : 1; // Force interior lights to be on (like m_nVehicleFlags.bInteriorLightOn, but ignores day/night fade)
u8 m_padding : 1;
bool m_usePlayerLightSettings;
u8 m_prevNaturalAmbientScale;
u8 m_prevArtificialAmbientScale;
// misc
u32 m_nFixedWaitingForCollisionCheckTimer;
CEntity::eHomingLockOnState m_eHomingLockOnState; // Is this vehicle locked onto a target? - Value gets reset every frame and set by other systems
CEntity::eHomingLockOnState m_eHomingLockedOntoState; // Is something locked onto this vehicle? - Value gets reset every frame and set by other systems
float m_fTargetableDistance; // The los targeting checks for lock on pass within this distance
float m_fHomingProjectileDistance; // The distance to the closest homing projectile
s8 m_nHomingLockOnStateResetFrame; // Number of frames before the lock on state is reset
s8 m_nHomingLockedOntoStateResetFrame; // Number of frames before the lock on state is reset
s8 m_nHomingProjectileDistanceResetFrame; // Number of frames before the lock on distance is reset
u8 m_AirResistanceState; // Used to reduce work we have to do for AI vehicles in UpdateAirResistance().
u32 m_uLastTimeHomedAt; // Last time a homing projectile was aimed at this vehicle.
RegdPhy m_pLockOnTarget; // The object being targetted
RegdPhy m_pGroundPhysical; // Ground physical used when wheels aren't touching the ground (i.e. when vehicle is flipped)
u32 m_uGroundPhysicalTime; // Time ground physical was registered
u32 m_iFullThrottleRecoveryTime; // Time until the Full Throttle effect stops being applied
bool m_bFullThrottleActive; // Time until the Full Throttle effect stops being applied
RegdPed m_pExclusiveDriverPeds[MAX_NUM_EXCLUSIVE_DRIVERS]; // If set, only these peds can drive this vehicle.
u32 m_wheelBrokenIndex;
float m_fFrictionOverride;
float m_fDragCoeff;
float m_EngineTemperature; // Between ambient temperature and 100 degrees. Affects engine starting.
u32 m_EngineSwitchedOnTime; // This is in place until the audio scripts take over the responsibility of switching on the engine
// bit masks for the different extra rules setups
u32 m_nDisableExtras;
static u32 ms_nExtrasMasks[EXTRAS_MASK_NUM_MASKS];
// last activation
u32 m_iLastActivationTime;
u32 m_iNextValidHornTime;
static Vector3 smVecSelfRightBiasCGOffset;
static bool sm_bUseNewSelfRighting;
static bool sm_bEnableHeadlightShadows;
static bool sm_bEnableSirenShadows;
static bool sm_bJetWashEnabled;
static bool sm_bDisableExplosionDamage;
static bool sm_bDisableWeaponBladeForces;
static bool sm_bDoubleClickForJump;
//static bool sm_bInDetonationMode;
//static bool sm_bShuntOnStick;
bool m_bProducingSlipStreamForOther;
ObjectId m_VehicleProducingSlipstream;
float m_fTimeInSlipStream;
float m_fTimeProducingSlipStream;
float m_fSlipStreamRechargeAndDechargeTimer;
float m_fTimeInAir;
float m_fTimeInAirCrash;
float m_fTimeTouchingPavement;
float m_fSpeedToRestoreAfterFix;
float m_fPreviousSpeedForDash;
u32 m_dialsRequestFrame;
u16 CarAlarmState;
u8 m_failedEngineStartAttempts;
bool m_failNextEngineStartAttempt;
bool m_bInAirCrash;
bool m_bAllowRemoteDamageOnCreation;
bool m_bNoDamageFromExplosionsOwnedByDriver;
bool m_pedRemoteUsingDoor;
bool m_remoteDriverDoorClosing;
bool m_forceLightsOnAtNightRandomisationTime;
bool m_forceLightsOffAtMorningRandomisationTime;
bool m_bSuppressNeons;
bool m_bVehicleOccupantsTakeExplosiveDamage;
bool m_bCanEjectPassengersIfLocked;
bool m_bAllowHomingMissleLockOnSynced;
bool m_bSpecialEnterExit;
bool m_bDontProcessVehicleGlass;
bool m_bTyresDontBurstToRim;
bool m_bDriftTyres; // Sets the tyres to be easier to drift with
bool m_bUseDesiredZCruiseSpeedForLanding;
bool m_bDontResetTurretHeadingInScriptedCamera;
bool m_bDontOpenRearDoorsOnExplosion;
bool m_bOnlyStartVehicleEngineOnThrottle;
bool m_bClearWaitingOnCollisionOnPlayerEnter;
bool m_bUseMPDamageMultiplierForPlayerVehicle;
bool m_bShouldVehicleExplodesOnExplosionDamageAtZeroBodyHealth;
bool m_bBlockDueToEnterExit;
bool m_bDisablePlayerCanStandOnTop;
bool m_bSubmarineCarTransformPrevented;
bool m_bDisableWantedConesResponse;
bool m_bHasDeformationBeenApplied;
fwUniqueObjId m_iPrevSpeedBoostObjectID;
fwUniqueObjId m_iCurrentSpeedBoostObjectID;
static dev_float FLIGHT_CEILING_PLANE;
static dev_float FLIGHT_MICROLIGHT_CEILING_PLANE;
static float ms_fFlightCeilingScripted;
// Air defence flag/explosion timer
bool m_bAirDefenceExplosionTriggered;
u32 m_uTimeAirDefenceExplosionTriggered;
float m_VehicleTopSpeedPercent;
float m_fOverrideArriveDistForVehPersuitAttack;
int m_LaunchedInAirTimer;
int m_ForcedMaximumUpdateRateTimer;
u32 m_kersToggledTime;
// debug
#if __DEV
phCollider *m_pDebugColliderDO_NOT_USE;
#endif
#if __BANK
static bool* GetConsumePetrolPtr() { return &m_consumePetrol; }
static bool m_bDebugVisPetrolLevel;
static void UpdateVehicleHandlingInfo(CVehicleModelInfo* pVehicleModelInfo);
bool GetCoordsAndAlphaForDebugText(Vector3 &vecReturnWorldCoors, u8 &ReturnAlpha) const;
static bool m_bDebugEngineTemperature;
static bool ms_bDebugWheelTemperatures;
static bool ms_bDebugWheelFlags;
static bool ms_bDebugIgnoreHoldGearWithWheelspinFlag;
static bool ms_bDebugVehicleHealth;
static bool ms_bDebugVehicleWeapons;
static bool ms_bDebugVehicleStatus;
static bool ms_bDebugVehicleIsDriveableFail;
static u32 ms_uZeroToSixtyStartTime;
static u32 ms_uZeroToSixtyEndTime;
static float ms_fBestZeroToSixtyTime;
static float ms_fBestSixtyToZeroTime;
static float ms_fHighestGForce;
#endif
#if USE_PHYSICAL_HISTORY
CPhysicalHistory m_physicalHistory;
#endif
Vec3V m_vecInitialSpawnPosition;
#if __BANK
ePopType m_CreationPopType;
#endif
float m_fDownforceModifierFront;
float m_fDownforceModifierRear;
protected:
// Cache all this at the beginning of the AI update so we can avoid recomputing it later
// This is a seperate struct in case we want to move it out of CVehicle at some point
struct CachedAiData
{
Vec4V m_VelocityAndXYSpeed;
};
CachedAiData m_CachedAiData;
Vector3 m_vecInternalForce;
Vector3 m_vecInternalTorque;
Vector3 m_vFoliageDragForce;
Vector3 m_vFoliageDragTorque;
// Velocity for superdummy (*only* used when CVehicleAiLodManager::ms_bDisablePhysicsInSuperDummyMode is true)
Vector3 m_vSuperDummyVelocity;
// Velocities for inactive vehicle that's following the playback
Vector3 m_vInactivePlaybackVelocity;
Vector3 m_vInactivePlaybackAngVelocity;
// The last position the object tried to generate cover at
Vector3 m_vLastCoverPosition;
// The last forward direction the object tried to generate cover at
Vector3 m_vLastCoverForwardDirection;
Vector3 m_parentCargenPos;
// veh ai
CVehicleIntelligence *m_pIntelligence;
CVehicleAILod m_vehicleAiLod;
VehicleType m_vehicleType;
// array of pointers to wheels
CWheel** m_ppWheels;
int m_nNumWheels;
u8 m_WheelIndexById[NUM_VEH_CWHEELS_MAX];
bool m_WheelsAreJustProbes;
//Need to make door array protected to make sure that doors are accessed by function by referencing either the
//eDoors enum or the hierarchyId enum.
CCarDoor *m_pDoors;
int m_nNumDoors;
bool m_bWindowsRolledDown[VEH_LAST_WINDOW-VEH_WINDSCREEN_R];
s32 m_iWindowComponent[VEH_LAST_WINDOW - VEH_FIRST_WINDOW + 1];
CVehicleWeaponMgr* m_pVehicleWeaponMgr;
atArray<CVehicleGadget*> m_pVehicleGadgets;
float m_fVerticalVelocityToKnockOffThisBike;
float m_fGravityForWheelIntegrator; // Use the SetGravityForWheelIntegrator function to set this.
CSeatManager m_SeatManager;
CComponentReservationManager m_ComponentReservationMgr;
// The last orientation the object tried to generate cover at
CoverOrientation m_eLastCoverOrientation;
// The last door intact status for generated cover
bool m_bLastCoverDoorIntactList[MAX_NUM_COVER_DOORS];
// The last door ratios for generated cover
float m_fLastCoverDoorRatioList[MAX_NUM_COVER_DOORS];
TDynamicObjectIndex m_iPathServerDynObjId;
// PURPOSE: Used between PreRender() and PreRender2() to ensure that we wait for eactly
// the animation updates we started.
bool m_StartedAnimDirectorPreRenderUpdate;
// Used for when a remotely owned quad bike toggles it's tuck in state for its wheels
bool m_bToggleTuckInWheelsFromNetwork;
// Allow script to set an ammo limit for a particular vehicle weapon
s32 m_iRestrictedAmmoCount[MAX_NUM_VEHICLE_WEAPONS];
// Network-synced ammo counts for bombs and countermeasures (can't be tied to a specific player)
s32 m_iBombAmmoCount;
s32 m_iCountermeasureAmmoCount;
RegdObj m_detachedTombstone;
#if __ASSERT
enum WhichVelFlags
{
EDIT_MODE_ACTIVE,
REPLAY_IS_LOADING,
HAS_COLLIDER,
DISABLE_SUPERDUMMY_PHYSICS,
IS_SUPERDUMMY,
IS_DOING_PLAYBACK,
};
atFixedBitSet32 m_WhichVelocityFlags; // TODO: Russ should delete this as soon as B* 1037671 and friends are resolved
#endif
#if __BANK
mutable const char *m_pNonConversionReasonString;
mutable const char *m_pLastVehPopRemovalFailReason;
mutable u32 m_iLastVehPopRemovalFailFrame;
#endif
#if !__FINAL
// Debug name that can be set from script and displayed to help designers debug problems.
char m_strDebugName[DEBUG_VEH_NAME_STRING_LENGTH];
#endif
CTrailer* m_parentTrailer;
CSpatialArrayNode m_spatialArrayNode;
friend class CSpatialArray;
#if __ASSERT
u32 m_notInWorldTimer;
#endif // __ASSERT
#if DEBUG_DRAW
public:
Vec3V m_vCreatedPos;
Vec3V m_vCreatedDir;
#endif
#if __BANK
public:
enum VehicleCreationMethod
{
VEHICLE_CREATION_RANDOM =0,
VEHICLE_CREATION_PATHS,
VEHICLE_CREATION_CARGEN,
VEHICLE_CREATION_CRIMINAL,
VEHICLE_CREATION_EMERGENCY,
VEHICLE_CREATION_SCRIPT,
VEHICLE_CREATION_TRAILER,
VEHICLE_CREATION_INVALID
};
VehicleCreationMethod m_CreationMethod;
u32 m_iCreationCost;
#endif
#if __BANK
public:
enum RealPedFailReason
{
RPFR_SUCCEEDED,
RPFR_IS_NET_CLONE,
RPFR_IS_NOT_NET_OBJECT,
RPFR_NET_OBJ_REGISTER_FAILED,
RPFR_PED_POOL_FULL,
RPFR_NO_FALLBACK_PED,
RPFR_ADD_POLICE_FAILED,
RPFR_NET_REQUEST_DRIVER_MODEL,
RPFR_NET_SET_UP_DRIVER,
RPFR_FILTERED_SETUP_DRIVER,
RPFR_UNFILTERED_SETUP_DRIVER,
RPFR_ADD_FOR_TRAIN,
RPFR_ADD_FOR_VEH
};
int m_RealPedFailReason;
static const char *GetRealPedFailReason(int realPedFailReason);
#endif // __BANK
private:
#if GTA_REPLAY
// During replay playback we don't have any physics instances to contain
// the vehicles velocity so store it here instead.
Vector3 m_replayVelocity;
//
u8 m_appliedVehicleDamage;
bool m_replayOverrideWheelsRot;
#endif // GTA_REPLAY
#if GPU_DAMAGE_WRITE_ENABLED
bool m_bDamageWasUpdatedByGPU;
bool m_bEnableDamage;
#endif
// Dummy attachments
RegdVeh m_DummyAttachmentParent;
atRangeArray<RegdVeh, MAX_CARGO_VEHICLES> m_DummyAttachmentChildren;
int m_nDummyAttachmentChildren;
phMaterialMgr::Id m_dummyMtlId; // the id of the material that the car is on (valid when this is a dummy and the wheels aren't active to query the material from)
sirenInstanceData* m_sirenData;
s32 m_iPrevCurrentMissile;
u32 m_iTimeLastVisible;
u32 m_nNumPixelsVisible;
u32 m_uRespottingCollisionCarPedFrameCount;
u32 m_uSecondaryRespotOverrideTimeout;
u32 m_nVehicleCheats;
float m_fCheatPowerIncrease;
float m_fDrivenDangerouslyTime;
float m_fLodMult;
#ifdef __BANK
public:
float m_fDebugCheatPowerIncrease;
private:
#endif
// lighting configuration
float m_timeLightsTurnOn;
float m_timeLightsTurnOff;
eVehicleLodState m_vehicleLodState;
//Destruction
DestructionInfo m_DestructionInfo;
eCarLockState m_eDoorLockState;
CNodeAddress m_StartNodes[2];
s16 m_StartLink;
u16 m_nNetworkRespotCounter; // when veh gets re-spotted in a network game, want to disable collisions with other network vehicles
s8 m_StartLane;
u8 m_nNumInternalWindshieldHits; //After shooting your own windshield too many times, it breaks
u8 m_nNumInternalWindshieldRearHits; //After shooting your own rear windshield too many times, it breaks
u8 m_lightingConfig;
u8 m_sirenConfig;
s8 m_clampedRenderLod;
bool m_bRespottingCollisionCarPed;
bool m_bFlashRemotelyDuringRespotting;
bool m_bFlashLocallyDuringRespotting;
static bool m_consumePetrol;
float m_triggerRumbleTime; // The amount of time the triggers have been continuously rumbling.
mutable u8 m_EmblemMaterialGroup : 1; // 0 no particular group, 1 local player.
u8 m_BeastVehicle : 1;
u8 m_RampOrRammingAllowed : 1;
ATTR_UNUSED u8 m_nUnused : 5;
float mf_BoostAppliedTimer;
float mf_BoostAmount;
float m_fSlowdownDuration;
float m_ScriptRampImpulseScale;
bool m_allowSpecialFlightMode;
public:
bool m_easyToLand;
bool m_forceUpdateBoundsAndBodyFromSkeleton;
bool m_hasHitRampCar;
bool m_disableRampCarImpactDamage;
bool m_applyRampCarSideImpulse;
bool m_normaliseRampHitVelocity;
bool m_activateBoostEffect;
bool m_resetBoostObjects;
//////////////////////////////////////////////////////////////////////////
// static vehicle members
static bool ms_forceActualVehicleLightsOff;
static dev_bool ms_forceVehicleLightsOff;
static dev_float ms_fVehicleSubmergeSleepGlobalZ;
static bank_bool ms_bUseAutomobileBVHupdate;
static bank_bool ms_bAlwaysUpdateCompositeBound;
static bank_float ms_fAOHeightCutoff;
// Foliage constants:
static bank_float ms_fFoliageVehicleDragCoeff;
static bank_float ms_fFoliageDragDistanceScaleCoeff;
static bank_float ms_fFoliageBoundRadiusScaleCoeff;
static bank_float ms_fMinVehicleSpeedForFoliageDrag;
static bank_float ms_fMaxAngAccel;
static dev_float ms_fVerticalVelocityToKnockOffVehicle;
static dev_float ms_fVerticalVelocityToKnockOffHoverBike;
static bank_float ms_fFoliageMaxDoorAccel;
static bank_float ms_fFoliageDoorForceScaleCoeff;
#if __DEV
static Vector3 ms_vFoliageDragForceAppliedThisFrame;
static float ms_fFoliageDragForceMagSqrAppliedThisFrame;
#endif // __DEV
#if HACK_GTA4_BOUND_GEOM_SECOND_SURFACE
static CPhysical::CSecondSurfaceConfig ms_vehicleSecondSurfaceConfig;
static CPhysical::CSecondSurfaceConfig ms_vehicleSecondSurfaceConfigLessSink;
#endif // HACK_GTA4_BOUND_GEOM_SECOND_SURFACE
// This number decreases as more cars start using wheel shapetests
static s32 ms_nNumAvailableShapetests;
static float ms_fLightCutoffDistanceTweak;
static bank_bool ms_bSuperLowLod_DisableCollisions;
static bank_bool ms_bSuperLowLod_DisableGravity;
static bank_bool ms_bWreckVehicleOnFirstExplosion;
static bank_float ms_fVehicleExplosionDelayMax;
static bank_float ms_fVehicleExplosionDelayMin;
static dev_float ms_fBicyclePavementVelocitySquaredThreshold;
static dev_float ms_fVehiclePavementVelocitySquaredThreshold;
static dev_float ms_fTimeTouchingPavementBeforeAddingEvent;
static const u32 MAX_NUM_DOOR_COMPONENTS = 8;
static eHierarchyId ms_aDoorComponentIds[MAX_NUM_DOOR_COMPONENTS];
static eHierarchyId ms_aBobbleHeadIds[ BHT_MAX ];
static CSpatialArray* ms_spatialArray;
static bank_float ms_fSpeedToStartSlipstream;
static bank_float ms_fSpeedToStartSlipstreamBoat;
static bank_float ms_fMaxSpeedOfSlipStream;
static bank_float ms_fSlipstreamMaxDragReduction;
static bank_float ms_fSlipstreamMaxDistance;
static bank_float ms_fSlipstreamMaxTime;
static bank_float ms_fSlipstreamMaxTimeBeforeBeingDisabled;
static bool ms_bSlipstreamApplyMaxTimeBeforeBeingDisabled;
static bank_bool ms_bRealisticSlipstreamMode;
static bank_float ms_fBikeGravityMult;
static bank_float ms_fQuadbikeGravityMult;
static bank_float ms_fOffRoadAbilityGravityMult;
static bank_float ms_fOffRoadAbility2GravityMult;
#if USE_SIXAXIS_GESTURES
// six-axis motion control multipliers
static bank_float ms_fDefaultMotionContolPitchMin;
static bank_float ms_fDefaultMotionContolPitchMax;
static bank_float ms_fDefaultMotionContolRollMin;
static bank_float ms_fDefaultMotionContolRollMax;
static bank_float ms_fDefaultMotionContolAftertouchMult;
static bank_float ms_fDefaultMotionContolSteerSmoothRate;
#endif // USE_SIXAXIS_GESTURES
static bank_bool ms_bForceBikeLean;
#if __BANK
static int ms_nVehicleDebug;
static float ms_fHydraulicSuspension;
static float ms_fForcedGroundClearance;
static bool ms_bForceSlowZone;
static bool ms_bPrecomputeExtraWheelBoundImpacts;
static bool ms_bVehicleDownforceDebug;
static bool ms_bVehicleQADebug;
static float ms_fVehicleDebugScale;
static bool ms_bDebugDrawRevRatio;
static bool ms_bDebugDrawSpeedRatio;
static bool ms_bDebugDrawDriveForce;
static bool ms_bDebugDrawClutchRatio;
static bool ms_bDebugDrawWheelSpeed;
static bool ms_bDebugDrawManifoldPressure;
static bool ms_bDebugDrawLargeText;
#if STENCIL_VEHICLE_INTERIOR
static bool ms_StencilOutInterior;
#endif // STENCIL_VEHICLE_INTERIOR
#endif
static const u32 ms_MaxNumVehicleBreaksInWindow = 200; // GetNumVehicleBreaksPerSecond is limited by sm_MaxNumVehicleBreaksInWindow/m_fVehicleBreakWindowSize so it may be necessary to increase this if m_fVehicleBreakWindowSize increases
static atQueue<u32,ms_MaxNumVehicleBreaksInWindow> ms_RecentVehicleBreakTimes;
static float ms_VehicleBreaksPerSecond;
static bank_float ms_MaxVehicleBreaksPerSecond;
static bank_u32 ms_VehicleBreakWindowSize;
static bank_u32 ms_uTimeToIgnoreButtonHeldDown;
static bank_float sm_WheelDamageRadiusThreshold;
static bank_float sm_WheelDamageRadiusThreshWheelDamageMax;
static bank_float sm_WheelDamageRadiusThreshWheelDamageScale;
static bank_float sm_WheelDamageRadiusScale;
static bank_float sm_WheelSelfRadiusScale;
static bank_float sm_WheelHeavyDamageRadiusScale;
static bank_float sm_WheelSelfHeavyWheelRadiusScale;
static bank_float sm_HairScaleDisableThreshold;
static void ForceActualVehicleLightsOff(bool value) { ms_forceActualVehicleLightsOff = value; }
//Called from CPhysics::SetGravitationalAcceleration();
static void SetGravitationalAcceleration(const float fGravitationalAcceleration);
static void SetGravityScale(float fGravityScale);
static void ResetGravityScale();
static float ms_fGravityScale;
static RegdVeh ms_requestedHdVeh;
static u32 ms_lastTimeRequestedHd;
static s8 ms_slotTurnedOff;
static s32 ms_boneTurnedOff;
static bool ms_CanEnterLockedForSpecialEditionVehicles;
static bool ms_DisableHDVehicles;
static bool ms_bDialsScriptOveridden;
struct sirenPriorityItem {
CVehicle *vehicle;
Vec3V vehPos;
int priority;
};
static atFixedArray<sirenPriorityItem, 16> sirenVehicleList;
static atFixedArray<CBobbleHead, MAX_NUM_BOBBLE_HEADS> ms_bobbleHeads;
static void CalcSirenPriorities();
static void PreVisUpdate();
static u32 ms_insideVehicleMode;
static atHashString ms_speedBoostAirScreenEffect;
static atHashString ms_speedBoostScreenEffect;
static atHashString ms_slowDownScreenEffect;
static bool ms_DisableSlowDownEffect;
static bool ms_DisableSpeedBoostEffect;
static ObjectId ms_VehicleIdToLookFor;
static u32 ms_iSlipstreamingVehiclesFound;
//online tunable for bikes camera collision flag
static bool ms_enableBikesCameraCollisionFlag;
static float ms_rampCarCollisionDamageScale;
static float ms_scoopCarCollisionDamageScale;
static bool ms_modifyPhantomCollisionWithPeds;
static bool ms_enablePatrolBoatSingleTimeSliceFix;
static const float ROCKET_BOOST_RECHARGE_RATE;
static const float ROCKET_BOOST_RECHARGE_RATE_PLANE;
static const float SIDE_SHUNT_DURATION;
static float sfPitchStabilisationMult;
static float sfRollStabilisationMult;
public:
static void SetFormationLeader( CVehicle* pLeader, Vector3& offset, float radius )
{
ms_formationLeader = pLeader;
ms_formationOffset = offset;
ms_formationRadius = radius;
}
static void ResetFormationLeader() { ms_formationLeader = NULL; }
static void SetUseBoostButtonForWheelRetract( bool useBoost ) { ms_useBoostButtonForRetract = useBoost; }
private:
static CVehicle* ms_formationLeader;
static Vector3 ms_formationOffset;
static float ms_formationRadius;
static bool ms_useBoostButtonForRetract;
// Ruiner 2 weapon animations
float m_fCurrentWeaponGrillOffset;
float m_fCurrentWeaponRackOffset;
bool m_bWheeliesEnabled; // Flag for script to disable/enable wheelies on bikes/quadbikes/trikes
public:
bool GetWheeliesEnabled() { return m_bWheeliesEnabled; }
void SetWheeliesEnabled( bool bNewValue ) { m_bWheeliesEnabled = bNewValue; }
void SetSpecialFlightModeRatio( float modeRatio ) { m_specialFlightModeRatio = modeRatio; }
void SetSpecialFlightModeTargetRatio( float modeRatio ) { m_specialFlightModeTargetRatio = modeRatio; }
float GetSpecialFlightModeTargetRatio() { return m_specialFlightModeTargetRatio; }
bool GetSpecialFlightModeAllowed() { return m_allowSpecialFlightMode; }
void SetSpecialFlightModeAllowed( bool allowSpecialFlight ) { m_allowSpecialFlightMode = allowSpecialFlight; }
// Slides a part of the vehicle attached to the bone to a desired position
// Params:
// iBoneIndex - Bone that controls the part we want to slide
// fDesiredOffset - Offset to which we want to slide
// rfCurrentOffset - Current offset of the mechanical part
// vSlideDirection - the axis on which the part slides (in local space)
// fMovementSpeed - speed at which to move (default is 1.0f)
void SlideMechanicalPart(int iBoneIndex, float fDesiredOffset, float& rfCurrentOffset, Vector3 vSlideDirection, float fMovementSpeed = 1.0f);
void OffsetBonePosition( int iBoneIndex, float fDesiredOffset, Vector3 vOffsetDirection );
void RotateMechanicalPart(int iBoneIndex, float fDesiredOffset, float& rfCurrentOffset, eRotationAxis axis, float fMovementSpeed = 1.0f);
void ProcessJetWash();
bool IsWeaponBladeImpact( phCachedContactIterator& impacts );
void SetIncreaseWheelCrushDamage( bool increaseDamage ) { m_bIncreaseWheelCrushDamage = increaseDamage; }
bool GetIncreaseWheelCrushDamage() { return m_bIncreaseWheelCrushDamage; }
float GetDownforceModifierFront() { return m_fDownforceModifierFront; }
float GetDownforceModifierRear() { return m_fDownforceModifierRear; }
void SetDownforceModifierFront(float val) { m_fDownforceModifierFront = val; }
void SetDownforceModifierRear(float val) { m_fDownforceModifierRear = val; }
#if !__NO_OUTPUT
void LogDeletionFailReason(const char *pReasonString, const bool bLogClearCarFromAreaFailures) const;
#endif // !__NO_OUTPUT
enum VEHICLE_WEAPON_BLADES
{
VWB_REAR = 0,
VWB_LEFT,
VWB_RIGHT,
VWB_FRONT,
MAX_NUM_WEAPON_BLADES,
};
private:
// weapon blades
int m_numWeaponBlades;
CWeaponBlade m_weaponBlades[ MAX_NUM_WEAPON_BLADES ];
public:
void ApplyExplosionEffectEMP(u32 weaponHash = 0);
void ApplyExplosionEffectSlick() { m_bExplosionEffectSlick = true; m_uLastHitByExplosionEffectSlick = fwTimer::GetTimeInMilliseconds(); }
void ApplyExplosionEffectSlowdown( Vector3 explosionPosition, float explosionRadius );
bool GetExplosionEffectEMP() const { return m_bExplosionEffectEMP; }
bool GetExplosionEffectSlick() const { return m_bExplosionEffectSlick; }
bool GetWeaponModHasElectricEffect() const { return m_bWeaponModHasElectricEffect; }
u8 GetNumSequentialSirenPresses() const { return m_uNumSequentialSirenPresses; }
void ResetNumSequentialSirenPresses() { m_uNumSequentialSirenPresses = 0u; }
private:
void ProcessExplosionEffects();
bool m_bExplosionEffectEMP;
bool m_bExplosionEffectSlick;
bool m_bIncreaseWheelCrushDamage;
bool m_bWeaponModHasElectricEffect;
bool m_bSirenSwitchPending;
bool m_bUseIncreasedEMPDuration;
u8 m_uNumSequentialSirenPresses;
u32 m_uLastHitByExplosionEffectEMP;
u32 m_uLastHitByExplosionEffectSlick;
};
template<> inline CVehicle* fwPool<CVehicle>::GetSlot(s32 index)
{
CVehicle* veh = (CVehicle*)fwBasePool::GetSlot(index);
if (!veh || veh->GetIsInPopulationCache())
return NULL;
return veh;
}
template<> inline const CVehicle* fwPool<CVehicle>::GetSlot(s32 index) const
{
CVehicle* veh = (CVehicle*)fwBasePool::GetSlot(index);
if (!veh || veh->GetIsInPopulationCache())
return NULL;
return veh;
}
SuspensionType GetSuspensionTypeFromFlags(int iModelFlags, bool bRearSuspension);
void SetSuspensionTransformation(crSkeleton* pSkeleton, eHierarchyId compId, eHierarchyId wheelId, SuspensionType nType, CVehicleStructure* pStructure, CHandlingData *pHandlingData, const Vec3V *pDeformation = NULL);
void SetTransmissionRotation(crSkeleton* pSkeleton, eHierarchyId compId, eHierarchyId wheelIdL, eHierarchyId wheelIdR, CVehicleStructure* pStructure);
void SetTransmissionRotationForTrike(crSkeleton* pSkeleton, eHierarchyId compId, eHierarchyId wheelIdL, CVehicleStructure* pStructure);
// ------------------------------------------------------------------------------
#ifdef DEBUG
void AssertVehiclePointerValid(CVehicle* pVeh);
#else
#define AssertVehiclePointerValid( A )
#endif
#ifdef DEBUG
void AssertVehiclePointerValid_NotInWorld(CVehicle* pVeh);
#else
#define AssertVehiclePointerValid_NotInWorld( A )
#endif
bool IsVehiclePointerValid(CVehicle* pVeh);
bool IsVehiclePointerValid_NotInWorld(CVehicle* pVeh);
//
// name: GetPosition
// description: Get position from matrix (should exist for vehicle)
/*inline const Vector3& CVehicle::GetPosition() const
{
Assert(m_pMat);
return m_pMat->GetVector(3);
}*/
//
// name: GetPosition
// description: Get position from matrix (should exist for vehicle)
/*inline Vector3& CVehicle::GetPosition()
{
Assert(m_pMat);
return *(Vector3*)&m_pMat->GetVector(3);
}*/
#endif // _VEHICLE_H_
// VEHICLE MOD TO WEAPONS
//Standard
//VMT_CHASSIS Body Armor
//VMT_ROOF Roof Spikes
//VMT_BUMPER_F Front Bumper
//VMT_BUMPER_R Rear Bumper
//VMT_SKIRT Side Skirts
//VMT_BONNET Bonnet
//VMT_GRILL Grill
//VMT_SPOILER Spoiler
//VMT_EXHAUST Exhaust
//VMT_WING_L
//
//Supermod
//VMT_PLTHOLDER
//VMT_PLTVANITY
//VMT_INTERIOR1 Bobblheads
//VMT_INTERIOR2 Rollcage
//VMT_INTERIOR3
//VMT_INTERIOR4
//VMT_INTERIOR5
//VMT_SEATS Seats
//VMT_STEERING Steering Wheel
//VMT_KNOB Gear Knobs
//VMT_PLAQUE
//VMT_ICE
//VMT_TRUNK Rear Mounted Grenade Launcher ( issi & interceptor )
//VMT_HYDRO
//VMT_ENGINEBAY1
//VMT_ENGINEBAY2 NITROUS Phyical model + Stat
//VMT_ENGINEBAY3 JUMP Phyical model + Stat
//VMT_CHASSIS2 Front mountd mods - Scoop S / M / L, Ram Bar S / M / L, Spikes ( Front )
//VMT_CHASSIS3 Spikes ( body )
//VMT_CHASSIS4 Side & Rear Blades
//VMT_CHASSIS5 Fixed Forward Machine Gun
//VMT_DOOR_L
//VMT_DOOR_R
//VMT_LIVERY_MOD Livery