Game Development Community

Triggers and Shapes

by Ken Finney · in Torque Game Engine · 06/13/2002 (10:14 pm) · 8 replies

Much to my chagrin, I've discovered that that Item shapes don't activate triggers like players do. Does anyone know which needs to be modified, the trigger code, or the Items ?


I can get the item to bounce on top of the polyhedron and other things, but the OnEnterTrigger doesn't fire.

example:

datablock TriggerData(GoalTrigger)
{
   tickPeriodMS = 100;
};


//-----------------------------------------------------------------------------

function GoalTrigger::onEnterTrigger(%this,%trigger,%obj)
{
   if (!strstr( %trigger.getName(),"home") )   // is the home team's net ?
   {
      messageAll('MsgGoalScored','VISITING TEAM SCORES !!!');
   }
   else if (!strstr( %trigger.getName(),"visit") )    // is the visiting team's net ?
   {
      messageAll('MsgGoalScored','HOME TEAM SCORES !!!');
   }

   Parent::onEnterTrigger(%this,%trigger,%obj);

}

#1
06/13/2002 (10:54 pm)
It's the code in the particular object class that looks for triggers.

Item does (like Player) include TriggerObjectType objects in its collision working list, but (unlike Player) does not ever do anything with them.
#2
06/14/2002 (10:05 am)
This is similar to the problem I encountered with bots. However, I was under the impression that AIPlayers derived actions from the player class. Is this true? I can't get bots to trigger events.
#3
11/16/2002 (3:24 am)
I too would like item shapes to activate triggers. I have already copied the following code from player.cc to item.cc:
Item::updatePos, block "Normal Contact"

if (isServerObject() && (typeMask & TriggerObjectType))
{
Trigger* pTrigger = static_cast<Trigger*>(rinfo.object);
pTrigger->potentialEnterObject(this);
}
But that didn't help so far. Has anybody got items to collide with triggers yet?
#4
11/16/2002 (1:58 pm)
Ok, I got it to work.

The sServerCollisionMask should contain TriggerObjectType so the trigger objects are collected during updateWorkingCollisionSet.

Then trigger activation code like the one above needs to be added to Item::updatePos but later in the function during the tough collision check while processing the working list from mConvex.

All other mask checks in Item::updatePos (those used for actual movement) should be excluding TriggerObjectType (like sCollisionMoveMask in player.cc) so that the items don't bounce off the invisible trigger (in which case they might not even trigger it).

All done, now you can throw stuff to activate triggers.
#5
05/25/2005 (6:21 pm)
Thank the lord!~

I'm glad i found this resource because I really needed it, so to help everyone out I offer this:

Here is what I did exactly as instructed by Matthes above:

added/changed code is in bold

in item.cc

...
#include "collision/extrudedPolyList.h"
#include "math/mathIO.h"
[b]#include "game/trigger.h"[/b]

...

const U32 sClientCollisionMask = (TerrainObjectType     | InteriorObjectType |
                                  StaticShapeObjectType | VehicleObjectType  |
                                  PlayerObjectType      | StaticTSObjectType);

const U32 sServerCollisionMask = (sClientCollisionMask | [b]TriggerObjectType[/b]);

const S32 Item::csmAtRestTimer = 64;

...

