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

📄 lightning.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 3 页
字号:
{
   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);

   // This should be sufficient for most objects that don't manage zones, and
   //  don't need to return a specialized RenderImage...
   if (state->isObjectRendered(this)) {
      SceneRenderImage* image = new SceneRenderImage;
      image->obj = this;
      image->isTranslucent = true;
      image->sortType = SceneRenderImage::EndSort;
      state->insertRenderImage(image);
   }

   return false;
}


void Lightning::renderObject(SceneState* state, SceneRenderImage*)
{
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");

   RectI viewport;
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   dglGetViewport(&viewport);

   // Uncomment this if this is a "simple" (non-zone managing) object
   state->setupObjectProjection(this);


   // RENDER CODE HERE
   MatrixF mv;
   dglGetModelview(&mv);
   Point3F camAxis;
   mv.getRow(1, &camAxis);

   glDisable(GL_CULL_FACE);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE);
   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   glDepthMask( GL_FALSE );

   if( useFog )
   {

      if (dglDoesSupportARBMultitexture() && dglDoesSupportFogCoord()) {
         glEnable(GL_FOG);
         glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
         GLfloat fogColor[4];
         fogColor[0] = state->getFogColor().red;
         fogColor[1] = state->getFogColor().green;
         fogColor[2] = state->getFogColor().blue;
         fogColor[3] = 0.5f;
         glFogfv(GL_FOG_COLOR, fogColor);
         glFogi(GL_FOG_MODE, GL_LINEAR);
         glFogf(GL_FOG_START, 0.0f);
         glFogf(GL_FOG_END, 1.0f);
      }
   }

   Strike* walk = mStrikeListHead;
   while (walk != NULL) {

      glBindTexture(GL_TEXTURE_2D, mDataBlock->strikeTextures[0].getGLName());

      for( U32 i=0; i<3; i++ )
      {
         if( walk->bolt[i].isFading )
         {
            F32 alpha = 1.0 - walk->bolt[i].percentFade;
            if( alpha < 0.0 ) alpha = 0.0;
            glColor4f( fadeColor.red, fadeColor.green, fadeColor.blue, alpha );
         }
         else
         {
            glColor4fv( color );
         }
         walk->bolt[i].render( state->getCameraPosition() );
      }


      walk = walk->next;
   }

   glDepthMask( GL_TRUE );

   glDisable(GL_FOG);
   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   dglSetViewport(viewport);

   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}

void Lightning::scheduleThunder(Strike* newStrike)
{
   AssertFatal(isClientObject(), "Lightning::scheduleThunder: server objects should not enter this version of the function");

   // If no thunder sounds, don't schedule anything!
   if (mDataBlock->numThunders == 0)
      return;

   GameConnection* connection = GameConnection::getConnectionToServer();
   if (connection) {
      MatrixF cameraMatrix;

      if (connection->getControlCameraTransform(0, &cameraMatrix)) {
         Point3F worldPos;
         cameraMatrix.getColumn(3, &worldPos);

         worldPos.x -= newStrike->xVal;
         worldPos.y -= newStrike->yVal;
         worldPos.z  = 0;

         F32 dist = worldPos.len();
         F32 t    = dist / 330.0;

         // Ok, we need to schedule a random strike sound t secs in the future...
         //
         if (t <= 0.03) {
            // If it's really close, just play it...
            U32 thunder = sgLightningRand.randI(0, mDataBlock->numThunders - 1);
            alxPlay(mDataBlock->thunderSounds[thunder]);
         } else {
            Thunder* pThunder = new Thunder;
            pThunder->tRemaining = t;
            pThunder->next       = mThunderListHead;
            mThunderListHead     = pThunder;
         }
      }
   }
}


//--------------------------------------------------------------------------
void Lightning::processTick(const Move* move)
{
   Parent::processTick(move);

   if (isServerObject()) {
      S32 msBetweenStrikes = (S32)(60.0 / strikesPerMinute * 1000.0);

      mLastThink += TickMs;
      if( mLastThink > msBetweenStrikes )
      {
         strikeRandomPoint();
         mLastThink -= msBetweenStrikes;
      }
   }
}

