📄 player.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "game/player.h"
#include "platform/platform.h"
#include "platform/profiler.h"
#include "dgl/dgl.h"
#include "dgl/materialPropertyMap.h"
#include "math/mMath.h"
#include "core/stringTable.h"
#include "core/bitStream.h"
#include "core/dnet.h"
#include "core/resManager.h"
#include "console/simBase.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "collision/extrudedPolyList.h"
#include "collision/clippedPolyList.h"
#include "collision/earlyOutPolyList.h"
#include "sim/decalManager.h"
#include "ts/tsShapeInstance.h"
#include "audio/audioDataBlock.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "sceneGraph/detailManager.h"
#include "terrain/terrData.h"
#include "terrain/terrRender.h"
#include "terrain/waterBlock.h"
#include "game/game.h"
#include "game/moveManager.h"
#include "game/gameConnection.h"
#include "game/trigger.h"
#include "game/physicalZone.h"
#include "game/item.h"
#include "game/shadow.h"
#include "game/missionArea.h"
#include "game/fx/particleEngine.h"
#include "game/fx/splash.h"
#include "game/fx/cameraFXMgr.h"
//#define ENBABLE_RPG_COLLISION
//----------------------------------------------------------------------------
// Amount we try to stay out of walls by...
static F32 sWeaponPushBack = 0.03;
// Amount of time if takes to transition to a new action sequence.
static F32 sAnimationTransitionTime = 0.25;
static bool sUseAnimationTransitions = true;
static F32 sLandReverseScale = 0.25;
static F32 sStandingJumpSpeed = 2.0;
static F32 sJumpingThreshold = 4.0;
static F32 sSlowStandThreshSquared = 1.69;
static S32 sRenderMyPlayer = true;
static S32 sRenderMyItems = true;
// Chooses new action animations every n ticks.
static const F32 sNewAnimationTickTime = 4;
static const F32 sMountPendingTickWait = (13 * 32);
// Number of ticks before we pick non-contact animations
static const S32 sContactTickTime = 30;
// Downward velocity at which we consider the player falling
static const F32 sFallingThreshold = -10;
// Movement constants
static F32 sVerticalStepDot = 0.173; // 80
static F32 sMinFaceDistance = 0.01;
static F32 sTractionDistance = 0.03;
static F32 sNormalElasticity = 0.01;
static U32 sMoveRetryCount = 5;
// Client prediction
static F32 sMinWarpTicks = 0.5; // Fraction of tick at which instant warp occures
static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
static S32 sMaxPredictionTicks = 30; // Number of ticks to predict
// Anchor point compression
const F32 sAnchorMaxDistance = 32;
//
static U32 sCollisionMoveMask = (TerrainObjectType | InteriorObjectType |
WaterObjectType | PlayerObjectType |
StaticShapeObjectType | VehicleObjectType |
PhysicalZoneObjectType | StaticTSObjectType);
static U32 sServerCollisionContactMask = (sCollisionMoveMask |
(ItemObjectType |
TriggerObjectType |
CorpseObjectType));
static U32 sClientCollisionContactMask = sCollisionMoveMask | PhysicalZoneObjectType;
enum PlayerConstants {
JumpSkipContactsMax = 8
};
//----------------------------------------------------------------------------
// Player shape animation sequences:
// look Used to contol the upper body arm motion. Must animate
// vertically +-80 deg.
Player::Range Player::mArmRange(mDegToRad(-80.0f),mDegToRad(+80.0f));
// head Used to control the direction the head is looking. Must
// animated vertically +-80 deg .
Player::Range Player::mHeadVRange(mDegToRad(-80.0f),mDegToRad(+80.0f));
// Action Animations:
PlayerData::ActionAnimationDef PlayerData::ActionAnimationList[NumTableActionAnims] =
{
// *** WARNING ***
// This array is indexed useing the enum values defined in player.h
// Root is the default animation
/// TGE_PlayerAnim
//{ "root" }, // RootAnim,
{ "idle" }, // IdleAnim,
{ "swimidle" }, // SwimIdleAnim,
// These are selected in the move state based on velocity
/// TGE_PlayerAnim
{ "walk", { 0,+1,0 } }, // WalkAnim,
{ "walk", { 0,-1,0 } }, // WalkBackwardAnim 与walk相同,在pickAction时,设为反方向播放
{ "run", { 0,+1,0 } }, // RunAnim,
{ "run", { 0,-1,0 } }, // RunBackwardAnim 与run相同,在pickAction时,设为反方向播放
{ "walk2", { 0,+1,0 } }, // Walk2Anim,
{ "walk2", { 0,-1,0 } }, // Walk2BackwardAnim 与walk相同,在pickAction时,设为反方向播放
{ "run2", { 0,+1,0 } }, // Run2Anim,
{ "run2", { 0,-1,0 } }, // Run2BackwardAnim 与run相同,在pickAction时,设为反方向播放
{ "swim", { 0,+1,0 } }, // SwimAnim,
{ "swim", { 0,-1,0 } }, // SwimBackwardAnim 与swim相同,在pickAction时,设为反方向播放
//{ "run", { 0,+1,0 } }, // RunForwardAnim,
//{ "back", { 0,-1,0 } }, // BackBackwardAnim
//{ "side", { -1,0,0 } }, // SideLeftAnim,
// These are set explicitly based on player actions
{ "agree" }, // AgreeAnim
{ "disagree" }, // DisagreeAnim
{ "bow" }, // BowAnim
{ "wave" }, // WaveAnim
{ "point" }, // PointAnim
{ "dance" }, // DanceAnim
{ "fall" }, // FallAnim
{ "jump" }, // JumpAnim
{ "standjump" }, // StandJumpAnim
{ "land" }, // LandAnim
};
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
IMPLEMENT_CO_DATABLOCK_V1(PlayerData);
PlayerData::PlayerData()
{
renderFirstPerson = true;
pickupRadius = 0;
minLookAngle = -1.4;
maxLookAngle = 1.4;
maxFreelookAngle = 3.0;
maxTimeScale = 1.5;
mass = 9;
maxEnergy = 60;
runForce = 40 * 9;
runEnergyDrain = 0;
minRunEnergy = 0;
maxForwardSpeed = 10;
maxBackwardSpeed = 10;
maxSideSpeed = 10;
maxUnderwaterForwardSpeed = 10;
maxUnderwaterBackwardSpeed = 10;
maxUnderwaterSideSpeed = 10;
#ifdef TGE_RPG
m_fRunRate = 1.5f;
#endif
maxStepHeight = 1;
runSurfaceAngle = 80;
recoverDelay = 30;
recoverRunForceScale = 1;
jumpForce = 75;
jumpEnergyDrain = 0;
minJumpEnergy = 0;
jumpSurfaceAngle = 78;
jumpDelay = 30;
minJumpSpeed = 500;
maxJumpSpeed = 2 * minJumpSpeed;
horizMaxSpeed = 80;
horizResistSpeed = 38;
horizResistFactor = 1;
upMaxSpeed = 80;
upResistSpeed = 38;
upResistFactor = 1;
minImpactSpeed = 25;
decalData = NULL;
decalID = 0;
decalOffset = 0.0f;
lookAction = 0;
// size of bounding box
boxSize.set(1,1,2.3);
// location of head, torso, legs
boxHeadPercentage = 0.85;
boxTorsoPercentage = 0.55;
// damage locations
boxHeadLeftPercentage = 0;
boxHeadRightPercentage = 1;
boxHeadBackPercentage = 0;
boxHeadFrontPercentage = 1;
for (S32 i = 0; i < MaxSounds; i++)
sound[i] = 0;
footPuffEmitter = NULL;
footPuffID = 0;
footPuffNumParts = 15;
footPuffRadius = .25;
dustEmitter = NULL;
dustID = 0;
splash = NULL;
splashId = 0;
splashVelocity = 1.0;
splashAngle = 45.0;
splashFreqMod = 300.0;
splashVelEpsilon = 0.25;
bubbleEmitTime = 0.4;
medSplashSoundVel = 2.0;
hardSplashSoundVel = 3.0;
exitSplashSoundVel = 2.0;
footSplashHeight = 0.1;
dMemset( splashEmitterList, 0, sizeof( splashEmitterList ) );
dMemset( splashEmitterIDList, 0, sizeof( splashEmitterIDList ) );
genericShadowLevel = Player_GenericShadowLevel;
noShadowLevel = Player_NoShadowLevel;
groundImpactMinSpeed = 10.0;
groundImpactShakeFreq.set( 10.0, 10.0, 10.0 );
groundImpactShakeAmp.set( 20.0, 20.0, 20.0 );
groundImpactShakeDuration = 1.0;
groundImpactShakeFalloff = 10.0;
}
bool PlayerData::preload(bool server, char errorBuffer[256])
{
if(!Parent::preload(server, errorBuffer))
return false;
#ifdef TGE_RPG
if(server)
return true;
#endif
// Resolve objects transmitted from server
if (!server)
{
for (S32 i = 0; i < MaxSounds; i++)
if (sound[i])
Sim::findObject(SimObjectId(sound[i]),sound[i]);
}
//
runSurfaceCos = mCos(mDegToRad(runSurfaceAngle));
jumpSurfaceCos = mCos(mDegToRad(jumpSurfaceAngle));
if (minJumpEnergy < jumpEnergyDrain)
minJumpEnergy = jumpEnergyDrain;
// Validate some of the data
if (recoverDelay > (1 << RecoverDelayBits) - 1) {
recoverDelay = (1 << RecoverDelayBits) - 1;
Con::printf("PlayerData:: Recover delay exceeds range (0-%d)",recoverDelay);
}
if (jumpDelay > (1 << JumpDelayBits) - 1) {
jumpDelay = (1 << JumpDelayBits) - 1;
Con::printf("PlayerData:: Jump delay exceeds range (0-%d)",jumpDelay);
}
#ifdef TGE_RPG
if(shape)
{
#endif
// Go ahead a pre-load the player shape
TSShapeInstance* si = new TSShapeInstance(shape, false);
TSThread* thread = si->addThread();
// Extract ground transform velocity from animations
// Get the named ones first so they can be indexed directly.
ActionAnimation *dp = &actionList[0];
for (int i = 0; i < NumTableActionAnims; i++,dp++)
{
ActionAnimationDef *sp = &ActionAnimationList[i];
dp->name = sp->name;
dp->dir.set(sp->dir.x,sp->dir.y,sp->dir.z);
dp->sequence = shape->findSequence(sp->name);
dp->velocityScale = true;
dp->death = false;
if (dp->sequence != -1)
getGroundInfo(si,thread,dp);
#ifdef TGE_RPG
if(GameBase::g_bInGameWorld)
#endif
AssertWarn(dp->sequence != -1, avar("PlayerData::preload - Unable to find named animation sequence '%s'!", sp->name));
}
for (int b = 0; b < shape->sequences.size(); b++)
{
if (!isTableSequence(b))
{
dp->sequence = b;
dp->name = shape->getName(shape->sequences[b].nameIndex);
dp->velocityScale = false;
getGroundInfo(si,thread,dp++);
}
}
actionCount = dp - actionList;
AssertFatal(actionCount <= NumActionAnims, "Too many action animations!");
delete si;
// Resolve lookAction index
dp = &actionList[0];
const char *lookName = StringTable->insert("look");
for (int c = 0; c < actionCount; c++,dp++)
if (dp->name == lookName)
lookAction = c;
// Resolve spine
spineNode[0] = shape->findNode("Bip01 Pelvis");
spineNode[1] = shape->findNode("Bip01 Spine");
spineNode[2] = shape->findNode("Bip01 Spine1");
spineNode[3] = shape->findNode("Bip01 Spine2");
spineNode[4] = shape->findNode("Bip01 Neck");
spineNode[5] = shape->findNode("Bip01 Head");
// Recoil animations
recoilSequence[0] = shape->findSequence("light_recoil");
recoilSequence[1] = shape->findSequence("medium_recoil");
recoilSequence[2] = shape->findSequence("heavy_recoil");
#ifdef TGE_RPG
}//if(shape)
#endif
// Lookup shadow node (shadow center moves in synch with this node)
shadowNode = spineNode[0];
// Convert pickupRadius to a delta of boundingBox
F32 dr = (boxSize.x > boxSize.y)? boxSize.x: boxSize.y;
if (pickupRadius < dr)
pickupRadius = dr;
else
if (pickupRadius > 2 * dr)
pickupRadius = 2 * dr;
pickupDelta = (S32)(pickupRadius - dr);
// Validate jump speed
if (maxJumpSpeed <= minJumpSpeed)
maxJumpSpeed = minJumpSpeed + 0.1;
// Load up all the emitters
if (!footPuffEmitter && footPuffID != 0)
if (!Sim::findObject(footPuffID, footPuffEmitter))
Con::errorf(ConsoleLogEntry::General, "PlayerData::preload - Invalid packet, bad datablockId(footPuffEmitter): 0x%x", footPuffID);
if (!decalData && decalID != 0 )
if (!Sim::findObject(decalID, decalData))
Con::errorf(ConsoleLogEntry::General, "PlayerData::preload - Invalid packet, bad datablockId(decalData): 0x%x", decalID);
if (!dustEmitter && dustID != 0 )
if (!Sim::findObject(dustID, dustEmitter))
Con::errorf(ConsoleLogEntry::General, "PlayerData::preload - Invalid packet, bad datablockId(dustEmitter): 0x%x", dustID);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -