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

📄 projectile.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "dgl/dgl.h"
#include "sceneGraph/sceneState.h"
#include "sceneGraph/sceneGraph.h"
#include "console/consoleTypes.h"
#include "console/typeValidators.h"
#include "core/bitStream.h"
#include "game/fx/explosion.h"
#include "game/fx/splash.h"
#include "game/shapeBase.h"
#include "ts/tsShapeInstance.h"
#include "game/projectile.h"
#include "audio/audioDataBlock.h"
#include "math/mathUtils.h"
#include "math/mathIO.h"
#include "sim/netConnection.h"
#include "terrain/waterBlock.h"
#include "game/fx/particleEngine.h"
#include "sim/decalManager.h"

IMPLEMENT_CO_DATABLOCK_V1(ProjectileData);
IMPLEMENT_CO_NETOBJECT_V1(Projectile);

const U32 Projectile::csmStaticCollisionMask =  TerrainObjectType    |
                                                InteriorObjectType   |
                                                StaticObjectType;

const U32 Projectile::csmDynamicCollisionMask = PlayerObjectType        |
                                                VehicleObjectType       |
                                                DamagableItemObjectType;

const U32 Projectile::csmDamageableMask = Projectile::csmDynamicCollisionMask;

U32 Projectile::smProjectileWarpTicks = 5;


//--------------------------------------------------------------------------
//
ProjectileData::ProjectileData()
{
   projectileShapeName = NULL;

   sound = NULL;
   soundId = 0;

   explosion = NULL;
   explosionId = 0;

   waterExplosion = NULL;
   waterExplosionId = 0;

   splash = NULL;
   splashId = 0;

   hasLight = false;
   lightRadius = 1;
   lightColor.set(1, 1, 1);

   hasWaterLight = false;
   waterLightColor.set(1, 1, 1);

   faceViewer = false;
   scale.set( 1.0, 1.0, 1.0 );

   isBallistic = false;

	velInheritFactor = 1.0;
	muzzleVelocity = 50;

	armingDelay = 0;
   fadeDelay = 20000 / 32;
   lifetime = 20000 / 32;

   activateSeq = -1;
   maintainSeq = -1;

   gravityMod = 1.0;
   bounceElasticity = 0.999;
   bounceFriction = 0.3;

   particleEmitter = NULL;
   particleEmitterId = 0;

   particleWaterEmitter = NULL;
   particleWaterEmitterId = 0;

   decalCount = 0;
   for (U32 i = 0; i < NumDecals; i++)
   {
      decals[i] = NULL;
      decalId[i] = 0;
   }
}

//--------------------------------------------------------------------------
IMPLEMENT_CONSOLETYPE(ProjectileData)
IMPLEMENT_GETDATATYPE(ProjectileData)
IMPLEMENT_SETDATATYPE(ProjectileData)

void ProjectileData::initPersistFields()
{
   Parent::initPersistFields();

   addNamedField(particleEmitter,  TypeParticleEmitterDataPtr, ProjectileData);
   addNamedField(particleWaterEmitter, TypeParticleEmitterDataPtr, ProjectileData);

   addNamedField(projectileShapeName, TypeFilename, ProjectileData);
   addNamedField(scale, TypePoint3F, ProjectileData);

   addNamedField(sound, TypeAudioProfilePtr, ProjectileData);

   addNamedField(explosion, TypeExplosionDataPtr, ProjectileData);
   addNamedField(waterExplosion, TypeExplosionDataPtr, ProjectileData);

   addNamedField(splash, TypeSplashDataPtr, ProjectileData);
   addField("decals", TypeDecalDataPtr, Offset(decals, ProjectileData), NumDecals);

   addNamedField(hasLight, TypeBool, ProjectileData);
   addNamedFieldV(lightRadius, TypeF32, ProjectileData, new FRangeValidator(1, 20));
   addNamedField(lightColor, TypeColorF, ProjectileData);
	
   addNamedField(hasWaterLight, TypeBool, ProjectileData);
   addNamedField(waterLightColor, TypeColorF, ProjectileData);

   addNamedField(isBallistic, TypeBool, ProjectileData);
	addNamedFieldV(velInheritFactor, TypeF32, ProjectileData, new FRangeValidator(0, 1));
   addNamedFieldV(muzzleVelocity, TypeF32, ProjectileData, new FRangeValidator(0, 10000));

	addNamedFieldV(lifetime, TypeS32, ProjectileData, new IRangeValidatorScaled(TickMs, 0, Projectile::MaxLivingTicks));
   addNamedFieldV(armingDelay, TypeS32, ProjectileData, new IRangeValidatorScaled(TickMs, 0, Projectile::MaxLivingTicks));
   addNamedFieldV(fadeDelay, TypeS32, ProjectileData, new IRangeValidatorScaled(TickMs, 0, Projectile::MaxLivingTicks));

   addNamedFieldV(bounceElasticity, TypeF32, ProjectileData, new FRangeValidator(0, 0.999));
   addNamedFieldV(bounceFriction, TypeF32, ProjectileData, new FRangeValidator(0, 1));
   addNamedFieldV(gravityMod, TypeF32, ProjectileData, new FRangeValidator(0, 1));
}