void Lightning::interpolateTick(F32 dt)
{
   Parent::interpolateTick(dt);
}

void Lightning::advanceTime(F32 dt)
{
   Parent::advanceTime(dt);

   Strike** pWalker = &mStrikeListHead;
   while (*pWalker != NULL) {
      Strike* pStrike = *pWalker;

      for( U32 i=0; i<3; i++ )
      {
         pStrike->bolt[i].update( dt );
      }

      pStrike->currentAge += dt;
      if (pStrike->currentAge > pStrike->deathAge) {
         *pWalker = pStrike->next;
         delete pStrike;
      } else {
         pWalker = &((*pWalker)->next);
      }
   }

   Thunder** pThunderWalker = &mThunderListHead;
   while (*pThunderWalker != NULL) {
      Thunder* pThunder = *pThunderWalker;

      pThunder->tRemaining -= dt;
      if (pThunder->tRemaining <= 0.0) {
         *pThunderWalker = pThunder->next;
         delete pThunder;

         // Play the sound...
         U32 thunder = sgLightningRand.randI(0, mDataBlock->numThunders - 1);
         alxPlay(mDataBlock->thunderSounds[thunder]);
      } else {
         pThunderWalker = &((*pThunderWalker)->next);
      }
   }
}


//--------------------------------------------------------------------------
void Lightning::processEvent(LightningStrikeEvent* pEvent)
{
      AssertFatal(pEvent->mStart.x >= 0 && pEvent->mStart.x <= 1.0, "Out of bounds coord!");

      Strike* pStrike = new Strike;

      Point3F strikePoint;
      strikePoint.zero();

      if( pEvent->mTarget )
      {
         Point3F objectCenter;
         pEvent->mTarget->getObjBox().getCenter( &objectCenter );
         objectCenter.convolve( pEvent->mTarget->getScale() );
         pEvent->mTarget->getTransform().mulP( objectCenter );

         strikePoint = objectCenter;
      }
      else
      {
         strikePoint.x = pEvent->mStart.x;
         strikePoint.y = pEvent->mStart.y;
         strikePoint *= mObjScale;
         strikePoint += getPosition();
         strikePoint += Point3F( -mObjScale.x * 0.5, -mObjScale.y * 0.5, 0.0 );

         RayInfo rayInfo;
         Point3F start = strikePoint;
         start.z = mObjScale.z * 0.5 + getPosition().z;
         strikePoint.z += -mObjScale.z * 0.5;
         bool rayHit = gClientContainer.castRay( start, strikePoint,
                                      (STATIC_COLLISION_MASK | WaterObjectType),
                                      &rayInfo);
         if( rayHit )
         {
            strikePoint.z = rayInfo.point.z;
         }
         else
         {
            strikePoint.z = pStrike->bolt[0].findHeight( strikePoint, mSceneManager );
         }
      }

      pStrike->xVal       = strikePoint.x;
      pStrike->yVal       = strikePoint.y;

      pStrike->deathAge   = 1.6;
      pStrike->currentAge = 0.0;
      pStrike->next       = mStrikeListHead;

      for( U32 i=0; i<3; i++ )
      {
         F32 randStart = boltStartRadius;
         F32 height = mObjScale.z * 0.5 + getPosition().z;
         pStrike->bolt[i].startPoint = Point3F( pStrike->xVal + gRandGen.randF( -randStart, randStart ), pStrike->yVal + gRandGen.randF( -randStart, randStart ), height );
         pStrike->bolt[i].endPoint = strikePoint;
         pStrike->bolt[i].width = strikeWidth;
         pStrike->bolt[i].numMajorNodes = 10;
         pStrike->bolt[i].maxMajorAngle = 30;
         pStrike->bolt[i].numMinorNodes = 4;
         pStrike->bolt[i].maxMinorAngle = 15;
         pStrike->bolt[i].generate();
         pStrike->bolt[i].startSplits();
         pStrike->bolt[i].lifetime = 1.0;
         pStrike->bolt[i].fadeTime = 0.2;
         pStrike->bolt[i].renderTime = gRandGen.randF(0.0, 0.25);
      }

      mStrikeListHead     = pStrike;

      scheduleThunder(pStrike);

      MatrixF trans(true);
      trans.setPosition( strikePoint );

      if (mDataBlock->strikeSound)
      {
         alxPlay(mDataBlock->strikeSound, &trans );
      }

}

