Game Development Community

GClientContainer.castRay oddities

by Danni · in Torque Game Engine Advanced · 04/12/2008 (11:16 am) · 2 replies

Forewarning: I have modified the engine to allow the use of shared scripts so I can create client side effects and do damage server side. The script below is a shared script. %obj->getRandom is synchronized between client server to create identical replications.

The script below works just fine on a normal server, but the second i create a dedicated server it fails miserably client side. I traced it down to the fact gClientContainer.castRay returns nothing no matter what I aim and shoot at and i cannot figure out why it does this. Can anyone provide insight why this could be the case?

function VulcanImage::onFire(%this, %obj, %slot)
{
    %weapon = %obj.getMountedImage(%slot); 
    %searchMasks = $TypeMasks::PlayerObjectType | $TypeMasks::StaticObjectType | $TypeMasks::AtlasObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::WaterObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::VehicleBlockerObjectType | $TypeMasks::CorpseObjectType | $TypeMasks::DebrisObjectType | $TypeMasks::AIObjectType; 

    if (!%obj.isServerObject()) %weapon.doRecoil();

    %damage = 3*(%obj.getRandom()%6+1);
    %muzzzleVector = %obj.getMuzzleVector(%slot);
    %muzzzleVector = VectorNormalize(%muzzzleVector);
    %yaw   = YawFromVector(%muzzzleVector);
    %pitch = PitchFromVector(%muzzzleVector);
    %yaw   += mDegToRad(((((%obj.getRandom()-128) << 17) / 65536.0)/65536.0)*360);
    %pitch += mDegToRad(((((%obj.getRandom()-128) << 17) / 65536.0)/65536.0)*360);
    %muzzzleVector = VectorFromAngles(%yaw, %pitch);
    %muzzzleVector = VectorScale(%muzzzleVector, %this.ballisticsRange);
    %muzzlePoint = %obj.getMuzzlePoint(%slot); 
    %distance = VectorAdd(%muzzlePoint, %muzzzleVector);

    // Do a "hitscan"
    [b]%scanTarg = ContainerRayCast(%muzzlePoint, %distance, %searchMasks, %obj);[/b]
    if(%scanTarg) 
    { 
         if (%obj.isServerObject())
         {
            %target = firstWord(%scanTarg);
            %target.damage(%obj,%pos,%damage,%this.meansOfDeath);
         }
         else
         {
            %target = firstWord(%scanTarg);
            %pos = getWords(%scanTarg, 1, 3);
            %target.BallisticImpactEmitter(%pos, "1 1 1");
         }
    }
  }
}

ConsoleFunction( containerRayCast, const char*, 4, 5, "( Point3F start, Point3F end, bitset mask, SceneObject exempt=NULL )"
                "Cast a ray from start to end, checking for collision against items matching mask.\n\n"
{
   char *returnBuffer = Con::getReturnBuffer(256);
   Point3F start, end;
   dSscanf(argv[1], "%g %g %g", &start.x, &start.y, &start.z);
   dSscanf(argv[2], "%g %g %g", &end.x,   &end.y,   &end.z);
   U32 mask = dAtoi(argv[3]);
 [b]  bool isServer = true;[/b]

   SceneObject* pExempt = NULL;
   if (argc > 4) {
      U32 exemptId = dAtoi(argv[4]);
      Sim::findObject(exemptId, pExempt);
   }
   if (pExempt)
   {
		pExempt->disableCollision();
[b]		if (!pExempt->isServerObject())
			isServer = false;[/b]
   }

   RayInfo rinfo;
   S32 ret = 0;
[b]	if (isServer)
	{
		if (gServerContainer.castRay(start, end, mask, &rinfo) == true)
			ret = rinfo.object->getId();
	}
	else
	{
		if (gClientContainer.castRay(start, end, mask, &rinfo) == true)
			ret = rinfo.object->getId();
	}
[/b]
   if (pExempt)
      pExempt->enableCollision();

   // add the hit position and normal?
   if(ret)
   {
      dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g",
               ret, rinfo.point.x, rinfo.point.y, rinfo.point.z,
               rinfo.normal.x, rinfo.normal.y, rinfo.normal.z);
   }
   else
   {
      returnBuffer[0] = '0';
      returnBuffer[1] = '[[62818c10e2e3b]]';
   }

   return(returnBuffer);
}

#1
04/12/2008 (11:19 am)
Doh! I just realised the problem. %this.ballisticsRange is set server side, but the datablock client side is ignored so it is never set. Oh well, i was considering using a static value here anyway, great opportunity to do so. :) It works as intended now.
#2
04/12/2008 (1:34 pm)
In addition, there is no gClientContainer in a dedicated server. Your code does cover this, but for future readers I wanted to make sure that it was understood--dedicated servers only create the "server" simulation, while selecting "host multiplayer" creates both a server simulation and a client simulation, which in effect can let you become sloppy (again, the code above handles it correctly, this is just a warning for others).

Good catch on the networking issue--part of the challenge with using dynamic fields--they are not networked!