//--------------------------------------------------------------------------
bool ProjectileData::onAdd()
{
   if(!Parent::onAdd())
      return false;

   if (!particleEmitter && particleEmitterId != 0)
      if (Sim::findObject(particleEmitterId, particleEmitter) == false)
         Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockId(particleEmitter): %d", particleEmitterId);

   if (!particleWaterEmitter && particleWaterEmitterId != 0)
      if (Sim::findObject(particleWaterEmitterId, particleWaterEmitter) == false)
         Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockId(particleWaterEmitter): %d", particleWaterEmitterId);

   if (!explosion && explosionId != 0)
      if (Sim::findObject(explosionId, explosion) == false)
         Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockId(explosion): %d", explosionId);

   if (!waterExplosion && waterExplosionId != 0)
      if (Sim::findObject(waterExplosionId, waterExplosion) == false)
         Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockId(waterExplosion): %d", waterExplosionId);

   if (!splash && splashId != 0)
      if (Sim::findObject(splashId, splash) == false)
         Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockId(splash): %d", splashId);

   if (!sound && soundId != 0)
      if (Sim::findObject(soundId, sound) == false)
         Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockid(sound): %d", soundId);

   lightColor.clamp();
   waterLightColor.clamp();

   return true;
}


bool ProjectileData::preload(bool server, char errorBuffer[256])
{
   if (Parent::preload(server, errorBuffer) == false)
      return false;

   if (projectileShapeName && projectileShapeName[0] != '\0')
   {
      projectileShape = ResourceManager->load(projectileShapeName);
      if (bool(projectileShape) == false)
      {
         dSprintf(errorBuffer, sizeof(errorBuffer), "ProjectileData::load: Couldn't load shape \"%s\"", projectileShapeName);
         return false;
      }
      activateSeq = projectileShape->findSequence("activate");
      maintainSeq = projectileShape->findSequence("maintain");
   }

   if (bool(projectileShape)) // create an instance to preload shape data
   {
      TSShapeInstance* pDummy = new TSShapeInstance(projectileShape, !server);
      delete pDummy;
   }

   // load up all the supplied decal datablocks
   //  move non-null ones to the front of the array
   //  for our random decal picker later
   U32 i;
   DecalData *tmpDecals[NumDecals];
   for (i = 0; i < NumDecals; i++)
   {
      tmpDecals[i] = NULL;
      if(!decals[i] && decalId[i] != 0)
         if(!Sim::findObject(decalId[i], decals[i]))
            Con::errorf( ConsoleLogEntry::General, "ProjectileData::preload Invalid packet, bad datablockId(decals): 0x%x", decalId[i]);

      if (!server && decals[i])
      {
         tmpDecals[decalCount] = decals[i];
         decalCount++;
      }
   }
   if (!server && decalCount > 0)
      for (i = 0; i < NumDecals; i++)
         decals[i] = tmpDecals[i];

   return true;
}

//--------------------------------------------------------------------------
void ProjectileData::packData(BitStream* stream)
{
   Parent::packData(stream);

   stream->writeString(projectileShapeName);
   stream->writeFlag(faceViewer);
   if(stream->writeFlag(scale.x != 1 || scale.y != 1 || scale.z != 1))
   {
      stream->write(scale.x);
      stream->write(scale.y);
      stream->write(scale.z);
   }

   if (stream->writeFlag(particleEmitter != NULL))
      stream->writeRangedU32(particleEmitter->getId(), DataBlockObjectIdFirst,
                                                   DataBlockObjectIdLast);
   if (stream->writeFlag(particleWaterEmitter != NULL))
      stream->writeRangedU32(particleWaterEmitter->getId(), DataBlockObjectIdFirst,
                                                   DataBlockObjectIdLast);
   if (stream->writeFlag(explosion != NULL))
      stream->writeRangedU32(explosion->getId(), DataBlockObjectIdFirst,
                                                 DataBlockObjectIdLast);
   if (stream->writeFlag(waterExplosion != NULL))
      stream->writeRangedU32(waterExplosion->getId(), DataBlockObjectIdFirst,
                                                      DataBlockObjectIdLast);
   if (stream->writeFlag(splash != NULL))
      stream->writeRangedU32(splash->getId(), DataBlockObjectIdFirst,
                                              DataBlockObjectIdLast);
   if (stream->writeFlag(sound != NULL))
      stream->writeRangedU32(sound->getId(), DataBlockObjectIdFirst,
                                             DataBlockObjectIdLast);
   for (U32 i = 0; i < NumDecals; i++)
      if (stream->writeFlag(decals[i] != NULL))
         stream->writeRangedU32(decals[i]->getId(), DataBlockObjectIdFirst,
                                                 DataBlockObjectIdLast);

   if(stream->writeFlag(hasLight))
   {
      stream->writeFloat(lightRadius/20.0, 8);
      stream->writeFloat(lightColor.red,7);
      stream->writeFloat(lightColor.green,7);
      stream->writeFloat(lightColor.blue,7);
   }

   if(stream->writeFlag(hasWaterLight))
   {
      stream->writeFloat(waterLightColor.red, 7);
      stream->writeFloat(waterLightColor.green, 7);
      stream->writeFloat(waterLightColor.blue, 7);
   }

   stream->writeRangedU32(lifetime, 0, Projectile::MaxLivingTicks);
   stream->writeRangedU32(armingDelay, 0, Projectile::MaxLivingTicks);
   stream->writeRangedU32(fadeDelay, 0, Projectile::MaxLivingTicks);

   if(stream->writeFlag(isBallistic))
   {
      stream->write(gravityMod);
      stream->write(bounceElasticity);
      stream->write(bounceFriction);
   }

   // Neither velInheritVelocity nor muzzleVelocity are transmitted to the
   // client. This is because in stock Torque, it is not needed for the
   // client-side simulation - in general, it is good design to not transmit
   // useless information. You could easily add stream->write() calls here,
   // and read calls in unpackData, if you did have need of them.
}