void Lightning::warningFlashes()
{
   AssertFatal(isServerObject(), "Error, client objects may not initiate lightning!");


   SimGroup* pClientGroup = Sim::getClientGroup();
   for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++) {
      NetConnection* nc = static_cast<NetConnection*>(*itr);
      if (nc != NULL)
      {
         LightningStrikeEvent* pEvent = new LightningStrikeEvent;
         pEvent->mLightning = this;

         nc->postNetEvent(pEvent);
      }
   }
}

void Lightning::strikeRandomPoint()
{
   AssertFatal(isServerObject(), "Error, client objects may not initiate lightning!");


   Point3F strikePoint;
   strikePoint.x = gRandGen.randF( 0.0, 1.0 );
   strikePoint.y = gRandGen.randF( 0.0, 1.0 );
   strikePoint.z = 0.0;

   // check if an object is within target range

   strikePoint *= mObjScale;
   strikePoint += getPosition();
   strikePoint += Point3F( -mObjScale.x * 0.5, -mObjScale.y * 0.5, 0.0 );

   Box3F queryBox;
   F32 boxWidth = strikeRadius * 2;

   queryBox.min.set( -boxWidth * 0.5, -boxWidth * 0.5, -mObjScale.z * 0.5 );
   queryBox.max.set(  boxWidth * 0.5,  boxWidth * 0.5,  mObjScale.z * 0.5 );
   queryBox.min += strikePoint;
   queryBox.max += strikePoint;

   SimpleQueryList sql;
   getContainer()->findObjects(queryBox, DAMAGEABLE_MASK,
                               SimpleQueryList::insertionCallback, &sql);

   SceneObject *highestObj = NULL;
   F32 highestPnt = 0.0;

   for( U32 i = 0; i < sql.mList.size(); i++ )
   {
      Point3F objectCenter;
      sql.mList[i]->getObjBox().getCenter(&objectCenter);
      objectCenter.convolve(sql.mList[i]->getScale());
      sql.mList[i]->getTransform().mulP(objectCenter);

      // check if object can be struck

      RayInfo rayInfo;
      Point3F start = objectCenter;
      start.z = mObjScale.z * 0.5 + getPosition().z;
      Point3F end = objectCenter;
      end.z = -mObjScale.z * 0.5 + getPosition().z;
      bool rayHit = gServerContainer.castRay( start, end,
                                   (0xFFFFFFFF),
                                   &rayInfo);

      if( rayHit && rayInfo.object == sql.mList[i] )
      {
         if( !highestObj )
         {
            highestObj = sql.mList[i];
            highestPnt = objectCenter.z;
            continue;
         }

         if( objectCenter.z > highestPnt )
         {
            highestObj = sql.mList[i];
            highestPnt = objectCenter.z;
         }
      }


   }

   // hah haaaaa, we have a target!
   SceneObject *targetObj = NULL;
   if( highestObj )
   {
      F32 chance = gRandGen.randF();
      if( chance <= chanceToHitTarget )
      {
         Point3F objectCenter;
         highestObj->getObjBox().getCenter(&objectCenter);
         objectCenter.convolve(highestObj->getScale());
         highestObj->getTransform().mulP(objectCenter);

         bool playerInWarmup = false;
         Player *playerObj = dynamic_cast< Player * >(highestObj);
         if( playerObj )
         {
            if( !playerObj->getControllingClient() )
            {
               playerInWarmup = true;
            }
         }

         if( !playerInWarmup )
         {
            applyDamage( objectCenter, VectorF( 0.0, 0.0, 1.0 ), highestObj );
            targetObj = highestObj;
         }
      }
   }

   SimGroup* pClientGroup = Sim::getClientGroup();
   for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++)
   {
      NetConnection* nc = static_cast<NetConnection*>(*itr);

      LightningStrikeEvent* pEvent = new LightningStrikeEvent;
      pEvent->mLightning = this;

⌨️ 快捷键说明

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