Game Development Community

Reticle

by Carl A Harris · in Torque 3D Professional · 11/03/2010 (9:25 pm) · 33 replies

Is it possible, to determine what a player's reticle is pointing at? Be it a building, vehicle, player, or whatever. Possibly even what their cursor is pointing at also?

I'm not sure what a key word would be to look that up.

Would this have to be implemented through source, or can it be done through script.
I don't have the source for T3D, though I do have the source for TGE & TGEA.
Page «Previous 1 2
#1
11/03/2010 (9:31 pm)
There is an old "super crosshair resource" for TGE/A you might want to look at.

I believe that's really more source code ... though I can think of a script off the top of my head that might work ...
... goes something like this ...

1. raycast from player.geteyevector() out to x units
2. if != 0 object.getClassname()
3. normalReticle.setVisible(false); objectTypeReticle.setVisible(true);
4. schedule repeat every 100m/s
#2
11/03/2010 (9:37 pm)
Thanks Steve.
I'll try your script idea first, then go for the source.
#3
11/03/2010 (9:40 pm)
Try doRaycast(), it's a builtin function ... though I'm not sure if it returns an ID or just a bool on whether it hit something.
#4
11/04/2010 (7:47 am)
it returns the first object id it encounters that match your mask.

#5
11/05/2010 (7:57 am)
Guys. I might be doing this wrong, or you might even have a better way of doing this.

Opinions?

function cursorIDobj()
{
	// Figure out which object I'm attached to
	%player = ServerConnection.getControlObject();
	
	// Set RayTrace typemasks to look for
	%typeMasks = $TypeMasks::PlayerObjectType | 
					 $TypeMasks::StaticObjectType | 
					 $TypeMasks::InteriorObjectType | 
					 $TypeMasks::WaterObjectType | 
					 $TypeMasks::VehicleObjectType | 
					 $TypeMasks::VehicleBlockerObjectType | 
					 $TypeMasks::CorpseObjectType | 
					 $TypeMasks::DebrisObjectType | 
					 $TypeMasks::AIObjectType;

	// Set starting point for Raytrace.
	// Here I moved the start point out 2, so it would his the player
	// Because the exception only worked once. This works always.
	%Start = vectorScale(%player.getEyePoint(),2);
	// Get the player's eyevector
	%EyeVec = %player.getEyeVector(); 
	// Obtain distance to endpoint end point of raytrace 
	%EndVec = vectorScale(%EyeVec, 1000);  
	// determine vector of endpoint
	%End = VectorAdd(%Start, %EndVec); 
	// Trace from eye+2 out to eye+1000
	%objData = containerRayCast(%Start, %End, %typeMasks);
	// return ID of first object hit by raytrace
	%objHitID = firstWord(%objData);


	//error(%objData);

	if( %objHitID != false )
	{
		%target = %objHitID.getClassName();
		if(%target $= "Player") // if its a player
		{
			%target = %objHitID.getShapeName(); // Get the name of our PC
		}
		error("Target = " @ %target);
		error("Distance = "@VectorLen(getWord(%objData,1)@getWord(%objData,2)@getWord(%objData,3)));
		echo("");
	}
	schedule(2000, 0, "cursorIDobj", %player);

}
#6
11/05/2010 (2:53 pm)
Instead of using ServerConnection.getControlObject() why not make it a player function? (If there's a valid reason for not doing this, someone pipe up)

And you'll probably need the playerObject as an exclude on the raycast or you'll be hitting your own boundingbox alot.

//make all typemasks a global and then you can use them again for other stuff
     $Collisions = $TypeMasks::PlayerObjectType |   
                      $TypeMasks::StaticObjectType |   
                      $TypeMasks::InteriorObjectType |   
                      $TypeMasks::WaterObjectType |   
                      $TypeMasks::VehicleObjectType |   
                      $TypeMasks::VehicleBlockerObjectType |   
                      $TypeMasks::CorpseObjectType |   
                      $TypeMasks::DebrisObjectType |   
                      $TypeMasks::ForestObjectType;
//aiObjectType comes under PlayerObjectType - replaced with Forest

function Player::cursorIDobj(%this)
{
   %eyeVector = %this.geteyeVector();
   %eyePoint = %this.getEyePoint();//note this doesn't update with crouching cos of a bug with bone positions not updating with animations - been reported

   %aimpoint = VectorAdd(%eyePoint, VectorScale(%eyeVector, 1000));
//1000 is a pretty long way
	

   %targetsearch = containerRayCast(%eyePoint, %aimpoint, $Collisions, %this.getID());
   %impact = firstWord(%targetsearch);
   echo(%targetsearch);
   if(%impact != 0)
   {
      %target = %impact.getClassName();
      //Ai has the same mask as player but not the same classname
      if(%target $="Player" || %target $="AiPlayer")
      {
         %targetName = %impact.getShapeName();
         echo("targetName = " @ %targetname);
         //and put your change hud/reticle command here
      }
   }
   %this.schedule(2000, "cursorIdObj");
//2 seconds seems a bit of a long time
}

I was thinking something like that ... but it's my first cuppa tea of the day ...
#7
11/05/2010 (5:29 pm)
I believe I'm over complicating things. Probably because I can't remember everything I've read in all of these years.
---
I had not considered attaching the function to the Player DB.
Here is my twisted thought process.
I had this function starting from the GUI. Why? In case the player wasn't attached to a player in game. So it was an attempt to determine what object the GUI was attached to.

However. This morning, it dawned on me:
1) Why wouldn't someone be attached to some form of a Player DB?
2) If they weren't attached to a Player DB, the object they were attached to probably wouldn't have an EYE to get the vector from.