void ProjectileData::unpackData(BitStream* stream)
{
   Parent::unpackData(stream);

   projectileShapeName = stream->readSTString();

   faceViewer = stream->readFlag();
   if(stream->readFlag())
   {
      stream->read(&scale.x);
      stream->read(&scale.y);
      stream->read(&scale.z);
   }
   else
      scale.set(1,1,1);

   if (stream->readFlag())
      particleEmitterId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   if (stream->readFlag())
      particleWaterEmitterId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   if (stream->readFlag())
      explosionId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   if (stream->readFlag())
      waterExplosionId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   if (stream->readFlag())
      splashId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   if (stream->readFlag())
      soundId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   for (U32 i = 0; i < NumDecals; i++)
      if (stream->readFlag())
         decalId[i] = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);

   hasLight = stream->readFlag();
   if(hasLight)
   {
      lightRadius = stream->readFloat(8) * 20;
      lightColor.red = stream->readFloat(7);
      lightColor.green = stream->readFloat(7);
      lightColor.blue = stream->readFloat(7);
   }
   hasWaterLight = stream->readFlag();
   if(hasWaterLight)
   {
      waterLightColor.red = stream->readFloat(7);
      waterLightColor.green = stream->readFloat(7);
      waterLightColor.blue = stream->readFloat(7);
   }
   lifetime = stream->readRangedU32(0, Projectile::MaxLivingTicks);
   armingDelay = stream->readRangedU32(0, Projectile::MaxLivingTicks);
   fadeDelay = stream->readRangedU32(0, Projectile::MaxLivingTicks);

   isBallistic = stream->readFlag();
   if(isBallistic)
   {
      stream->read(&gravityMod);
      stream->read(&bounceElasticity);
      stream->read(&bounceFriction);
   }
}


//--------------------------------------------------------------------------
//--------------------------------------
//
Projectile::Projectile()
{
   // Todo: ScopeAlways?
   mNetFlags.set(Ghostable);
   mTypeMask |= ProjectileObjectType;

   mCurrPosition.set(0, 0, 0);
   mCurrVelocity.set(0, 0, 1);

   mSourceObjectId = -1;
   mSourceObjectSlot = -1;

   mCurrTick         = 0;

   mParticleEmitter   = NULL;
   mParticleWaterEmitter = NULL;

   mSoundHandle = NULL_AUDIOHANDLE;

   mProjectileShape   = NULL;
   mActivateThread    = NULL;
	mMaintainThread    = NULL;

   mCollideHitType   = 0;

   mHidden           = false;
   mFadeValue        = 1.0;
}

Projectile::~Projectile()
{
   delete mProjectileShape;
   mProjectileShape = NULL;
}

//--------------------------------------------------------------------------
void Projectile::initPersistFields()
{
   Parent::initPersistFields();

   addGroup("Physics");
   addField("initialPosition",  TypePoint3F, Offset(mCurrPosition, Projectile));
   addField("initialVelocity", TypePoint3F, Offset(mCurrVelocity, Projectile));
   endGroup("Physics");

   addGroup("Source");
   addField("sourceObject",     TypeS32,     Offset(mSourceObjectId, Projectile));
   addField("sourceSlot",       TypeS32,     Offset(mSourceObjectSlot, Projectile));
   endGroup("Source");
}

bool Projectile::calculateImpact(float,
                                 Point3F& pointOfImpact,
                                 float&   impactTime)
{
   Con::warnf(ConsoleLogEntry::General, "Projectile::calculateImpact: Should never be called");

   impactTime = 0;
   pointOfImpact.set(0, 0, 0);
   return false;
}


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

⌨️ 快捷键说明

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