Announcement

Collapse
No announcement yet.

Making changes to ProcessTouch or ProcessInstantHit

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Making changes to ProcessTouch or ProcessInstantHit

    Myself and a small team are attempting a game type/total conversion (we'll see how far this goes) where your weapon is actually a camera. The idea is that the camera will "shoot" out either a grid of projectiles or a grid of traces that would hit objects in the world. Each projectile would return information about what it hit, and the game could use this information to understand what is in the picture.

    The problem is that both ProcessTouch and ProcessInstantHit seem to have the necessary logic written in a native class. BUT, maybe I don't need the information in those two methods, or can get the necessary information some other way. Here's the info I need:

    1. Identity of the projectile in the grid
    2. Information from the object the projectile hit.

    If I go the projectile route, I'll need the projectile to travel in a perfectly straight line from its source (the lens of the camera the player will be carrying), travel the full length of the map until it hits any object (which means it will sometimes be traveling all the way to the skybox), and it must happen perceptually instantly.

    Any thoughts or hints in the right direction?

    Thanks in advance

    #2
    Look at the trace functions in the Actor class. Specifically:
    Code:
    /**
     * Trace a line and see what it collides with first.
     * Takes this actor's collision properties into account.
     * Returns first hit actor, Level if hit level, or None if hit nothing.
     */
    native(277) noexport final function Actor Trace
    (
    	out vector					HitLocation,
    	out vector					HitNormal,
    	vector						TraceEnd,
    	optional vector				TraceStart,
    	optional bool				bTraceActors,
    	optional vector				Extent,
    	optional out TraceHitInfo	HitInfo,
    	optional int				ExtraTraceFlags
    );

    Comment


      #3
      Ooo, thank you. I just looked up the TraceHitInfo struct to see if it could contain all the necessary info. It doesn't QUITE, but I think I can hack it together.

      Code:
      struct native transient TraceHitInfo
      {
          var Material            Material; // Material we hit.
          var PhysicalMaterial    PhysMaterial; // The Physical Material that was hit
          var int                    Item; // Extra info about thing we hit.
          var int                    LevelIndex; // Level index, if we hit BSP.
          var name                BoneName; // Name of bone if we hit a skeletal mesh.
          var PrimitiveComponent    HitComponent; // Component of the actor that we hit.
      };
      What information exactly is contained in the int LevelIndex? I created a new brush called ColorVolume that essentially acts as an invisible BSP I could drape over meshes that the trace could hit and return a color value. Would I be able to send the color information as, say, a hard coded int in LevelIndex, or is it something else entirely. If not there, maybe in int Item? If not either of those, would I be able to use ExtraTraceFlags?

      Thanks in advance.

      Comment


        #4
        I'm not following what you are trying to get out of the trace. Perhaps you could offer some more details on what it is you are trying to implement?

        Comment


          #5
          DrawDebugLine can help you visualize your traces, which may be invaluable in debugging this type of stuff.

          Comment


            #6
            Originally posted by Micah71381 View Post
            I'm not following what you are trying to get out of the trace. Perhaps you could offer some more details on what it is you are trying to implement?
            I'd say he's trying to implement a system where the game analyses what the player has "taken a photo" of, probably for a system to rate the photo taken or to check off that a certain thing has been photographed.

            Comment


              #7
              That sounds like a frustum test, not a trace. trace checks to see if something it directly along a line between two points. You could easily screw up your pokemon pictures if you dont test the entire frustum.

              Comment


                #8
                Good call Xyx. I missed that one.

                Can you get access to the frustum with UnrealScript? In other 3D engines, you usually need access to the frame buffer to do that, but it seems like that is pretty low level for UnrealScript.

                I'm not following what you are trying to get out of the trace. Perhaps you could offer some more details on what it is you are trying to implement?
                The goal is to, like DazJW said, rate the photos taken and check off that certain things have been photographed. Emphasis on rating photos. It would be pretty easy, I imagine, to run a series of traces to find out if a certain subject was in the frame of the photo. The big question I have is, when I run the trace, how can I know what types of objects I hit? Say I created a brush in the editor that contains information about the object (the objects color or importance to the storyline, for example) and want to know where in the frame this object is so I can judge composition of the photo within the frame. I could pretty easily figure out if it was in or out of focus by knowing the current depth of field and distance of the trace. And I could know that a certain trace hit a certain object. I need to be able to store information in the object that gets "triggered" when a trace hits the object.

                Comment


                  #9
                  Good call Xyx. I missed that one.

                  Can you get access to the frustum with UnrealScript? In other 3D engines, you usually need access to the frame buffer to do that, but it seems like that is pretty low level for UnrealScript.

                  I'm not following what you are trying to get out of the trace. Perhaps you could offer some more details on what it is you are trying to implement?
                  The goal is to, like DazJW said, rate the photos taken and check off that certain things have been photographed. Emphasis on rating photos. It would be pretty easy, I imagine, to run a series of traces to find out if a certain subject was in the frame of the photo. The big question I have is, when I run the trace, how can I know what types of objects I hit? Say I created a brush in the editor that contains information about the object (the object's color or importance to the storyline, for example) and want to know where in the frame this object is so I can judge composition of the photo within the frame. I could pretty easily figure out if it was in or out of focus by knowing the current depth of field and distance of the trace. And I could know that a certain trace hit a certain object. I need to be able to store information in the object that gets "triggered" when a trace hits the object. Kinda like how you can put triggers on things in UnrealEd to respond to being shot at, but more robust.

                  Comment


                    #10
                    ack, sorry for double post.

                    Comment


                      #11
                      You can iterate through Actor.VisibleActors. That will essentially give you a "list" of actors that are visible to you. For each of those actors you can do a little vector math to figure out if they are in your field of view (just use the players current direction normal against the normal between the player and the visible actor and see if it's within FOV, probably 90 degrees or so).

                      If the actor ends up being within 90 degrees then you can inspect the actor for whatever properties you are interested in, which the level designer would presumably be able to modify at design time.

                      Comment


                        #12
                        draft of code

                        Here's the code I have been working on. Even after all this time, I still cannot get the camera to behave just right.

                        Code:
                        class CamWeap_Camera extends UTWeap_SniperRifle;
                        
                        simulated function bool ActorIsInFOV( Vector VisActorLoc, Vector VectView )
                        {
                        	local float FOV, DifferenceAngleDegrees, DifferenceAngleRadians;
                        	local Vector DirVect, DirVectToVisActor, Location;
                        	local Rotator Rotation;
                        	
                        	//First get the player's FOV in degrees, Location as a vector, and Rotation as a Rotator
                        	FOV = PlayerController(Pawn(Owner).Controller).GetFOVAngle(); //in degrees
                        	UTPlayerController(Pawn(Owner).Controller).GetPlayerViewPoint(Location, Rotation);
                        
                        	/*Get the direction vectors from the player's location to the Actor's location
                        	Get the direction vector of the player's current viewing direction*/
                        	DirVectToVisActor = Location - VisActorLoc;
                        	DirVect = Vector(Rotation);
                        	
                        	//Calculate the angle between the two vectors...
                        	DifferenceAngleDegrees = Acos( Normal(DirVect) dot Normal(DirVectToVisActor) ) * 180/3.14159265358;
                        	DifferenceAngleRadians = Acos( Normal(DirVect) dot Normal(DirVectToVisActor) );
                        	
                        	//...and compare it to the FOV angle.
                        	if( DifferenceAngleDegrees <= (FOV / 2) )
                        	{
                        		return true;
                        	}
                        	else
                        	{
                        		return false;	
                        	}
                        }
                        
                        simulated function ProcessInstantHit( byte FiringMode, ImpactInfo ImpactInfo)
                        {
                        	local Actor Other;
                        	local CGStaticMeshActor CGS;
                        	local int i, CGlocalLength;
                        	local Vector VisActorLoc, HitLocation, HitNormal, X, Y, Z;
                        	local array<CGStaticMeshActor> CurrentlyVisibleCGActors;
                        	
                        	`log("Inside: ProcessInstantHit");
                        	
                        	/*First, we're going to iterate through all of the visible actors
                        	and put them in an array*/
                        	
                        	foreach VisibleActors( class 'CGStaticMeshActor', CGS )
                        	{
                        		if(CGS != none)
                        		{	
                        			CurrentlyVisibleCGActors.AddItem(CGS);
                        		}	
                        	}
                        	
                        	/*Then we're gonna iterate through the array and discard Actors that
                        	are not in the player's FOV (just use the players current direction
                        	normal against the normal between the player and the visible actor
                        	and see if it's within FOV)*/
                        	
                        	//GetAxes(Pawn(Owner).ViewRotation, X, Y, Z);
                        	GetAxes( Instigator.Rotation, X, Y, Z );
                        
                        	Other = Trace(HitLocation, HitNormal, Owner.Location + X * 25000.0, Owner.Location); //Trace(HitLocation, HitNormal, TraceEnd, TraceStart)
                        	CGlocalLength = CurrentlyVisibleCGActors.Length;
                        	
                        	for( i = 0; i < CGlocalLength; i++ )
                        	{
                        	VisActorLoc = CurrentlyVisibleCGActors[i].Location;
                        	
                        		if( ActorIsInFOV(VisActorLoc, HitLocation) == false )
                        		{
                        			CurrentlyVisibleCGActors.Remove(i, 1);
                        		}
                        	}
                        	
                        	//And we're going to print out all actors that are within FOV
                        	CGlocalLength = CurrentlyVisibleCGActors.Length;
                        	WorldInfo.Game.BroadcastHandler.Broadcast(self, "The following "@CGlocalLength@" CGActors are in the picture...");
                        	`log("The following "@CGlocalLength@"CGActors are in the picture...");
                        	for( i = 0; i < CGlocalLength; i++)
                        	{
                        		WorldInfo.Game.BroadcastHandler.Broadcast( self, "CGActor: "@CurrentlyVisibleCGActors[i]@" - String[0]: "@CurrentlyVisibleCGActors[i].CGStrings[0] );
                        		`log( "CGActor: "@CurrentlyVisibleCGActors[i]@" - String[0]: "@CurrentlyVisibleCGActors[i].CGStrings[0] );		
                        	}
                        	//WorldInfo.Game.BroadcastHandler.Broadcast(self, "...and no more.");
                        	`log("...and no more.");
                        }
                        Something is still janky in there. I'll "shoot" the camera, and I'll get log data back something behind me was in my FOV.

                        I have two places I'm guessing to be at fault, but for the life of me I can't find any errors. Either my vector Math is messed up or I'm doing something wrong with the dynamic array (get "out of bounds" runtime errors in the log).

                        Code:
                        ScriptLog: Inside: ProcessInstantHit
                        ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:00DE) Accessed array 'CamWeap_Camera_0.CurrentlyVisibleActors' out of bounds (2/2)
                        ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:00DE) Accessed None 'CurrentlyVisibleActors'
                        ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:00DE) Accessed array 'CamWeap_Camera_0.CurrentlyVisibleActors' out of bounds (3/2)
                        ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:00DE) Accessed None 'CurrentlyVisibleActors'
                        ScriptLog: The following actors are in the picture...
                        ScriptLog: UTPawn_0
                        ScriptLog: UTAttachment_SniperRifle_0
                        ScriptLog: ...and no more.
                        Any ideas?

                        Comment


                          #13
                          Is this some sort of photo quest minigame where you get points for photographing as many of X at once as possible? If so, using VisibleActors and checking if they're in the FOV is much more efficient.

                          Comment


                            #14
                            !! Finally !!
                            I got the weapon behaving as I wanted it to. Oddly, I'm still getting out of bounds errors in the log, even though I'm not creating any dynamic arrays. Any idea where these ScriptWarnings are coming from and whether they will hamper me in the future?

                            Code:
                            class CamWeap_Camera extends UTWeap_SniperRifle;
                            
                            simulated function bool ActorIsInFOV( Vector VisableActorLocation )
                            {
                            	local float FOV, AngleDifferenceDegrees;
                            	local Vector CameraDirectionVector, PlayerToVisableActorDirectionVector, PlayerLocation;
                            	local Rotator PlayerRotation;
                            	
                            	//First get the player's FOV in degrees, Location as a vector, and Rotation as a Rotator
                            	FOV = PlayerController(Pawn(Owner).Controller).GetFOVAngle(); //in degrees
                            	UTPlayerController(Pawn(Owner).Controller).GetPlayerViewPoint(PlayerLocation, PlayerRotation);
                            
                            	/*Get the direction vectors from the player's location to the Actor's location
                            	Get the direction vector of the player's current viewing direction*/
                            	PlayerToVisableActorDirectionVector = VisableActorLocation - PlayerLocation;
                            	CameraDirectionVector = Vector(PlayerRotation);
                            	
                            	//Calculate the angle between the two vectors...
                            	//AngleDifferenceRadians = Acos( Normal(CameraDirectionVector) dot Normal(PlayerToVisableActorDirectionVector) );
                            	AngleDifferenceDegrees = Acos( Normal(CameraDirectionVector) dot Normal(PlayerToVisableActorDirectionVector) ) * 180/3.14159265358;
                            	
                            	//...and compare it to the FOV angle.
                            	if( AngleDifferenceDegrees <= (FOV / 2) )
                            	{
                            		return true;
                            	}
                            	else
                            	{
                            		return false;	
                            	}
                            }
                            
                            simulated function ProcessInstantHit( byte FiringMode, ImpactInfo ImpactInfo)
                            {
                            	local CGStaticMeshActor CGS;
                            	
                            	`log("Inside: ProcessInstantHit");
                            	
                            	/*First, we iterate through all of the visible CGStaticMeshActors.
                            	We check that theCGStaticMeshActor is within the player's FOV.*/
                            	WorldInfo.Game.BroadcastHandler.Broadcast(self, "The following CGStaticMeshActors' String[0]s are in the frame...");
                            	`log("The following CGActors are in the frame...");
                            	foreach VisibleActors( class 'CGStaticMeshActor', CGS )
                            	{
                            		if(CGS != none)
                            		{	
                            			if( ActorIsInFOV(CGS.Location) == true )
                            			{
                            				WorldInfo.Game.BroadcastHandler.Broadcast( self, "CGActor: "@CGS@" - String[0]: "@CGS.CGStrings[0] );
                            				`log( "CGActor: "@CGS@" - String[0]: "@CGS.CGStrings[0] );
                            			}
                            		}	
                            	}
                            	`log("...and no more.");
                            }
                            
                            DefaultProperties
                            {
                            	InstantHitDamage(0) = 0
                            	InstantHitDamage(1) = 0
                            	InstantHitMomentum(0)=0
                            	
                            	InstantHitDamageTypes(0)=None
                            }
                            Code:
                            ScriptLog: Inside: ProcessInstantHit
                            ScriptLog: The following CGActors are in the frame...
                            ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:014D) Accessed array 'CamWeap_Camera_0.CGStrings' out of bounds (0/0)
                            ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:0188) Accessed array 'CamWeap_Camera_0.CGStrings' out of bounds (0/0)
                            ScriptLog: CGActor:  CGStaticMeshActor_7  - String[0]:  
                            ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:014D) Accessed array 'CamWeap_Camera_0.CGStrings' out of bounds (0/0)
                            ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:0188) Accessed array 'CamWeap_Camera_0.CGStrings' out of bounds (0/0)
                            ScriptLog: CGActor:  CGStaticMeshActor_10  - String[0]:  
                            ScriptLog: CGActor:  CGStaticMeshActor_23  - String[0]:  WaterfallPool
                            ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:014D) Accessed array 'CamWeap_Camera_0.CGStrings' out of bounds (0/0)
                            ScriptWarning: CamWeap_Camera DM-MountainRoad.TheWorld:PersistentLevel.CamWeap_Camera_0 (Function CameraGameMutator.CamWeap_Camera:ProcessInstantHit:0188) Accessed array 'CamWeap_Camera_0.CGStrings' out of bounds (0/0)
                            ScriptLog: CGActor:  CGStaticMeshActor_4  - String[0]:  
                            ScriptLog: ...and no more.

                            Comment

                            Working...
                            X