Weapon Charging 2 : Particles
by Owen "WDA" Ashcroft · 07/17/2002 (9:22 am) · 2 comments
Please ensure you have completed the previous tutorial as it builds on that.
All alterations that take place in this tutorial are within the source code itself, if you don't have the source code you will not be able to
implement this as you have to alter the partical engine itself.
The first task is to allow the engine to see the modifier variable. Open crossbow.cs and scroll to the bottom and look for the following
block:
become visible to the engine itself.
Now fire up the source code, please ensure that your source code compiles by compiling it clean, nothing is worse than thinking that something you
are following is wrong, when in reality there is something wrong with the set up, so just compile it quickly and make sure you get no errors.
Done, good, ok now goto projectile.h now goto line 116 you should see
Now switch to projectile.cc, goto line 45ish you should see ProjectileData::ProjectileData() anywhere in that section add
Now goto line 260 to the Projectile::Projectile() section and in there add:
value.
Goto line 300 and look for the block of code that looks like:
puts generalModifier into mGeneralModifier when it comes through from the script.
Next you need to write the mGeneralModifier to the network stream, and conversely include a section so it can be read from it.
Goto line 700 and look for U32 Projectile::packUpdate(NetConnection* con, U32 mask, BitStream* stream) just above return retMask add
stream->write(mGeneralModifier); so the bottom resembles:
Next you have to add something so it can be read from it. Scroll down about 4 lines and you will see void
Projectile::unpackUpdate(NetConnection* con, BitStream* stream) at the very bottom (just before the closing bracket) add
stream->read(&mGeneralModifier);.
We still need to make some changes to projectile.cc however we need to add an additional variable to particleEngine.h so load that
up and goto line 135. You should see
Return to projectile.cc. Around line 360 you should see the lines:
That's Projectile.cc[b] finished with, we now turn out attention to [b]ParticleEngine.cc, so load that up.
Goto line 700 you should see the block ParticleEmitter::ParticleEmitter(), you need to add modifier to it so it has a default value, my
code looks like:
Next goto line 1470 and look for the lines:
That should do it, compile the code and charge up the crossbow, if you don't see much change increase to maximum charge from 5 to 25 and just keep
the button held for longer, you should notice a significant size different in the particle effects depending on the length of time the fire button
is held.
All alterations that take place in this tutorial are within the source code itself, if you don't have the source code you will not be able to
implement this as you have to alter the partical engine itself.
The first task is to allow the engine to see the modifier variable. Open crossbow.cs and scroll to the bottom and look for the following
block:
%p = new (%this.projectileType)() {
dataBlock = %projectile;
initialVelocity = %muzzleVelocity;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
client = %obj.client;
};change it to%p = new (%this.projectileType)() {
dataBlock = %projectile;
initialVelocity = %muzzleVelocity;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
client = %obj.client;
generalModifier = %modifier;
};This creates another variable called generalModifier that is specific to that particular projectile and with some extra additions will become visible to the engine itself.
Now fire up the source code, please ensure that your source code compiles by compiling it clean, nothing is worse than thinking that something you
are following is wrong, when in reality there is something wrong with the set up, so just compile it quickly and make sure you get no errors.
Done, good, ok now goto projectile.h now goto line 116 you should see
Point3F mCurrPosition; Point3F mCurrVelocity; S32 mSourceObjectId; S32 mSourceObjectSlot;add the variable S32 mGeneralModifier just underneath that so it looks like
Point3F mCurrPosition; Point3F mCurrVelocity; S32 mSourceObjectId; S32 mSourceObjectSlot; S32 mGeneralModifier;This gives us a variable to put our generalModifier variable from the script into.
Now switch to projectile.cc, goto line 45ish you should see ProjectileData::ProjectileData() anywhere in that section add
generalModifier = 1;This gives a default value for our scripting variable incase we don't use for a different projectile.
Now goto line 260 to the Projectile::Projectile() section and in there add:
mGeneralModifier = 0;This again provides a default
value.
Goto line 300 and look for the block of code that looks like:
void Projectile::initPersistFields()
{
Parent::initPersistFields();
addField("initialPosition", TypePoint3F, Offset(mCurrPosition, Projectile));
addField("initialVelocity", TypePoint3F, Offset(mCurrVelocity, Projectile));
addField("sourceObject", TypeS32, Offset(mSourceObjectId, Projectile));
addField("sourceSlot", TypeS32, Offset(mSourceObjectSlot, Projectile));
} add addField("generalModifier", TypeS32, Offset(mGeneralModifier, Projectile));to the bottom of the addFields, this puts generalModifier into mGeneralModifier when it comes through from the script.
Next you need to write the mGeneralModifier to the network stream, and conversely include a section so it can be read from it.
Goto line 700 and look for U32 Projectile::packUpdate(NetConnection* con, U32 mask, BitStream* stream) just above return retMask add
stream->write(mGeneralModifier); so the bottom resembles:
stream->write(mGeneralModifier); return retMask;This will write the variable to the network stream.
Next you have to add something so it can be read from it. Scroll down about 4 lines and you will see void
Projectile::unpackUpdate(NetConnection* con, BitStream* stream) at the very bottom (just before the closing bracket) add
stream->read(&mGeneralModifier);.
We still need to make some changes to projectile.cc however we need to add an additional variable to particleEngine.h so load that
up and goto line 135. You should see
void emitParticles(const Point3F& rCenter,
const Point3F& rNormal,
const F32 radius,
const Point3F& velocity,
S32 count);
// Internal interface
protected:
void addParticle(const Point3F&, const Point3F&, const Point3F&, const Point3F&);
void renderBillboardParticle( Particle &part, Point3F *basePnts, MatrixF &camView, F32 spinFactor );make it look likevoid emitParticles(const Point3F& rCenter,
const Point3F& rNormal,
const F32 radius,
const Point3F& velocity,
S32 count);
S32 modifier; //Added variable for modifier.
// Internal interface
protected:
void addParticle(const Point3F&, const Point3F&, const Point3F&, const Point3F&);
void renderBillboardParticle( Particle &part, Point3F *basePnts, MatrixF &camView, F32 spinFactor );This gives us somewhere to attach our modifier to the particle emitter so the particle engine has access to it.Return to projectile.cc. Around line 360 you should see the lines:
if (mDataBlock->particleEmitter != NULL)
{
ParticleEmitter* pEmitter = new ParticleEmitter;you need to add a line here so the modifier is transferred to the new ParticleEmitter:if (mDataBlock->particleEmitter != NULL)
{
ParticleEmitter* pEmitter = new ParticleEmitter;
pEmitter->modifier = mGeneralModifier; //copies modifier valueThat's Projectile.cc[b] finished with, we now turn out attention to [b]ParticleEngine.cc, so load that up.
Goto line 700 you should see the block ParticleEmitter::ParticleEmitter(), you need to add modifier to it so it has a default value, my
code looks like:
ParticleEmitter::ParticleEmitter()
{
mDeleteWhenEmpty = false;
mDeleteOnTick = false;
mParticleListHead = NULL;
mInternalClock = 0;
mNextParticleTime = 0;
mLastPosition.set(0, 0, 0);
mHasLastPosition = false;
mLifetimeMS = 0;
mElapsedTimeMS = 0;
modifier = 0; //new modifier default value
}This is to ensure that we always know what the value is and we don't get wacky values.Next goto line 1470 and look for the lines:
if( emitter.getDataBlock()->useEmitterSizes )
{
particle->size = (emitter.sizes[i-1] * (1.0 - firstPart)) +
(emitter.sizes[i] * firstPart);
}
else
{
particle->size = (particle->dataBlock->sizes[i-1] * (1.0 - firstPart)) +
(particle->dataBlock->sizes[i] * firstPart);
}This determines the size of the various particles, if needs to look like:if( emitter.getDataBlock()->useEmitterSizes )
{
if(emitter.modifier != 0)
{
particle->size = (emitter.sizes[i-1] * (1.0 - firstPart)) +
(emitter.sizes[i] * firstPart)
* emitter.modifier;
}else{
particle->size = (emitter.sizes[i-1] * (1.0 - firstPart)) +
(emitter.sizes[i] * firstPart);
}
}
else
{
if(emitter.modifier != 0)
{
particle->size = (particle->dataBlock->sizes[i-1] * (1.0 - firstPart)) +
(particle->dataBlock->sizes[i] * firstPart)
* emitter.modifier;
}else{
particle->size = (particle->dataBlock->sizes[i-1] * (1.0 - firstPart)) +
(particle->dataBlock->sizes[i] * firstPart);
}
}This will then adjust each particle's size according to its emitters modifier value, as long as that value is not 0.That should do it, compile the code and charge up the crossbow, if you don't see much change increase to maximum charge from 5 to 25 and just keep
the button held for longer, you should notice a significant size different in the particle effects depending on the length of time the fire button
is held.
About the author

Torque Owner Sabrecyd
I did anyway, to make it compile. I put it around line 68 by the explosion stuff. I think that's right. I don't have my code with me at the moment to check.