⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 movemgr.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "client_de.h"
#include "physics_lt.h"
#include "MoveMgr.h"
#include "BloodClientShell.h"
#include "SharedMovement.h"
#include "Commands.h"
#include "ClientServerShared.h"
#include "SharedDefs.h"
#include "ClientUtilities.h"


#define MIN_SWIM_ON_SURFACE_TIME	0.5f
#define SPECTATOR_ACCELERATION		100000.0f

#define LADDER_STOP_TIME			0.2f
#define SWIM_STOP_TIME				1.0f
#define DEFAULT_JUMPVEL				600.0f


// Values to use for acceleration & velocity
//DFLOAT gMoveAccel[6] = { 3300.0f, 3750.0f, 4200.0f, 4650.0f, 4950.0f, 5250.0f };
static DFLOAT fDragCoeff = 15.0f;

// Max velocity is gMoveAccel/fDragCoeff




class Pusher
{
public:
			Pusher()
			{
				m_Link.m_pData = this;
			}
	
	DVector	m_Pos;
	float	m_Radius;
	float	m_Delay;	// How long before it starts actually pushing.
	float	m_TimeLeft; // Time left for this sphere.
	float	m_Strength;
	DLink	m_Link;
};


CMoveMgr::CMoveMgr(CBloodClientShell *pShell)
{
	VEC_SET(m_WantedDims, 1, 1, 1);
	m_nStillAnims		= 0;
	m_bSwimmingJump		= DFALSE;
	m_eLastContainerCode= CC_NOTHING;
	m_nContainers		= 0;
	m_hObject			= DNULL;
	m_pClientDE			= DNULL;
	m_pClientShell		= pShell;
	dl_TieOff(&m_Pushers);
	m_dwControlFlags	= 0;
	m_dwLastControlFlags= 0;
	m_bMovementBlocked	= DFALSE;
	m_bForcedCrouch		= DFALSE;
	m_wLastChangeFlags	= 0;
	m_eLastSurface		= SURFTYPE_UNKNOWN;
}


CMoveMgr::~CMoveMgr()
{
	DLink *pCur, *pNext;

	for(pCur=m_Pushers.m_pNext; pCur != &m_Pushers; pCur=pNext)
	{
		pNext = pCur->m_pNext;
		delete (Pusher*)pCur->m_pData;
	}
	dl_TieOff(&m_Pushers);
}


DBOOL CMoveMgr::Init(ClientDE *pClientDE)
{
	m_pClientDE = pClientDE;
	m_pPhysicsLT = pClientDE->Physics();

	// Init some defaults.  These should NEVER get used because we don't
	// have our object until the server sends the physics update.
	m_fMoveVel = 0.0f;
	m_fJumpVel = DEFAULT_JUMPVEL;
	m_fSwimVel = DEFAULT_SWIM_VEL;
	m_fLadderVel = DEFAULT_LADDER_VEL;
	m_fFrictionCoeff = 0.0f;
	m_fMoveMultiplier = 1.0f;
	m_bBodyInLiquid = DFALSE;
	m_bBodyOnLadder = DFALSE;
	m_bBodyOnConveyor = DFALSE;
	m_bOnGround = DTRUE;
	m_nMouseStrafeFlags = 0;
	m_bSwimmingOnSurface = DFALSE;
	m_bCanSwimJump = DFALSE;

	m_fLeashLen = 100.0f;
	m_fBaseMoveAccel = 0.0f;
	m_fMoveAccelMultiplier = 1.0f;
	m_fJumpMultiplier = 1.0f;

	VEC_INIT( m_vServerVelocity );

	return DTRUE;
}


void CMoveMgr::UpdateAxisMovement(DBOOL bUseAxisForwardBackward, float fForwardBackward, float fForwardBackwardDeadZone,
								 DBOOL bUseAxisLeftRight, float fLeftRight, float fLeftRightDeadZone )
{
	m_bUseAxisForwardBackward = bUseAxisForwardBackward;
	m_fAxisForwardBackwardVel = fForwardBackward;
	m_fAxisForwardBackwardDeadZone = fForwardBackwardDeadZone;
	m_bUseAxisLeftRight = bUseAxisLeftRight;
	m_fAxisLeftRightVel = fLeftRight;
	m_fAxisLeftRightDeadZone = fLeftRightDeadZone;
}


