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

📄 player.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:

Player::Player()
{
   mTypeMask |= PlayerObjectType;

   delta.pos = mAnchorPoint = Point3F(0,0,100);
   delta.rot = delta.head = Point3F(0,0,0);
   delta.rotOffset = delta.warpOffset = Point3F(0,0,0);
   delta.posVec = delta.rotVec = delta.headVec = VectorF(0,0,0);
   delta.warpTicks = 0;
   delta.dt = 1;
   delta.move = NullMove;
   mPredictionCount = sMaxPredictionTicks;
   mObjToWorld.setColumn(3,delta.pos);
   mRot = delta.rot;
   mHead = delta.head;
   mVelocity.set(0,0,0);
   mDataBlock = 0;
   mHeadHThread = mHeadVThread = mRecoilThread = 0;
   mArmAnimation.action = PlayerData::NullAnimation;
   mArmAnimation.thread = 0;
   mActionAnimation.action = PlayerData::NullAnimation;
   mActionAnimation.thread = 0;
   mActionAnimation.delayTicks = 0;
   mActionAnimation.forward = true;
   mActionAnimation.firstPerson = false;
   mActionAnimation.waitForEnd = false;
   mActionAnimation.holdAtEnd = false;
   mActionAnimation.animateOnServer = false;
   mActionAnimation.atEnd = false;
   //mState = MoveState; /// TGE_PlayerAnim
   mState = WalkState;
   mFalling = false;
   mContactTimer = 0;
   mJumpDelay = 0;
   mJumpSurfaceLastContact = 0;
   mJumpSurfaceNormal.set(0,0,1);
   mControlObject = 0;
   mGenerateShadow = true;
   dMemset( mSplashEmitter, 0, sizeof( mSplashEmitter ) );

   mImpactSound = 0;
   mRecoverTicks = 0;
   mReversePending = 0;

   mLastPos.set( 0.0, 0.0, 0.0 );

   mMoveBubbleHandle = 0;
   mWaterBreathHandle = 0;
   inLiquid = false;

   mConvex.init(this);
   mWorkingQueryBox.min.set(-1e9, -1e9, -1e9);
   mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);

   mWeaponBackFraction = 0.0;

   mInMissionArea = true;

   mBubbleEmitterTime = 10.0;
   mLastWaterPos.set( 0.0, 0.0, 0.0 );

   mMountPending = 0;

#ifdef TGE_RPG /// TGE_Move
	m_ptOriginBak.set(-1.0,-1.0,-1.0);
	m_fMoveRate		= 1.0f;
	m_fMoveSpeed	= 0.f;
	m_fRunRate		= 0.f;
#endif
}

Player::~Player()
{
}


//----------------------------------------------------------------------------

bool Player::onAdd()
{
   ActionAnimation serverAnim = mActionAnimation;
   if(!Parent::onAdd() || !mDataBlock)
      return false;

   mWorkingQueryBox.min.set(-1e9, -1e9, -1e9);
   mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);

   addToScene();

   // Make sure any state and animation passed from the server
   // in the initial update is set correctly.
   ActionState state = mState;
   mState = NullState;
   setState(state);
   if (serverAnim.action != PlayerData::NullAnimation)
   {
      setActionThread(serverAnim.action, true, serverAnim.holdAtEnd, true, false, true);
      if (serverAnim.atEnd)
      {
         mShapeInstance->clearTransition(mActionAnimation.thread);
         mShapeInstance->setPos(mActionAnimation.thread,
                                mActionAnimation.forward? 1: 0);
         if (inDeathAnim())
            mDeath.lastPos = 1.0;
      }

      // We have to leave them sitting for a while since mounts don't come through right
      // away (and sometimes not for a while).  Still going to let this time out because
      // I'm not sure if we're guaranteed another anim will come through and cancel.
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
         mMountPending = (S32) sMountPendingTickWait;
#else
      if (!isServerObject() && inSittingAnim())
         mMountPending = (S32) sMountPendingTickWait;
      else
         mMountPending = 0;
#endif
   }
   if (mArmAnimation.action != PlayerData::NullAnimation)
      setArmThread(mArmAnimation.action);

   //
   if (isServerObject())
   {
      scriptOnAdd();
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
   }
   else
   {
#endif
      U32 i;
      for( i=0; i<PlayerData::NUM_SPLASH_EMITTERS; i++ )
      {
         mSplashEmitter[i] = new ParticleEmitter;
         mSplashEmitter[i]->onNewDataBlock( mDataBlock->splashEmitterList[i] );
         if( !mSplashEmitter[i]->registerObject() )
         {
            Con::warnf( ConsoleLogEntry::General, "Could not register dust emitter for class: %s", mDataBlock->getName() );
            delete mSplashEmitter[i];
            mSplashEmitter[i] = NULL;
         }
      }
      mLastWaterPos = getPosition();

      // clear out all camera effects
      gCamFXMgr.clear();
   }

   return true;
}

