📄 movemgr.cpp
字号:
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 + -