Torque3D/Engine/source/T3D/player.h
2026-06-24 17:31:46 -06:00

934 lines
35 KiB
C++

//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _PLAYER_H_
#define _PLAYER_H_
#ifndef _SHAPEBASE_H_
#include "T3D/shapeBase.h"
#endif
#ifndef _BOXCONVEX_H_
#include "collision/boxConvex.h"
#endif
#include "T3D/assets/SoundAsset.h"
#include "T3D/gameBase/gameProcess.h"
class Material;
class ParticleEmitter;
class ParticleEmitterData;
class DecalData;
class SplashData;
class PhysicsPlayer;
class Player;
#ifdef TORQUE_OPENVR
class OpenVRTrackedObject;
#endif
#ifdef TORQUE_NAVIGATION_ENABLED
#include "navigation/navPath.h"
#include "navigation/navMesh.h"
#include "navigation/coverPoint.h"
#endif // TORQUE_NAVIGATION_ENABLED
//----------------------------------------------------------------------------
struct PlayerData: public ShapeBaseData /*protected AssetPtrCallback < already in shapebasedata. */ {
typedef ShapeBaseData Parent;
enum Constants {
RecoverDelayBits = 7,
ProneRecoverDelayBits = 7, //Skurps
JumpDelayBits = 7,
NumSpineNodes = 6,
ImpactBits = 3,
NUM_SPLASH_EMITTERS = 3,
BUBBLE_EMITTER = 2,
};
bool renderFirstPerson; ///< Render the player shape in first person
/// Render shadows while in first person when
/// renderFirstPerson is disabled.
bool firstPersonShadows;
StringTableEntry imageAnimPrefix; ///< Passed along to mounted images to modify
/// animation sequences played in third person. [optional]
bool allowImageStateAnimation; ///< When true a new thread is added to the player to allow for
/// mounted images to request a sequence be played on the player
/// through the image's state machine. It is only optional so
/// that we don't create a TSThread on the player if we don't
/// need to.
AssetRef<ShapeAsset> shapeFPAssetRef[ShapeBase::MaxMountedImages];
StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify
/// animation sequences played in first person. [optional]
U32 mCRCFP[ShapeBase::MaxMountedImages]; ///< Computed CRC values for the first person mounted image shapes
/// Depends on the ShapeBaseData computeCRC field.
bool mValidShapeFP[ShapeBase::MaxMountedImages]; ///< Indicates that there is a valid first person mounted image shape
F32 pickupRadius; ///< Radius around player for items (on server)
F32 maxTimeScale; ///< Max timeScale for action animations
F32 minLookAngle; ///< Lowest angle (radians) the player can look
F32 maxLookAngle; ///< Highest angle (radians) the player can look
F32 maxFreelookAngle; ///< Max left/right angle the player can look
F32 minProneLookAngle; //< Lowest angle (radians) the player can look when prone. Should be >= minLookAngle. -Skurps
F32 maxProneLookAngle; ///< Highest angle (radians) the player can look when prone. Should be <= maxLookAngle. -Skurps
/// @name Physics constants
/// @{
F32 maxStepHeight; ///< Maximum height the player can step up
F32 runSurfaceAngle; ///< Maximum angle from vertical in degrees the player can run up
F32 horizMaxSpeed; ///< Max speed attainable in the horizontal
F32 horizResistSpeed; ///< Speed at which resistance will take place
F32 horizResistFactor; ///< Factor of resistance once horizResistSpeed has been reached
F32 upMaxSpeed; ///< Max vertical speed attainable
F32 upResistSpeed; ///< Speed at which resistance will take place
F32 upResistFactor; ///< Factor of resistance once upResistSpeed has been reached
F32 fallingSpeedThreshold; ///< Downward speed at which we consider the player falling
S32 recoverDelay; ///< # tick
F32 recoverRunForceScale; ///< RunForce multiplier in recover state
F32 landSequenceTime; ///< If greater than 0 then the legacy fall recovery system will be bypassed
/// in favour of just playing the player's land sequence. The time to
/// recover from a fall then becomes this parameter's time and the land
/// sequence's playback will be scaled to match.
bool transitionToLand; ///< When going from a fall to a land, should we transition between the two?
F32 proneInSequenceTime; ///< Time for getting in prone, proneIn sequence is scaled to match this-Skurps
F32 proneDiveSequenceTime; ///< Time for diving into prone, dive sequence is scaled to match this-Skurps
F32 proneOutSequenceTime; ///< Time for getting up from prone, proneOut sequence is scaled to match this-Skurps
// Running/Walking
F32 runForce; ///< Force used to accelerate player
F32 runEnergyDrain; ///< Energy drain/tick
F32 minRunEnergy; ///< Minimum energy required to run
F32 maxForwardSpeed; ///< Maximum forward speed when running
F32 maxBackwardSpeed; ///< Maximum backward speed when running
F32 maxSideSpeed; ///< Maximum side speed when running
// Jumping
F32 jumpForce; ///< Force exerted per jump
F32 jumpEnergyDrain; ///< Energy drained per jump
F32 minJumpEnergy; ///< Minimum energy required to jump
F32 minJumpSpeed; ///< Minimum speed needed to jump
F32 maxJumpSpeed; ///< Maximum speed before the player can no longer jump
F32 jumpSurfaceAngle; ///< Angle from vertical in degrees where the player can jump
S32 jumpDelay; ///< Delay time in ticks between jumps
// Sprinting
F32 sprintForce; ///< Force used to accelerate player
F32 sprintEnergyDrain; ///< Energy drain/tick
F32 minSprintEnergy; ///< Minimum energy required to sprint
F32 maxSprintForwardSpeed; ///< Maximum forward speed when sprinting
F32 maxSprintBackwardSpeed; ///< Maximum backward speed when sprinting
F32 maxSprintSideSpeed; ///< Maximum side speed when sprinting
F32 sprintStrafeScale; ///< Amount to scale strafing motion vector while sprinting
F32 sprintYawScale; ///< Amount to scale yaw motion while sprinting
F32 sprintPitchScale; ///< Amount to scale pitch motion while sprinting
bool sprintCanJump; ///< Can the player jump while sprinting
// Swimming
F32 swimForce; ///< Force used to accelerate player while swimming
F32 maxUnderwaterForwardSpeed; ///< Maximum underwater forward speed when running
F32 maxUnderwaterBackwardSpeed; ///< Maximum underwater backward speed when running
F32 maxUnderwaterSideSpeed; ///< Maximum underwater side speed when running
F32 swimYawScale; ///< Amount to scale yaw motion while swimming -Skurps
F32 swimPitchScale; ///< Amount to scale pitch motion while swimming -Skurps
// Crouching
F32 crouchForce; ///< Force used to accelerate player while crouching
F32 maxCrouchForwardSpeed; ///< Maximum forward speed when crouching
F32 maxCrouchBackwardSpeed; ///< Maximum backward speed when crouching
F32 maxCrouchSideSpeed; ///< Maximum side speed when crouching
F32 crouchYawScale; ///< Amount to scale yaw motion while crouching -Skurps
F32 crouchPitchScale; ///< Amount to scale pitch motion while crouching -Skurps
// Prone
F32 proneForce; ///< Force used to accelerate player while prone
F32 maxProneForwardSpeed; ///< Maximum forward speed when prone
F32 maxProneBackwardSpeed; ///< Maximum backward speed when prone
F32 maxProneSideSpeed; ///< Maximum side speed when prone
F32 proneYawScale; ///< Amount to scale yaw motion while prone -Skurps
F32 pronePitchScale; ///< Amount to scale pitch motion while prone -Skurps
// Jetting
F32 jetJumpForce;
F32 jetJumpEnergyDrain; ///< Energy per jump
F32 jetMinJumpEnergy;
F32 jetMinJumpSpeed;
F32 jetMaxJumpSpeed;
F32 jetJumpSurfaceAngle; ///< Angle vertical degrees
/// @}
/// @name Hitboxes
/// @{
F32 boxHeadPercentage;
F32 boxTorsoPercentage;
//Skurps changed from Head to Torso
F32 boxTorsoLeftPercentage;
F32 boxTorsoRightPercentage;
F32 boxTorsoBackPercentage;
F32 boxTorsoFrontPercentage;
/// @}
F32 minImpactSpeed; ///< Minimum impact speed required to apply fall damage
F32 minLateralImpactSpeed; ///< Minimum impact speed required to apply non-falling damage.
F32 decalOffset;
F32 groundImpactMinSpeed; ///< Minimum impact speed required to apply fall damage with the ground
VectorF groundImpactShakeFreq; ///< Frequency in each direction for the camera to shake
VectorF groundImpactShakeAmp; ///< How much to shake
F32 groundImpactShakeDuration; ///< How long to shake
F32 groundImpactShakeFalloff; ///< How fast the shake disapates
/// Zounds!
enum Sounds {
FootSoft,
FootHard,
FootMetal,
FootSnow,
WaterStart,
FootShallowSplash,
FootWading,
FootUnderWater,
FootBubbles,
MoveBubbles,
WaterBreath,
ImpactStart,
ImpactSoft,
ImpactHard,
ImpactMetal,
ImpactSnow,
ImpactWaterEasy,
ImpactWaterMedium,
ImpactWaterHard,
ExitWater,
Crawl,//Skurps
MaxSounds
};
DECLARE_SOUNDASSET_ARRAY(PlayerData, PlayerSound, Sounds::MaxSounds);
Point3F boxSize; ///< Width, depth, height
Point3F crouchBoxSize;
Point3F proneBoxSize;
Point3F swimBoxSize;
/// Animation and other data initialized in onAdd
struct ActionAnimationDef {
const char* name; ///< Sequence name
struct Vector {
F32 x,y,z;
} dir; ///< Default direction
};
struct ActionAnimation {
const char* name; ///< Sequence name
S32 sequence; ///< Sequence index
VectorF dir; ///< Dir of animation ground transform
F32 speed; ///< Speed in m/s
bool velocityScale; ///< Scale animation by velocity
bool death; ///< Are we dying?
F32 angularSpeed; ///< Radians per frame -Skurps
};
enum {
// *** WARNING ***
// These enum values are used to index the ActionAnimationList
// array instantiated in player.cc
// The first several are selected in the move state based on velocity
RootAnim,
RunForwardAnim,
BackBackwardAnim,
SideLeftAnim,
SideRightAnim,
TurnLeftAnim, //Skurps
TurnRightAnim, //Skurps
SprintRootAnim,
SprintForwardAnim,
SprintBackwardAnim,
SprintLeftAnim,
SprintRightAnim,
CrouchRootAnim,
CrouchForwardAnim,
CrouchBackwardAnim,
CrouchLeftAnim,
CrouchRightAnim,
CrouchTurnLeftAnim, //Skurps
CrouchTurnRightAnim, //Skurps
ProneRootAnim,
ProneForwardAnim,
ProneBackwardAnim,
ProneLeftAnim, //Skurps
ProneRightAnim, //Skurps
ProneTurnLeftAnim, //Skurps
ProneTurnRightAnim, //Skurps
SwimRootAnim,
SwimForwardAnim,
SwimBackwardAnim,
SwimLeftAnim,
SwimRightAnim,
// These are set explicitly based on player actions
FallAnim,
JumpAnim,
StandJumpAnim,
LandAnim,
JetAnim,
ProneInAnim, //Skurps
ProneOutAnim, //Skurps
DiveAnim, //Skurps
NumTableActionAnims = DiveAnim + 1, //Skurps
NumExtraActionAnims = 512 - NumTableActionAnims,
NumActionAnims = NumTableActionAnims + NumExtraActionAnims,
ActionAnimBits = 10, // Skurps changed from 9
NullAnimation = (1 << ActionAnimBits) - 1
};
int mDynamicAnimsStart;
static ActionAnimationDef ActionAnimationList[NumTableActionAnims];
ActionAnimation actionList[NumActionAnims];
U32 actionCount;
U32 lookAction;
S32 spineNode[NumSpineNodes];
S32 pickupDelta; ///< Base off of pcikupRadius
F32 runSurfaceCos; ///< Angle from vertical in cos(runSurfaceAngle)
F32 jumpSurfaceCos; ///< Angle from vertical in cos(jumpSurfaceAngle)
enum Impacts {
ImpactNone,
ImpactNormal,
};
enum Recoil {
LightRecoil,
MediumRecoil,
HeavyRecoil,
NumRecoilSequences
};
S32 recoilSequence[NumRecoilSequences];
/// @name Particles
/// All of the data relating to environmental effects
/// @{
ParticleEmitterData * footPuffEmitter;
S32 footPuffID;
S32 footPuffNumParts;
F32 footPuffRadius;
DecalData* decalData;
S32 decalID;
ParticleEmitterData * dustEmitter;
S32 dustID;
SplashData* splash;
S32 splashId;
F32 splashVelocity;
F32 splashAngle;
F32 splashFreqMod;
F32 splashVelEpsilon;
F32 bubbleEmitTime;
F32 medSplashSoundVel;
F32 hardSplashSoundVel;
F32 exitSplashSoundVel;
F32 footSplashHeight;
// Air control
F32 airControl;
// Jump off surfaces at their normal rather than straight up
bool jumpTowardsNormal;
StringTableEntry mControlMap;
// For use if/when mPhysicsPlayer is created
StringTableEntry physicsPlayerType;
ParticleEmitterData* splashEmitterList[NUM_SPLASH_EMITTERS];
S32 splashEmitterIDList[NUM_SPLASH_EMITTERS];
/// @}
//
DECLARE_CONOBJECT(PlayerData);
PlayerData();
bool preload(bool server, String &errorStr) override;
void getGroundInfo(TSShapeInstance*,TSThread*,ActionAnimation*);
bool isTableSequence(S32 seq);
bool isJumpAction(U32 action);
bool isTurnAction(U32 action);//Skurps
static void initPersistFields();
void packData(BitStream* stream) override;
void unpackData(BitStream* stream) override;
void onShapeChanged()
{
reloadOnLocalClient();
}
/// @name Callbacks
/// @{
DECLARE_CALLBACK( void, onPoseChange, ( Player* obj, const char* oldPose, const char* newPose ) );
DECLARE_CALLBACK( void, onStartSwim, ( Player* obj ) );
DECLARE_CALLBACK( void, onStopSwim, ( Player* obj ) );
DECLARE_CALLBACK( void, onStartSprintMotion, ( Player* obj ) );
DECLARE_CALLBACK( void, onStopSprintMotion, ( Player* obj ) );
DECLARE_CALLBACK( void, doDismount, ( Player* obj ) );
DECLARE_CALLBACK( void, onEnterLiquid, ( Player* obj, F32 coverage, const char* type ) );
DECLARE_CALLBACK( void, onLeaveLiquid, ( Player* obj, const char* type ) );
DECLARE_CALLBACK( void, animationDone, ( Player* obj, const char* animName) );
DECLARE_CALLBACK( void, onEnterMissionArea, ( Player* obj ) );
DECLARE_CALLBACK( void, onLeaveMissionArea, ( Player* obj ) );
/// @}
protected:
void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override
{
reloadOnLocalClient();
}
};
//----------------------------------------------------------------------------
class Player: public ShapeBase
{
public:
typedef ShapeBase Parent;
enum Pose {
StandPose = 0,
SprintPose,
CrouchPose,
PronePose,
SwimPose,
NumPoseBits = 3
};
/// The ExtendedMove position/rotation index used for head movements
static S32 smExtendedMoveHeadPosRotIndex;
protected:
/// Bit masks for different types of events
enum MaskBits {
ActionMask = Parent::NextFreeMask << 0,
MoveMask = Parent::NextFreeMask << 1,
ImpactMask = Parent::NextFreeMask << 2,
TriggerMask = Parent::NextFreeMask << 3,
NextFreeMask = Parent::NextFreeMask << 4
};
SimObjectPtr<ParticleEmitter> mSplashEmitter[PlayerData::NUM_SPLASH_EMITTERS];
F32 mBubbleEmitterTime;
/// Client interpolation/warp data
struct StateDelta {
Move move; ///< Last move from server
F32 dt; ///< Last interpolation time
/// @name Interpolation data
/// @{
Point3F pos;
Point3F rot;
Point3F head;
VectorF posVec;
VectorF rotVec;
VectorF headVec;
/// @}
/// @name Warp data
/// @{
S32 warpTicks;
Point3F warpOffset;
Point3F rotOffset;
/// @}
};
StateDelta mDelta; ///< Used for interpolation on the client. @see StateDelta
S32 mPredictionCount; ///< Number of ticks to predict
// Current pos, vel etc.
Point3F mHead; ///< Head rotation, uses only x & z
Point3F mRot; ///< Body rotation, uses only z
VectorF mVelocity; ///< Velocity
VectorF mAngularVelocity; ///< Angular Velocity (only z), Radians / Sec - Skurps
VectorF mAnimVelocity; ///< Skurps
Point3F mAnchorPoint; ///< Pos compression anchor
S32 mImpactSound;
bool mUseHeadZCalc; ///< Including mHead.z in transform calculations
F32 mLastAbsoluteYaw; ///< Stores that last absolute yaw value as passed in by ExtendedMove
F32 mLastAbsolutePitch; ///< Stores that last absolute pitch value as passed in by ExtendedMove
F32 mLastAbsoluteRoll; ///< Stores that last absolute roll value as passed in by ExtendedMove
S32 mMountPending; ///< mMountPending suppresses tickDelay countdown so players will sit until
///< their mount, or another animation, comes through (or 13 seconds elapses).
/// Main player state
enum ActionState {
NullState,
MoveState,
RecoverState,
ProneRecoverState, // Skurps
NumStateBits = 4 // Skurps
};
ActionState mState; ///< What is the player doing? @see ActionState
bool mFalling; ///< Falling in mid-air?
S32 mJumpDelay; ///< Delay till next jump
Pose mPose;
bool mAllowJumping;
bool mAllowJetJumping;
bool mAllowSprinting;
bool mAllowCrouching;
bool mAllowProne;
bool mAllowSwimming;
S32 mContactTimer; ///< Ticks since last contact
Point3F mJumpSurfaceNormal; ///< Normal of the surface the player last jumped on
U32 mJumpSurfaceLastContact; ///< How long it's been since the player landed (ticks)
F32 mWeaponBackFraction; ///< Amount to slide the weapon back (if it's up against something)
SFXSource* mMoveBubbleSound; ///< Sound for moving bubbles
SFXSource* mWaterBreathSound; ///< Sound for underwater breath
SimObjectPtr<ShapeBase> mControlObject; ///< Controlling object
/// @name Animation threads & data
/// @{
struct ActionAnimation {
S32 action;
TSThread* thread;
S32 delayTicks; // before picking another.
bool forward;
bool firstPerson;
bool waitForEnd;
bool holdAtEnd;
bool animateOnServer;
bool atEnd;
bool callbackTripped;
bool useSynchedPos;
} mActionAnimation;
struct ArmAnimation {
U32 action;
TSThread* thread;
} mArmAnimation;
TSThread* mArmThread;
TSThread* mHeadVThread;
TSThread* mHeadHThread;
TSThread* mRecoilThread;
TSThread* mImageStateThread;
/// @}
bool mInMissionArea; ///< Are we in the mission area?
//
S32 mRecoverTicks; ///< same as recoverTicks in the player datablock
U32 mReversePending;
F32 mRecoverDelay; ///< When bypassing the legacy recover system and only using the land sequence,
/// this is how long the player will be in the land sequence.
F32 mProneRecoverDelay; ///< How long player takes to get up from Prone -Skurps
bool mInWater; ///< Is true if WaterCoverage is greater than zero
bool mSwimming; ///< Is true if WaterCoverage is above the swimming threshold
//
PlayerData* mDataBlock; ///< MMmmmmm...datablock...
Point3F mLastPos; ///< Holds the last position for physics updates
Point3F mLastWaterPos; ///< Same as mLastPos, but for water
#ifdef TORQUE_OPENVR
SimObjectPtr<OpenVRTrackedObject> mControllers[2];
#endif
struct ContactInfo
{
bool contacted, jump, run;
SceneObject *contactObject;
VectorF contactNormal;
void clear()
{
contacted=jump=run=false;
contactObject = NULL;
contactNormal.set(1,1,1);
}
ContactInfo() { clear(); }
} mContactInfo;
struct Death {
F32 lastPos;
Point3F posAdd;
VectorF rotate;
VectorF curNormal;
F32 curSink;
void clear() {dMemset(this, 0, sizeof(*this)); initFall();}
VectorF getPosAdd() {VectorF ret(posAdd); posAdd.set(0,0,0); return ret;}
bool haveVelocity() {return posAdd.x != 0 || posAdd.y != 0;}
void initFall() {curNormal.set(0,0,1); curSink = 0;}
Death() {clear();}
MatrixF* fallToGround(F32 adjust, const Point3F& pos, F32 zrot, F32 boxRad);
} mDeath;
PhysicsPlayer *mPhysicsRep;
// First person mounted image shapes
TSShapeInstance* mShapeFPInstance[ShapeBase::MaxMountedImages];
TSThread *mShapeFPAmbientThread[ShapeBase::MaxMountedImages];
TSThread *mShapeFPVisThread[ShapeBase::MaxMountedImages];
TSThread *mShapeFPAnimThread[ShapeBase::MaxMountedImages];
TSThread *mShapeFPFlashThread[ShapeBase::MaxMountedImages];
TSThread *mShapeFPSpinThread[ShapeBase::MaxMountedImages];
public:
// New collision
OrthoBoxConvex mConvex;
Box3F mWorkingQueryBox;
/// Standing / Crouched / Prone or Swimming
Pose getPose() const { return mPose; }
virtual const char* getPoseName() const;
/// Setting this from script directly might not actually work,
/// This is really just a helper for the player class so that its bounding box
/// will get resized appropriately when the pose changes
void setPose( Pose pose );
PhysicsPlayer* getPhysicsRep() const { return mPhysicsRep; }
#ifdef TORQUE_OPENVR
void setControllers(Vector<OpenVRTrackedObject*> controllerList);
#endif
protected:
void setState(ActionState state, U32 ticks=0);
void updateState();
// Jetting
bool mJetting;
///Update the movement
virtual void updateMove(const Move *move);
///Interpolate movement
Point3F _move( const F32 travelTime, Collision *outCol );
F32 _doCollisionImpact( const Collision *collision, bool fallingCollision);
void _handleCollision( const Collision &collision );
virtual bool updatePos(const F32 travelTime = TickSec);
// PATHSHAPE
virtual void updateAttachment();
// PATHSHAPE END
///Update head animation
void updateLookAnimation(F32 dt = 0.0f);
///Update other animations
void updateAnimation(F32 dt);
void updateAnimationTree(bool firstPerson);
bool step(Point3F *pos,F32 *maxStep,F32 time);
///See if the player is still in the mission area
void checkMissionArea();
virtual U32 getArmAction() const { return mArmAnimation.action; }
virtual bool setArmThread(U32 action);
virtual void setActionThread(U32 action,bool forward,bool hold = false,bool wait = false,bool fsp = false, bool forceSet = false);
virtual void updateActionThread();
virtual void pickBestMoveAction(U32 startAnim, U32 endAnim, U32 * action, bool * forward) const;
virtual void pickActionAnimation();
/// @name Mounted objects
/// @{
void onUnmount( SceneObject *obj, S32 node ) override;
void unmount() override;
/// @}
void setPosition(const Point3F& pos,const Point3F& viewRot);
void setRenderPosition(const Point3F& pos,const Point3F& viewRot,F32 dt=-1);
void _findContact( SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects );
void findContact( bool *run, bool *jump, VectorF *contactNormal );
void buildImagePrefixPaths(String* prefixPaths);
S32 findPrefixSequence(String* prefixPaths, const String& baseSeq);
S32 convertActionToImagePrefix(U32 action);
void onImage(U32 imageSlot, bool unmount) override;
void onImageRecoil(U32 imageSlot,ShapeBaseImageData::StateData::RecoilState) override;
void onImageStateAnimation(U32 imageSlot, const char* seqName, bool direction, bool scaleToState, F32 stateTimeOutValue) override;
const char* getImageAnimPrefix(U32 imageSlot, S32 imageShapeIndex) override;
void onImageAnimThreadChange(U32 imageSlot, S32 imageShapeIndex, ShapeBaseImageData::StateData* lastState, const char* anim, F32 pos, F32 timeScale, bool reset=false) override;
void onImageAnimThreadUpdate(U32 imageSlot, S32 imageShapeIndex, F32 dt) override;
void updateDamageLevel() override;
void updateDamageState() override;
/// Set which client is controlling this player
void setControllingClient(GameConnection* client) override;
void calcClassRenderData() override;
/// Play sound for foot contact.
///
/// @param triggeredLeft If true, left foot hit; right otherwise.
/// @param contactMaterial Material onto which the player stepped; may be NULL.
/// @param contactObject Object onto which the player stepped; may be NULL.
void playFootstepSound( bool triggeredLeft, Material* contactMaterial, SceneObject* contactObject );
/// Skurps prone crawl sound
void playCrawlSound();
/// Play an impact sound.
void playImpactSound();
/// Are we in the process of dying?
bool inDeathAnim();
F32 deathDelta(Point3F &delta);
void updateDeathOffsets();
bool inSittingAnim();
/// @name Water
/// @{
void updateSplash(); ///< Update the splash effect
void updateFroth( F32 dt ); ///< Update any froth
void updateWaterSounds( F32 dt ); ///< Update water sounds
void createSplash( Point3F &pos, F32 speed ); ///< Creates a splash
bool collidingWithWater( Point3F &waterHeight ); ///< Are we colliding with water?
/// @}
void disableHeadZCalc() { mUseHeadZCalc = false; }
void enableHeadZCalc() { mUseHeadZCalc = true; }
public:
DECLARE_CONOBJECT(Player);
DECLARE_CATEGORY("Actor \t Controllable");
Player();
~Player();
static void consoleInit();
/// @name Transforms
/// @{
void setTransform(const MatrixF &mat) override;
void getEyeTransform(MatrixF* mat) override;
void getEyeBaseTransform(MatrixF* mat, bool includeBank) override;
void getRenderEyeTransform(MatrixF* mat) override;
void getRenderEyeBaseTransform(MatrixF* mat, bool includeBank) override;
void getCameraParameters(F32 *min, F32 *max, Point3F *offset, MatrixF *rot) override;
void getMuzzleTransform(U32 imageSlot,MatrixF* mat) override;
void getRenderMuzzleTransform(U32 imageSlot,MatrixF* mat) override;
void getMuzzleVector(U32 imageSlot,VectorF* vec) override;
/// @}
F32 getSpeed() const;
Point3F getVelocity() const override;
void setVelocity(const VectorF& vel) override;
/// Apply an impulse at the given point, with magnitude/direction of vec
void applyImpulse(const Point3F& pos,const VectorF& vec) override;
/// Get the rotation of the player
const Point3F& getRotation() { return mRot; }
/// Get the rotation of the head of the player
const Point3F& getHeadRotation() { return mHead; }
void getDamageLocation(const Point3F& in_rPos, const char *&out_rpVert, const char *&out_rpQuad);
void allowAllPoses();
void allowJumping(bool state) { mAllowJumping = state; }
void allowJetJumping(bool state) { mAllowJetJumping = state; }
void allowSprinting(bool state) { mAllowSprinting = state; }
void allowCrouching(bool state) { mAllowCrouching = state; }
void allowProne(bool state) { mAllowProne = state; }
void allowSwimming(bool state) { mAllowSwimming = state; }
bool canJump(); ///< Can the player jump?
bool canJetJump(); ///< Can the player jet?
bool canSwim(); ///< Can the player swim?
bool canCrouch();
bool canStand();
bool canProne();
bool canSprint();
bool haveContact() const { return !mContactTimer; } ///< Is it in contact with something
void getMuzzlePointAI( U32 imageSlot, Point3F *point );
F32 getMaxForwardVelocity() const { return (mDataBlock != NULL ? mDataBlock->maxForwardSpeed : 0); }
bool isDisplacable() const override;
Point3F getMomentum() const override;
void setMomentum(const Point3F &momentum) override;
bool displaceObject(const Point3F& displaceVector) override;
bool checkDismountPosition(const MatrixF& oldPos, const MatrixF& newPos); ///< Is it safe to dismount here?
//
bool onAdd() override;
void onRemove() override;
bool onNewDataBlock( GameBaseData *dptr, bool reload ) override;
void onScaleChanged() override;
Box3F mScaledBox;
// Animation
const char* getStateName();
bool setActionThread(const char* sequence,bool hold,bool wait,bool fsp = false);
const String& getArmThread() const;
bool setArmThread(const char* sequence);
// Object control
void setControlObject(ShapeBase *obj) override;
ShapeBase* getControlObject() override;
//
void updateWorkingCollisionSet();
void processTick(const Move *move) override;
void interpolateTick(F32 delta) override;
void advanceTime(F32 dt) override;
bool castRay(const Point3F &start, const Point3F &end, RayInfo* info) override;
bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF &sphere) override;
void buildConvex(const Box3F& box, Convex* convex) override;
bool isControlObject();
void onCameraScopeQuery(NetConnection *cr, CameraScopeQuery *) override;
void writePacketData(GameConnection *conn, BitStream *stream) override;
void readPacketData (GameConnection *conn, BitStream *stream) override;
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream) override;
void unpackUpdate(NetConnection *conn, BitStream *stream) override;
void prepRenderImage( SceneRenderState* state ) override;
virtual void renderConvex( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
void renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRenderState *state ) override;
protected:
static void afx_consoleInit();
void afx_init();
U32 afx_packUpdate(NetConnection*, U32 mask, BitStream*, U32 retMask);
void afx_unpackUpdate(NetConnection*, BitStream*);
private:
static bool sCorpsesHiddenFromRayCast;
public:
void restoreAnimation(U32 tag) override;
U32 getAnimationID(const char* name) override;
U32 playAnimationByID(U32 anim_id, F32 pos, F32 rate, F32 trans, bool hold, bool wait, bool is_death_anim) override;
F32 getAnimationDurationByID(U32 anim_id) override;
bool isBlendAnimation(const char* name) override;
const char* getLastClipName(U32 clip_tag) override;
void unlockAnimation(U32 tag, bool force=false) override;
U32 lockAnimation() override;
bool isAnimationLocked() const override { return ((anim_clip_flags & BLOCK_USER_CONTROL) != 0); }
protected:
bool overrideLookAnimation;
F32 armLookOverridePos;
F32 headVLookOverridePos;
F32 headHLookOverridePos;
public:
void setLookAnimationOverride(bool flag);
void copyHeadRotation(const Player* p) { mHead = p->mHead; }
public:
bool ignore_updates;
void resetContactTimer() { mContactTimer = 0; }
protected:
U8 move_trigger_states;
U32 fx_s_triggers;
U32 mark_fx_c_triggers;
U32 fx_c_triggers;
F32 z_velocity;
bool mark_idle;
F32 idle_timer;
bool mark_s_landing;
void process_client_triggers(bool triggeredLeft, bool triggeredRight);
public:
enum {
// server events
PLAYER_MOVE_TRIGGER_0 = BIT(0),
PLAYER_MOVE_TRIGGER_1 = BIT(1),
PLAYER_MOVE_TRIGGER_2 = BIT(2),
PLAYER_MOVE_TRIGGER_3 = BIT(3),
PLAYER_MOVE_TRIGGER_4 = BIT(4),
PLAYER_MOVE_TRIGGER_5 = BIT(5),
PLAYER_LANDING_S_TRIGGER = BIT(6),
PLAYER_FIRE_S_TRIGGER = PLAYER_MOVE_TRIGGER_0,
PLAYER_FIRE_ALT_S_TRIGGER = PLAYER_MOVE_TRIGGER_1,
PLAYER_JUMP_S_TRIGGER = BIT(7),
// client events
PLAYER_LF_FOOT_C_TRIGGER = BIT(16),
PLAYER_RT_FOOT_C_TRIGGER = BIT(17),
PLAYER_LANDING_C_TRIGGER = BIT(18),
PLAYER_IDLE_C_TRIGGER = BIT(19),
};
U32 getClientEventTriggers() const { return fx_c_triggers; }
U32 getServerEventTriggers() const { return fx_s_triggers; }
protected:
F32 speed_bias;
F32 speed_bias_goal;
bool override_movement;
Point3F movement_data;
U8 movement_op;
U32 last_movement_tag;
static U32 unique_movement_tag_counter;
public:
void setMovementSpeedBias(F32 bias);
U32 setMovementOverride(F32 bias, const Point3F* mov=0, U32 op=1);
void restoreMovement(U32 tag);
protected:
S32 footfallDecalOverride;
S32 footfallSoundOverride;
S32 footfallDustOverride;
bool noFootfallFX;
public:
void overrideFootfallFX(bool decals=true, bool sounds=true, bool dust=true);
void restoreFootfallFX(bool decals=true, bool sounds=true, bool dust=true);
};
typedef Player::Pose PlayerPose;
DefineEnumType( PlayerPose );
#endif