void Item::updatePos(const U32 /*mask*/, const F32 dt)
{
   // Try and move
   Point3F pos;
   mObjToWorld.getColumn(3,&pos);
   delta.posVec = pos;

...
   if (doToughCollision)
   {
      U32 count;
      for (count = 0; count < 3; count++)
      {
         // Build list from convex states here...
         end = pos + mVelocity * time;

         
         collisionMatrix.setColumn(3, end);
         Box3F wBox = getObjBox();
         collisionMatrix.mul(wBox);
         Box3F testBox = wBox;
         Point3F oldMin = testBox.min;
         Point3F oldMax = testBox.max;
         testBox.min.setMin(oldMin + (mVelocity * time));
         testBox.max.setMin(oldMax + (mVelocity * time));

         sEarlyOutPolyList.clear();
         sEarlyOutPolyList.mNormal.set(0,0,0);
         sEarlyOutPolyList.mPlaneList.setSize(6);
         sEarlyOutPolyList.mPlaneList[0].set(wBox.min,VectorF(-1,0,0));
         sEarlyOutPolyList.mPlaneList[1].set(wBox.max,VectorF(0,1,0));
         sEarlyOutPolyList.mPlaneList[2].set(wBox.max,VectorF(1,0,0));
         sEarlyOutPolyList.mPlaneList[3].set(wBox.min,VectorF(0,-1,0));
         sEarlyOutPolyList.mPlaneList[4].set(wBox.min,VectorF(0,0,-1));
         sEarlyOutPolyList.mPlaneList[5].set(wBox.max,VectorF(0,0,1));

         CollisionWorkingList& eorList = mConvex.getWorkingList();
         CollisionWorkingList* eopList = eorList.wLink.mNext;
         while (eopList != &eorList) {
[b]             if (eopList->mConvex->getObject()->getType() & TriggerObjectType) {
                 Trigger* pTrigger = static_cast<Trigger*>(eopList->mConvex->getObject());
                 pTrigger->potentialEnterObject(this);
             }
[/b]
            if ((eopList->mConvex->getObject()->getType() & [b] sClientCollisionMask [/b] ) != 0)
            {
               Box3F convexBox = eopList->mConvex->getBoundingBox();
               if (testBox.isOverlapped(convexBox))
               {
                  eopList->mConvex->getPolyList(&sEarlyOutPolyList);
                  if (sEarlyOutPolyList.isEmpty() == false)
                     break;
               }
            }
            eopList = eopList->wLink.mNext;
         }
         if (sEarlyOutPolyList.isEmpty())
         {
            pos = end;
            break;
         }
      
         collisionMatrix.setColumn(3, pos);
         sBoxPolyhedron.buildBox(collisionMatrix, mObjBox);

         // Build extruded polyList...
         VectorF vector = end - pos;
         sExtrudedPolyList.extrude(sBoxPolyhedron, vector);
         sExtrudedPolyList.setVelocity(mVelocity);
         sExtrudedPolyList.setCollisionList(&collisionList);

         CollisionWorkingList& rList = mConvex.getWorkingList();
         CollisionWorkingList* pList = rList.wLink.mNext;
         while (pList != &rList) {
            if ((pList->mConvex->getObject()->getType() & [b]sClientCollisionMask[/b]) != 0)
            {
               Box3F convexBox = pList->mConvex->getBoundingBox();
               if (testBox.isOverlapped(convexBox))
               {
                  pList->mConvex->getPolyList(&sExtrudedPolyList);
               }
            }
            pList = pList->wLink.mNext;
         }
...
#6
05/26/2005 (8:59 pm)
The ultimate solution to this problem lies right here in these lines of code.


Trigger* pTrigger = static_cast(rinfo.object);
pTrigger->potentialEnterObject(this);


Approach this the right way and you can actually remove a few dozen lines of code instead of putting them in.
#7
07/09/2006 (3:23 pm)
One additional modification:

In the section of UpdatePos that begins with the comment:

// Subtract out velocity into surface and friction
You need to enclose it with an if clause checking to make sure it is not a trigger object

if (!(rinfo.object->getType() & TriggerObjectType))

It looks like this in my code:

if (!(rinfo.object->getType() & TriggerObjectType))
   {
   // Subtract out velocity into surface and friction
   VectorF fv = mVelocity + rinfo.normal * bd;
   F32 fvl = fv.len();
   if (fvl) 
	{
	F32 ff = bd * mDataBlock->friction;
	if (ff < fvl) 
		{
		fv *= ff / fvl;
		fvl = ff;
		}
	}

	bd *= 1 + mDataBlock->elasticity;
	VectorF dv = rinfo.normal * (bd + 0.002);
	mVelocity += dv;
	mVelocity -= fv;

	// Keep track of what we hit
	contact = true;
	U32 typeMask = rinfo.object->getTypeMask();
	if (!(typeMask & StaticObjectType))
	nonStatic = true;
	if (isServerObject() && (typeMask & ShapeBaseObjectType)) 
	   {
	   ShapeBase* col = static_cast<ShapeBase*>(rinfo.object);
		queueCollision(col,mVelocity - col->getVelocity());
	   }
	}
   }

Failing to do this, your item may actually collide with and have its motion stopped by the mean ol' trigger volume.
#8
11/02/2006 (9:21 pm)
Shouldn't rinfo.object be collision->object instead? :)