Hitting Collision?
by Bobby Leighton · in Torque 3D Professional · 11/29/2010 (5:02 pm) · 51 replies
Ok I'm working on a zombie shooter game, and I am trying to work out a few things with projectile collision, here is what I want to do:
When projectile hits a certain collision marker I need it to return information about which on it hit, and then execute code based on which one it was.
I already have a test object setup with 9 collision markers setup, and collision is working. I can also get information that the collisions are returning values I just don't know how to separate from one collision box to another. Any help would be greatly appreciated!
Bobby
When projectile hits a certain collision marker I need it to return information about which on it hit, and then execute code based on which one it was.
I already have a test object setup with 9 collision markers setup, and collision is working. I can also get information that the collisions are returning values I just don't know how to separate from one collision box to another. Any help would be greatly appreciated!
Bobby
#2
if (Collision-1) is hit
then(more code here)
Does this make sense?
Also thank you for your help:O)
11/29/2010 (7:43 pm)
My test object is a wall with 9 colored squares on it so I can keep track in game where my collision boxes/markers are. Each marker in my modeling app is label Collision-1 up to Collision-9. here's some pseudo-code displaying what I want to do:if (Collision-1) is hit
then(more code here)
Does this make sense?
Also thank you for your help:O)
#3
11/30/2010 (6:48 am)
This will not work,because the ray cast cannot pull data about the shape instance.If you wish to implement this kind of functionality,search for the (Davide Archetti's) resource "HitBoxes for player".
#5
12/03/2010 (5:20 pm)
OK so I got that resource installed unfortunately I don't think anyone is watching the thread, and part of the code for projectiles has changed, any chance you or anyone else has got this working?
#6
12/03/2010 (10:01 pm)
Bobby, did you get the hitboxes and melee working, and only lack the missile part?
#7
12/04/2010 (12:07 am)
The projectile class has some changes to it over the years, but I wouldn't think it would be enough to affect that Resource beyond minor changes.
#8
12/04/2010 (3:53 am)
in projectile.cpp Con::executef isnt there anymore, so i dont know where to replace that part of the code, and it seems to be the final peice to make the projectiles hit gideon for testing
#9
12/04/2010 (3:55 am)
actually I will probably have to get a difrnt model, some dummy object with hitboxes cause the Gideon Source art Doesnt work with max9
#10
Near the top of projectile.cpp you'll find the onCollision callback, which I modified to be:
Then I modified the onCollision function itself like so:
Then you need to modify both of these in the projectile.h header as well:
And then finally find the call to "onCollision" in "Projectile::simulate" and add the hitbox to it:
And your onCollision script callback should now include an extra variable, the hitbox number (A=0, B=1, etc).
If you have other issues with this resource or setting up hitboxes in models I should be able to help.
12/04/2010 (7:37 pm)
You'll have to use the new Callback system instead of the old executef method. Here's what I did:Near the top of projectile.cpp you'll find the onCollision callback, which I modified to be:
// [HNT] Hitboxes
IMPLEMENT_CALLBACK( ProjectileData, onCollision, void, ( Projectile* proj, SceneObject* col, F32 fade, Point3F pos, Point3F normal, S32 hitbox ),
( proj, col, fade, pos, normal, hitbox ),
"Called when a projectile collides with another object.n"
"@param proj The projectile colliding.n"
"@param col The object hit by the projectile.n"
"@param fade The current fadeValue of the projectile, affects its visibility.n"
"@param pos The collision position.n"
"@param normal The collision normal.n"
"@param hitbox The hitbox ID.n"
"@see Projectile, ProjectileDatan"
);
// [HNT]Then I modified the onCollision function itself like so:
// [HNT]: hitbox added
void Projectile::onCollision(const Point3F& hitPosition, const Point3F& hitNormal, SceneObject* hitObject, S32 hitBox)
// [/HNT]
{
// No client specific code should be placed or branched from this function
if(isClientObject())
return;
if (hitObject != NULL && isServerObject())
{
// [HNT] include hitbox
mDataBlock->onCollision_callback( this, hitObject, mFadeValue, hitPosition, hitNormal, hitBox );
// [/HNT]
}
}Then you need to modify both of these in the projectile.h header as well:
DECLARE_CALLBACK( void, onCollision, ( Projectile* proj, SceneObject* col, F32 fade, Point3F pos, Point3F normal, S32 hitbox ) ); ... virtual void onCollision(const Point3F& p, const Point3F& n, SceneObject*, S32 hitbox);
And then finally find the call to "onCollision" in "Projectile::simulate" and add the hitbox to it:
onCollision(rInfo.point, rInfo.normal, rInfo.object, rInfo.HitBoxNum);
And your onCollision script callback should now include an extra variable, the hitbox number (A=0, B=1, etc).
If you have other issues with this resource or setting up hitboxes in models I should be able to help.
#11
12/04/2010 (9:05 pm)
Awesome! I will build this in and post back on my progress, thanks again:O)
#12
12/04/2010 (9:26 pm)
I probably will have questions, as I am unsure how to recieve information this way, I am used to keeping it all in C++, but i think I can get the hitboxes in my models without a problem
#13
12/04/2010 (9:28 pm)
I plan on using the mesh hiding part of T3D to swap out body-parts for damaged ones as the hitboxes chalk up the appropriate damage(to give an idea to what I am doing):O) almost built BTW:O)
#14
12/04/2010 (10:07 pm)
Successful build, now to see if I can get some kind of response from the hitboxes. I have a wall built with a bunch of hitboxes, starting with HBa0 being the first and so on...
#15
I gave up getting it to work for me,
and I want this for vehicles too,
keep us posted, or even better,
resource it?
12/05/2010 (12:53 am)
I'm very interested to see the outcome of this, Bobby,I gave up getting it to work for me,
and I want this for vehicles too,
keep us posted, or even better,
resource it?
#16
12/05/2010 (4:32 am)
Yes, as it is now it is in a clean T3D current beta. So when it is done I will pack up all the files I changed as they are and well post 'em somewhere:O)
#17
12/05/2010 (4:56 am)
awesome!!!
#18
Assuming you don't want to deal with that, here's basically what you do for the scripts. In scripts/server/projectile.cs add the hitbox ID to the script end of the Callback and send it along when you call the hit object's damage funciton:
In scripts/server/player.cs add the hitbox ID to the Armor::damage function:
Now some more general stuff about the hitboxes that may or may not be helpful...
12/05/2010 (7:44 am)
I'll probably have to split this into two posts. Anyway as far as dealing with the data the exisitng setup is that all damage gets processed through script. If you really don't like that method it's certainly possible to work with the collision event during Projectile::onCollision, however the projectile's damage value isn't actually part of the Datablock and can't be accessed from here unless you add it and include it during initPersistFields.Assuming you don't want to deal with that, here's basically what you do for the scripts. In scripts/server/projectile.cs add the hitbox ID to the script end of the Callback and send it along when you call the hit object's damage funciton:
// [HNT]
function ProjectileData::onCollision(%data, %proj, %col, %fade, %pos, %normal, %hitbox)
// [/HNT]
{
//echo("ProjectileData::onCollision("@%data.getName()@", "@%proj@", "@%col.getClassName()@", "@%fade@", "@%pos@", "@%normal@")");
// Apply damage to the object all shape base objects
if (%data.directDamage > 0)
{
if (%col.getType() & ($TypeMasks::ShapeBaseObjectType))
// [HNT]
%col.damage(%proj.sourceObject, %pos, %data.directDamage, %data.damageType, %hitbox);
// [/HNT]
}
}In scripts/server/player.cs add the hitbox ID to the Armor::damage function:
function Armor::damage(%this, %obj, %sourceObject, %position, %damage, %damageType, %hitbox)This is where you do whatever you need to with all the data. You have the damage and the hitbox ID in this function and can call whatever functions you might add for damaging limbs from here in addition to altering the total body damage before it gets applied to the Player. If you don't intend to network sync damage from each limb to the client for, say, limb health bars then it's probably easier to just store that damage in script variables on %obj (the Player) and just call your %obj.dismemberLimb("Nose") function when it comes time for it.
Now some more general stuff about the hitboxes that may or may not be helpful...
#19
In both files I put it right after applyImpulse, but really just toss it wherever you like it so long as it's under public in the header. Basically any object type could be modified the same way and would then use hitboxes, but of course if you replaced ShapeBase's castRay now every ShapeBase object would need hitboxes or Projectiles would pass right through.
I think it would be worthwhile to set up the system to revert to collision geometry (or in Player's case, bounding box) if hitbox #0 (A) couldn't be found, but I never actually got around to it. ... Actually, now that I look at the code, for Player you could just do this for the super-quick dirty fix:
The 3 lines with added comments which include the foundHB bool should do it. If HitBoxNum is -1 then info should still contain the stuff from the BBox check above so it should send back the right data for onCollision. I didn't test this and won't have a chance to until tomorrow but that seems pretty solid to me. Sorry if I'm kind of going beyond the range of this topic but I figured it might potentially be useful info. :P
12/05/2010 (8:15 am)
...I assume you're making your wall test model a Player object since you mentioned bodyparts. But just for the sake of general information (and because deepscratch mentioned vehicles) I'll mention the HB's only work for Player by default. As an example for getting them working in other objects, you can enable them for Vehicles by literally copying the Player::castRay function into Vehicle.cpp and renaming it Vehicle::castRay, since Vehicle is using ShapeBase's castRay by default. And pop the function into vehicle.h as well:bool Vehicle::castRay(const Point3F &start, const Point3F &end, RayInfo* info);
In both files I put it right after applyImpulse, but really just toss it wherever you like it so long as it's under public in the header. Basically any object type could be modified the same way and would then use hitboxes, but of course if you replaced ShapeBase's castRay now every ShapeBase object would need hitboxes or Projectiles would pass right through.
I think it would be worthwhile to set up the system to revert to collision geometry (or in Player's case, bounding box) if hitbox #0 (A) couldn't be found, but I never actually got around to it. ... Actually, now that I look at the code, for Player you could just do this for the super-quick dirty fix:
bool Player::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
{
<<...B-BOX STUFF...>>
if (mShapeInstance)
{
RayInfo shortest;
shortest.t = 1e8;
if (isServerObject())
{
mShapeInstance->animate(0); //Animate the model on the server
}
bool foundHB = false; // HAS HITBOXES CHECK
for (U32 i = 0; i < ShapeBaseData::Max_Hitboxes; i++)
{
if (mDataBlock->HBIndex[i] != -1)
{
foundHB = true; // HAS HITBOXES CHECK
if (mShapeInstance->castRayEA(start, end, info,0,mDataBlock->HBIndex[i]))
{
info->object = this;
if (info->t < shortest.t)
{
shortest = *info;
shortest.HitBoxNum = i+1; // +1 because the meshes HB## begin from 1
}
}
}
}
if (info->object == this)
{
// Copy out the shortest time...
*info = shortest;
}
if (info->HitBoxNum == -1 && foundHB) return false; // Only return false if found at least 1 hitbox and missed them all
info->point.interpolate(start,end,info->t);
}
return true;
}The 3 lines with added comments which include the foundHB bool should do it. If HitBoxNum is -1 then info should still contain the stuff from the BBox check above so it should send back the right data for onCollision. I didn't test this and won't have a chance to until tomorrow but that seems pretty solid to me. Sorry if I'm kind of going beyond the range of this topic but I figured it might potentially be useful info. :P
#20
12/05/2010 (8:26 pm)
Ok I made the script changes then made the code changes. C++ changes Built, but when aiming at a bot with no hitbox it gives a "Out of bound interpolation factor", and wont let me active Debugger, but I will take these changes out for now and test a Player with a hitbox as my wall won't work:O)
Torque Owner Ivan Mandzhukov
Liman3D
RayInfo can hold data about the object itself.I mean if your marker derives from SceneObject,you can get a valid pointer to this object and eventually distinguish these markers by name.
A second approach would be to get the collision point and provide a test where this point belongs to (this will be fast too).You have the box centers,you have a collision point.Just find the minimal distance (box_center - hit_point).len() and you get the correct box.