Files
GTASource/game/Vehicles/VehicleGadgets.h

1926 lines
65 KiB
C
Raw Permalink Normal View History

2025-02-23 17:40:52 +08:00
/********************************************************************
filename: VehicleGadgets.h
created: 2008/10/29
author: jack.potter
purpose: Code for handling special vehicle extras which might want to adjust
a vehicle's skeleton, contorls or physics.
*********************************************************************/
#ifndef __VEHICLE_GADGETS_H__
#define __VEHICLE_GADGETS_H__
// rage headers
#include "vector/vector3.h"
#include "atl/array.h"
#include "atl/string.h"
#include "camera/helpers/HandShaker.h"
#include "network/General/NetworkUtil.h"
#include "Streaming/streamingrequest.h"
#include "Scene/RegdRefTypes.h"
#include "Scene/Physical.h"
#include "Vehicles/VehicleDefines.h"
#include "Vehicles/handlingMgr.h"
#include "renderer/HierarchyIds.h"
#include "physics/rope.h"
#include "physics/constrainthandle.h"
#include "physics/constraintRotation.h"
#include "physics/WorldProbe/worldprobe.h"
#include "timecycle/TimeCycleConfig.h"
#include "network/General/NetworkUtil.h"
#include "control/replay/replay.h"
#include "game/ModelIndices.h"
#include "weapons/WeaponEnums.h"
//Forward declarations
class CVehicle;
class CWeapon;
class CVehicleModelInfo;
class CWeaponInfo;
class CTrailer;
class audVehicleTurret;
class audVehicleForks;
class audVehicleDigger;
class audVehicleHandlerFrame;
class audVehicleTowTruckArm;
class audVehicleGrapplingHook;
class audVehicleGadgetMagnet;
class audVehicleGadgetDynamicSpoiler;
#define SEARCHLIGHTSAMPLES (6) // Number of predictions stored for the //searchlight
namespace rage
{
struct fragHierarchyInst;
class ropeInstance;
};
enum eVehicleGadgetType
{
// networked types
VGT_FORKS,
VGT_SEARCHLIGHT,
VGT_PICK_UP_ROPE,
VGT_DIGGER_ARM,
VGT_HANDLER_FRAME,
VGT_PICK_UP_ROPE_MAGNET,
VGT_BOMBBAY,
VGT_NUM_NETWORKED_TYPES,
// non-networked types
VGT_FIXED_VEHICLE_WEAPON,
VGT_VEHICLE_WEAPON_BATTERY,
VGT_TURRET,
VGT_TURRET_PHYSICAL,
VGT_TRACKS,
VGT_LEAN_HELPER,
VGT_TRAILER_ATTACH_POINT,
VGT_TRAILER_LEGS,
VGT_ARTICULATED_DIGGER_ARM,
VGT_PARKING_SENSOR,
VGT_TOW_TRUCK_ARM,
VGT_THRESHER,
VGT_BOATBOOM,
VGT_RADAR,
VGT_DYNAMIC_SPOILER,
};
struct JointInfo
{
s32 m_iFragChild;
s32 m_iBone;
float m_fDesiredAcceleration;
float m_fSpeed;
float m_fPrevPosition;
bool m_bPrismatic;
bool m_bContinuousInput; // False for joint that get targets set once(fire and forget) - True for periodic updates of target (typically user input)
Vector3 m_vecJointChildPosition;//Only used for prismatic joints, can't add vector3 to union
bool m_bSwingFreely;
union{
struct{
float m_fPosition;
float m_fDesiredPosition;
float m_fOpenPosition;
float m_fClosedPosition;
bool m_bOnlyControlSpeed;
}m_PrismaticJointInfo;
struct{
eRotationAxis m_eRotationAxis;
float m_fAngle;
float m_fDesiredAngle;
float m_fOpenAngle;
float m_fClosedAngle;
bool m_bOnlyControlSpeed;
bool m_bSnapToAngle;
}m_1dofJointInfo;
};
};
struct SearchLightLightInfo {
float falloffScale;
float falloffExp;
float innerAngle;
float outerAngle;
float globalIntensity;
float lightIntensityScale;
float volumeIntensityScale;
float volumeSizeScale;
Color32 outerVolumeColor;
float outerVolumeIntensity;
float outerVolumeFallOffExponent;
bool enable;
bool specular;
bool shadow;
bool volume;
float lightFadeDist;
float coronaIntensity;
float coronaIntensityFar;
float coronaOffset;
float coronaSize;
float coronaSizeFar;
float coronaZBias;
#if __BANK
void InitWidgets(bkBank &bank);
#endif
};
struct SearchLightInfo {
float length;
float offset;
Color32 color;
SearchLightLightInfo mainLightInfo;
SearchLightInfo();
void Set(const CVisualSettings& visualSettings, const char* type);
#if __BANK
void InitWidgets(bkBank &bank);
#endif
};
// defines interface used to control custom parts of vehicles
// e.g. tank turrets, watercannons, guns, etc.
class CVehicleGadget
{
public:
CVehicleGadget() :m_bEnabled(true) {};
virtual ~CVehicleGadget() {}
#if __BANK
static void AddWidgets(bkBank& bank);
#endif //__BANK
virtual void ProcessPrePhysics(CVehicle* UNUSED_PARAM(pParent)) {}
virtual void ProcessPhysics(CVehicle* UNUSED_PARAM(pParent), const float UNUSED_PARAM(fTimestep), const int UNUSED_PARAM(nTimeSlice)) {}
virtual void ProcessPhysics2(CVehicle* UNUSED_PARAM(pParent), const float UNUSED_PARAM(fTimestep)) {}
virtual void ProcessPhysics3(CVehicle* UNUSED_PARAM(pParent), const float UNUSED_PARAM(fTimestep)) {}
virtual void ProcessPreRender(CVehicle* UNUSED_PARAM(pParent)) {}
virtual void ProcessPostPreRender(CVehicle* UNUSED_PARAM(pParent)) {}
virtual void ProcessControl(CVehicle* UNUSED_PARAM(pParent)) {}
virtual void Fix() {}
// ProcessPreComputeImpacts should reset the impact iterator after use.
virtual void ProcessPreComputeImpacts(CVehicle *UNUSED_PARAM(pVehicle), phCachedContactIterator &UNUSED_PARAM(impacts)){}
virtual s32 GetType() const = 0;
virtual bool IsVehicleWeapon() const { return false;}
// Check whether the physics on this vehicle should be activated this frame
virtual bool WantsToBeAwake(CVehicle* UNUSED_PARAM(pParent)) { return false; }
// Transition this gadget's LOD
virtual void ChangeLod(CVehicle & UNUSED_PARAM(parentVehicle), int UNUSED_PARAM(lod)) { };
virtual void BlowUpCarParts(CVehicle* UNUSED_PARAM(pParent)){}
virtual int GetGadgetEntities(int UNUSED_PARAM(entityListSize), const CEntity ** UNUSED_PARAM(entityListOut)) const { return 0; };
virtual void SetIsVisible(CVehicle* UNUSED_PARAM(pParent), bool UNUSED_PARAM(bIsVisible)) {}
//helper functions for 1dof joints
static void DriveComponentToAngle(fragHierarchyInst* pHierInst,
s32 iFragChild,
float fDesiredAngle,
float fDesiredSpeed,
float& fCurrentAngleOut,
float fMuscleStiffness = 0.05f,
float fMuscleAngleStrength = 10.0f,
float fMuscleSpeedStrength = 20.0f,
float fMinAndMaxMuscleTorque = 100.0f,
bool bOnlyControlSpeed = false,
float fSpeedStrengthFadeOutAngle = (PI / 45.0f),
bool bOnlyUpdateCurrentAngle = false);
static void SnapComponentToAngle(fragInstGta* pFragInst,
s32 iFragChild,
float fDesiredAngle,
float& fCurrentAngleOut);
static void DriveHiearchyIdToAngle(eHierarchyId nId,
CVehicle* pParent,
float fDesiredAngle,
float fDesiredSpeed,
float& fCurrentAngleOut);
static float GetJointAngle(fragHierarchyInst* pHierInst,
s32 iFragChild);
//helper functions for prismatic joints
static void DriveComponentToPosition(fragHierarchyInst* pHierInst,
s32 iFragChild,
float fDesiredPosition,
float fDesiredSpeed,
float &fCurrentPositionOut,
Vector3 &vecJointChildPosition,
float fMuscleStiffness = 0.05f,
float fMusclePositionStrength = 10.0f,
float fMuscleSpeedStrength = 20.0f,
float fMinAndMaxMuscleForce = 100.0f,
bool bOnlyControlSpeed = true);
static void SwingJointFreely(fragHierarchyInst* pHierInst,
s32 iFragChild);
// This allows us to disable weapons individually
virtual void SetEnabled( CVehicle* , bool bEnabled ) { m_bEnabled = bEnabled; }
bool GetIsEnabled() const { return m_bEnabled; }
// network methods:
virtual bool IsNetworked() const { return false; }
virtual void Serialise(CSyncDataBase&) { Assertf(0, "Serialiser not defined for networked vehicle gadget"); }
// collision flag reset
virtual void ResetIncludeFlags(CVehicle* UNUSED_PARAM(pParent)) {}
private:
bool m_bEnabled;
};
// For updating vehicle tank tracks
class CVehicleTracks : public CVehicleGadget
{
public:
CVehicleTracks(u32 iWheelMask = 0xffffffff);
virtual void ProcessPhysics(CVehicle* pParent, const float fTimeStep, const int nTimeSlice);
virtual void ProcessPreRender(CVehicle* pParent);
virtual s32 GetType() const { return VGT_TRACKS; }
protected:
float m_fWheelAngleLeft;
float m_fWheelAngleRight;
// Defines which wheels are driving the track
u32 m_iWheelMask;
};
class CVehicleLeanHelper : public CVehicleGadget
{
public:
CVehicleLeanHelper();
virtual void ProcessPhysics2(CVehicle* pParent, const float fTimeStep);
virtual s32 GetType() const { return VGT_LEAN_HELPER; }
protected:
void ProcessLeanSideways(CVehicle* pParent);
// fLeanInput: 1.0f lean fully back, -1.0f lean fully forward
void ProcessLeanFwd(CVehicle* pParent, float fLeanInputY);
static dev_float ms_fAngInertiaRaiseFactor;
// Static members
static dev_float ms_fLeanMinSpeed;
static dev_float ms_fLeanBlendSpeed;
static dev_float ms_fLeanForceSpeedMult;
static dev_float ms_fWheelieForceCgMult;
// Triggers for stabilising wheelies
static dev_float ms_fWheelieOvershootAngle; // Start helping after we overshoot by this far
static dev_float ms_fWheelieOvershootCap; // Scale forces up to this angle
static dev_float ms_fStoppieStabiliserMult;
};
class CVehicleWeapon : public CVehicleGadget
{
public:
CVehicleWeapon() { m_weaponIndex = 0; m_handlingIndex = -1;}
virtual void Fire(const CPed* pFiringPed, CVehicle* pParent, const Vector3& vTargetPosition, const CEntity* pTarget = NULL, bool bForceShotInWeaponDirection = false) = 0;
virtual const CWeaponInfo* GetWeaponInfo() const = 0;
virtual u32 GetHash() const = 0;
virtual bool IsVehicleWeapon() const { return true;}
virtual bool IsWaterCannon() const {return false;}
virtual void TriggerEmptyShot(CVehicle* UNUSED_PARAM(pParent)) const {};
virtual bool GetReticlePosition(Vector3&) const { return false; }
virtual void GetForceShotInWeaponDirectionEnd(CVehicle* UNUSED_PARAM(pParent), Vector3& UNUSED_PARAM(vForceShotInWeaponDirectionEnd)) {};
virtual void SetOverrideWeaponDirection(const Vector3 &UNUSED_PARAM(vOverrideDirection)) {}
virtual void SetOverrideLaunchSpeed(float UNUSED_PARAM(fOverrideLaunchSpeed)) {}
virtual bool IsUnderwater(const CVehicle* UNUSED_PARAM(pParent)) const { return false; }
#if !__NO_OUTPUT
virtual const char* GetName() const = 0;
#endif
#if !__FINAL
virtual bool HasWeapon(const CWeapon* pWeapon) const = 0;
#endif
s32 m_weaponIndex;
s32 m_handlingIndex;
};
// Class CTurret
//
// Rotates a turret to face desired direction
// Note it does not handle any weapons, these are handled by seperate 'gadgets'
class CTurret : public CVehicleGadget
{
public:
enum eFlags
{
TF_RenderDesiredAngleForPhysicalTurret = BIT0,
TF_HaveUsedDesiredAngleForRendering = BIT1,
TF_UseDesiredAngleForPitch = BIT2,
TF_DisableMovement = BIT3,
TF_InitialAdjust = BIT4,
TF_Hide = BIT5,
};
CTurret(eHierarchyId iBaseBone, eHierarchyId iPitchBone, float fTurretSpeed, float fTurretPitchMin, float fTurretPitchMax, float fTurretCamPitchMin,
float fTurretCamPitchMax, float fBulletVelocityForGravity, float fTurretPitchForwardMin, CVehicleWeaponHandlingData::sTurretPitchLimits sPitchLimits);
virtual void InitJointLimits(const CVehicleModelInfo* pModelInfo);
virtual void ProcessPreRender(CVehicle* pParent);
virtual void ProcessControl(CVehicle* pParent);
void InitAudio(CVehicle* pParent);
virtual s32 GetType() const { return VGT_TURRET; }
// returns the matrix of the turret's barrel
// This will be correct whether the parent vehicle's world matrices are up to date or not
void GetTurretMatrixWorld(Matrix34& matOut, const CVehicle* pParent) const;
void AimAtWorldPos(const Vector3& vDesiredTarget, CVehicle* pParent, const bool bDoCamCheck, const bool bSnapAim);
void AimAtLocalDir(const Vector3& vLocalTargetDir, CVehicle* pParent, const bool bDoCamCheck, const bool bSnapAim); // Local means in _turret's_ space
Vector3 ComputeLocalDirFromWorldPos(const Vector3& vDesiredTarget, const CVehicle* pParent) const;
Vector3 ComputeWorldPosFromLocalDir(const Vector3& vDesiredTarget, const CVehicle* pParent) const;
float ComputeRelativeHeadingDelta(const CVehicle* pParent) const;
void SetAssociatedSeatIndex(s32 iSeatIndex) { m_AssociatedSeatIndex = iSeatIndex; }
void SetMinPitch(float fMinPitch) {m_fMinPitch = fMinPitch;}
float GetMinPitch() const {return m_fMinPitch;}
void SetMaxPitch(float fMaxPitch) {m_fMaxPitch = fMaxPitch;}
float GetMaxPitch() const {return m_fMaxPitch;}
float GetCurrentPitch() const { return m_AimAngle.TwistAngle(XAXIS); }
float GetDesiredPitch() const { return m_DesiredAngle.TwistAngle(XAXIS); }
float GetLerpValueForRearMountedTurret(float fdesiredAngMag, float& fForcedPitchAng);
float GetCurrentHeading(const CVehicle* pParent) const;
float GetDesiredHeading() const { return m_DesiredAngle.TwistAngle(ZAXIS); }
float GetAimHeading() const { return m_AimAngle.TwistAngle(ZAXIS); }
float GetLocalHeading(const CVehicle& rParent) const;
void SetMinHeading(float fMinHeading) {m_fMinHeading = fMinHeading;}
float GetMinHeading() const {return m_fMinHeading;}
void SetMaxHeading(float fMaxHeading) {m_fMaxHeading = fMaxHeading;}
float GetMaxHeading() const {return m_fMaxHeading;}
void SetHeadingSpeedModifier(float fPerFrameHeadingModifier) { m_fPerFrameHeadingModifier = fPerFrameHeadingModifier; }
void SetPitchSpeedModifier(float fPitchSpeedModifier) { m_fPerFramePitchModifier = fPitchSpeedModifier; }
void SetTurretSpeedModifier(float fTurretSpeedModifier) { m_fSpeedModifier = fTurretSpeedModifier; }
void SetTurretSpeedOverride(float fSpeed) { m_fTurretSpeedOverride = fSpeed; }
void SetTurretSpeed(float fSpeed) { m_fTurretSpeed = fSpeed; }
float GetTurretSpeed() const;
float GetBulletVelocityForGravity() const { return m_fBulletVelocityForGravity; }
inline virtual bool IsPhysicalTurret() const {return false;}
bool IsWithinFiringAngularThreshold( float fAngularThresholdInRads ) const;
void SetDesiredAngle(const Quaternion& desiredAngle, CVehicle* pParent);
eHierarchyId GetBaseBoneId() const { return m_iBaseBoneId; }
eHierarchyId GetBarrelBoneId() const { return m_iPitchBoneId; }
fwFlags32& GetFlags() { return m_Flags; }
const fwFlags32& GetFlags() const { return m_Flags; }
protected:
float CalculateTrajectoryForGravity(const Vector3& vLocalDir, float projVelocity);
float GetTurretSpeedModifier() const { return m_fSpeedModifier; }
void ComputeTurretSpeedModifier(const CVehicle *pParent);
eHierarchyId m_iBaseBoneId;
eHierarchyId m_iPitchBoneId;
Quaternion m_DesiredAngleUnclamped;
Quaternion m_DesiredAngle;
Quaternion m_AimAngle;
s32 m_AssociatedSeatIndex;
audVehicleTurret* m_VehicleTurretAudio;
float m_fSpeedModifier;
float m_fPerFrameHeadingModifier;
float m_fPerFramePitchModifier;
float m_fTurretSpeedOverride; //Used to override turret speed from script per-frame
// Configuration vars
// From bone dofs
float m_fMinPitch;
float m_fMaxPitch;
float m_fMinHeading;
float m_fMaxHeading;
// From handling.dat
float m_fTurretSpeed;
float m_fTurretPitchMin;
float m_fTurretPitchMax;
float m_fTurretCamPitchMin;
float m_fTurretCamPitchMax;
float m_fBulletVelocityForGravity;
float m_fTurretPitchForwardMin; //This is used for the firetruck to limit it's pitch aiming forwards and back as the water would hit the truck. It lerps between this and m_fTurretPitchMin at the sides.
CVehicleWeaponHandlingData::sTurretPitchLimits m_PitchLimits;
fwFlags32 m_Flags;
};
class CTurretPhysical : public CTurret
{
public:
CTurretPhysical(eHierarchyId iBaseBone, eHierarchyId iPitchBone, float fTurretSpeed, float fTurretPitchMin, float fTurretPitchMax,
float fTurretCamPitchMin, float fTurretCamPitchMax, float fBulletVelocityForGravity, float fTurretPitchForwardMin,
CVehicleWeaponHandlingData::sTurretPitchLimits sPitchLimits);
virtual ~CTurretPhysical() {};
virtual void InitJointLimits(const CVehicleModelInfo* pModelInfo);
virtual void ProcessPreRender(CVehicle* pParent);
virtual void ProcessControl(CVehicle* ){};
virtual void ProcessPhysics(CVehicle* pParent, const float fTimeStep, const int nTimeSlice);
void ProcessPreComputeImpacts(CVehicle *pVehicle, phCachedContactIterator &impacts);
virtual s32 GetType() const { return VGT_TURRET_PHYSICAL; }
void DriveTurret(CVehicle* pParent, const int nTimeSlice = 0);
void SetEnabled( CVehicle* pParent, bool bEnabled );
inline virtual bool IsPhysicalTurret() const {return true;}
s32 GetBaseFragChild() const {return m_iBaseFragChild;}
s32 GetBarrelFragChild() const {return m_iBarrelFragChild;}
virtual void BlowUpCarParts(CVehicle* pParent);
void ResetTurretsMuscles(CVehicle* pParent);
void SetPedHasControl( bool bPedHasControl ) { m_bPedHasControlOfTurret = bPedHasControl; }
void ResetIncludeFlags(CVehicle* pParent);
float ClampAngleToJointLimits(float fAngle, const CVehicle& rParent, s32 iFragChild);
bool WantsToBeAwake(CVehicle *pVehicle);
bool GetIsBarrelInCollision() { return m_bBarrelInCollision; }
protected:
s32 m_iBaseFragChild;
s32 m_iBarrelFragChild;
float m_fTimeSinceTriggerDesiredAngleBlendInOut;
float m_RenderAngleX;
float m_RenderAngleZ;
bool m_bBarrelInCollision;
bool m_bHasReachedDesiredAngle;
bool m_bPedHasControlOfTurret;
bool m_bHeldTurret;
bool m_bResetTurretHeading;
bool m_bHidden;
};
// Class to represent a single weapon mounted to a vehicle
// The weapon is fixed (always points along bone's forward vector)
class CFixedVehicleWeapon : public CVehicleWeapon
{
public:
CFixedVehicleWeapon(u32 nWeaponHash, eHierarchyId iWeaponBone);
virtual ~CFixedVehicleWeapon();
virtual void ProcessPreRender(CVehicle* pParent);
virtual void ProcessPostPreRender(CVehicle* pParent);
virtual void ProcessControl(CVehicle* pParent);
virtual s32 GetType() const { return VGT_FIXED_VEHICLE_WEAPON; }
virtual f32 GetProbeDist() const { return m_fProbeDist; }
eHierarchyId GetWeaponBone() const { return m_iWeaponBone; }
CWeapon* GetWeapon() const { return m_pVehicleWeapon; }
virtual void TriggerEmptyShot(CVehicle* pParent) const;
virtual void Fire(const CPed* pFiringPed, CVehicle* pParent, const Vector3& vTargetPosition, const CEntity* pTarget = NULL, bool bForceShotInWeaponDirection = false);
void SpinUp(CPed* pFiringPed);
virtual const CWeaponInfo* GetWeaponInfo() const;
virtual u32 GetHash() const;
virtual bool GetReticlePosition(Vector3&) const;
virtual void GetForceShotInWeaponDirectionEnd(CVehicle* pParent, Vector3& vForceShotInWeaponDirectionEnd);
virtual void SetOverrideWeaponDirection(const Vector3 &vOverrideDirection);
virtual void SetOverrideLaunchSpeed(float fOverrideLaunchSpeed);
void ClearOverrideWeaponDirection()
{
m_bUseOverrideWeaponDirection = false;
m_vOverrideWeaponDirection.Zero();
}
void ResetIncludeFlags(CVehicle* pParent);
virtual bool IsUnderwater(const CVehicle* pParent) const;
#if !__NO_OUTPUT
virtual const char* GetName() const;
#endif
#if !__FINAL
virtual bool HasWeapon(const CWeapon* pWeapon) const { return m_pVehicleWeapon == pWeapon; }
#endif
protected:
Vector3 GetForwardNormalBasedOnGround(const CVehicle* pVehicle);
bool IsWeaponBoneValidForRotaryCannon();
s32 GetRotationBoneOffset();
CFixedVehicleWeapon();
CWeapon* m_pVehicleWeapon;
eHierarchyId m_iWeaponBone;
// Kickback vars
u32 m_iTimeLastFired;
// Fire vars need queuing so that weapon is only fired at the correct point in the frame
RegdConstPed m_pFiringPed;
RegdConstEnt m_pQueuedTargetEnt;
Vector3 m_vQueuedTargetPos;
Vector3 m_vQueuedFireDirection;
Vector3 m_vOverrideWeaponDirection;
Vector3 m_vTurretForwardLastUpdate;
bool m_bFireIsQueued;
bool m_bForceShotInWeaponDirection;
bool m_bUseOverrideWeaponDirection;
float m_fOverrideLaunchSpeed;
// Required to cache off in post pre render
Vector3 m_v3ReticlePosition;
// Total dist used for frame by frame line probe
f32 m_fProbeDist;
// Number of radians still to rotate "ammo belt" through after firing a bullet.
float m_fAmmoBeltAngToTurn;
// Called from pre render so that all matrices have been updated
virtual bool FireInternal(CVehicle* pParent);
void ApplyBulletDirectionOffset(Matrix34 &weaponMat, CVehicle* pParent);
private:
strLocalIndex GetModelLocalIndexForStreaming() const;
strRequest m_projectileRequester;
};
class CVehicleWaterCannon : public CFixedVehicleWeapon
{
public:
CVehicleWaterCannon(u32 nWeaponHash, eHierarchyId iWeaponBone);
virtual ~CVehicleWaterCannon();
virtual const CWeaponInfo* GetWeaponInfo() const;
virtual bool IsWaterCannon() const {return true;}
virtual void ProcessControl(CVehicle* pParent);
//This function allows cloned vehicles to update collision of the water stream to reflect remote machine
bool FireWaterCannonFromMatrixPositionAndAlignment(CVehicle* pParent, const Matrix34 &weaponMat);
virtual u32 GetHash() const;
#if !__NO_OUTPUT
virtual const char* GetName() const;
#endif
static const float FIRETRUCK_CANNON_RANGE;
private:
// Called from pre render so that all matrices have been updated
// We're gonna overload this to use the water cannon manager instead of
// some CWeapon, since the water cannon doesn't really jive with a lot
// of the assumptions of the weapon code
virtual bool FireInternal(CVehicle* pParent);
static const float FIRETRUCK_CANNON_JET_SPEED;
Vec3V m_CannonDirLastFrame;
};
class CSearchLight : public CFixedVehicleWeapon
{
public:
CSearchLight(u32 nWeaponHash, eHierarchyId iWeaponBone);
virtual ~CSearchLight();
static void UpdateVisualDataSettings();
#if __BANK
static void InitWidgets(bkBank& pBank);
#endif // __BANK
virtual void ProcessPostPreRender(CVehicle* parent);
virtual s32 GetType() const { return VGT_SEARCHLIGHT; }
void SetLightOn(bool b);
bool GetLightOn() const { return m_lightOn; }
void SetForceLightOn(bool b) { m_bForceOn = b; }
bool GetForceLightOn() const { return m_bForceOn; }
float GetSweepTheta() const { return m_SweepTheta; }
void SetSweepTheta(float in_Value) { m_SweepTheta = in_Value; }
Vector3 GetSearchLightExtendTimer() const { return m_fSearchLightExtendTimer; }
void SetSearchLightExtendTimer(Vector3& in_Value) { m_fSearchLightExtendTimer = in_Value; }
void SetTargetPosition(const Vector3& targetPos) {m_targetPos = targetPos;}
const Vector3 &GetTargetPos() {return m_targetPos;}
void ProcessSearchLight(CVehicle* parent);
CPhysical *GetSearchLightTarget() {return SafeCast(CPhysical, m_SearchLightTarget.GetEntity());}
#if GTA_REPLAY
CReplayID GetSearchLightTargetReplayId() {return m_SearchLightTargetReplayId;}
#endif // GTA_REPLAY
void SetSearchLightTarget(CPhysical* pTarget);
float GetLightBrightness() {return m_LightBrightness;}
bool GetSearchLightBlocked() {return m_searchLightBlocked;}
void SetHasPriority(bool value) {m_bHasPriority = value;}
bool GetHasPriority() {return m_bHasPriority;}
bool GetIsDamaged() {return m_isDamaged;}
void SetIsDamaged() {m_isDamaged = true;}
// network methods:
virtual bool IsNetworked() const { return true; }
virtual void Serialise(CSyncDataBase& serialiser);
static const SearchLightInfo &GetSearchLightInfo(CVehicle *parent);
void CopyTargetInfo( CSearchLight& searchLight);
Vector3 GetCloneTargetPos() {return m_CloneTargetPos; }
protected:
// Called from pre render so that all matrices have been updated
virtual bool FireInternal(CVehicle* pParent);
float m_SweepTheta;
bool m_searchLightBlocked;
bool m_lightOn;
bool m_bHasPriority;
bool m_isDamaged;
bool m_bForceOn;
//new heli search lights stuff
CSyncedEntity m_SearchLightTarget;
#if GTA_REPLAY
CReplayID m_SearchLightTargetReplayId;
#endif // GTA_REPLAY
Vector3 m_OldSearchLightTargetPos[SEARCHLIGHTSAMPLES];
Vector3 m_targetPos;
Vector3 m_CloneTargetPos;
Vector3 m_fSearchLightExtendTimer;
camHandShaker m_searchLightTilt;
WorldProbe::CShapeTestSingleResult m_targetProbeHandle;
u32 m_LastSearchLightSample;
float m_LightBrightness;
};
class CVehicleRadar : public CFixedVehicleWeapon
{
public:
CVehicleRadar(u32 nWeaponHash, eHierarchyId iWeaponBone) : CFixedVehicleWeapon(nWeaponHash, iWeaponBone)
{
m_fAngle = 0.0f;
}
virtual ~CVehicleRadar() {};
#if __BANK
static void InitWidgets(bkBank& pBank);
#endif // __BANK
virtual void ProcessPostPreRender(CVehicle* parent);
virtual s32 GetType() const { return VGT_RADAR; }
protected:
float m_fAngle;
};
// Gadget to handle multiple vehicle weapons fired sequentially
// e.g. a load of weapons on the front of a helicopter
class CVehicleWeaponBattery : public CVehicleWeapon
{
public:
enum eMissileFlapState
{
MFS_CLOSED,
MFS_OPEN,
MFS_CLOSING,
MFS_OPENING
};
enum eMissileBatteryState
{
MBS_IDLE,
MBS_RELOADING
};
CVehicleWeaponBattery();
virtual ~CVehicleWeaponBattery();
static void InitTunables();
virtual void ProcessControl(CVehicle* pParent);
virtual void ProcessPostPreRender(CVehicle* pParent);
virtual void ProcessPreRender(CVehicle* pParent);
virtual s32 GetType() const { return VGT_VEHICLE_WEAPON_BATTERY; }
virtual void Fire(const CPed* pFiringPed, CVehicle* pParent, const Vector3& vTargetPosition, const CEntity* pTarget = NULL, bool bForceShotInWeaponDirection = false);
// Returns the first weapon's weapon info
// (although it is possible to have different weapon types in a single battery)
virtual const CWeaponInfo* GetWeaponInfo() const;
virtual u32 GetHash() const;
void AddVehicleWeapon(CVehicleWeapon* pNewWeapon);
const CVehicleWeapon* GetVehicleWeapon(s32 iIndex) const {return (Verifyf(iIndex < m_iNumVehicleWeapons && iIndex >= 0,"Invalid index")) ? m_VehicleWeapons[iIndex] : NULL; }
CVehicleWeapon* GetVehicleWeapon(s32 iIndex) {return (Verifyf(iIndex < m_iNumVehicleWeapons && iIndex >= 0,"Invalid index")) ? m_VehicleWeapons[iIndex] : NULL; }
s32 GetNumWeaponsInBattery() const {return m_iNumVehicleWeapons; }
eMissileBatteryState GetMissileBatteryState() const { return m_MissileBatteryState; }
void SetMissileBatteryState(eMissileBatteryState state) { m_MissileBatteryState = state; }
eMissileFlapState GetMissileFlapState(s32 iIndex) const { return m_MissileFlapState[iIndex]; }
void SetMissileFlapState(s32 iIndex, eMissileFlapState state) { m_MissileFlapState[iIndex] = state; }
void DeleteAllVehicleWeapons();
virtual void SetOverrideWeaponDirection(const Vector3 &vOverrideDirection);
virtual void SetOverrideLaunchSpeed(float fOverrideLaunchSpeed);
s32 GetFiredWeaponCounter() const { return m_iCurrentWeaponCounter; }
void IncrementCurrentWeaponCounter(CVehicle& rVeh);
bool CanFire() { return fwTimer::GetTimeInMilliseconds() > m_uNextLaunchTime; }
s32 GetLastFiredWeapon() const { return m_iLastFiredWeapon; }
s32 GetTimeToNextLaunch() const { return rage::Max((s32)m_uNextLaunchTime - (s32)fwTimer::GetTimeInMilliseconds(), 0); }
virtual bool IsUnderwater(const CVehicle* pParent) const;
#if !__NO_OUTPUT
virtual const char* GetName() const;
#endif
#if !__FINAL
virtual bool HasWeapon(const CWeapon* pWeapon) const;
#endif
private:
static float sm_fOppressor2MissileAlternateWaitTimeOverride;
CVehicleWeapon* m_VehicleWeapons[MAX_NUM_BATTERY_WEAPONS];
eMissileFlapState m_MissileFlapState[MAX_NUM_BATTERY_WEAPONS]; // Probably should live on vehicle weapon?
eMissileBatteryState m_MissileBatteryState;
s32 m_iLastFiredWeapon;
s32 m_iNumVehicleWeapons;
// Weapons are not fired in order
s32 m_iCurrentWeaponCounter;
u32 m_uNextLaunchTime;
#if !__NO_OUTPUT
atString m_debugName;
#endif
};
// Num CVehicleWeapons per vehicle
// e.g. a primary and secondary
// note: 1 weapon could be a battery of rocket launchers
class CVehicleWeaponMgr
{
public:
CVehicleWeaponMgr();
virtual ~CVehicleWeaponMgr();
void ProcessControl(CVehicle* pParent);
void ProcessPreRender(CVehicle* pParent);
void ProcessPostPreRender(CVehicle* pParent);
void ProcessPhysics(CVehicle* pParent, float fTimeStep, int nTimeSlice);
void ProcessPreComputeImpacts(CVehicle* pVehicle, phCachedContactIterator &impacts);
void AimTurretsAtWorldPos(const Vector3 &vWorldPos, CVehicle* pParent, const bool bDoCamCheck, const bool bSnapAim);
void AimTurretsAtLocalDir(const Vector3 &vLocalDir, CVehicle* pParent, const bool bDoCamCheck, const bool bSnapAim);
bool AddVehicleWeapon(CVehicleWeapon* pVehicleWeapon, s32 seatIndex);
CVehicleWeapon* GetVehicleWeapon(s32 iIndex) const { Assert(iIndex < m_iNumVehicleWeapons && iIndex > -1); return m_pVehicleWeapons[iIndex]; }
s32 GetVehicleWeaponIndexByHash(u32 iHash) const;
void DisableAllWeapons(CVehicle* pParent);
void DisableWeapon( bool bDisable, CVehicle* pParent, int index );
bool AddTurret(CTurret* pTurret, s32 seatIndex, s32 weaponIndex);
CTurret* GetTurret(s32 iIndex) const { Assert(iIndex < m_iNumTurrets && iIndex > -1); return m_pTurrets[iIndex]; }
void GetWeaponsForSeat(s32 seatIndex, atArray<CVehicleWeapon*>& weaponOut);
void GetWeaponsForSeat(s32 seatIndex, atArray<const CVehicleWeapon*>& weaponOut) const;
void GetWeaponsAndTurretsForSeat(s32 seatIndex, atArray<CVehicleWeapon*>& weaponOut, atArray<CTurret*>& turretOut);
void GetWeaponsAndTurretsForSeat(s32 seatIndex, atArray<const CVehicleWeapon*>& weaponOut, atArray<const CTurret*>& turretOut) const;
CTurret* GetFirstTurretForSeat(s32 seatIndex) const;
CFixedVehicleWeapon* GetFirstFixedWeaponForSeat(s32 seatIndex) const;
s32 GetNumWeaponsForSeat(s32 seatIndex) const;
s32 GetNumTurretsForSeat(s32 seatIndex) const;
s32 GetSeatIndexForTurret(const CTurret& rTurret) const;
s32 GetWeaponIndexForTurret(const CTurret& rTurret) const;
#if GTA_REPLAY
s32 GetSeatIndexFromWeaponIdx(s32 weaponIndex) const;
#endif
void Fire(const CPed* pFiringPed, CVehicle* pParent, s32 iWeaponIndex);
bool WantsToBeAwake(CVehicle* pParent);
s32 GetNumVehicleWeapons() const {return m_iNumVehicleWeapons;}
s32 GetNumTurrets() const {return m_iNumTurrets;}
void ResetIncludeFlags(CVehicle* pParent);
// Returns the weapon battery with weapons of the fire type specified (projectile, instant hit, etc.)
CVehicleWeaponBattery* GetWeaponBatteryOfType(eFireType fireType);
s32 GetIndexOfVehicleWeapon(const CVehicleWeapon* pVehicleWeapon) const;
protected:
CTurret* m_pTurrets[MAX_NUM_VEHICLE_TURRETS];
CVehicleWeapon* m_pVehicleWeapons[MAX_NUM_VEHICLE_WEAPONS];
s32 m_WeaponSeatIndices[MAX_NUM_VEHICLE_WEAPONS]; // Vehicle seat index that an entry in m_pVehicleWeapons is associated with
s32 m_TurretSeatIndices[MAX_NUM_VEHICLE_TURRETS]; // Vehicle seat index that an entry in m_pTurrets is associated with
s32 m_TurretWeaponIndices[MAX_NUM_VEHICLE_TURRETS]; // Vehicle weapon index (to be used as m_pVehicleWeapons lookup) that an entry in m_pTurrets is associated with
s32 m_iNumTurrets;
s32 m_iNumVehicleWeapons;
// Static functions
public:
// Creates a weapon manager if one is needed for this vehicle
// otherwise returns null
static CVehicleWeaponMgr* CreateVehicleWeaponMgr(CVehicle* pVehicle);
static bool IsValidModTypeForVehicleWeapon(eVehicleModType modtype);
};
//////////////////////////////////////////////////////////////////////////
// Lives on any CVehicle, and will attach its specified attach bone to a CTrailer when in range
class CVehicleTrailerAttachPoint : public CVehicleGadget
{
public:
// iAttachBoneIndex - The attach bone whose position we use to search for trailers near by. E.g. a truck's rear hook
CVehicleTrailerAttachPoint(s32 iAttachBoneIndex);
s32 GetType() const { return VGT_TRAILER_ATTACH_POINT; }
virtual void ProcessControl(CVehicle* pParent);
void DetachTrailer(CVehicle* pParent);
CTrailer* GetAttachedTrailer(const CVehicle* const pParent) const;
void SetAttachedTrailer( CVehicle *pTrailer );
static bank_float ms_fAttachRadius; // Tolerance distance on attach bones before attach can be made
protected:
s32 m_iAttachBone;
RegdPhy m_pTrailer;
// Dont try to re attach immediately after detaching
u32 m_uIgnoreAttachTimer;
// Static config variables
static bank_float ms_fAttachSearchRadius; // Distance of initial shapetest to look for trailers
static bank_u32 ms_uAttachResetTime;
};
//////////////////////////////////////////////////////////////////////////
//Base class for gadgets with articulated joints.
class CVehicleGadgetWithJointsBase : public CVehicleGadget
{
public:
CVehicleGadgetWithJointsBase( s16 iNumberOfJoints,
float fMoveSpeed,
float fMuscleStiffness,
float fMuscleAngleOrPositionStrength,
float fMuscleSpeedStrength,
float fMinAndMaxMuscleTorqueOrForce );
~CVehicleGadgetWithJointsBase();
virtual void ProcessPrePhysics(CVehicle* pParent);
virtual void ProcessPhysics(CVehicle* pParent, const float fTimeStep, const int nTimeSlice);
void InitJointLimits(const CVehicleModelInfo* pVehicleModelInfo);
void SetupTransmissionScale(const CVehicleModelInfo* pVehicleModelInfo, s32 boneIndex);
bool SetJointLimits(CVehicle* pParent, s16 iJointIndex, const float fOpenAngle, const float fClosedAngle);//modify joint limits, returns true if they have been modified successfully
void DriveJointToRatio(CVehicle* pParent, s16 iJointIndex, float fTargetRatio);
virtual bool WantsToBeAwake(CVehicle*);
JointInfo *GetJoint(s16 iJointIndex);
protected:
s16 m_iNumberOfJoints;
JointInfo *m_JointInfo;
float m_fMoveSpeed;
float m_fMuscleStiffness;
float m_fMuscleAngleOrPositionStrength;
float m_fMuscleSpeedStrength;
float m_fMinAndMaxMuscleTorqueOrForce;
};
//////////////////////////////////////////////////////////////////////////
// A digger arm is rotated to pick things up
class CVehicleGadgetDiggerArm : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetDiggerArm(s32 iDiggerArmBoneIndex, float fMoveSpeed);
s32 GetType() const { return VGT_DIGGER_ARM; }
void ProcessControl(CVehicle* pParent);
void InitAudio(CVehicle* pParent);
void SetDesiredPitch( float desiredPitch){GetJoint(0)->m_1dofJointInfo.m_fDesiredAngle = desiredPitch;}
void SetSnapToPosition( bool bSnapToPosition){GetJoint(0)->m_1dofJointInfo.m_bSnapToAngle = bSnapToPosition;}
void SetDesiredAcceleration( float acceleration){GetJoint(0)->m_fDesiredAcceleration = acceleration;}
float GetJointPositionRatio();
void SetDefaultRatioOverride(bool bRatioOverride) { m_bDefaultRatioOverride = bRatioOverride; }
// network methods:
virtual bool IsNetworked() const { return true; }
virtual void Serialise(CSyncDataBase& serialiser);
protected:
bool m_bDefaultRatioOverride;
audVehicleDigger* m_VehicleDiggerAudio;
float m_fJointPositionRatio;
};
/*
//Naming of the different parts of a Backhoe/JCB
// ____
// / |
// / /| |
// Boom-/ / | |
// _______ / / | |-Stick
// | |/ / | |
// ___| |__/ /__/-Bucket
// ( )
// (____________)-Base
//
*/
enum eDiggerJoints
{
DIGGER_JOINT_BASE,
DIGGER_JOINT_BOOM,
DIGGER_JOINT_STICK,
DIGGER_JOINT_BUCKET,
DIGGER_JOINT_MAX,
};
// An articulated digger arm is moved to dig up dirt
class CVehicleGadgetArticulatedDiggerArm : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetArticulatedDiggerArm( float fMoveSpeed );
void SetDiggerJointBone(eDiggerJoints diggerJointType, s32 iBoneIndex);
s32 GetType() const { return VGT_ARTICULATED_DIGGER_ARM; }
void InitAudio(CVehicle* pParent);
void ProcessControl(CVehicle* pParent);
s32 GetNumberOfSetupDiggerJoint();//returns the number of joints that have valid bone indices
bool GetJointSetup(eDiggerJoints diggerJoint);
float GetJointAngle(eDiggerJoints diggerJointType) { return GetJoint((s16)diggerJointType)->m_1dofJointInfo.m_fAngle; }
void SetDesiredAcceleration(eDiggerJoints diggerJointType, float acceleration){GetJoint((s16)diggerJointType)->m_fDesiredAcceleration = acceleration;}
protected:
audVehicleDigger* m_VehicleDiggerAudio;
float m_fMoveSpeed;
};
//////////////////////////////////////////////////////////////////////////
struct ParkingSensorInfo
{
Vector3 startPosition;
Vector3 endPosition;
};
#define PARKING_SENSOR_CAPSULE_MAX 3
// Beeps when something is close to the back of a car
class CVehicleGadgetParkingSensor : public CVehicleGadget
{
public:
CVehicleGadgetParkingSensor(CVehicle* pParent, float parkingSensorRadius = 0.4f, float parkingSensorLength = 2.5f);
s32 GetType() const { return VGT_PARKING_SENSOR; }
virtual void ProcessControl(CVehicle* pParent);
protected:
void Init(CVehicle* pParent);
bool m_BeepPlaying;
float m_TimeToStopParkingBeep;
float m_ParkingSensorRadius;
float m_ParkingSensorLength;
float m_VehicleWidth;
ParkingSensorInfo m_ParkingSensorCapsules[PARKING_SENSOR_CAPSULE_MAX];
};
//////////////////////////////////////////////////////////////////////////
// Tow truck arm and hook
class CVehicleGadgetTowArm : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetTowArm(s32 iTowArmBoneIndex, s32 iTowMountABoneIndex, s32 iTowMountBBoneIndex, float fMoveSpeed);
~CVehicleGadgetTowArm();
void DeleteRopesHookAndConstraints(CVehicle* pParent = NULL);
s32 GetType() const { return VGT_TOW_TRUCK_ARM; }
void SetPropObject(CObject* pObject) { m_PropObject = pObject; }
CObject* GetPropObject() { return m_PropObject; }
void Init(CVehicle* pParent, const CVehicleModelInfo* pVehicleModelInfo);
virtual void BlowUpCarParts(CVehicle* pParent);
void SetDesiredPitch( CVehicle *pVehicle, float desiredPitch);
void SetDesiredPitchRatio( CVehicle *pVehicle, float desiredPitchRatio);
void SetDesiredAcceleration( CVehicle *pVehicle, float acceleration);
void SetIsTeleporting(bool bIsTeleporting) { m_bIsTeleporting = bIsTeleporting; }
void ProcessPreComputeImpacts(CVehicle *pVehicle, phCachedContactIterator &impacts);
void ProcessPhysics(CVehicle* pParent, const float fTimestep, const int nTimeSlice);
void ProcessControl(CVehicle* pParent);
bool WantsToBeAwake(CVehicle *pVehicle);
void ProcessTowArmAndHook(CVehicle *pVehicle);
void ChangeLod(CVehicle & parentVehicle, int lod);
virtual void SetIsVisible(CVehicle* pParent, bool bIsVisible);
void DetachVehicle(CVehicle *pTowTruck = NULL, bool bReAttachHook = true, bool bImmediateDetach = false); // Sets a flag to detach the vehicle
const CVehicle* GetAttachedVehicle() const;
void AttachRopesToObject( CVehicle* pParent, CPhysical *pObject, s32 iComponentIndex = 0, bool REPLAY_ONLY(bReattachHook) = false );
void AttachVehicleToTowArm( CVehicle *pTowTruck, CVehicle *pVehicleToAttach, const Vector3 &vPositionToAttach, s32 iComponentIndex = 0 );
void AttachVehicleToTowArm( CVehicle *pTowTruck, CVehicle *pVehicleToAttach, s16 vehicleBoneIndex, const Vector3 &vVehicleOffsetPosition, s32 iComponentIndex = 0 );
int GetGadgetEntities(int entityListSize, const CEntity ** entityListOut) const;
void WarpToPosition(CVehicle* pTowTruck, bool bUpdateConstraints = true);
void Teleport(CVehicle *pTwoTruck, const Matrix34 &matOld);
ropeInstance* GetRopeA() const { return m_RopeInstanceA; }
ropeInstance* GetRopeB() const { return m_RopeInstanceB; }
void SetRopeA(ropeInstance* rope) { m_RopeInstanceA = rope; }
void SetRopeB(ropeInstance* rope) { m_RopeInstanceB = rope; }
bool IsRopeAndHookInitialised() const { return m_bRopesAndHookInitialized; }
#if GTA_REPLAY
void SnapToAngleForReplay(float snapToAngle);
#endif //GTA_REPLAY
protected:
void ActuallyDetachVehicle( CVehicle *pTowTruck, bool bReattachHook = true ); // This function actually detached the vehicle inside process physics
void UpdateConstraintDistance( CVehicle *pTowTruck );
void UpdateHookPosition(CVehicle *pTowTruck, bool bUpdateConstraints = false);
void UpdateTowedVehiclePosition(CVehicle *pTowTruck, CVehicle *pVehicleToAttach);
float GetTowArmPositionRatio();
void GetTowHookIdealPosition(CVehicle *pParent, Vector3 &vecTowHookIdealPosition_Out, float fTowArmPositionRatio);
void SetDesiredHookPositionWithDamage(CVehicle *pVehicleToAttach, float hookVehicleOffsetY, float hookPointPositionZ);
void EnforceConstraintLimits(phConstraintRotation* pConstraint, float fMin, float fMax, float fCurrent, bool bIsPitch);
void AddRopesAndHook(CVehicle & parentVehicle);
void RemoveRopesAndHook();
inline bool HasTowArm() {return m_iNumberOfJoints > 0;}
bool IsPickUpFromTopVehicle(const CVehicle *pParent) const;
bool m_Setup;
bool m_bHoldsDrawableRef;
bool m_bRopesAndHookInitialized;
bool m_bJointLimitsSet;
bool m_bIsTeleporting;
s32 m_iTowMountAChild;
s32 m_iTowMountA;
s32 m_iTowMountBChild;
s32 m_iTowMountB;
f32 m_fPrevJointPosition;
float m_LastTowArmPositionRatio;//used to work out whether we should be winding the rope
bool m_HookRestingOnTruck;
Vector3 m_vLastFramesDistance;
RegdObj m_PropObject;
float m_fForceMultToApplyInConstraint;
audVehicleTowTruckArm* m_VehicleTowArmAudio;
ropeInstance* m_RopeInstanceA;
ropeInstance* m_RopeInstanceB;
phInst* m_RopesAttachedVehiclePhysicsInst; // The physics inst the rope is attached to
phConstraintHandle m_posConstraintHandle;
phConstraintHandle m_sphericalConstraintHandle;
phConstraintHandle m_rotYConstraintHandle;
RegdPhy m_pTowedVehicle;
bool m_bDetachVehicle;
u32 m_uIgnoreAttachTimer; // Don't try to re attach immediately after detaching
Vector3 m_vTowedVehicleOriginalAngDamp;
Vector3 m_vStartTowHookPosition;// varaible to deal with lerping the initial hoom position to the middle of the car
Vector3 m_vCurrentTowHookPosition;
Vector3 m_vDesiredTowHookPosition;
float m_fTowTruckPositionTransitionTime; //1.0f if the tow hook has moved to the center of the car
Vec3V m_vLocalPosConstraintStart;
bool m_bUsingSphericalConstraint;
bool m_bTowTruckTouchingTowVehicle;
bool m_bIsVisible;
// Static config variables
static bank_float ms_fAttachSearchRadius; // Distance of initial shape test to look for trailers
static bank_float ms_fAttachRadius; // Tolerance distance on attach bones before attach can be made
static bank_u32 ms_uAttachResetTime;
};
//////////////////////////////////////////////////////////////////////////
// A forklift's forks
class CVehicleGadgetForks : public CVehicleGadgetWithJointsBase
{
public:
enum PalletBounds
{
// The "extra" bounds added at runtime for better stability.
PALLET_EXTRA_BOX_BOUND_MIDDLE,
PALLET_EXTRA_BOX_BOUND_TOP,
PALLET_EXTRA_BOX_BOUND_BOTTOM,
NUM_EXTRA_PALLET_BOUNDS
};
CVehicleGadgetForks(s32 iForksBoneIndex, s32 iCarriageBoneIndex, float fMoveSpeed);
s32 GetType() const { return VGT_FORKS; }
void Init(CVehicle* pVehicle);
virtual void InitJointLimits(const CVehicleModelInfo* pModelInfo);
static void CreateNewBoundsForPallet(phArchetypeDamp* pPhysics, float vBoundingBoxMinZ, float vBoundingBoxMaxZ, bool bAddTopAndBottomBoxBounds);
static void SetTypeAndIncludeFlagsForPallet(CObject* pObject, u32 nIndexOfFirstExtraBoxBound, const bool bAddTopAndBottomBoxBounds);
void SetDesiredHeight( float desiredPosition){GetJoint(0)->m_PrismaticJointInfo.m_fDesiredPosition = desiredPosition;}
void SetDesiredAcceleration( float acceleration);
void ProcessControl(CVehicle* pParent);
void ProcessPreComputeImpacts(CVehicle *pVehicle, phCachedContactIterator &impacts);
void AttachPalletInstanceToForks(CEntity* pPallet);
void DetachPalletFromForks();
void DetachPalletImmediatelyAndCleanUp(CVehicle* pParent);
bool IsAtLowestPosition();
bool CanMoveForksUp() { return m_bCanMoveForksUp; }
bool CanMoveForksDown() { return m_bCanMoveForksDown; }
void LockForks() { m_bForksLocked = true; }
void UnlockForks() { m_bForksLocked = false; }
bool AreForksLocked() const { return m_bForksLocked; }
virtual bool WantsToBeAwake(CVehicle*);
// Does a breadth first walk over the tree of attachments to the pallet and stores a list
// of all nodes in the atArray passed in.
void PopulateListOfAttachedObjects();
// Get a reference to the list objects attached to the forks. The camera code (for example) can query this
// to know which objects it should ignore occlusion clipping on.
// NB - This is a const-reference since the forklift attach/detach code should be the only thing altering
// this list!
atArray<CPhysical*> const& GetListOfAttachedObjects() const { return m_AttachedObjects; }
#if __BANK
static void RenderDebug();
#endif // __BANK
#if __BANK
static bool ms_bShowAttachFSM;
static bool ms_bDrawForkAttachPoints;
static bool ms_bHighlightExtraPalletBoundsInUse;
static bool ms_bDrawContactsInExtraPalletBounds;
static bool ms_bRenderDebugInfoForSelectedPallet;
static bool ms_bRenderTuningValuesForSelectedPallet;
static float ms_fPalletAttachBoxWidth;
static float ms_fPalletAttachBoxLength;
static float ms_fPalletAttachBoxHeight;
static float ms_vPalletAttachBoxOriginX;
static float ms_vPalletAttachBoxOriginY;
static float ms_vPalletAttachBoxOriginZ;
#endif // __BANK
// network methods:
virtual bool IsNetworked() const { return true; }
virtual void Serialise(CSyncDataBase& serialiser);
protected:
enum eForkLiftAttachState
{
UNATTACHED = 0,
READY_TO_ATTACH,
ATTACHING,
ATTACHED,
DETACHING
};
audVehicleForks* m_VehicleForksAudio;
eForkLiftAttachState m_attachState;
f32 m_PrevPrismaticJointDistance;
s32 m_iForksChild;
s32 m_iForks;
s32 m_iCarriageChild;
s32 m_iCarriage;
// Constraint for attaching pallet to forklift.
phConstraintHandle m_constraintHandle;
// This is a reference to the pallet for attaching / detaching.
RegdEnt m_pAttachEntity;
atArray<CPhysical*> m_AttachedObjects;
// This variable is used to force a pallet to be attached, usually after warping it through script.
bool m_bForceAttach;
bool m_bCanMoveForksUp;
bool m_bCanMoveForksDown;
// Set by script to stop the forks moving under player control.
bool m_bForksLocked;
// Used for deciding on the context of whether the forks should collide against the middle box bound
// or the two outer box bounds.
bool m_bForksWithinPalletMiddleBox;
bool m_bForksInRegionAboveOrBelowPallet;
bool m_bForksWereWithinPalletMiddleBox;
bool m_bForksWereInRegionAboveOrBelowPallet;
};
//////////////////////////////////////////////////////////////////////////
// Class to support the "Handler" vehicle.
class CVehicleGadgetHandlerFrame : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetHandlerFrame(s32 iFrame1BoneIndex, s32 iFrame2BoneIndex, float fMoveSpeed);
s32 GetType() const { return VGT_HANDLER_FRAME; }
void Init(CVehicle* pVehicle);
virtual void InitJointLimits(const CVehicleModelInfo* pModelInfo);
void SetDesiredHeight( float desiredPosition) { GetJoint(1)->m_PrismaticJointInfo.m_fDesiredPosition = desiredPosition; }
void SetDesiredAcceleration( float acceleration);
float GetCurrentHeight() { return GetJoint(1)->m_PrismaticJointInfo.m_fPosition; }
void ProcessControl(CVehicle* pParent);
void ProcessPreComputeImpacts(CVehicle* pVehicle, phCachedContactIterator& impacts);
bool TestForGoodAttachmentOrientation(CVehicle* pHandler, CEntity* pContainer);
void AttachContainerInstanceToFrame(CEntity* pContainer);
void AttachContainerInstanceToFrameWhenLinedUp(CEntity* pContainer);
void DetachContainerFromFrame();
bool IsAtLowestPosition();
bool IsReadyToAttach() const { return m_bReadyToAttach; }
bool CanMoveFrameUp() { return m_bCanMoveFrameUp; }
bool CanMoveFrameDown() { return m_bCanMoveFrameDown; }
void SetTryingToMoveFrameDown(bool bValue) { m_bTryingToMoveFrameDown = bValue; }
void LockFrame() { m_bHandlerFrameLocked = true; }
void UnlockFrame() { m_bHandlerFrameLocked = false; }
bool IsFrameLocked() const { return m_bHandlerFrameLocked; }
virtual bool WantsToBeAwake(CVehicle* pParent);
bool IsContainerAttached() { return m_attachEntity.GetEntity()!=NULL; }
const CEntity* GetAttachedObject() const { return m_attachEntity.GetEntity(); }
#if __BANK
void DebugFrameMotion(CVehicle* pParent);
static bool ms_bShowAttachFSM;
static bool ms_bDebugFrameMotion;
#endif // __BANK
// network methods:
virtual bool IsNetworked() const { return true; }
virtual void Serialise(CSyncDataBase& serialiser);
protected:
enum eHandlerAttachState
{
UNATTACHED = 0,
READY_TO_ATTACH,
ATTACHING,
ATTACHED,
DETACHING
};
eHandlerAttachState m_attachState;
s32 m_iFrame1;
s32 m_iFrame2;
// Constraint for attaching container to Handler.
phConstraintHandle m_constraintHandle;
// This is a reference to the container for attaching / detaching.
CSyncedEntity m_attachEntity;
// The matrix of the container at the initial point of attaching.
Matrix34 m_matContainerInitial;
// Scalar value to track how far the interpolation from initial to ideal attach matrix we are.
float m_fInterpolationValue;
// The position we are driving the frame to while attaching.
float m_fFrameDesiredAttachHeight;
//atArray<CPhysical*> m_AttachedObjects;
// This variable is used to force a container to be attached, usually after warping it through script.
bool m_bForceAttach;
// Is the frame in a good position to attach to the container?
bool m_bReadyToAttach;
bool m_bCanMoveFrameUp;
bool m_bCanMoveFrameDown;
// Is the player pushing down on the left stick?
bool m_bTryingToMoveFrameDown;
// The position at which we disabled moving the frame down.
float m_fLockedDownwardMotionPos;
// How many frames have we gone without any contact on the frame.
u32 m_nFramesWithoutCollisionHistory;
// Set by script to stop the frame moving under player control.
bool m_bHandlerFrameLocked;
audVehicleHandlerFrame* m_VehicleHandlerAudio;
f32 m_PrevPrismaticJointDistance;
// Some tunable parameters for the attachment tests.
#if __BANK
public:
#endif // __BANK
static float ms_fTestSphereRadius;
static float ms_fTransverseOffset;
static float ms_fLongitudinalOffset;
static float ms_fFrameUpwardOffsetAfterAttachment;
};
//////////////////////////////////////////////////////////////////////////
//This gadget rotates the thresher parts of the combine harvester
class CVehicleGadgetThresher : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetThresher(CVehicle* pParent, s32 iReelBoneId, s32 iAugerBoneId, float fRotationSpeed);
s32 GetType() const { return VGT_THRESHER; }
virtual void ProcessPhysics(CVehicle* pParent, const float fTimeStep, const int nTimeSlice);
protected:
s32 m_iReelBoneId;
s32 m_iAugerBoneId;
float m_ThresherAngle;
float m_fRotationSpeed;
};
//This gadget opens and closes bomb bay doors
class CVehicleGadgetBombBay : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetBombBay( s32 iDoorOneBoneId, s32 iDoorTwoBoneId, float fSpeed);
s32 GetType() const { return VGT_BOMBBAY; }
virtual void ProcessPhysics(CVehicle* pParent, const float fTimeStep, const int nTimeSlice);
void OpenDoors(CVehicle* pVehicle);
void CloseDoors(CVehicle* pVehicle);
bool GetOpen() { return m_bOpen; }
// network methods:
virtual bool IsNetworked() const { return true; }
virtual void Serialise(CSyncDataBase& serialiser);
protected:
s32 m_iDoorOneBoneId;
s32 m_iDoorTwoBoneId;
float m_fSpeed;
bool m_bOpen;
bool m_bShouldBeOpen;
};
//This gadget rotates the boat boom
class CVehicleGadgetBoatBoom : public CVehicleGadgetWithJointsBase
{
public:
CVehicleGadgetBoatBoom( s32 iBoomBoneId, float fRotationSpeed);
s32 GetType() const { return VGT_BOATBOOM; }
virtual void ProcessPhysics(CVehicle* pParent, const float fTimeStep, const int nTimeSlice);
void SwingInBoatBoom(CVehicle* pVehicle);
void SwingOutBoatBoom(CVehicle* pVehicle);
void SwingToRatio(CVehicle* pVehicle, float fTargetRatio);
void SetSwingFreely(CVehicle* pVehicle, bool bSwingFreely);
float GetPositionRatio();
void SetAllowBoomToAnimate(CVehicle* pVehicle, bool bAnimateBoom);
protected:
s32 m_iBoomBoneId;
float m_fRotationSpeed;
};
//////////////////////////////////////////////////////////////////////////
enum ePickupRopeGadgetType
{
PICKUP_HOOK,
PICKUP_MAGNET,
};
// Base for cargobob pick-up rope gadgets.
class CVehicleGadgetPickUpRope : public CVehicleGadget
{
public:
CVehicleGadgetPickUpRope(s32 iTowMountABoneIndex, s32 iTowMountBBoneIndex);
~CVehicleGadgetPickUpRope();
void DeleteRopesPropAndConstraints(CVehicle* pParent = NULL);
s32 GetType() const { return VGT_PICK_UP_ROPE; }
virtual ePickupRopeGadgetType GetPickupType() = 0;
CObject* GetPropObject() { return m_PropObject; }
void Init(CVehicle* pParent);
void BlowUpCarParts(CVehicle* pParent);
virtual void ProcessPreComputeImpacts(CVehicle *pVehicle, phCachedContactIterator &impacts);
virtual void ProcessPhysics3(CVehicle* pParent, const float fTimestep);
virtual void ProcessControl(CVehicle* pParent);
bool WantsToBeAwake(CVehicle *pVehicle);
void ChangeLod(CVehicle & parentVehicle, int lod);
void DetachEntity(CVehicle *pParentVehicle = NULL, bool bReAttachHook = true, bool bImmediateDetach = false); // Sets a flag to detach the vehicle
const CVehicle* GetAttachedVehicle() const;
const CPhysical* GetAttachedEntity() const;
void AttachRopesToObject( CVehicle* pParent, CPhysical *pObject, s32 iComponentIndex = 0 );
void AttachEntityToPickUpProp( CVehicle *pPickUpVehicle, CPhysical *pEntityToAttach, const Vector3 &vPositionToAttach, s32 iComponentIndex = 0, bool bNetAssert = true );
virtual void AttachEntityToPickUpProp( CVehicle *pPickUpVehicle, CPhysical *pEntityToAttach, s16 iBoneIndex, const Vector3 &vVehicleOffsetPosition, s32 iComponentIndex = 0, bool bNetAssert = true );
static bool ComputeIdealAttachmentOffset(const CEntity *pEntity, Vector3 &vIdealPosition);
int GetGadgetEntities(int entityListSize, const CEntity **entityListOut) const;
void WarpToPosition(CVehicle* pParentVehicle, bool bUpdateConstraints = true);
void Teleport(CVehicle *pParentVehicle, const Matrix34 &matOld);
void SetRopeLength(float fDetachedRopeLength, float fAttachedRopeLength, bool bSetRopeLengthInstantly);
bool IsDetaching() const {return m_bDetachVehicle;}
void SetForceNoVehicleDetach( bool bNoDetach ) { m_bForceDontDetachVehicle = bNoDetach; }
bool GetForceNoVehicleDetach() { return m_bForceDontDetachVehicle; }
void SetExcludeEntity( CPhysical* excludeEntity ) { m_excludeEntity = excludeEntity; }
CEntity* GetExcludeEntity() { return m_excludeEntity.GetEntity(); }
virtual void Trigger();
float GetExtraPickupBoundAllowance() const { return m_fExtraBoundAttachAllowance; }
void SetExtraPickupBoundAllowance( float extraAllowance ) { m_fExtraBoundAttachAllowance = extraAllowance; }
// network methods:
virtual bool IsNetworked() const { return true; }
virtual void Serialise(CSyncDataBase&);
float m_fDampingMultiplier;
bool m_bEnsurePickupEntityUpright; // If true, the attachment transition will always blend the picked-up entity such that it is the right way up relative to the pick-up prop.
// Otherwise, the entity will blend to whichever OOB orientation is closest.
// RAG overrides for tuning.
static bool ms_bShowDebug;
static bool ms_logCallStack;
static bool ms_bEnableDamping;
static float ms_fSpringConstant;
static float ms_fDampingConstant;
static float ms_fDampingFactor;
static float ms_fMaxDampAccel;
protected:
virtual void ProcessInRangeVehicle(CVehicle* pParent, CVehicle *pVehicle, Vector3 vPosition, Vector3 vNormal, int nComponent, phMaterialMgr::Id nMaterial, bool bIsClosest) = 0;
virtual void ProcessInRangeObject(CVehicle* pParent, CObject *pObject, Vector3 vPosition, int nComponent, phMaterialMgr::Id nMaterial, bool bIsClosest) = 0;
virtual void ProcessNothingInRange(CVehicle* pParent) = 0;
virtual Matrix34 GetPickUpPropMatrix();
virtual void ActuallyDetachVehicle( CVehicle *pParentVehicle, bool bReattachHook = true ); // This function actually detached the vehicle inside process physics
void UpdateAttachments( CVehicle *pParentVehicle );
void UpdateHookPosition(CVehicle *pParentVehicle, bool bUpdateConstraints = false);
void UpdateTowedVehiclePosition(CVehicle *pParentVehicle, CPhysical *pEntityToAttach);
void GetPickupPropIdealPosition(CVehicle *pParent, Vector3 &vecTowHookIdealPosition_Out);
void EnforceConstraintLimits(phConstraintRotation* pConstraint, float fMin, float fMax, float fCurrent, bool bIsPitch);
virtual void AddRopesAndProp(CVehicle & parentVehicle);
void RemoveRopesAndProp();
void ComputeAndSetInverseMassScale(CVehicle *pParentVehicle);
inline bool CheckObjectDimensionsForPickup(CObject *pObject);
virtual float GetPropObjectMass() = 0;
virtual s32 GetPropRopeAttachBoneA() = 0;
virtual s32 GetPropRopeAttachBoneB() = 0;
virtual s32 GetPickupAttachBone() = 0;
virtual Vector3 GetPickupAttachOffset() = 0;
virtual u32 GetAttachResetTime() = 0;
virtual float GetEntitySearchRadius() = 0;
virtual Vector3 GetEntitySearchCentreOffset() = 0;
virtual bool GetAffectsVehicles() = 0;
virtual bool GetAffectsObjects() = 0;
virtual bool ShouldBeScanningForPickup() = 0;
virtual bool UseIdealAttachPosition() = 0;
bool m_Setup;
bool m_bHoldsDrawableRef;
bool m_bRopesAndHookInitialized;
s32 m_iTowMountAChild;
s32 m_iTowMountA;
s32 m_iTowMountBChild;
s32 m_iTowMountB;
f32 m_fPrevJointPosition;
bool m_bAdjustingRopeLength;
float m_fRopeLength;
float m_fPreviousDesiredRopeLength;
float m_fDetachedRopeLength;
float m_fAttachedRopeLength;
float m_fPickUpRopeLengthChangeRate;
bool m_bUnwindRope;
//Vector3 m_vPickupPropPointDirection;
bool m_bEnableDamping;
Vector3 m_vLastFramesDistance;
RegdObj m_PropObject;
float m_fForceMultToApplyInConstraint;
audVehicleGrapplingHook* m_VehicleTowArmAudio;
ropeInstance* m_RopeInstanceA;
ropeInstance* m_RopeInstanceB;
phInst* m_RopesAttachedVehiclePhysicsInst; // The physics inst the rope is attached to
RegdPhy m_pTowedEntity;
CSyncedEntity m_excludeEntity;
bool m_bDetachVehicle;
bool m_bForceDontDetachVehicle;
bool m_bEnableFreezeWaitingOnCollision;
u32 m_uIgnoreAttachTimer; // Don't try to re attach immediately after detaching
Vector3 m_vTowedVehicleOriginalAngDamp;
Vector3 m_vTowedVehicleOriginalAngDampC;
// Information to allow for the pickup prop to lerp from the initial attach position to the "ideal" attach position (Usually so the object is centred on the pickup prop).
Vector3 m_vStartPickupPropPosition;
Vector3 m_vCurrentPickupPropPosition;
Vector3 m_vDesiredPickupPropPosition;
Quaternion m_qStartPickupPropRotation;
Quaternion m_qCurrentPickupPropRotation;
Quaternion m_qDesiredPickupPropRotation;
float m_fPickupPositionTransitionTime; //1.0f if the tow hook has moved to the center of the car
float m_fExtraBoundAttachAllowance;
private:
inline void SetupRopeWithPickupProp(CVehicle *pParent);
inline void HandleRopeVisibilityAndLength(CVehicle *pParent);
inline void DoSmoothPickupTransition(CVehicle *pParent);
inline void DampAttachedEntity(CVehicle *pParent);
inline void ScanForPickup(CVehicle *pParent);
};
//////////////////////////////////////////////////////////////////////////
// Pick up rope with a hook.
class CVehicleGadgetPickUpRopeWithHook: public CVehicleGadgetPickUpRope
{
public:
CVehicleGadgetPickUpRopeWithHook(s32 iTowMountABoneIndex, s32 iTowMountBBoneIndex);
virtual ePickupRopeGadgetType GetPickupType() {return PICKUP_HOOK; }
protected:
virtual void ProcessInRangeVehicle(CVehicle* pParent, CVehicle *pVehicle, Vector3 vPosition, Vector3 vNormal, int nComponent, phMaterialMgr::Id nMaterial, bool bIsClosest);
virtual void ProcessInRangeObject(CVehicle* pParent, CObject *pObject, Vector3 vPosition, int nComponent, phMaterialMgr::Id nMaterial, bool bIsClosest);
virtual void ProcessNothingInRange(CVehicle* UNUSED_PARAM(pParent)) {}
virtual float GetPropObjectMass() { return 50.0f; }
virtual s32 GetPropRopeAttachBoneA() { return 2; }
virtual s32 GetPropRopeAttachBoneB() { return 3; }
virtual s32 GetPickupAttachBone() { return 0; }
virtual Vector3 GetPickupAttachOffset() { return Vector3(0, 0, -0.25f); }
virtual u32 GetAttachResetTime() { return 6000; }
virtual float GetEntitySearchRadius() { return 0.4f; }
virtual Vector3 GetEntitySearchCentreOffset() { return Vector3(0, 0, 0); }
virtual bool GetAffectsVehicles() { return true; }
virtual bool GetAffectsObjects() { return true; }
virtual bool ShouldBeScanningForPickup() { return m_pTowedEntity ? false : true; }
virtual bool UseIdealAttachPosition() { return true; }
};
//////////////////////////////////////////////////////////////////////////
// Pick up rope with a magnet.
class CVehicleGadgetPickUpRopeWithMagnet : public CVehicleGadgetPickUpRope
{
public:
CVehicleGadgetPickUpRopeWithMagnet(s32 iTowMountABoneIndex, s32 iTowMountBBoneIndex);
~CVehicleGadgetPickUpRopeWithMagnet();
s32 GetType() const { return VGT_PICK_UP_ROPE_MAGNET; }
virtual ePickupRopeGadgetType GetPickupType() { return PICKUP_MAGNET; }
virtual void ProcessPhysics3(CVehicle* pParent, const float fTimestep);
virtual void ProcessPreComputeImpacts(CVehicle *pVehicle, phCachedContactIterator &impacts);
virtual void ProcessControl(CVehicle* pParent);
virtual void Trigger();
virtual void ActuallyDetachVehicle( CVehicle *pParentVehicle, bool bReattachHook = true ); // This function actually detached the vehicle inside process physics
// We do some extra stuff when something is attached to the magnet.
virtual void AttachEntityToPickUpProp( CVehicle *pPickUpVehicle, CPhysical *pEntityToAttach, s16 iBoneIndex, const Vector3 &vVehicleOffsetPosition, s32 iComponentIndex = 0, bool bNetAssert = true );
void InitAudio(CVehicle* pParent);
void SetTargetedMode(CPhysical *pTargetEntity);
void SetAmbientMode(bool bAffectVehicles, bool bAffectObjects);
CPhysical *GetTargetEntity() { return m_pAttractEntity; }
bool GetIsActive() { return m_bActive; }
// Network methods.
virtual void Serialise(CSyncDataBase&);
bool m_bOwnerSetup; // If we are running a clone version of the heli/magnet, we need to know if the owner has fully setup their ropes.
// If they haven't, we override the network blender for the magnet to prevent non-physical behaviour being forced on our physical magnet/rope system.
float m_fMagnetStrength; // Overall multiplier for the magnet force.
float m_fMagnetFalloff; // Power that defines how the magnet force magnitude drops off the further from the magnet an entity is.
float m_fReducedMagnetStrength; // Overall multiplier for the reduced magnet force applied while the magnet is not yet "active".
float m_fReducedMagnetFalloff; // Falloff for the reduced magnet effect.
float m_fMagnetPullStrength; // How strongly the magnet itself will pull towards the nearest entity.
float m_fMagnetPullRopeLength; // How much extra rope can be provided to allow the magnet to pull itself to the entity.
float m_fMagnetEffectRadius; // Size of the area of the magnet effect.
// RAG overrides for tuning.
static bool ms_bOverrideParameters;
static float ms_fMagnetStrength;
static float ms_fMagnetFalloff;
static float ms_fReducedMagnetStrength;
static float ms_fReducedMagnetFalloff;
static float ms_fMagnetPullStrength;
static float ms_fMagnetPullRopeLength;
static float ms_fMagnetEffectRadius;
private:
void DoReducedMagnet(CVehicle* pParent, CPhysical *pPhysical, Vector3 vPosition, bool bIsClosest); //, Vector3 vNormal, int nComponent, bool bIsClosest);
void DoFullMagnet(CVehicle* pParent);
inline void PointMagnetAtTarget(CVehicle* pParent, Vector3 vTargetPos);
bool m_bFullyDisabled; // No aspect of the magnet is active. For when there's no driver.
bool m_bActive;
protected:
virtual void ProcessInRangeVehicle(CVehicle* pParent, CVehicle *pVehicle, Vector3 vPosition, Vector3 vNormal, int nComponent, phMaterialMgr::Id nMaterial, bool bIsClosest);
virtual void ProcessInRangeObject(CVehicle* pParent, CObject *pObject, Vector3 vPosition, int nComponent, phMaterialMgr::Id nMaterial, bool bIsClosest);
virtual void ProcessNothingInRange(CVehicle* pParent);
virtual void AddRopesAndProp(CVehicle &parentVehicle);
virtual Matrix34 GetPickUpPropMatrix();
virtual float GetPropObjectMass() { return 50.0f; }
virtual s32 GetPropRopeAttachBoneA() { return 1; }
virtual s32 GetPropRopeAttachBoneB() { return 1; }
virtual s32 GetPickupAttachBone() { return 2; }
virtual Vector3 GetPickupAttachOffset();
virtual u32 GetAttachResetTime() { return 0; }
virtual float GetEntitySearchRadius() { return m_fMagnetEffectRadius; }
virtual Vector3 GetEntitySearchCentreOffset() { return Vector3(0, 0, -(m_fMagnetEffectRadius * 0.4f)); }
virtual bool GetAffectsVehicles() { return m_bAffectsVehicles; }
virtual bool GetAffectsObjects() { return m_bAffectsObjects; }
virtual bool ShouldBeScanningForPickup() { return true; }
virtual bool UseIdealAttachPosition() { return false; }
enum MagnetOperatingMode
{
VEH_PICK_UP_MAGNET_AMBIENT_MODE, // The magnet will affect any entity of a type specified in the type include flags below. Only one entity can be properly attached.
VEH_PICK_UP_MAGNET_TARGETED_MODE, // The magnet will affect only the entity specified as the attract entity.
};
MagnetOperatingMode m_nMode;
bool m_bAffectsVehicles;
bool m_bAffectsObjects;
RegdPhy m_pAttractEntity; // The entity that is the target of the magnet in targeted mode.
CSyncedEntity m_pNetMagnetProp;
CSyncedEntity m_pNetAttractEntity;
audVehicleGadgetMagnet* m_pAudioMagnetGadget;
};
// For updating dynamic spoilers
class CVehicleGadgetDynamicSpoiler : public CVehicleGadget
{
public:
CVehicleGadgetDynamicSpoiler();
virtual void ProcessPrePhysics(CVehicle* pParent);
virtual void Fix();
virtual s32 GetType() const { return VGT_DYNAMIC_SPOILER; }
void SetDynamicSpoilerEnabled(bool enabled) { m_bEnableDynamicSpoilers = enabled; }
void InitAudio(CVehicle* pParent);
void ResetSpoilerBones() {m_bResetSpoilerBones = true;}
protected:
audVehicleGadgetDynamicSpoiler* m_pDynamicSpoilerAudio;
float m_fCurrentSpoilerRise;
float m_fCurrentStrutRise;
float m_fCurrentSpoilerAngle;
bool m_bEnableDynamicSpoilers;
bool m_bResetSpoilerBones;
};
// For updating dynamic flaps
class CVehicleGadgetDynamicFlaps : public CVehicleGadget
{
public:
CVehicleGadgetDynamicFlaps();
virtual void ProcessPrePhysics(CVehicle* pParent);
virtual void Fix();
virtual s32 GetType() const { return VGT_DYNAMIC_SPOILER; }
void SetDynamicFlapsEnabled(bool enabled) { m_bEnableDynamicFlaps = enabled; }
void InitAudio(CVehicle* pParent);
protected:
Vec3V m_vPrevVelocity;
float m_fDesiredFlapAmount[ MAX_NUM_SPOILERS ];
bool m_bEnableDynamicFlaps;
bool m_bResetFlapBones;
};
#endif // #ifdef __VEHICLE_GADGETS_H__