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

📄 movemgr.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				if(dist < pPusher->m_Radius)
				{
					memset(&iQuery, 0, sizeof(iQuery));
					iQuery.m_From = pPusher->m_Pos;
					iQuery.m_To = myPos;
					if(!m_pClientDE->IntersectSegment(&iQuery, &iInfo))
					{
						velocity = 1.0f - (dist / pPusher->m_Radius);
						velocity *= pPusher->m_Strength;

						// If we're in the air, apply less (since there's no friction).
						m_pPhysicsLT->GetStandingOn(m_hObject, &info);					
						if(!info.m_hObject) 
						{
							velocity /= 10.0f;
						}

						pushVec = myPos - pPusher->m_Pos;
						pushVec.Norm(velocity);

						m_pPhysicsLT->GetVelocity(m_hObject, &vel);
						vel += pushVec;
						m_pPhysicsLT->SetVelocity(m_hObject, &vel);
					}
				}
			}
		}
	}
}


void CMoveMgr::UpdatePlayerAnimation()
{
	HOBJECT hClientObj;
	DDWORD modelAnim, curModelAnim, curFlags;
	DVector oldDims, offset;

	
	if(!(hClientObj = m_pClientDE->GetClientObject()))
		return;
	
	// Make sure our solid object is on the same animation.
	modelAnim = m_pClientDE->GetModelAnimation(hClientObj);
	curModelAnim = m_pClientDE->GetModelAnimation(m_hObject);
	if(modelAnim != curModelAnim)
	{
		// Kind of wierd what we do here.. the engine sets the dims automatically when
		// we change animations but it doesn't do collision detection (and we don't want
		// it to) so we may end up clipping into the world so we set it to a small cube
		// and resize the dims with collision detection.
		curFlags = m_pClientDE->GetObjectFlags(m_hObject);
		m_pClientDE->SetObjectFlags(m_hObject, (curFlags|FLAG_GOTHRUWORLD) & ~FLAG_SOLID);

		m_pClientDE->SetModelAnimation(m_hObject, modelAnim);
		
		// Get our wanted dims.
		oldDims = m_WantedDims;
		VEC_SET(m_WantedDims, 1, 1, 1);
		m_pClientDE->Common()->GetModelAnimUserDims(m_hObject, &m_WantedDims, modelAnim);
//		m_WantedDims *= m_DimsScale[MS_NORMAL];

		// Figure out a position offset.
		VEC_INIT(offset);
		if (m_WantedDims.y < oldDims.y)
		{
			offset.y = -(oldDims.y - m_WantedDims.y);
			offset.y += .01f; // Fudge factor
		}

		m_pClientDE->SetObjectFlags(m_hObject, curFlags);
		
		// This makes you small before setting the dims so you don't clip thru stuff.
		ResetDims(&offset);
	}
}


DBOOL CMoveMgr::AreDimsCorrect()
{
	DVector curDims;

	if(!m_hObject || !m_pPhysicsLT)
		return DTRUE;

	m_pPhysicsLT->GetObjectDims(m_hObject, &curDims);
	return fabs(curDims.x-m_WantedDims.x) < 0.1f && fabs(curDims.y-m_WantedDims.y) < 0.1f &&
		fabs(curDims.z-m_WantedDims.z) < 0.1f;
}


void CMoveMgr::ResetDims(DVector *pOffset)
{
	DVector smallDims, pos;

	smallDims.Init(0.5f, 0.5f, 0.5f);
	m_pPhysicsLT->SetObjectDims(m_hObject, &smallDims, 0);
	
	// Move them if they want.
	if(pOffset)
	{
		m_pClientDE->GetObjectPos(m_hObject, &pos);
		pos += *pOffset;
		m_pPhysicsLT->MoveObject(m_hObject, &pos, 0);
	}
	
	m_pPhysicsLT->SetObjectDims(m_hObject, &m_WantedDims, SETDIMS_PUSHOBJECTS);
}


void CMoveMgr::MoveLocalSolidObject()
{
	MoveInfo info;
	DVector newPos, curPos, vVel;

	info.m_hObject = m_hObject;
	info.m_dt = m_FrameTime;
	m_pPhysicsLT->UpdateMovement(&info);

	if(info.m_Offset.MagSqr() > 0.01f)
	{
		m_pClientDE->GetObjectPos(m_hObject, &curPos);
		newPos = curPos + info.m_Offset;

		// Get the velocity before moving the object, because the moveobject will zero the velocity if 
		// we hit anything.
		m_pPhysicsLT->GetVelocity( m_hObject, &m_vServerVelocity );
		m_pPhysicsLT->MoveObject(m_hObject, &newPos, 0);
	}
}


