Getting an item to explode?
by Julian Ridley · in Torque Game Engine · 06/23/2004 (12:41 pm) · 19 replies
Heya. I have implemented mines into my game, it works fine, except I am clueless as to how I can get it to do an explosion and make noise when you hit it(like any normal weapon when they hit). Can someone tell me how I can do this? Thanks.
Also, When a player walks over it, it does everything fine. But if I shoot it with a weapon, it just gets pushed. Why is this? Shouldn't the onCollision be called even for a projectile? Is there some way to make it a destroyable item? Thanks.
Also, When a player walks over it, it does everything fine. But if I shoot it with a weapon, it just gets pushed. Why is this? Shouldn't the onCollision be called even for a projectile? Is there some way to make it a destroyable item? Thanks.
About the author
#2
Also, I want it to blow up when it gets hit with a gun, buts it just flys away, like a health patch.
06/24/2004 (11:12 pm)
There is no explosion, it does everything but explode and make sound, I am not sure about how to go about adding that to it, as it is an item and not a weapon.Also, I want it to blow up when it gets hit with a gun, buts it just flys away, like a health patch.
#3
I implemented some mines myself and I have them using StaticShapeData. I have the mine setup with a maxDamage value for it's internal health meter. Then I do:
Then on it's onDamage function I do a check if it's dead by getting it's damagelevel...if it doesn'thave any health left then I throw a call to blowup(%ourmine). The blowup function I made is as follows...needs to be cleaned up but it does work.
So basically I create an explosion and then delete the mine. You could also toss in a sound effect in the blowup function.
06/25/2004 (12:22 am)
Hey Julian,I implemented some mines myself and I have them using StaticShapeData. I have the mine setup with a maxDamage value for it's internal health meter. Then I do:
function SimpleMine::damage(%this, %obj, %sourceObj, %vel, %damage, %damageType)
{
%obj.applyDamage(%damage);
}Then on it's onDamage function I do a check if it's dead by getting it's damagelevel...if it doesn'thave any health left then I throw a call to blowup(%ourmine). The blowup function I made is as follows...needs to be cleaned up but it does work.
function blowup(%obj)
{
%pos = %obj.getposition();
//%dblock = %obj.getdatablock();
%p = new explosion() {
dataBlock = "CrossbowExplosion";
position = %pos;
};
MissionCleanup.add(%p);
%obj.delete();
}So basically I create an explosion and then delete the mine. You could also toss in a sound effect in the blowup function.
#4
You are going to need to add in some "onCollision" code that checks for specific items. Also, a trick I used was to make small mines (about 8 inches is the feel of them, but the bounds box around my model is a 2 meter diameter sphere. This way if any object comes within 1 meter of the mine, it will trigger "onCollision" and you can detonate it. For the record, I implemented them as Item class also. They work better that way and give you far more options...
Here's the explosion function I made....
It includes some alternate checking because as you add various different classes like grenades, mines, and spawned explosions from projectiles, things get more complicated. I also send an amount and distance to aply some impulse settings incase objects need to be moved. You might not want to blast them across a room with a flash grenade for example. Also I threw in damage type for scoring and death messages, etc...
Also when I get the position of the object, I add in just a little bit because fast moving objects tend to get blown upward more than backward when hitting a mine, and in my game it appears more realistic in effect.
The sound for your explosion should come from your explosions datablock. not from script. You can spawn a sound every time if you like, but that's wasted game cycles and should only be done for special circumstances IMO.
06/25/2004 (2:27 am)
Julian, you are wanting a lot of different things as a matter of fact...You are going to need to add in some "onCollision" code that checks for specific items. Also, a trick I used was to make small mines (about 8 inches is the feel of them, but the bounds box around my model is a 2 meter diameter sphere. This way if any object comes within 1 meter of the mine, it will trigger "onCollision" and you can detonate it. For the record, I implemented them as Item class also. They work better that way and give you far more options...
Here's the explosion function I made....
function blowup(%obj,%dmgtype,%impulse,%dis)
{
%pos = vectorAdd(%obj.getPosition(), "0 0 0.2");
if(%obj.explosion $= "")
{
%explode = %obj.getdatablock();
}
else
{
%explode = %obj;
}
%p = new Explosion()
{
dataBlock = %explode.explosion;
position = %pos;
sourceObject = %obj.sourceObject;
sourceSlot = %obj.sourceSlot;
client = %obj.client;
};
MissionCleanup.add(%p);
if(%obj){%obj.delete();}
radiusDamage(%p,%pos,%explode.damageRadius,%explode.radiusDamage,%dmgtype,%impulse);
}It includes some alternate checking because as you add various different classes like grenades, mines, and spawned explosions from projectiles, things get more complicated. I also send an amount and distance to aply some impulse settings incase objects need to be moved. You might not want to blast them across a room with a flash grenade for example. Also I threw in damage type for scoring and death messages, etc...
Also when I get the position of the object, I add in just a little bit because fast moving objects tend to get blown upward more than backward when hitting a mine, and in my game it appears more realistic in effect.
The sound for your explosion should come from your explosions datablock. not from script. You can spawn a sound every time if you like, but that's wasted game cycles and should only be done for special circumstances IMO.
#5
If there gets to be to many items being checked here, them I would go with a "switch/case" setup to find the classname and then perform appropriate actions.
06/25/2004 (2:34 am)
This is the collision function I use. At this time it only checks collisions with Armor(players) and other mines but more will be added to it later...function Mine::onCollision(%this,%obj,%col)
{
if(%col.getDataBlock().className $= Armor || %col.getDataBlock().className $= Mine)
{
blowup(%obj, Mine, 200);
}
}If there gets to be to many items being checked here, them I would go with a "switch/case" setup to find the classname and then perform appropriate actions.
#6
06/28/2004 (7:18 pm)
Gonzo, thx for the blowup function. However I can only get it to work when a player goes over it. What classname should I search for, I tried weapon and projectile to no avail... Thanks again.
#7
If so, then the problem is you haven't implemented mines the way I have. Here is the Mine datablock I use...
If you try to use that code though, you'll need to make an explosion datablock for it or rename the above to use your existing explosion.
06/28/2004 (9:25 pm)
If I understand you correctly you are saying that two mines touching each other does not spawn a detonation. Correct?If so, then the problem is you haven't implemented mines the way I have. Here is the Mine datablock I use...
datablock ItemData(Mine)
{
pickUpName = "some mines.";
explosion = MineExplosion;
friction = 1.5;
elasticity = 0.3;
sticky = 0.0;
gravityMod = 1.0;
maxVelocity = 50.0;
mass = 1.0;
density = 1.0;
drag = 0.5;
damageRadius = 15.0; // How much area
radiusDamage = 20.0; // How Much damage
damageType = "Mine";
lightType = "PulsingLight";
lightColor = "0.5 0.5 0.5 1.0";
lightTime = "1000";
lightRadius = "1";
lightOnlyStatic = true;
category = "Ammo";
className = "Mine";
shapeFile = "Shared/Shapes/Mines/Mine.dts
emap = true;
pickUpValue = 3;
maxDamage = 2.0;
};If you try to use that code though, you'll need to make an explosion datablock for it or rename the above to use your existing explosion.
#8
I think it's just a matter of tweaking the "if" to include a check for the projectile's classname. Not sure offhand, but I'm sure it's in crossbow.cs (in my sample app that is).
-ner
06/28/2004 (9:57 pm)
I believe his original question was for a weapon (I assume projectile) to cause the explosion, so that a crossbow bolt would detonate it.I think it's just a matter of tweaking the "if" to include a check for the projectile's classname. Not sure offhand, but I'm sure it's in crossbow.cs (in my sample app that is).
-ner
#9
This will detonate the mine when any damage is applied to it from outside sources such as explosions or projectiles.
06/28/2004 (10:00 pm)
In that case what you would want to do is....function Mine::Damage(%this,%obj,%sourceObject, %position, %damage, %damageType)
{
blowup(%obj, Mine, 200);
}This will detonate the mine when any damage is applied to it from outside sources such as explosions or projectiles.
#10
I've got everything working great on my mines except I would like some proximity detection. When I increase the bounding box, the mines never sit properly on varied terrain.
07/04/2004 (6:47 pm)
Gonzo, did you have a problem with your mines appearing to float or inaccurately laying on terrain because of the larger bounds? If so, did you solve it?I've got everything working great on my mines except I would like some proximity detection. When I increase the bounding box, the mines never sit properly on varied terrain.
#11
07/04/2004 (7:45 pm)
Why not just do a container radius check for mines?
#12
I'm guessing that something like this would have to be done at some reoccuring interval/tick. Would a constant check such as this from every player entity get expensive?
07/04/2004 (8:56 pm)
That sounds promising, Ben. :) Looking through the code for something akin to that description, I've found containerFindFirst. Is this what you're referring to?I'm guessing that something like this would have to be done at some reoccuring interval/tick. Would a constant check such as this from every player entity get expensive?
#13
07/04/2004 (9:11 pm)
Yes. No.
#14
My first thought is to set up a schedule that re-schedules itself and performs this check every 100ms, is this appropriate? Or is there some inherent hook somewhere in script that I can sync up with the engine's real move/tick cycle?
07/04/2004 (9:36 pm)
That's good to hear, thanks a lot for the point in the right direction.My first thought is to set up a schedule that re-schedules itself and performs this check every 100ms, is this appropriate? Or is there some inherent hook somewhere in script that I can sync up with the engine's real move/tick cycle?
#15
07/04/2004 (10:34 pm)
The every 100ms (or even 200 or 300ms) is probably a great idea.
#16
07/04/2004 (10:42 pm)
Wicked, Ben. Thanks as always. :)
#17
07/05/2004 (7:56 am)
Glad to help!
#18
The line(approx line# 27):
dSscanf(argv[1], "%f %f %f", &origin.x, &origin.y, &origin.z);
needs to be changed to:
dSscanf(argv[2], "%f %f %f", &origin.x, &origin.y, &origin.z);
Otherwise the routine is trying to pull the container center from the first arg, which is the type mask. It chokes on the dSscanf and defaults to the origin of "0 0 0" always. Works GREAT once this is changed.
07/05/2004 (12:22 pm)
Looks like containerFindFirst as defined in gameFunctions.cc is slightly bugged.The line(approx line# 27):
dSscanf(argv[1], "%f %f %f", &origin.x, &origin.y, &origin.z);
needs to be changed to:
dSscanf(argv[2], "%f %f %f", &origin.x, &origin.y, &origin.z);
Otherwise the routine is trying to pull the container center from the first arg, which is the type mask. It chokes on the dSscanf and defaults to the origin of "0 0 0" always. Works GREAT once this is changed.
#19
In case anyone is looking to do proximity-based mines (or anything else), here's a quick rundown of how I implemented it.
First, in player.cs in Armor::onAdd function, I added the following:
This kicks off what will become the reoccuring proximity check. Elsewhere in player.cs I added:
This does the actual container radius check specifically for objects of type Item. It is genericized to allow any item to become proximity-aware. The three 15's are the size of the area to check (centered around the player.position); if any item needs a larger check, this global setting needs to be increased. In my own landmine.cs, in the mine's ItemData datablock, I added:
This is the distance (between the item and the player) at which the item will be notified that a player is in the proximity boundary. Elsewhere in landmine.cs I added:
which just tells my landmine to treat it like a collision. To be thorough, I added a stub of triggerProximity for ItemData in item.cs:
Without the above, there could be innocuous but annoying console errors for other ItemData objects.
The generic nature of the player.cs modification means any Item can be easily modified (by adding the proxTriggerDist variable and a triggerProximity function) to handle players entering its proximity boundary. Other types of (non-Item) objects could be added (change the TypeMasks in player.cs) too if one desires.
I haven't tried this stuff multiplayer yet, so there's a chance I'm forgetting something in that regard. Guess now is as good a time to find out; time to go try it...
07/05/2004 (8:35 pm)
Works like a charm!In case anyone is looking to do proximity-based mines (or anything else), here's a quick rundown of how I implemented it.
First, in player.cs in Armor::onAdd function, I added the following:
%obj.schedule( 300, "checkForProximity" );
This kicks off what will become the reoccuring proximity check. Elsewhere in player.cs I added:
function Player::checkForProximity( %this )
{
%anItem = containerFindFirst( $TypeMasks::ItemObjectType, %this.position, 15, 15, 15 );
while ( %anItem !$= "" ) {
// Loop through
if( vectorDist( %anItem.position, %this.position ) < %anItem.getDataBlock().proxTriggerDist ) {
%anItem.getDatablock().triggerProximity( %anItem, %this );
}
%anItem = containerFindNext();
}
%this.schedule( 300, "checkForProximity" );
}This does the actual container radius check specifically for objects of type Item. It is genericized to allow any item to become proximity-aware. The three 15's are the size of the area to check (centered around the player.position); if any item needs a larger check, this global setting needs to be increased. In my own landmine.cs, in the mine's ItemData datablock, I added:
proxTriggerDist = 5;
This is the distance (between the item and the player) at which the item will be notified that a player is in the proximity boundary. Elsewhere in landmine.cs I added:
function Landmine::triggerProximity(%this, %obj, %col)
{
%this.onCollision( %obj, %col );
}which just tells my landmine to treat it like a collision. To be thorough, I added a stub of triggerProximity for ItemData in item.cs:
//-----------------------------------------------------------------------------
// Receives a proximity trigger from a nearby player
function ItemData::triggerProximity(%this, %obj, %col)
{
// Override to do something when a player comes within range of this item
}Without the above, there could be innocuous but annoying console errors for other ItemData objects.
The generic nature of the player.cs modification means any Item can be easily modified (by adding the proxTriggerDist variable and a triggerProximity function) to handle players entering its proximity boundary. Other types of (non-Item) objects could be added (change the TypeMasks in player.cs) too if one desires.
I haven't tried this stuff multiplayer yet, so there's a chance I'm forgetting something in that regard. Guess now is as good a time to find out; time to go try it...
Torque 3D Owner Billy L
Do you have the explosion ?