void CMoveMgr::UpdateControlFlags()
{
	// Clear control flags...

	m_dwLastControlFlags = m_dwControlFlags;
	m_dwControlFlags = 0; 


	// Make sure it's ok for us to move...

	if (g_pBloodClientShell->IsDead()) return;
	if (!(m_pClientShell->GetCDataFlags() & CDATA_CANMOVE)) return;
	if (g_pBloodClientShell->IsWonkyNoMove()) return;	// [blg] 01/13/99


	// Determine what commands are currently on...

	if (m_pClientDE->IsCommandOn(COMMAND_RUN) || m_pClientShell->GetCDataFlags() & CDATA_RUNLOCK)
	{
		m_dwControlFlags |= CTRLFLAG_RUN;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_JUMP))
	{
		m_dwControlFlags |= CTRLFLAG_JUMP;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_DUCK))
	{
		m_dwControlFlags |= CTRLFLAG_CROUCH;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_FORWARD))
	{
		m_dwControlFlags |= CTRLFLAG_FORWARD;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_BACKWARD))
	{
		m_dwControlFlags |= CTRLFLAG_BACKWARD;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_LEFT))
	{
		m_dwControlFlags |= CTRLFLAG_LEFT;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_RIGHT))
	{
		m_dwControlFlags |= CTRLFLAG_RIGHT;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_STRAFE))
	{
		m_dwControlFlags |= CTRLFLAG_STRAFE;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_STRAFERIGHT))
	{
		m_dwControlFlags |= CTRLFLAG_STRAFERIGHT;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_STRAFELEFT))
	{
		m_dwControlFlags |= CTRLFLAG_STRAFELEFT;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_FIRE))
	{
		m_dwControlFlags |= CTRLFLAG_FIRE;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_ALTFIRE))
	{
		m_dwControlFlags |= CTRLFLAG_ALTFIRE;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_GRAB))
	{
		m_dwControlFlags |= CTRLFLAG_GRAB;
	}

	if (m_pClientDE->IsCommandOn(COMMAND_TAUNT))
	{
		m_dwControlFlags |= CTRLFLAG_TAUNT;
	}
}


