Material Based Effects - Appliation - Shapebase vs Shapebase Collisions
From TDN
Shapebase revisited: shapebase.h
Contents |
Per material Spark Definitions:
inside struct ShapeBaseData : public GameBaseData {
ExplosionData* mSpark[MAX_MAT_FX]; S32 mSparkId[MAX_MAT_FX]; ParticleEmitterData* SparkEmitter; S32 SparkEmitterId; protected: bool onAdd();
inside class ShapeBase : public GameBase
alter:
enum ShapeBaseMasks {
SparkMask = Parent::NextFreeMask,
NameMask = Parent::NextFreeMask << 1, //change each of these up by 1 till you hit ThreadMaskN = SoundMaskN << MaxSoundThreads,
and add:
SimObjectPtr<ParticleEmitter> mSparkParticleEmitter; Point3F mSparkPosition; Point3F mSparkNormal; U32 mCollideSparkHitType; bool mHasCollided; SimObjectPtr<ShapeBase> lastHitObject; void ShapeBase::processFX(); /// What to do when this projectile explodes virtual void ShapeBase::Spark(const Point3F& p, const Point3F& n, S32 matFxIndex); void emitParticles(const Point3F&, const Point3F&, const Point3F&, const U32); bool mFadeValue;
again, you'll note the funcname's processFX, to denote were gonna be working with more than just visuals here
shapebase.cc/.cpp
Per material Spark Initialisation:
inside ShapeBaseData::ShapeBaseData()
for (int i = 0; i<MAX_MAT_FX; i++)
{
mSpark[i] = NULL;
mSparkId[i] = 0;
}
}
also add:
bool ShapeBaseData::onAdd()
{
if(!Parent::onAdd())
return false;
for (int i = 0; i<MAX_MAT_FX; i++)
if (!mSpark[i] && mSparkId[i] != 0)
if (Sim::findObject(mSparkId[i], mSpark[i]) == false)
Con::errorf(ConsoleLogEntry::General, "ProjectileData::onAdd: Invalid packet, bad datablockId(explosion)[%i]: %d", mSparkId[i],i);
return true;
}
Per material Spark Script-hook:
inside void ShapeBaseData::initPersistFields()
addField("Sparks", TypeExplosionDataPtr, Offset(mSpark, ShapeBaseData), MAX_MAT_FX);
(yes, I know. explosions. I'll explain that in a sec)
Per material Spark Transmission:
inside void ShapeBaseData::packData(BitStream* stream)
for (int i=0; i<MAX_MAT_FX; i++)
if (stream->writeFlag(mSpark[i] != NULL))
stream->writeRangedU32(mSpark[i]->getId(), DataBlockObjectIdFirst,
DataBlockObjectIdLast);
inside void ShapeBaseData::unpackData(BitStream* stream)
for (int i = 0; i<MAX_MAT_FX; i++)
if (stream->readFlag())
mSparkId[i] = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
Per material Spark Support Functionality:
//add
//==============================================================================
//---------------------- Start FX Implementation ------------------------
//==============================================================================
void ShapeBase::Spark(const Point3F& p, const Point3F& n, S32 matFxIndex)
{
// Make sure we don't explode twice...
//if (mHidden == true)
//return;
//mHidden = true;
// Client just plays the explosion at the right place...
//
Explosion* pSpark = NULL;
F32 waterHeight;
if (mDataBlock->mSpark[matFxIndex])
{
pSpark = new Explosion;
pSpark->onNewDataBlock(mDataBlock->mSpark[matFxIndex]);
}
if( pSpark )
{
MatrixF xform(true);
xform.setPosition(p);
pSpark->setTransform(xform);
pSpark->setInitialState(p, n);
pSpark->setCollideType( STATIC_COLLISION_MASK );
if (pSpark->registerObject() == false)
{
Con::errorf(ConsoleLogEntry::General, "Projectile(%s)::Spark: couldn't register Spark",
mDataBlock->getName() );
delete pSpark;
pSpark = NULL;
}
}
// Client object
//updateSound();
}
void ShapeBase::processFX()
{
if (!isClientObject()) return;
this->disableCollision();
TriRayInfo rInfo;
for (CollisionTimeout* ptr = mTimeoutList; ptr; ptr = ptr->next)
{
ShapeBase* obj = static_cast<ShapeBase*>(Sim::findObject(ptr->objectNumber));
if (obj != NULL)
{
Point3F sp, ep;
sp = this->getPosition();
ep = obj->getPosition();
if (obj->castRay(sp, ep, &rInfo))
{
Material* matInst = static_cast<Material*>(Sim::findObject(rInfo.material));
if (matInst != NULL)
{
//Con::errorf("Tex: %s", matInst->getName());
//if (this->mDataBlock->tireEmitter[matInst->mFXIndex] != NULL)
//{
Spark(rInfo.point, rInfo.normal,matInst->mFXIndex);
//Con::errorf("FX: %s", mDataBlock->tireEmitter[matInst->mFXIndex]->getName());
//}
}
//else Con::errorf("matInst Still Registers as (%i)",matInst);
}
}
//else Con::errorf("CollisionTimeout Object (%i) Still Registers as (%i)",ptr->objectNumber, obj);
}
//since there's no listing for static objects /interiorinstances in the CollisionTimeout list, we'll just have to
//do this the brute-force way, till someone brighter throws us a bone
Point3F sp, ep;
sp = this->getPosition();
ep = sp + this->getVelocity()/2;
if (mContainer->castRay(sp, ep, STATIC_COLLISION_MASK, &rInfo))
{
Material* matInst = static_cast<Material*>(Sim::findObject(rInfo.material));
if (matInst != NULL)
{
//Con::errorf("Tex: %s", matInst->getName());
Spark(rInfo.point, rInfo.normal,matInst->mFXIndex);
}
//else Con::errorf("matInst Still Registers as (%i)",matInst);
}
this->enableCollision();
}
Per material Spark Usage:
inside void Vehicle::updatePos(F32 dt) after the check
if (isServerObject()) {
...
}
replacing
else {
// Play impact sounds on the client.
with
else {
notifyCollision();
// Server side impact script callback
if (collided) {
VectorF collVec = mRigid.linVelocity - origVelocity;
F32 collSpeed = collVec.len();
if (collSpeed > mDataBlock->minImpactSpeed)
onImpact(collVec);
}
// Play impact sounds on the client.
Sets it up to run the onImpact func on clients as well as servers. Once you have that knocked on out, it's a simple matter of altering
void ShapeBase::onImpact(SceneObject* obj, VectorF vec) to
{
if (!isGhost()) {
char buff1[256];
char buff2[32];
dSprintf(buff1,sizeof(buff1),"%g %g %g",vec.x, vec.y, vec.z);
dSprintf(buff2,sizeof(buff2),"%g",vec.len());
Con::executef(mDataBlock,5,"onImpact",scriptThis(), obj->getIdString(), buff1, buff2);
}
else processFX();
}
and
void ShapeBase::onImpact(VectorF vec) to:
{
if (!isGhost()) {
char buff1[256];
char buff2[32];
dSprintf(buff1,sizeof(buff1),"%g %g %g",vec.x, vec.y, vec.z);
dSprintf(buff2,sizeof(buff2),"%g",vec.len());
Con::executef(mDataBlock,5,"onImpact",scriptThis(), "0", buff1, buff2);
}
else processFX();
}
Backtrace: Material Based Effects Projects