void CMoveMgr::UpdateVelMagnitude()
{
	DVector vel;

	if(!m_pPhysicsLT || !m_pClientShell || !m_hObject)
		return;

	m_pPhysicsLT->GetVelocity(m_hObject, &vel);
	vel.y = 0;
	m_pClientShell->SetVelMagnitude(vel.Mag());
}


void CMoveMgr::SetClientObjNonsolid()
{
	HOBJECT hObj;

	if(hObj = m_pClientDE->GetClientObject())
	{
		DDWORD dwFlags = m_pClientDE->GetObjectFlags(hObj);
		m_pClientDE->SetObjectFlags(hObj, dwFlags | FLAG_CLIENTNONSOLID);
	}
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CMoveMgr::UpdateFriction
//
//	PURPOSE:	Update player fricton
//
// ----------------------------------------------------------------------- //

void CMoveMgr::UpdateFriction()
{

	if (m_bOnGround && (m_pClientShell->GetCurContainerCode() == CC_NOTHING))
	{
		DVector vCurVel;
		m_pPhysicsLT->GetVelocity(m_hObject, &vCurVel);

		DFLOAT fYVal = vCurVel.y;
		vCurVel.y = 0.0f;

		if (VEC_MAG(vCurVel) > 0.1f)
		{
			DVector vDir, vVel;
			VEC_COPY(vDir, vCurVel);
			VEC_NORM(vDir);
/*
			DFLOAT fExp = (DFLOAT)exp(-fDragCoeff*m_pClientDE->GetFrameTime());
			DVector vTemp, vTemp2;
			m_pPhysicsLT->GetAcceleration(m_hObject, &vTemp);
			vTemp /= fDragCoeff;
			vTemp2 = vCurVel - vTemp;
			vTemp2 *= fExp;
			vVel = vTemp2 + vTemp;
*/
/*			DFLOAT fAdjust = m_pClientDE->GetFrameTime()*(m_fMoveVel/SLIDE_TO_STOP_TIME);

			VEC_MULSCALAR(vVel, vDir, fAdjust);

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

			vVel.y = fYVal;
			m_pPhysicsLT->SetVelocity(m_hObject, &vVel);
*/
		}
	}
}


void CMoveMgr::ShowPos(char *pBlah)
{
	DVector pos;
	m_pClientDE->GetObjectPos(m_hObject, &pos);
	m_pClientDE->CPrint("%s: %.1f %.1f %.1f", pBlah, VEC_EXPAND(pos));
}

void CMoveMgr::Update()
{
	HOBJECT hObj;

	hObj = m_pClientDE->GetClientObject();
	if(!m_hObject || !hObj)
		return;
			   
	// m_pClientDE->CPrint("On Ground: %s", m_bOnGround ? "TRUE" : "FALSE");

	m_FrameTime = m_pClientDE->GetFrameTime();
	if(m_FrameTime > 0.1f)
		m_FrameTime = 0.1f;

	// We don't want to hit the real client object.
	SetClientObjNonsolid();

	UpdatePlayerAnimation();

	UpdateControlFlags();

	if(!m_pClientShell->IsTrapped())
	{
		UpdateMotion();
		// Update friction...
//		UpdateFriction();
		UpdatePushers();
	}

	// Make sure we have desired dims.
	if(!AreDimsCorrect())
		ResetDims();

	if(!m_pClientShell->IsTrapped())
	{
		MoveLocalSolidObject();
		UpdateVelMagnitude();
	}
	else
	{
		DVector vTemp;
		VEC_INIT(vTemp);
		m_pPhysicsLT->SetVelocity(m_hObject, &vTemp);
	}

	// Clear these and they'll get set if mouse is moving.
	m_nMouseStrafeFlags = 0;
}


void CMoveMgr::OnPhysicsUpdate(HMESSAGEREAD hRead)
{
	ObjectCreateStruct theStruct;
	D_WORD changeFlags;
	DVector grav;
	HOBJECT hClientObj;
	DDWORD i; 

	if(!m_pClientDE)
		return;

	changeFlags = m_pClientDE->ReadFromMessageWord(hRead);

	// Change our model file?
	if (changeFlags & PSTATE_MODELFILENAMES)
	{
		INIT_OBJECTCREATESTRUCT(theStruct);

		hClientObj = m_pClientDE->GetClientObject();

		if(m_hObject)
		{
			m_pClientDE->GetObjectPos( m_hObject, &theStruct.m_Pos );
			m_pClientDE->DeleteObject(m_hObject);
		}
		else if( hClientObj )
		{
			m_pClientDE->GetObjectPos(hClientObj, &theStruct.m_Pos);
		}

		SAFE_STRCPY(theStruct.m_Filename, m_pClientDE->ReadFromMessageString(hRead));
		SAFE_STRCPY(theStruct.m_SkinName, m_pClientDE->ReadFromMessageString(hRead));
		theStruct.m_ObjectType = OT_MODEL;
		theStruct.m_Flags = FLAG_SOLID | FLAG_GRAVITY | FLAG_STAIRSTEP;
		
		m_hObject = m_pClientDE->CreateObject(&theStruct);
		if(m_hObject)
		{
			m_pClientDE->SetObjectClientFlags(m_hObject, CF_DONTSETDIMS|CF_NOTIFYREMOVE);
			m_pPhysicsLT->SetFrictionCoefficient( m_hObject, m_fFrictionCoeff );
		}

		// Reset dims..
		m_pClientDE->Common()->GetModelAnimUserDims(m_hObject, &m_WantedDims, 0);
		
		// This makes you small before setting the dims so you don't clip thru stuff.
		ResetDims();
	}

	if (changeFlags & PSTATE_ADDVELOCITY)
	{
		DVector vAddVel, vVel;
		m_pClientDE->ReadFromMessageVector(hRead, &vAddVel);
		m_pPhysicsLT->GetVelocity(m_hObject, &vVel);
		vVel = vVel + vAddVel;
		m_pPhysicsLT->SetVelocity(m_hObject, &vVel);
	}

	if (changeFlags & PSTATE_GRAVITY)
	{
		m_pClientDE->ReadFromMessageVector(hRead, &grav);
		m_pPhysicsLT->SetGlobalForce(grav);
	}

	if (changeFlags & PSTATE_CONTAINERTYPE)
	{
		m_nContainers = m_pClientDE->ReadFromMessageByte(hRead);
		if(m_nContainers >= MAX_TRACKED_CONTAINERS)
			return;

		for(i=0; i < m_nContainers; i++)
		{
			m_Containers[i].m_ContainerCode = (ContainerCode)m_pClientDE->ReadFromMessageByte(hRead);

			m_pClientDE->ReadFromMessageVector(hRead, &m_Containers[i].m_Current);
			m_Containers[i].m_fGravity = m_pClientDE->ReadFromMessageFloat(hRead);
			m_Containers[i].m_bHidden = m_pClientDE->ReadFromMessageByte(hRead);
		}
	}

	if (changeFlags & PSTATE_SPEEDS)
	{
		m_fMoveVel = m_pClientDE->ReadFromMessageFloat(hRead);
		m_fJumpVel = m_pClientDE->ReadFromMessageFloat(hRead);
		m_fSwimVel = m_pClientDE->ReadFromMessageFloat(hRead);

		m_fMoveMultiplier = m_pClientDE->ReadFromMessageFloat(hRead);
		m_fMoveAccelMultiplier = m_pClientDE->ReadFromMessageFloat(hRead);

		m_fLeashLen = m_pClientDE->ReadFromMessageFloat(hRead);
		m_fBaseMoveAccel = m_pClientDE->ReadFromMessageFloat(hRead);
		m_fJumpMultiplier = m_pClientDE->ReadFromMessageFloat(hRead);
		m_fLadderVel = m_pClientDE->ReadFromMessageFloat(hRead);
		
		m_fFrictionCoeff = m_pClientDE->ReadFromMessageFloat(hRead);
		m_pPhysicsLT->SetFrictionCoefficient(m_hObject, m_fFrictionCoeff);
	}

	// Update crouch state
	if (changeFlags & PSTATE_CROUCH)
	{
		m_bForcedCrouch = m_pClientDE->ReadFromMessageByte(hRead);
	}
}


DRESULT CMoveMgr::OnObjectMove(HOBJECT hObj, DBOOL bTeleport, DVector *pPos)
{
	HOBJECT hClientObj;
	DDWORD type;

	if(!m_hObject || !m_pClientDE)
		return LT_OK;

	hClientObj = m_pClientDE->GetClientObject();

	// If it's a solid world model moving, do a regular MoveObject on it so it
	// can carry/push the player object around.
	if(!bTeleport && hObj != hClientObj && hObj != m_hObject)
	{
		type = m_pClientDE->GetObjectType(hObj);
		if(type == OT_WORLDMODEL)
		{
			if(m_pClientDE->GetObjectFlags(hObj) & FLAG_SOLID)
			{
				m_pPhysicsLT->MovePushObjects(hObj, *pPos, &m_hObject, 1);
			}
		}	
	}

	return LT_OK;
}


DRESULT CMoveMgr::OnObjectRotate(HOBJECT hObj, DBOOL bTeleport, DRotation *pNewRot)
{
	HOBJECT hClientObj;
	DDWORD type;

	if(!m_hObject || !m_pClientDE)
		return LT_OK;

	hClientObj = m_pClientDE->GetClientObject();

	// If it's a solid world model moving, do a regular MoveObject on it so it
	// can carry/push the player object around.
	if(!bTeleport && hObj != hClientObj && hObj != m_hObject)
	{
		type = m_pClientDE->GetObjectType(hObj);
		if(type == OT_WORLDMODEL)
		{
			if(m_pClientDE->GetObjectFlags(hObj) & FLAG_SOLID)
			{
				m_pPhysicsLT->RotatePushObjects(hObj, *pNewRot, &m_hObject, 1);
			}
		}	
	}

	return LT_OK;
}


void CMoveMgr::OnObjectRemove(HOBJECT hObj)
{
	if(hObj == m_hObject)
	{
		m_hObject = DNULL;
	}
}


DRESULT CMoveMgr::AddPusher(DVector &pos, float radius, float startDelay, float duration, float strength)
{
	Pusher *pPusher;

	if(!(pPusher = new Pusher))
		return LT_ERROR;
	
	pPusher->m_Pos = pos;
	pPusher->m_Radius = radius;
	pPusher->m_Delay = startDelay;
	pPusher->m_TimeLeft = duration;
	pPusher->m_Strength = strength;
	dl_Insert(&m_Pushers, &pPusher->m_Link);
	
	return LT_OK;
}


void CMoveMgr::MoveToClientObj()
{
	DVector cObjPos;
	HOBJECT hObj;

	if(!m_hObject || !(hObj = m_pClientDE->GetClientObject()))
		return;

	m_pClientDE->GetObjectPos(hObj, &cObjPos);
	m_pPhysicsLT->MoveObject(m_hObject, &cObjPos, MOVEOBJECT_TELEPORT);
}


void CMoveMgr::OnServerForcePos(HMESSAGEREAD hRead)
{
	DVector zeroVec, tempDims, pos, curDims;

	if(!m_pClientDE || !m_pPhysicsLT)
		return;

	m_ClientMoveCode = m_pClientDE->ReadFromMessageByte(hRead);

	// Teleport to where it says.
	if(m_hObject)
	{
		SetClientObjNonsolid();

		// Move there.  We make our object a point first and then resize the dims so 
		// we don't teleport clipping into the world.
		m_pClientDE->ReadFromMessageVector(hRead, &pos);
		
		tempDims.Init(0.5f, 0.5f, 0.5f);
		m_pPhysicsLT->GetObjectDims(m_hObject, &curDims);
		m_pPhysicsLT->SetObjectDims(m_hObject, &tempDims, 0);
		m_pPhysicsLT->MoveObject(m_hObject, &pos, MOVEOBJECT_TELEPORT);
		m_pPhysicsLT->SetObjectDims(m_hObject, &curDims, SETDIMS_PUSHOBJECTS);

		// Clear our velocity and acceleration.
		zeroVec.Init();
		m_pPhysicsLT->SetVelocity(m_hObject, &zeroVec);
		m_pPhysicsLT->SetAcceleration(m_hObject, &zeroVec);
	}
}


void CMoveMgr::WritePositionInfo(HMESSAGEWRITE hWrite)
{
	DVector myPos, myVel;
	short compVel[3];
	DBYTE nMovementFlags;

	if(!m_pClientDE)
		return;

	if(m_hObject)
	{
		m_pClientDE->GetObjectPos(m_hObject, &myPos);
//		m_pPhysicsLT->GetVelocity(m_hObject, &myVel);
		VEC_COPY( myVel, m_vServerVelocity );
	}
	else
	{
		myPos.Init();
		myVel.Init();
	}
	
	m_pClientDE->WriteToMessageByte(hWrite, m_ClientMoveCode);
	m_pClientDE->WriteToMessageVector(hWrite, &myPos);
	
	compVel[0] = (short)myVel.x;
	compVel[1] = (short)myVel.y;
	compVel[2] = (short)myVel.z;
	m_pClientDE->WriteToMessageWord(hWrite, compVel[0]);
	m_pClientDE->WriteToMessageWord(hWrite, compVel[1]);
	m_pClientDE->WriteToMessageWord(hWrite, compVel[2]);

	nMovementFlags = 0;
	if( m_bOnGround )
		nMovementFlags |= CLIENTMOVEMENTFLAG_ONGROUND;
	m_pClientDE->WriteToMessageByte(hWrite, (DBYTE)nMovementFlags);
	m_pClientDE->WriteToMessageByte(hWrite, (DBYTE)m_eLastSurface);
}


⌨️ 快捷键说明

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