void CMoveMgr::UpdateInLiquid(CContainerInfo *pInfo)
{
	if(pInfo->m_bHidden)
		return;

	// If head is above water and standing on something, then don't inhibit movement.
	DBOOL bHeadInLiquid = IsLiquid(m_pClientShell->GetCurContainerCode());

	// Don't limit velocity if on the ground
	if( !bHeadInLiquid && m_bOnGround )
		return;

	m_bBodyInLiquid = DTRUE;

	// Do REAL friction dampening (i.e., actually change our velocity)...

	DVector vVel;
	m_pPhysicsLT->GetVelocity(m_hObject, &vVel);

	DFLOAT fTimeDelta = m_FrameTime;

	DVector vCurVel;
	VEC_COPY(vCurVel, vVel);

	if (VEC_MAG(vCurVel) > 1.0f)
	{
		DVector vDir;
		VEC_COPY(vDir, vCurVel);
		VEC_NORM(vDir);

		DFLOAT fAdjust = m_FrameTime*(m_fSwimVel/SWIM_STOP_TIME);

		VEC_MULSCALAR(vVel, vDir, fAdjust);

		if (VEC_MAG(vVel) < VEC_MAG(vCurVel))
		{
			VEC_SUB(vVel, vCurVel, vVel);
		}
		else
		{
			VEC_INIT(vVel);
		}
	}

	DVector curAccel;
	m_pPhysicsLT->GetAcceleration(m_hObject, &curAccel);

	// Handle floating around on the surface...

	if (m_bSwimmingOnSurface)
	{
		DBOOL bMoving = ((VEC_MAG(curAccel) > 0.01f) || (VEC_MAG(vVel) > 0.01f));
	
		// Disable gravity.
		m_pClientDE->SetObjectFlags(m_hObject, 
			m_pClientDE->GetObjectFlags(m_hObject) & ~FLAG_GRAVITY);

		if (bMoving)  // Turn off y acceleration and velocity
		{
			if (vVel.y > 0.0f || curAccel.y > 0.0f)
			{
				vVel.y = 0.0f;
				curAccel.y = 0.0f;
			}
		}
		else // Pull us down if we're not moving (fast enough)
		{
			curAccel.y += pInfo->m_fGravity;
		}
	}
	else if (IsLiquid(pInfo->m_ContainerCode))
	{
		m_pClientDE->SetObjectFlags(m_hObject, 
			m_pClientDE->GetObjectFlags(m_hObject) & ~FLAG_GRAVITY);

		curAccel.y += pInfo->m_fGravity;
	}

	m_pPhysicsLT->SetVelocity(m_hObject, &vVel);
	m_pPhysicsLT->SetAcceleration(m_hObject, &curAccel);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::UpdateOnLadder
//
//	PURPOSE:	Update movement when on a ladder
//
// ----------------------------------------------------------------------- //

void CMoveMgr::UpdateOnLadder(CContainerInfo *pInfo)
{
	if(pInfo->m_bHidden)
		return;

	m_bBodyOnLadder = DTRUE;

	// Do REAL friction dampening (i.e., actually change our velocity)...

	DVector vVel;
	m_pPhysicsLT->GetVelocity(m_hObject, &vVel);

	DVector vCurVel;
	VEC_COPY(vCurVel, vVel);

	if (VEC_MAG(vCurVel) > 1.0f)
	{
		DVector vDir;
		VEC_COPY(vDir, vCurVel);
		VEC_NORM(vDir);

		DFLOAT fAdjust = m_FrameTime*(m_fLadderVel/LADDER_STOP_TIME);

		VEC_MULSCALAR(vVel, vDir, fAdjust);

		if (VEC_MAG(vVel) < VEC_MAG(vCurVel))
		{
			VEC_SUB(vVel, vCurVel, vVel);
		}
		else
		{
			VEC_INIT(vVel);
		}

		m_pPhysicsLT->SetVelocity(m_hObject, &vVel);
	}

	m_pClientDE->SetObjectFlags(m_hObject, 
		m_pClientDE->GetObjectFlags(m_hObject) & ~FLAG_GRAVITY);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::UpdateOnConveyor
//
//	PURPOSE:	Update movement when on a conveyor.  Just use ladder
//				restrictions.
//
// ----------------------------------------------------------------------- //

void CMoveMgr::UpdateOnConveyor(CContainerInfo *pInfo)
{
	if(pInfo->m_bHidden)
		return;

	m_bBodyOnConveyor = DTRUE;

	// Do REAL friction dampening (i.e., actually change our velocity)...

	DVector vVel;
	m_pPhysicsLT->GetVelocity(m_hObject, &vVel);

	DVector vCurVel;
	VEC_COPY(vCurVel, vVel);

	if (VEC_MAG(vCurVel) > 1.0f)
	{
		DVector vDir;
		VEC_COPY(vDir, vCurVel);
		VEC_NORM(vDir);

		DFLOAT fAdjust = m_FrameTime*(m_fLadderVel/LADDER_STOP_TIME);

		VEC_MULSCALAR(vVel, vDir, fAdjust);

		if (VEC_MAG(vVel) < VEC_MAG(vCurVel))
		{
			VEC_SUB(vVel, vCurVel, vVel);
		}
		else
		{
			VEC_INIT(vVel);
		}

		m_pPhysicsLT->SetVelocity(m_hObject, &vVel);
	}
}

void CMoveMgr::UpdateOnGround(CollisionInfo *pInfo)
{
	DVector vAccel, vCross1, vCross2;
	DVector vVel;

	// Lets see if we are in the ground or in the air.

	m_pPhysicsLT->GetStandingOn(m_hObject, pInfo);

	if (pInfo->m_hObject) 
	{
		m_bOnGround = DTRUE;

		// Get the last surface type (for footsteps, etc)
		m_eLastSurface = ::GetSurfaceType(pInfo->m_hObject, pInfo->m_hPoly);

		// Don't allow climbing slopes greater than 60 degrees.
		if( pInfo->m_Plane.m_Normal.y < 0.5 )
		{
			m_pPhysicsLT->GetAcceleration( m_hObject, &vAccel );
			DVector vCross1, vCross2;
			VEC_SET(vCross1, 0.0, 1.0, 0.0);
			VEC_CROSS(vCross2, pInfo->m_Plane.m_Normal, vCross1);
			VEC_NORM(vCross2);
			VEC_CROSS(vCross1, vCross2, pInfo->m_Plane.m_Normal);
			VEC_MULSCALAR(vCross1, vCross1, -2000.0f);
			VEC_ADD(vAccel, vAccel, vCross1);
			m_pPhysicsLT->SetAcceleration( m_hObject, &vAccel );

			m_bOnGround = DFALSE;

			// Force us down...

			m_pPhysicsLT->GetVelocity(m_hObject, &vVel);

			vVel.y = - VEC_MAG(vVel);
			vVel.x = vVel.z = 0.0f;
			m_pPhysicsLT->SetVelocity(m_hObject, &vVel);
		}
	} 
	else 
	{
		m_bOnGround = DFALSE;
	}
}


DBOOL CMoveMgr::IsBodyInLiquid()
{
	DDWORD i;

	for(i=0; i < m_nContainers; i++)
	{
		if(IsLiquid(m_Containers[i].m_ContainerCode))
			return DTRUE;
	}
	return DFALSE;
}


DBOOL CMoveMgr::IsDead()
{
	return m_pClientShell->IsDead();
}


void CMoveMgr::UpdateMotion()
{
	DVector		vMyVel;
	DVector		vAccel;
	DVector		vUp;
	DVector		vRight;
	DVector		vForward;
	DVector		vMyPos;
	DFLOAT		fMaxMoveAccel;
	DFLOAT		fMaxMoveVel;
	DFLOAT		fMoveAccel = 0.0;
	DFLOAT		fStrafeAccel = 0;
	DFLOAT		fMoveVel;
	DFLOAT		fOrigMaxMoveVel;

	// Normally we have gravity on, but the containers might turn it off.
	DDWORD dwFlags = m_pClientDE->GetObjectFlags(m_hObject);

	if(!m_pClientShell->IsSpectatorMode())
	{
		dwFlags |= FLAG_GRAVITY | FLAG_SOLID;
		dwFlags &= ~(FLAG_GOTHRUWORLD);
	}
	else
	{
		dwFlags &= ~(FLAG_SOLID | FLAG_GRAVITY);
		dwFlags |= FLAG_GOTHRUWORLD;
	}

	m_pClientDE->SetObjectFlags(m_hObject, dwFlags);
	
	// Zero acceleration to start with
	VEC_INIT(vAccel);
	m_pPhysicsLT->SetAcceleration(m_hObject, &vAccel);


	// Get the axis offset
	DFLOAT offsets[3];
	g_pClientDE->GetAxisOffsets(offsets);

	DFLOAT fMouseAxis0 = offsets[0];
	DFLOAT fMouseAxis1 = offsets[1];

	
	// Update containers
	DBOOL		bDidLiquid = DFALSE;
	DBOOL		bDidLadder = DFALSE;
	DBOOL		bDidConveyor = DFALSE;
	for(unsigned i=0; i < m_nContainers; i++)
	{
		if(IsLiquid(m_Containers[i].m_ContainerCode) && !bDidLiquid)
		{
			UpdateInLiquid(&m_Containers[i]);
			bDidLiquid = DTRUE;
		}
		else if(m_Containers[i].m_ContainerCode == CC_LADDER && !bDidLadder)
		{
			UpdateOnLadder(&m_Containers[i]);
			bDidLadder = DTRUE;
		}
		else if( m_Containers[i].m_ContainerCode == CC_CONVEYOR && !bDidConveyor )
		{
			UpdateOnConveyor(&m_Containers[i]);
			bDidConveyor = DTRUE;
		}
	
		if(!m_Containers[i].m_bHidden)
		{
			m_pPhysicsLT->GetVelocity(m_hObject, &vMyVel);
			vMyVel += m_Containers[i].m_Current * m_FrameTime;
			m_pPhysicsLT->SetVelocity(m_hObject, &vMyVel);
		}
	}

	DBOOL		bHeadInLiquid = IsLiquid(m_pClientShell->GetCurContainerCode());
	DBOOL		bInLiquid	  = bHeadInLiquid || m_bBodyInLiquid;
	DBOOL		bFreeMovement = bHeadInLiquid || m_bBodyOnLadder || m_pClientShell->IsSpectatorMode();
	DBOOL		bLateralMovement = DFALSE;


	// Get my position
	m_pClientDE->GetObjectPos(m_hObject, &vMyPos);

	CollisionInfo collisionInfo;
	UpdateOnGround(&collisionInfo);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -