|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
or by snail mail at:
|
|
|
|
Cyan Worlds, Inc.
|
|
|
|
14617 N Newport Hwy
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
//#pragma warning(disable: 4503 4786)
|
|
|
|
//#define HK_HARDCORE
|
|
|
|
//
|
|
|
|
//#include <hkmath/vector3.h> // for havok Vector3
|
|
|
|
////#include <.//gpi/math/quaternion.h> // for havok Vector3
|
|
|
|
//#include <hkgeometry/geomdef.h> // for havok Vertex
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//#include "hsTypes.h"
|
|
|
|
//#include "../plInterp/plController.h"
|
|
|
|
//#include "plPlayerModifier.h"
|
|
|
|
//#include "hsTimer.h"
|
|
|
|
//#include "../pnSceneObject/plSceneObject.h"
|
|
|
|
//#include "../pnSceneObject/plSimulationInterface.h"
|
|
|
|
//#include "../pnInputCore/plControlEventCodes.h"
|
|
|
|
//#include "../pnMessage/plTimeMsg.h"
|
|
|
|
//#include "../pnMessage/plWarpMsg.h"
|
|
|
|
//#include "../pnMessage/plCameraMsg.h"
|
|
|
|
//#include "../pnSceneObject/plCoordinateInterface.h"
|
|
|
|
//#include "plgDispatch.h"
|
|
|
|
//#include "../pfCamera/plCameraModifier.h"
|
|
|
|
//#include "hsResMgr.h"
|
|
|
|
//#include "../pnKeyedObject/plKey.h"
|
|
|
|
//#include "../plNetClient/plNetClientMgr.h"
|
|
|
|
//#include "../plModifier/plSpawnModifier.h"
|
|
|
|
//#include "../plMessage/plMatrixUpdateMsg.h"
|
|
|
|
//
|
|
|
|
//#include "../pnTimer/plTimerCallbackManager.h"
|
|
|
|
//#include "../plAudio/plAudioSystem.h"
|
|
|
|
//#include "../plMessage/plInputEventMsg.h"
|
|
|
|
//#include "../plMessage/plSpawnRequestMsg.h"
|
|
|
|
//#include "../plMessage/plSpawnModMsg.h"
|
|
|
|
//#include "../plMessage/plPlayerMsg.h"
|
|
|
|
//#include "../pnMessage/plAudioSysMsg.h"
|
|
|
|
//#include "../pfCamera/plCameraBrain.h"
|
|
|
|
//
|
|
|
|
//#include "../plHavok1/plHKPhysical.h"
|
|
|
|
//
|
|
|
|
//hsScalar plPlayerModifier::fTurnRate = 1.0f;
|
|
|
|
//hsScalar plPlayerModifier::fAcceleration = 80.0f;
|
|
|
|
//hsScalar plPlayerModifier::fDeceleration = 80.0f;
|
|
|
|
//hsScalar plPlayerModifier::fMaxVelocity = 200.0f;
|
|
|
|
//
|
|
|
|
//plPlayerModifier::plPlayerModifier() :
|
|
|
|
//bUseDesiredFacing(false),
|
|
|
|
//bUseDesiredMatrix(false)
|
|
|
|
//{
|
|
|
|
// fCurSpeed = 0.0f;
|
|
|
|
// fLastTime = 0.0;
|
|
|
|
// bMoving = false;
|
|
|
|
// fRotationScalar = 1.0f;
|
|
|
|
// bIgnoreDesiredMatrix = false;
|
|
|
|
// SetFlag( kWantsToSpawn );
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//plPlayerModifier::~plPlayerModifier()
|
|
|
|
//{
|
|
|
|
// for (int i = 0; i < fSpawnPoints.Count(); i++)
|
|
|
|
// delete fSpawnPoints[i];
|
|
|
|
// fSpawnPoints.SetCount(0);
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//// Adding RemoveTarget override of plSingleModifier to tell everyone we
|
|
|
|
//// told in AddTarget about our subject that he's gone now.
|
|
|
|
//void plPlayerModifier::RemoveTarget(plSceneObject* so)
|
|
|
|
//{
|
|
|
|
// if( fTarget && fTarget->IsLocallyOwned()==plSynchedObject::kYes )
|
|
|
|
// {
|
|
|
|
// plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
|
|
|
|
// pMsg->SetCmd(plCameraMsg::kSetSubject);
|
|
|
|
// pMsg->SetSubject(nil);
|
|
|
|
// pMsg->SetBCastFlag( plMessage::kBCastByExactType );
|
|
|
|
// plgDispatch::MsgSend(pMsg);
|
|
|
|
//
|
|
|
|
// plAudioSysMsg* pAudMsg1 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerCoordinateRefCamera);
|
|
|
|
// plAudioSysMsg* pAudMsg2 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerVelocityRefCamera);
|
|
|
|
// plAudioSysMsg* pAudMsg3 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerFacingRefCamera);
|
|
|
|
// plgDispatch::MsgSend(pAudMsg1);
|
|
|
|
// plgDispatch::MsgSend(pAudMsg2);
|
|
|
|
// plgDispatch::MsgSend(pAudMsg3);
|
|
|
|
// }
|
|
|
|
// plSingleModifier::RemoveTarget(so);
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void plPlayerModifier::AddTarget(plSceneObject* so)
|
|
|
|
//{
|
|
|
|
// fTarget = so;
|
|
|
|
// plSimulationInterface * pSI = IGetTargetSimulationInterface(0); // so->GetSimulationInterface(); //
|
|
|
|
//
|
|
|
|
// plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
|
|
|
//
|
|
|
|
// // set the desired rotation vector...
|
|
|
|
//// hsAssert(fTarget->GetCoordinateInterface(), "Player modifier target has no coordinate interface");
|
|
|
|
//
|
|
|
|
// // These are now set in the component
|
|
|
|
//// if(pSI)
|
|
|
|
//// {
|
|
|
|
//// pSI->SetProperty(plSimulationInterface::kAffectLOS, false);
|
|
|
|
//// pSI->SetProperty(kUpright, true);
|
|
|
|
//// }
|
|
|
|
//
|
|
|
|
// //
|
|
|
|
// // setup for local player if necessary
|
|
|
|
// //
|
|
|
|
// int locallyOwned=so->IsLocallyOwned();
|
|
|
|
// if (locallyOwned==plSynchedObject::kMaybe) // don't know since we're still loading, defer
|
|
|
|
// SetFlag(kNeedsLocalSetup);
|
|
|
|
// else if (locallyOwned==plSynchedObject::kYes)
|
|
|
|
// IDoLocalSetup(so);
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void plPlayerModifier::IDoLocalSetup(plSceneObject* so)
|
|
|
|
//{
|
|
|
|
// plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
|
|
|
|
// pMsg->SetCmd(plCameraMsg::kSetSubject);
|
|
|
|
// pMsg->SetSubject(so);
|
|
|
|
// pMsg->SetBCastFlag( plMessage::kBCastByExactType );
|
|
|
|
// plgDispatch::MsgSend(pMsg);
|
|
|
|
//
|
|
|
|
// // this is to solve the problem of physical vs nonphysical players...
|
|
|
|
//// plCameraMsg* pMsg2 = TRACKED_NEW plCameraMsg;
|
|
|
|
//// pMsg2->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
//// pMsg2->SetCmd(plCameraMsg::kSetOffset);
|
|
|
|
//// pMsg2->SetCmd(plCameraMsg::kEntering);
|
|
|
|
//// pMsg2->SetTriggerer(so->GetKey());
|
|
|
|
//// pMsg2->SetOffsetY(50);
|
|
|
|
//// pMsg2->SetOffsetZ(10);
|
|
|
|
//// plgDispatch::MsgSend(pMsg2);
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void plPlayerModifier::IMakeUsListener( plSceneObject *so )
|
|
|
|
//{
|
|
|
|
// // set the listener to use us...
|
|
|
|
// plAudioSysMsg* pAudMsg1 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerFacingRef);
|
|
|
|
// pAudMsg1->SetSceneObject(so->GetKey());
|
|
|
|
// plAudioSysMsg* pAudMsg2 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerCoordinateRef);
|
|
|
|
// pAudMsg2->SetSceneObject(so->GetKey());
|
|
|
|
// plAudioSysMsg* pAudMsg3 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerVelocityRef);
|
|
|
|
// pAudMsg3->SetSceneObject(so->GetKey());
|
|
|
|
// plgDispatch::MsgSend(pAudMsg1);
|
|
|
|
// plgDispatch::MsgSend(pAudMsg2);
|
|
|
|
// plgDispatch::MsgSend(pAudMsg3);
|
|
|
|
//
|
|
|
|
// // Now that we have a valid listener, unmute the audio system
|
|
|
|
// plgAudioSys::SetMuted( false );
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//hsBool plPlayerModifier::MsgReceive(plMessage* msg)
|
|
|
|
//{
|
|
|
|
// plControlEventMsg* pCommandMsg = plControlEventMsg::ConvertNoRef(msg);
|
|
|
|
// if (pCommandMsg)
|
|
|
|
// return(HandleControlInput(pCommandMsg));
|
|
|
|
//
|
|
|
|
// plMatrixUpdateMsg* pMMsg = plMatrixUpdateMsg::ConvertNoRef( msg );
|
|
|
|
// if (pMMsg && HasFlag(kHasSpawned))
|
|
|
|
// {
|
|
|
|
// hsAssert(GetTarget()->IsLocallyOwned()==plSynchedObject::kNo, "master objects should not get correction msgs");
|
|
|
|
// fDesiredMatrix = pMMsg->fMatrix;
|
|
|
|
// if (bIgnoreDesiredMatrix)
|
|
|
|
// bIgnoreDesiredMatrix = false;
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// bUseDesiredMatrix = true;
|
|
|
|
// }
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// plSpawnModMsg* pSpawn = plSpawnModMsg::ConvertNoRef(msg);
|
|
|
|
// if (pSpawn && HasFlag(kWantsToSpawn))
|
|
|
|
// {
|
|
|
|
// spawnPt* pt = TRACKED_NEW spawnPt;
|
|
|
|
// pt->pt = pSpawn->fPos;
|
|
|
|
//
|
|
|
|
// hsVector3 temp(fTarget->GetCoordinateInterface()->GetLocalToWorld().GetTranslate() - pt->pt);
|
|
|
|
// pt->dist = temp.MagnitudeSquared();
|
|
|
|
// fSpawnPoints.Append(pt);
|
|
|
|
// }
|
|
|
|
// plPlayerMsg* pPMsg = plPlayerMsg::ConvertNoRef(msg);
|
|
|
|
// if (pPMsg)
|
|
|
|
// {
|
|
|
|
// if (pPMsg->Cmd(plPlayerMsg::kWarpToSpawnPoint))
|
|
|
|
// {
|
|
|
|
// WarpToSpawnPoint();
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// return plSingleModifier::MsgReceive(msg);
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//hsBool plPlayerModifier::HandleControlInput(plControlEventMsg* pMsg)
|
|
|
|
//{
|
|
|
|
// hsBool ret=false;
|
|
|
|
//
|
|
|
|
// if (pMsg->ControlActivated() && (pMsg->GetControlCode() == B_CONTROL_ROTATE_RIGHT || pMsg->GetControlCode() == B_CONTROL_ROTATE_LEFT || pMsg->GetControlCode() == A_CONTROL_TURN))
|
|
|
|
// {
|
|
|
|
// fRotationScalar = pMsg->GetPct();
|
|
|
|
// if ( HasMovementFlag( pMsg->GetControlCode() ) )
|
|
|
|
// bIgnoreDesiredMatrix = true;
|
|
|
|
// }
|
|
|
|
// if (pMsg->ControlActivated() && !HasMovementFlag( pMsg->GetControlCode() ) )
|
|
|
|
// {
|
|
|
|
// SetMovementFlag( pMsg->GetControlCode() );
|
|
|
|
// if ( pMsg->GetControlCode() == B_CONTROL_TURN_TO )
|
|
|
|
// {
|
|
|
|
// //fFacingTarget = pMsg->GetTurnToPt();
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// if ( !pMsg->ControlActivated() && HasMovementFlag( pMsg->GetControlCode() ) )
|
|
|
|
// {
|
|
|
|
// ClearMovementFlag( pMsg->GetControlCode() );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// ret = true;
|
|
|
|
// return ret;
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//void plPlayerModifier::SetMoving(hsBool b)
|
|
|
|
//{
|
|
|
|
// if (b != bMoving)
|
|
|
|
// {
|
|
|
|
// plPlayerMsg* pMsg = TRACKED_NEW plPlayerMsg;
|
|
|
|
//
|
|
|
|
// if (b)
|
|
|
|
// pMsg->SetCmd( plPlayerMsg::kMovementStarted );
|
|
|
|
// else
|
|
|
|
// pMsg->SetCmd( plPlayerMsg::kMovementStopped );
|
|
|
|
//
|
|
|
|
// plgDispatch::MsgSend( pMsg );
|
|
|
|
// bMoving = b;
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//hsPoint3 forceForward(0,-200,0);
|
|
|
|
//hsPoint3 forceRight(-200,0,0);
|
|
|
|
//hsPoint3 forceUp(0,0,15);
|
|
|
|
//
|
|
|
|
//hsBool plPlayerModifier::IEval(double secs, hsScalar del, UInt32 dirty)
|
|
|
|
//{
|
|
|
|
// // setup for local player if necessary
|
|
|
|
// if (HasFlag(kNeedsLocalSetup))
|
|
|
|
// {
|
|
|
|
// int locallyOwned=fTarget->IsLocallyOwned();
|
|
|
|
// if (locallyOwned==plSynchedObject::kYes)
|
|
|
|
// IDoLocalSetup(fTarget);
|
|
|
|
// else
|
|
|
|
// if (locallyOwned==plSynchedObject::kNo)
|
|
|
|
// ClearFlag(kNeedsLocalSetup);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (HasFlag(kWantsToSpawn))
|
|
|
|
// {
|
|
|
|
// if (fTarget->IsLocallyOwned()==plSynchedObject::kNo)
|
|
|
|
// {
|
|
|
|
// // if our target is a proxy player, don't warp him to a spawn point;
|
|
|
|
// // we will receive his location as a state update.
|
|
|
|
// ClearFlag(kWantsToSpawn);
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// if (fSpawnPoints.Count()
|
|
|
|
// // if MP game, make sure we're connected before spawning
|
|
|
|
// && (!plNetClientMgr::GetInstance()->IsEnabled() ||
|
|
|
|
// plNetClientMgr::GetInstance()->HasJoined())
|
|
|
|
// )
|
|
|
|
// {
|
|
|
|
// int i;
|
|
|
|
//#if 0
|
|
|
|
// for (i = 0; i < fSpawnPoints.Count(); i++)
|
|
|
|
// {
|
|
|
|
// for (int j = i + 1; j < fSpawnPoints.Count(); j++)
|
|
|
|
// {
|
|
|
|
// if (fSpawnPoints[j]->dist < fSpawnPoints[i]->dist)
|
|
|
|
// {
|
|
|
|
// spawnPt* pt;
|
|
|
|
// pt = fSpawnPoints[j];
|
|
|
|
// fSpawnPoints[j] = fSpawnPoints[i];
|
|
|
|
// fSpawnPoints[i] = pt;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// hsPoint3 warpPoint = fSpawnPoints[0]->pt;
|
|
|
|
//#else
|
|
|
|
// // choose spawnPoint based on netID, not distance
|
|
|
|
// int netID = plNetClientMgr::GetInstance()->GetClientNum();
|
|
|
|
// if (netID==-1)
|
|
|
|
// netID=0;
|
|
|
|
// hsPoint3 warpPoint = netID>=fSpawnPoints.Count() ?
|
|
|
|
// fSpawnPoints[fSpawnPoints.Count()-1]->pt : fSpawnPoints[netID]->pt;
|
|
|
|
//#endif
|
|
|
|
// // Send msg for net synchronization
|
|
|
|
// plWarpMsg* warpMsg = TRACKED_NEW plWarpMsg;
|
|
|
|
// warpMsg->fPos = warpPoint;
|
|
|
|
// warpMsg->AddReceiver( fTarget->GetKey() );
|
|
|
|
// warpMsg->SetWarpFlags(warpMsg->GetWarpFlags() | plWarpMsg::kFlushTransform | plWarpMsg::kZeroVelocity );
|
|
|
|
// plgDispatch::MsgSend( warpMsg );
|
|
|
|
//#ifdef HS_DEBUGGING
|
|
|
|
// char str[256];
|
|
|
|
// sprintf(str, "%s has %d spawnPoints. Using pt %f %f %f\n",
|
|
|
|
// GetKeyName(), fSpawnPoints.GetCount(),
|
|
|
|
// fSpawnPoints[0]->pt.fX,fSpawnPoints[0]->pt.fY,fSpawnPoints[0]->pt.fZ);
|
|
|
|
// hsStatusMessage(str);
|
|
|
|
//#endif
|
|
|
|
// for (i = 0; i < fSpawnPoints.Count(); i++)
|
|
|
|
// delete fSpawnPoints[i];
|
|
|
|
//
|
|
|
|
// fSpawnPoints.SetCount(0);
|
|
|
|
// ClearFlag(kWantsToSpawn);
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// plSpawnRequestMsg* pMsg = TRACKED_NEW plSpawnRequestMsg;
|
|
|
|
// pMsg->SetSender(GetKey());
|
|
|
|
// plgDispatch::MsgSend( pMsg );
|
|
|
|
// }
|
|
|
|
// bIgnoreDesiredMatrix = true;
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// if( !HasFlag( kHasSpawned ) )
|
|
|
|
// {
|
|
|
|
// // Don't make us listener until we have actually spawned
|
|
|
|
// IMakeUsListener( fTarget );
|
|
|
|
// SetFlag(kHasSpawned);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (!fTarget->GetCoordinateInterface())
|
|
|
|
// return true;
|
|
|
|
//
|
|
|
|
// // update our desired position:
|
|
|
|
//// hsScalar eTime = secs - fLastTime;
|
|
|
|
// hsScalar eTime = hsTimer::GetDelSysSeconds();
|
|
|
|
//
|
|
|
|
// hsPoint3 newLinearForce(0,0,0);
|
|
|
|
//
|
|
|
|
// hsMatrix44 targetMatrix;
|
|
|
|
// if (bUseDesiredMatrix)
|
|
|
|
// targetMatrix = fDesiredMatrix;
|
|
|
|
// else
|
|
|
|
// targetMatrix = fTarget->GetCoordinateInterface()->GetLocalToWorld();
|
|
|
|
// hsPoint3 playerPos = targetMatrix.GetTranslate();
|
|
|
|
// hsVector3 view, up, right;
|
|
|
|
// targetMatrix.GetAxis(&view, &up, &right);
|
|
|
|
//
|
|
|
|
// hsScalar speed = fMaxVelocity;
|
|
|
|
// hsScalar turn = fTurnRate;
|
|
|
|
//
|
|
|
|
// if (HasMovementFlag(B_CONTROL_MODIFIER_FAST))
|
|
|
|
// {
|
|
|
|
// turn *= 0.25;
|
|
|
|
// speed *= 3.5;
|
|
|
|
// }
|
|
|
|
// if (HasMovementFlag(B_CONTROL_MOVE_FORWARD))
|
|
|
|
// {
|
|
|
|
// playerPos += view * speed * eTime;
|
|
|
|
// newLinearForce = newLinearForce + forceForward * speed * eTime; // calc force for physics
|
|
|
|
// }
|
|
|
|
// if (HasMovementFlag(B_CONTROL_MOVE_BACKWARD))
|
|
|
|
// {
|
|
|
|
// playerPos += view * speed * eTime * -1;
|
|
|
|
// newLinearForce = newLinearForce + forceForward * speed * eTime * -1; // calc force for physics
|
|
|
|
// }
|
|
|
|
// if (HasMovementFlag(B_CONTROL_STRAFE_LEFT))
|
|
|
|
// {
|
|
|
|
// playerPos += right * speed * eTime * -1;
|
|
|
|
//
|
|
|
|
// newLinearForce = newLinearForce + forceRight * speed * eTime * -1;
|
|
|
|
// }
|
|
|
|
// if (HasMovementFlag(B_CONTROL_STRAFE_RIGHT))
|
|
|
|
// {
|
|
|
|
// playerPos += right * speed * eTime;
|
|
|
|
//
|
|
|
|
// newLinearForce = newLinearForce + forceRight * speed * eTime;
|
|
|
|
// }
|
|
|
|
// if (HasMovementFlag(B_CONTROL_MOVE_DOWN))
|
|
|
|
// {
|
|
|
|
// playerPos += up * speed * eTime * -1;
|
|
|
|
//
|
|
|
|
// newLinearForce = newLinearForce + forceUp * speed * eTime * -1;
|
|
|
|
// }
|
|
|
|
// if (HasMovementFlag(B_CONTROL_MOVE_UP))
|
|
|
|
// {
|
|
|
|
// playerPos += up * speed * eTime;
|
|
|
|
//
|
|
|
|
// newLinearForce = newLinearForce + forceUp * speed * eTime;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// fDesiredPosition = playerPos;
|
|
|
|
//
|
|
|
|
// // move toward our desired position...
|
|
|
|
//
|
|
|
|
// hsPoint3 curPos = targetMatrix.GetTranslate();
|
|
|
|
// hsPoint3 newPos;
|
|
|
|
//
|
|
|
|
// hsVector3 dir(fDesiredPosition - curPos);
|
|
|
|
// hsScalar distToGoal=dir.Magnitude();
|
|
|
|
//
|
|
|
|
// if (dir.MagnitudeSquared() > 0.0f)
|
|
|
|
// dir.Normalize();
|
|
|
|
//
|
|
|
|
// hsVector3 vel( view * fCurSpeed );
|
|
|
|
//
|
|
|
|
// IAdjustVelocity(fAcceleration, fDeceleration, &dir, &vel, fMaxVelocity, distToGoal, eTime);
|
|
|
|
// fCurSpeed = vel.Magnitude();
|
|
|
|
//
|
|
|
|
// hsScalar distMoved = IClampVelocity(&vel, fMaxVelocity, eTime);
|
|
|
|
//
|
|
|
|
// // compute final pos
|
|
|
|
// if (distMoved > distToGoal)
|
|
|
|
// newPos = fDesiredPosition;
|
|
|
|
// else
|
|
|
|
// newPos = curPos + vel;
|
|
|
|
//
|
|
|
|
// // calculate rotation matrix
|
|
|
|
//
|
|
|
|
// hsVector3 rotUp(0,0,1);
|
|
|
|
// hsVector3 rotRight(1,0,0);
|
|
|
|
// hsMatrix44 rot;
|
|
|
|
//
|
|
|
|
// if ( HasMovementFlag( B_CONTROL_TURN_TO ) )
|
|
|
|
// {
|
|
|
|
// // compute view goal
|
|
|
|
//
|
|
|
|
// hsVector3 fPlayerViewGoal(&fFacingTarget,&curPos);
|
|
|
|
// fPlayerViewGoal.fZ = 0;
|
|
|
|
// fPlayerViewGoal.Normalize();
|
|
|
|
//
|
|
|
|
// // compute degrees needed to turn left/right
|
|
|
|
// hsVector3 cross = fPlayerViewGoal % view;
|
|
|
|
// hsScalar dot = fPlayerViewGoal * view;
|
|
|
|
// hsScalar rad = hsACosine(dot);
|
|
|
|
// fRotationScalar = 1.0f;
|
|
|
|
//
|
|
|
|
// if (cross.fZ<0)
|
|
|
|
// {
|
|
|
|
// SetMovementFlag( B_CONTROL_ROTATE_LEFT );
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// SetMovementFlag( B_CONTROL_ROTATE_RIGHT );
|
|
|
|
// }
|
|
|
|
// if (dot >= 0.999f)
|
|
|
|
// {
|
|
|
|
// ClearMovementFlag( B_CONTROL_TURN_TO );
|
|
|
|
// ClearMovementFlag( B_CONTROL_ROTATE_RIGHT );
|
|
|
|
// ClearMovementFlag( B_CONTROL_ROTATE_LEFT );
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// hsScalar angle = 0;
|
|
|
|
//
|
|
|
|
// if ( HasMovementFlag( B_CONTROL_ROTATE_RIGHT ) )
|
|
|
|
// {
|
|
|
|
// angle = fTurnRate * eTime * -1 * fRotationScalar;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if ( HasMovementFlag( B_CONTROL_ROTATE_LEFT ) || HasMovementFlag( A_CONTROL_TURN ) )
|
|
|
|
// {
|
|
|
|
// angle = fTurnRate * eTime * fRotationScalar;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// hsMatrix44 justRot(targetMatrix);
|
|
|
|
// hsPoint3 zero(0,0,0);
|
|
|
|
// justRot.SetTranslate(&zero);
|
|
|
|
//
|
|
|
|
// if(angle) {
|
|
|
|
// hsQuat q(angle, &rotUp);
|
|
|
|
// q.NormalizeIfNeeded();
|
|
|
|
// q.MakeMatrix(&rot);
|
|
|
|
//
|
|
|
|
// justRot = rot * justRot;
|
|
|
|
//
|
|
|
|
// targetMatrix = rot * targetMatrix;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // use the desired rotation matrix to set position and rotation:
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// plSimulationInterface * SI = IGetTargetSimulationInterface(0);
|
|
|
|
//
|
|
|
|
// if(SI)
|
|
|
|
// {
|
|
|
|
// Havok::Vector3 hkLocalForce(newLinearForce.fX, newLinearForce.fY, newLinearForce.fZ);
|
|
|
|
// if (bUseDesiredMatrix)
|
|
|
|
// {
|
|
|
|
// hsMatrix44 inv;
|
|
|
|
//
|
|
|
|
// fDesiredMatrix.GetInverse(&inv);
|
|
|
|
//
|
|
|
|
// // we're just going to set the position on the simulation interface directly
|
|
|
|
// // because it will then be further modified by the simulation and its final position
|
|
|
|
// // will *then* be sent to the coordinate interface
|
|
|
|
// SI->SetTransform(fDesiredMatrix, inv);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// SI->SetRotation(justRot);//rot);
|
|
|
|
// SI->ApplyForce(plSimulationInterface::kForce, hkLocalForce);
|
|
|
|
// } else {
|
|
|
|
// hsMatrix44 inv;
|
|
|
|
// targetMatrix.SetTranslate(&newPos);
|
|
|
|
// targetMatrix.GetInverse(&inv);
|
|
|
|
//
|
|
|
|
// plCoordinateInterface* pCI = pCI = IGetTargetCoordinateInterface(0);
|
|
|
|
// pCI->SetTransform(targetMatrix, inv);
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// fLastTime = secs;
|
|
|
|
// SetMoving(fCurSpeed);
|
|
|
|
//
|
|
|
|
// if (bUseDesiredMatrix)
|
|
|
|
// bUseDesiredMatrix = false;
|
|
|
|
// return true;
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
////
|
|
|
|
//// vector version. dir vector should be normalized
|
|
|
|
////
|
|
|
|
//void plPlayerModifier::IAdjustVelocity(hsScalar adjAccelRate, hsScalar adjDecelRate,
|
|
|
|
// hsVector3* dir, hsVector3* vel, hsScalar maxSpeed,
|
|
|
|
// hsScalar distToGoal, double elapsedTime)
|
|
|
|
//{
|
|
|
|
// hsScalar speed = vel->Magnitude(); // save current speed
|
|
|
|
// *vel = *dir * speed; // change vel to correct dir
|
|
|
|
//
|
|
|
|
// // compute accel/decel
|
|
|
|
// hsScalar finalAccelRate;
|
|
|
|
// if (IShouldDecelerate(adjDecelRate, speed, distToGoal))
|
|
|
|
// {
|
|
|
|
// finalAccelRate = -adjDecelRate;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// finalAccelRate = adjAccelRate;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (finalAccelRate != 0)
|
|
|
|
// {
|
|
|
|
// // compute accel vector in the direction of the goal
|
|
|
|
// hsVector3 accelVec = *dir * finalAccelRate;
|
|
|
|
// accelVec = accelVec * elapsedTime;
|
|
|
|
//
|
|
|
|
// // add acceleration to velocity
|
|
|
|
// *vel = *vel + accelVec;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// *vel = *dir * maxSpeed;
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//hsScalar plPlayerModifier::IClampVelocity(hsVector3* vel, hsScalar maxSpeed, double elapsedTime)
|
|
|
|
//{
|
|
|
|
// *vel = *vel * elapsedTime;
|
|
|
|
// maxSpeed *= elapsedTime;
|
|
|
|
//
|
|
|
|
// // clamp speed (clamp if going negative?)
|
|
|
|
// hsScalar distMoved = vel->Magnitude();
|
|
|
|
// if (distMoved > maxSpeed)
|
|
|
|
// {
|
|
|
|
// vel->Normalize();
|
|
|
|
// *vel = *vel * maxSpeed;
|
|
|
|
// return maxSpeed;
|
|
|
|
// }
|
|
|
|
// return distMoved;
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//hsBool32 plPlayerModifier::IShouldDecelerate(hsScalar decelSpeed, hsScalar curSpeed, hsScalar distToGoal)
|
|
|
|
//{
|
|
|
|
// if (decelSpeed == 0)
|
|
|
|
// // no deceleration
|
|
|
|
// return false;
|
|
|
|
//
|
|
|
|
// // compute distance required to stop, given decel speed (in units/sec sq)
|
|
|
|
// hsScalar stopTime = curSpeed / decelSpeed;
|
|
|
|
// hsScalar avgSpeed = curSpeed * .5f;
|
|
|
|
// hsScalar stopDist = avgSpeed * stopTime;
|
|
|
|
//
|
|
|
|
// return (hsABS(distToGoal) <= hsABS(stopDist)); // stopDist+avgSpeed?
|
|
|
|
//}
|
|
|
|
//
|