void Player::onRemove()
{
   setControlObject(0);
   scriptOnRemove();
   removeFromScene();

   U32 i;
   for( i=0; i<PlayerData::NUM_SPLASH_EMITTERS; i++ )
   {
      if( mSplashEmitter[i] )
      {
         mSplashEmitter[i]->deleteWhenEmpty();
         mSplashEmitter[i] = NULL;
      }
   }

   mWorkingQueryBox.min.set(-1e9, -1e9, -1e9);
   mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);

   Parent::onRemove();
}

void Player::onScaleChanged()
{
   const Point3F& scale = getScale();
   mScaledBox = mObjBox;
   mScaledBox.min.convolve( scale );
   mScaledBox.max.convolve( scale );
}


//----------------------------------------------------------------------------

bool Player::onNewDataBlock(GameBaseData* dptr)
{
   PlayerData* prevData = mDataBlock;
   mDataBlock = dynamic_cast<PlayerData*>(dptr);
   if (!mDataBlock || !Parent::onNewDataBlock(dptr))
      return false;

   // Initialize arm thread, preserve arm sequence from last datablock.
   // Arm animation can be from last datablock, or sent from the server.
   U32 prevAction = mArmAnimation.action;
   mArmAnimation.action = PlayerData::NullAnimation;
   if (mDataBlock->lookAction) {
      mArmAnimation.thread = mShapeInstance->addThread();
      mShapeInstance->setTimeScale(mArmAnimation.thread,0);
      if (prevData) {
         if (prevAction != prevData->lookAction && prevAction != PlayerData::NullAnimation)
            setArmThread(prevData->actionList[prevAction].name);
         prevAction = PlayerData::NullAnimation;
      }
      if (mArmAnimation.action == PlayerData::NullAnimation) {
         mArmAnimation.action = (prevAction != PlayerData::NullAnimation)?
            prevAction: mDataBlock->lookAction;
         mShapeInstance->setSequence(mArmAnimation.thread,
           mDataBlock->actionList[mArmAnimation.action].sequence,0);
      }
   }
   else
      mArmAnimation.thread = 0;

   // Initialize head look thread
   TSShape const* shape = mShapeInstance->getShape();
   S32 headSeq = shape->findSequence("head");
   if (headSeq != -1) {
      mHeadVThread = mShapeInstance->addThread();
      mShapeInstance->setSequence(mHeadVThread,headSeq,0);
      mShapeInstance->setTimeScale(mHeadVThread,0);
   }
   else
      mHeadVThread = 0;

   headSeq = shape->findSequence("headside");
   if (headSeq != -1) {
      mHeadHThread = mShapeInstance->addThread();
      mShapeInstance->setSequence(mHeadHThread,headSeq,0);
      mShapeInstance->setTimeScale(mHeadHThread,0);
   }
   else
      mHeadHThread = 0;

   // Recoil thread. The server player does not play this animation.
   mRecoilThread = 0;
   if (isGhost())
      for (U32 s = 0; s < PlayerData::NumRecoilSequences; s++)
         if (mDataBlock->recoilSequence[s] != -1) {
            mRecoilThread = mShapeInstance->addThread();
            mShapeInstance->setSequence(mRecoilThread,mDataBlock->recoilSequence[s],0);
            mShapeInstance->setTimeScale(mRecoilThread,0);
         }

   // Initialize the primary thread, the actual sequence is
   // set later depending on player actions.
   mActionAnimation.action = PlayerData::NullAnimation;
   mActionAnimation.thread = mShapeInstance->addThread();
   updateAnimationTree(!isGhost());

   mObjBox.max.x = mDataBlock->boxSize.x * 0.5;
   mObjBox.max.y = mDataBlock->boxSize.y * 0.5;
   mObjBox.max.z = mDataBlock->boxSize.z;
   mObjBox.min.x = -mObjBox.max.x;
   mObjBox.min.y = -mObjBox.max.y;
   mObjBox.min.z = 0;

   // Setup the box for our convex object...
   mObjBox.getCenter(&mConvex.mCenter);
   mConvex.mSize.x = mObjBox.len_x() / 2.0;
   mConvex.mSize.y = mObjBox.len_y() / 2.0;
   mConvex.mSize.z = mObjBox.len_z() / 2.0;

   // Initialize our scaled attributes as well
   onScaleChanged();

   scriptOnNewDataBlock();
   return true;
}


