Game Development Community

3D Vector help

by Jose Salinas · in Torque 3D Beginner · 08/29/2014 (8:06 pm) · 5 replies

Hi, I'am using Simple Faking Melee with Raycasts by Steve Acaster, It works fine but only for first person as the vector only detects for what is straight in front from the player. Is there a way to make that in a radius cone in front of the player? This is the code.

%eyeVec = %obj.getEyeVector();

%startPos = %obj.getEyePoint();
%endPos = VectorAdd(%startPos, VectorScale(%eyeVec, 2));

%target = ContainerRayCast(%startPos, %endPos, $melee_check2hit, %obj);
%col = firstWord(%target);

if(%col == 0)
return;

echo(%col);
//return the ID of what we've hit

// Apply damage to the object all shape base objects
if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
{
%col.damage(%obj, %pos, 15, "Cricket Bat Smack");

echo(%col.getname());

%vpos = %col.getWorldBoxCenter();
%pushDirection = VectorSub(%vpos,%obj.getWorldBoxCenter());
%pushDirection = VectorNormalize(%pushDirection);

%pushVec = VectorScale(%pushDirection,1000);
%pushVec= getwords(%pushVec,0,1);
%col.applyImpulse(%vpos, %pushVec);
}

#1
08/30/2014 (12:35 am)
Maybe replace eye vector with forward vector:
%eyeVec = %obj.getForwardVector();
Then regardless of which way the eye vector is pointing (I'm guessing you're working on some sort of third-person camera angle) it will get a vector that is forward of the player object.

To define a cone, you usually end up getting the vector between the objects, comparing the resulting vector to the forward vector and then deciding if the angle is right for a "hit."

/// <summary>
/// This function calculates the angle between two vectors.  Note! does not
/// take a %this parameter, so must be called scoped: 
/// %angle = AIPlayer::getAngle(%vec1, %vec2);
/// <summary>
/// <param name="vec1">The first vector.</param>
/// <param name="vec2">The second vector.</param>
/// <return>Returns a scalar angle in degrees between the two vectors.</return>
function AIPlayer::getAngle(%vec1, %vec2)
{
  %vec1n = VectorNormalize(%vec1);
  %vec2n = VectorNormalize(%vec2);

  %vdot = VectorDot(%vec1n, %vec2n);
  %angle = mACos(%vdot);

  // convert to degrees and return
  %degangle = mRadToDeg(%angle);
  return %degangle;
}

/// <summary>
/// This function calculates the angle between eye vector and %pos
/// <summary>
/// <param name="pos">The target position.</param>
/// <return>Returns a scalar angle in degrees.</return>
function AIPlayer::getAngleTo(%this, %pos)
{
    return AIPlayer::getAngle(%this.getVectorTo(%pos), %this.getEyeVector());
}

// Return position vector to a position
/// <summary>
/// This function calculates the vector to %pos from eye point
/// <summary>
/// <param name="pos">The target position.</param>
/// <return>Returns a 3D vector from eye pos to target pos (not normalized).</return>
function AIPlayer::getVectorTo(%this, %pos)
{
    if (getWordCount(%pos) < 2 && isObject(%pos))
        %pos = %pos.getPosition();
    return VectorSub(%pos, %this.getPosition());
}

/// <summary>
/// This function gets the direction from the unit to the target.
/// <summary>
/// <param name="target">The target object.</param>
/// <return>Returns a scalar angle in degrees.</return>
function AIPlayer::getTargetDirection(%this, %target)
{
    if (!%target)
        return 0;
    if (%target.getState() $= "dead")
        return 0;
    %tgtPos = %target.player.getPosition();
    %angle = %this.getAngleTo(%tgtPos);
    return %angle;
}

/// <summary>
/// This function determines if the target is within the unit's sight cone.
/// <summary>
/// <param name="objPos">The unit's position.</param>
/// <param name="targetPos">The target's position.</param>
/// <param name="angle">The target's angle off of direct front.</param>
/// <param name="viewAngle">The number of degrees off of forward that the cone extends (1/2 view width).</param>
/// <return>Returns true if the target is in "sight" or false if not.</return>
function AIPlayer::seeTarget(%this, %objPos, %targetPos, %angle, %viewAngle)
{
    if (%viewAngle $= "")
        %viewAngle = 80;
    if ( %angle <= %viewAngle )
    {
        %searchMasks = $TypeMasks::TerrainObjectType | $TypeMasks::StaticTSObjectType | 
            $TypeMasks::InteriorObjectType | $TypeMasks::ShapeBaseObjectType | 
            $TypeMasks::StaticObjectType | $TypeMasks::PlayerObjectType;

        // Search!
        %scanTarg = ContainerRayCast( %objPos, %targetPos, %searchMasks);
        if (%scanTarg)
        {
            %obj = getWord(%scanTarg, 0);
            %type = %obj.getClassName();
            if (%type $= "Player" || %type $= "AiPlayer")
            {
                %this.target = %obj;
                return true;
            }
            else
            {
                %this.target = "";
                return false;
            }
        }
    }
    return false;
}

// then call 
%obj.seeTarget(%obj.position, %target.position, %obj.getAngleTo(%target), 30.0);
// to see if you hit a target within 30 degrees of your forward vector (a 60 degree arc).
I think....
#2
08/30/2014 (2:34 am)
Thanks for the reply, That looks like an awesome way to detect a cone. I can also use it for a field of vision for a bot. I think I want a damage in all radius though. I got it to work but it hits me too lol.

I changed

%target = ContainerRayCast(%startPos, %endPos, $melee_check2hit, %obj);
%col = firstWord(%target);

to

InitContainerRadiusSearch(%centerPos, %radius, $melee_check2hit);
%col = containerSearchNext();

Is there a way for my weapon damage not to hit me?
#3
08/30/2014 (2:37 am)
or I can use

radiusDamage( %obj, %obj.getWorldBoxCenter(), 10, 100, "ExpoDamage");

that replaces all the code but it kills me too.
#4
08/30/2014 (4:22 am)
ok I got it. On the PlayerData::damage

I changed

if (!isObject(%obj) || %obj.getState() $= "Dead" || !%damage)
return;
to

if(%obj.getClassName() $= "Player")
return;
#5
08/30/2014 (8:17 am)
Glad it got you moving in the right direction!