So it still wouldn't have worked as intended.
---
Like elvince said. I too was thinking the raycast is only going to return an ID (character string), so I needed to hunt down a way of getting an object reference for the ID. Three hours and a ton of mistakes later, I woke up to stark realty. The client automatically associated the ID with an object. DOH!
---
With the raycast exception. I tried adding the player's ID to the raycast. It did work, once. On the initial call. After that, it only returned the player. So I pushed the start point out 2, so it couldn't run into itself. That seemed to work always. Most likely, I did something wrong.
---
I set the schedule to 2 seconds, because given my gross lack of experience. I didn't want my mistakes happening ten times per second.

If you're okay with it. I'm going to try your code too, and see what happens.
#8
11/05/2010 (7:41 pm)
I'm curious, where would you put the initial function?
#9
11/05/2010 (8:30 pm)
Maybe when a weapon was first selected... or from the start of the player spawning; Armor::onAdd - with a delay or it won't fire.
if (%obj.getClassName() $= "Player")
{
   %obj.schedule(150, "cursorIDobj");
    echo("Start fancy reticle script!");
}
#10
11/06/2010 (6:00 pm)
The ray cast keeps running into the player's bounding box.
I'm going to have to push it out like I did before.
#11
11/06/2010 (6:25 pm)
Is "%this" the player? The Player should be the exlude on the ray
#12
11/06/2010 (6:38 pm)
Just be aware that this won't work in a multiplayer setup as the raycasts are performed server-side, while the reticle is client-side. This is fine if you're only working on single player game, but will break down for multiplayer.

To make this multiplayer compatible, you would need to have the client send a command to the server asking it to do the raycast, then get the server to send back the results to the client. Slightly more complicated, but still possible with script only.
#13
11/06/2010 (8:22 pm)
So far, my biggest issue has come from not being able to figure out where to attached the code. For me, attaching it as "Armor::cursorIDobj" does work, because it doesn't have an eye point. Attaching it "Player::cursorIDobj" does, when (rarely) I can manage to call the bloody function to begin with.

Ultimately, the purpose is to make it possible for a player (in multiplay) to "scan", an object that they're looking at. So after a few seconds, the server would tell the player something about the object. I'm not looking to crash the server with scans. So I want the scan to take around 4 or 5 seconds to come back.

I probably wrong, but I'm still thinking it should be GUI function.

Steve: The raycast works once, in excluding the player. After that, it keeps picking up the player.
#14
11/06/2010 (8:33 pm)
Call me stupid, but I haven't been able to determine where the objects "Player" or "Armor" are being instantiated at. So attaching the function to either them seems purposeless.

I'm thinking I'll have to get Torsion to step through every line of code until I see where or if they're being used.
#15
11/06/2010 (10:33 pm)
In player.cs(scripts)
function Armor::onAdd(%this, %obj)//existing function
{
   // Vehicle timeout
   %obj.mountVehicle = true;

	if(%obj.getClassName() $= "Player")//add to existing function
		%obj.schedule(1000, "cursorIdObj");/add to existing function
}

function Player::cursorIDobj(%this)//new function!
{
	%eyeVector = %this.geteyeVector();
	%eyePoint = %this.getEyePoint();//note this doesn't update with crouching cos of a bug with bone positions not updating with animations - been reported

	%aimpoint = VectorAdd(%eyePoint, VectorScale(%eyeVector, 1000));

	%targetsearch = containerRayCast(%eyePoint, %aimpoint, $Collisions, %this);
	%impact = firstWord(%targetsearch);
	
	echo(%targetsearch);
	
	if(%impact != 0)
		echo(%impact SPC %impact.getClassName());

	%this.schedule(1000, "cursorIdObj");
}

Works fine for me, no issues.
#16
11/07/2010 (6:18 am)
I can't explain it, but even a verbatim copy of your code won't work on my T3D. I'm using T3D 101.

Attaching it to Armor::onAdd returns : 0

#17
11/07/2010 (7:16 am)
There is a "doRayTrace()" attached to the ShapeBase DB. Which I think is what you were referring to earlier. Good memory Steve. :)

Finally, I got something that works.
I attached it to the Player as you suggested, but called it initially from the "GameCore::loadOut" function. I figured, if that function can give me a launcher, the %player HAS to be correct.

Thanks for putting up with my questions guys.
#18
11/07/2010 (1:40 pm)
It should've occurred to me that there might be some decrepencies between the latest beta I'm using and the original Binary - though the new binary is the same version as 1.1b3.

Well, as long as you got the desired result in the end. :)
#19
11/08/2010 (1:42 am)
I appreciate you guys helping out with that. :)
#20
03/19/2011 (7:00 pm)
Just picked up the T3D Pro earlier this week. It was finally cheap enough for my broke @$$ to buy. :)

Earlier I mentioned not knowing where the "Armor" reference was being instantiated. I eventually gave up looking, and simply assumed it was some kind of internal c++ thing. I found where "Armor" was coming from this afternoon. It's in the PlayerData datablock.

It turns out that a className can have functions attached to it. I wasn't aware of this. Even through all of my reading. It doesn't make sense to me, but what ever.

So, I'm going to re-evaluate this code.
Page «Previous 1 2