//----------------------------------------------------------------------------

void Player::setControllingClient(GameConnection* client)
{
   Parent::setControllingClient(client);
   if (mControlObject)
      mControlObject->setControllingClient(client);
}

void Player::setControlObject(ShapeBase* obj)
{
   if (mControlObject) {
      mControlObject->setControllingObject(0);
      mControlObject->setControllingClient(0);
   }
   if (obj == this || obj == 0)
      mControlObject = 0;
   else {
      if (ShapeBase* coo = obj->getControllingObject())
         coo->setControlObject(0);
      if (GameConnection* con = obj->getControllingClient())
         con->setControlObject(0);

      mControlObject = obj;
      mControlObject->setControllingObject(this);
      mControlObject->setControllingClient(getControllingClient());
   }
}

void Player::onCameraScopeQuery(NetConnection *connection, CameraScopeQuery *query)
{
   // First, we are certainly in scope, and whatever we're riding is too...
   if(mControlObject.isNull() || mControlObject == mMount.object)
      Parent::onCameraScopeQuery(connection, query);
   else
   {
      connection->objectInScope(this);
      if (isMounted())
         connection->objectInScope(mMount.object);
      mControlObject->onCameraScopeQuery(connection, query);
   }
}

ShapeBase* Player::getControlObject()
{
   return mControlObject;
}


//-----------------------------------------------------------------------------

void Player::processTick(const Move* move)
{

   PROFILE_START(Player_ProcessTick);

   // If we're not being controlled by a client, let the
   // AI sub-module get a chance at producing a move.
   Move aiMove;

   if (!move && isServerObject() && getAIMove(&aiMove))
      move = &aiMove;

   // Manage the control object and filter moves for the player
   Move pMove,cMove;
   if (mControlObject) 
	{
      if (!move)
         mControlObject->processTick(0);
      else 
		{
         pMove = NullMove;
         cMove = *move;
         if (isMounted()) 
			{
            // Filter Jump trigger if mounted
            pMove.trigger[2] = move->trigger[2];
            cMove.trigger[2] = false;
         }
         if (move->freeLook) 
			{
            // Filter yaw/picth/roll when freelooking.
            pMove.yaw = move->yaw;
            pMove.pitch = move->pitch;
            pMove.roll = move->roll;
            pMove.freeLook = true;
            cMove.freeLook = false;
            cMove.yaw = cMove.pitch = cMove.roll = 0;
         }
         mControlObject->processTick((mDamageState == Enabled)? &cMove: &NullMove);
         move = &pMove;
      }
   }

   Parent::processTick(move);


	/// 只处理非ControlObject对象
   // Warp to catch up to server
   if (delta.warpTicks > 0) 
	{
		//Con::warnf("  warpTicks %d",delta.warpTicks);//Leo testing
      delta.warpTicks--;
		
      // Set new pos.
      getTransform().getColumn(3,&delta.pos);
      delta.pos += delta.warpOffset;
      delta.rot += delta.rotOffset;
      setPosition(delta.pos,delta.rot);
      setRenderPosition(delta.pos,delta.rot);
      updateDeathOffsets();
      updateLookAnimation();

      // Backstepping
      delta.posVec.x = -delta.warpOffset.x;
      delta.posVec.y = -delta.warpOffset.y;
      delta.posVec.z = -delta.warpOffset.z;
      delta.rotVec.x = -delta.rotOffset.x;
      delta.rotVec.y = -delta.rotOffset.y;
      delta.rotVec.z = -delta.rotOffset.z;
   } 
	else 
	{
      // If there is no move, the player is either an
      // unattached player on the server, or a player's
      // client ghost.
      if (!move) 
		{
         if (isGhost()) 
			{
            // If we haven't run out of prediction time,

⌨️ 快捷键说明

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