Redirecting Projectiles
by Todd Johnson · in Torque Game Engine · 12/07/2004 (12:52 pm) · 22 replies
How can I redirect a fired projectile in script?
#2
12/08/2004 (3:45 am)
Yea I have. There's an initial velocity however the velocity of the projectile is not available to script initially. The projectile flight path is located in proctile.cc in function processTick(). There you see how gravity constantly effects the trajectory so I do my one time reflection calculation there to redirect it.
#3
12/08/2004 (3:49 am)
Since I'm in the learning process, I might do my first resource on the matter.
#4
12/08/2004 (7:21 am)
Very interesting, the resource would be much appreciated :)
#5
12/08/2004 (7:29 am)
Very interesting, the resource would be much appreciated :)
#6
Becuase.... there are resource already to make it only bounce of certain object types... and also resources for heat seeking projectiles.... so I'm thinking, what you want might already be available.
12/08/2004 (7:49 am)
What do you mean by "redirecting" a projectile?Becuase.... there are resource already to make it only bounce of certain object types... and also resources for heat seeking projectiles.... so I'm thinking, what you want might already be available.
#7
12/08/2004 (6:59 pm)
I didn't want for it to bounce off anything. I wanted the projectile to simply redirect itself.
#8
ProjectileData::ProjectileData()
void ProjectileData::packData(BitStream* stream)
void ProjectileData::unpackData(BitStream* stream)
void Projectile::processTick(const Move* move)
12/09/2004 (6:59 am)
Ok, so I successfully got the math to do what I wanted. Only problem that remains is that , once I use this reflection technique, it stays for each new projectile I fire. Why doesn't mDatablock->isReflected get set to false every time a new projectlie is created? I want each projectile to have its own isReflected boolean. (Cmon Ben!)ProjectileData::ProjectileData()
isReflected = false;
void ProjectileData::packData(BitStream* stream)
stream->writeFlag(isReflected);
void ProjectileData::unpackData(BitStream* stream)
isReflected = stream->readFlag();
void Projectile::processTick(const Move* move)
if(mDataBlock->isReflected) ...do redirection math else ... do normal calcsWhy doesn't this get set to false when a new projectile is created?
void Projectile::setReflection(bool bolIsReflected)
{
mDataBlock->isReflected = bolIsReflected;
}
ConsoleMethod(Projectile, setReflection, void, 3, 3, "Makes a projectile reflect back")
{
object->setReflection(argv[2]);
}
#9
12/09/2004 (7:17 am)
DataBlocks are common to all objects that use them. You will either have to make a new datablock for each of your projectiles or (better implementation) move the data field that changes to the object itself, instead of the object's datablock.
#10
mProjectileShape = new TSShapeInstance(mDataBlock->projectileShape, isClientObject());
Would I put the boolean in TSShapeInstance?
12/09/2004 (7:32 am)
So I assume this is the object itself being created...mProjectileShape = new TSShapeInstance(mDataBlock->projectileShape, isClientObject());
Would I put the boolean in TSShapeInstance?
#11
12/09/2004 (7:35 am)
I'm getting lost again. :( Do you happen to know where this would be most appropriately put? The boolean that is...
#12
What you may want to do is to create a child of TSShapeInstance called TSShapeProjectileInstance or something similar with TSShapeInstance as parent, and then define it there. You'll need of course to do all the initialization, pack/unpack, etc. to make sure it can be scoped properly to the client.
Again, please keep in mind that I'm talking theory here, not specific "copy/paste and it will work" implementation.
12/09/2004 (7:39 am)
I haven't analyzed your current implementation in depth, so I'm not positive that TSShapeInstance is where your projectile should be in the first place (it probably is correct!), so I can't say 100 percent, but in general, yes.What you may want to do is to create a child of TSShapeInstance called TSShapeProjectileInstance or something similar with TSShapeInstance as parent, and then define it there. You'll need of course to do all the initialization, pack/unpack, etc. to make sure it can be scoped properly to the client.
Again, please keep in mind that I'm talking theory here, not specific "copy/paste and it will work" implementation.
#13
To add an object variable (i.e. not a datablock variable):
Key: + is a line added and - is a line removed.
projectile.h
This will put a variable in each projectile that you will be able to change.
HIH
12/09/2004 (8:23 am)
Todd,To add an object variable (i.e. not a datablock variable):
Key: + is a line added and - is a line removed.
projectile.h
class Projectile : public GameBase
{
...
+bool isReflected;
...
enum UpdateMasks {
BounceMask = Parent::NextFreeMask,
ExplosionMask = Parent::NextFreeMask << 1,
- NextFreeMask = Parent::NextFreeMask << 2
+ ReflectMask = Parent::NextFreeMask << 2,
+ NextFreeMask = Parent::NextFreeMask << 3
};
...
}projectile.ccProjectile::Projectile()
{
...
+isReflected = false;
...
}
void Projectile::initPersistFields()
{
...
+addField("isReflected", TypeBool, Offset(isReflected, Projectile));
...
}
void Projectile::processTick(const Move* move)
{
...
+if(isReflected)
+ ...do redirection math
+else
+ ... do normal calcs
...
}
U32 Projectile::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
{
...
else if (stream->writeFlag(mask & BounceMask))
{
// Bounce against dynamic object
mathWrite(*stream, mCurrPosition);
mathWrite(*stream, mCurrVelocity);
}
+ else if (stream->writeFlag(mask & ReflectMask))
+ {
+ mathWrite(*stream, mCurrPosition);
+ mathWrite(*stream, mCurrVelocity);
+ }
return retMask;
...
void Projectile::unpackUpdate(NetConnection* con, BitStream* stream)
{
...
else if(stream->readFlag())
{
mathRead(*stream, &mCurrPosition);
mathRead(*stream, &mCurrVelocity);
}
+ else if(stream->readFlag())
+ {
+ mathRead(*stream, &mCurrPosition);
+ mathRead(*stream, &mCurrVelocity);
+ }
}
...I assume that your console method and function is correctly defined in projectile.h+void Projectile::setReflection(bool bolIsReflected)
+{
+ isReflected = bolIsReflected;
+ setMaskBits(ReflectMask);
+}
+ConsoleMethod(Projectile, setReflection, void, 3, 3, "Makes a projectile reflect back")
+{
+ object->setReflection(argv[2]);
+}This will put a variable in each projectile that you will be able to change.
HIH
#14
12/09/2004 (9:15 am)
Oh wow, that's looking good. I'm having some slight issues however. As soon as I use my redirection , I notice that it redirects correctly for a second, then it follows the old path again. I've implemeted what was suggested above. Here's my code for right now...if(isReflected)
{
if(mDataBlock->isBallistic)
{
mCurrVelocity.z += 9.81 * mDataBlock->gravityMod * (F32(TickMs) / 1000.0f);
Con::printf("Reversing the upward lift");
}
else
{
if(mDataBlock->isBallistic)
mCurrVelocity.z -= 9.81 * mDataBlock->gravityMod * (F32(TickMs) / 1000.0f);
}
newPosition = oldPosition + mCurrVelocity * (F32(TickMs) / 1000.0f);
}
#15
12/09/2004 (9:16 am)
I took out my math before just because I want to look at something simple since my code didn't work with the new implementation. That above code is in void Projectile::processTick(const Move* move).
#16
12/09/2004 (9:21 am)
I took out my math before just because I want to look at something simple since my code didn't work with the new implementation. That above code is in void Projectile::processTick(const Move* move).
#17
12/09/2004 (9:23 am)
Ok, if I place a setMaskBits(ReflectMask); in the true block I have above, it has the desired effect. But it's really choppy and it seems like that's not the correct implementation.
#18
12/09/2004 (9:44 am)
Ok, if I place a setMaskBits(ReflectMask); in the true block I have above, it has the desired effect. But it's really choppy and it seems like that's not the correct implementation.
#19
12/09/2004 (11:29 am)
TSShapeInstance is a rendering class and nothing more. You should not be deriving or modifying it unless you want to change the way that objects are rendered. It exists solely to interface with the 3space library.
#20
12/09/2004 (11:32 am)
Good catch Ben...I hate when I talk about things I don't know enough about! Should have caught that myself.
Associate Kyle Carter