Tracing
Namespace:
DeadworksManaged.Api
A trace draws an invisible line through the world and tells you the first thing it hits. Use it to find what a player is looking at, whether two players can see each other, or where the ground is.
Trace a line between two points
var result = Trace.Ray(start, end);
if (result.DidHit)
{
Console.WriteLine($"Hit something at {result.HitPosition}");
}
DidHit is false when the line reached end without touching anything.
Find what a player is looking at
Start at the player's eyes and trace in the direction they are facing. Pass the player as ignore, or the line hits them first.
[Command("lookat")]
public void CmdLookAt(Caller caller)
{
var pawn = caller.Player?.GetHeroPawn();
if (pawn == null)
throw new CommandException("You need a hero to do that.");
var start = pawn.EyePosition;
var end = start + ForwardFromAngles(pawn.EyeAngles) * 5000f;
var result = Trace.Ray(start, end, ignore: pawn);
if (result.DidHit)
caller.Reply($"You are looking at {result.HitPosition}");
else
caller.Reply("You are looking at nothing.");
}
static Vector3 ForwardFromAngles(Vector3 angles)
{
float pitch = angles.X * MathF.PI / 180f;
float yaw = angles.Y * MathF.PI / 180f;
return new Vector3(
MathF.Cos(pitch) * MathF.Cos(yaw),
MathF.Cos(pitch) * MathF.Sin(yaw),
-MathF.Sin(pitch));
}
ForwardFromAngles turns the angles a player is facing into a direction. Copy it into your plugin.
Find out what was hit
result.Trace.HitEntity is the entity the line hit.
var result = Trace.Ray(start, end, ignore: pawn);
var target = result.Trace.HitEntity?.As<CCitadelPlayerPawn>();
if (target != null)
{
// The line hit another player's hero
target.Hurt(50f, attacker: pawn);
}
Find how far away something is
var result = Trace.Ray(start, end, ignore: pawn);
if (result.DidHit)
{
float distance = Vector3.Distance(start, result.HitPosition);
}
Find the ground below a point
Trace straight down, and only let the line hit solid things.
var start = pawn.Position;
var end = start - Vector3.UnitZ * 10000f;
var result = Trace.Ray(start, end, InteractionLayer.Solid, ignore: pawn);
if (result.DidHit)
{
Vector3 ground = result.HitPosition;
}
Choose what the line can hit
The third argument says which kinds of thing stop the line. Join more than one with |.
// Walls, floors and other solid things
Trace.Ray(start, end, InteractionLayer.Solid);
// Solid things, and the hitboxes of players and NPCs. This is the default
Trace.Ray(start, end, InteractionLayer.Solid | InteractionLayer.Hitbox);
Check whether one player can see another
Trace from one player's eyes to the other's, ignoring both of them. If nothing is hit, there is nothing in the way.
var trace = CGameTrace.Create();
Trace.SimpleTrace(
a.EyePosition, b.EyePosition,
RayType_t.Line, RnQueryObjectSet.All,
InteractionLayer.Solid, InteractionLayer.None, InteractionLayer.None,
CollisionGroup.CitadelBullet, ref trace,
filterEntity: a, filterSecondEntity: b);
bool canSee = !trace.DidHit;
Trace.Ray can only ignore one entity, so this uses Trace.SimpleTrace, which can ignore two.