143 lines
4.5 KiB
C#
143 lines
4.5 KiB
C#
using Fusion;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace TPSBR
|
|
{
|
|
public static class ProjectileUtility
|
|
{
|
|
public static bool ProjectileCast(NetworkRunner runner, PlayerRef owner, int ownerObjectInstanceID, Vector3 firePosition, Vector3 direction, float raycastDistance, LayerMask hitMask, List<LagCompensatedHit> validHits)
|
|
{
|
|
return ProjectileCast(runner, owner, ownerObjectInstanceID, firePosition, direction, 0f, raycastDistance, hitMask, validHits);
|
|
}
|
|
|
|
public static bool ProjectileCast(NetworkRunner runner, PlayerRef owner, int ownerObjectInstanceID, Vector3 firePosition, Vector3 direction, float distanceToTarget, float raycastDistance, LayerMask hitMask, List<LagCompensatedHit> validHits)
|
|
{
|
|
List<LagCompensatedHit> hits = ListPool.Get<LagCompensatedHit>(16);
|
|
|
|
int hitCount = runner.LagCompensation.RaycastAll(firePosition, direction, raycastDistance, owner, hits, hitMask, true, HitOptions.IncludePhysX | HitOptions.SubtickAccuracy);
|
|
if (hitCount <= 0)
|
|
{
|
|
ListPool.Return(hits);
|
|
validHits.Clear();
|
|
return false;
|
|
}
|
|
|
|
ProcessHits(hits, hitCount, ownerObjectInstanceID, distanceToTarget, validHits);
|
|
|
|
ListPool.Return(hits);
|
|
|
|
return validHits.Count > 0;
|
|
}
|
|
|
|
public static bool ProjectileCast(NetworkRunner runner, PlayerRef owner, int ownerObjectInstanceID, int fromTick, int toTick, float alpha, Vector3 firePosition, Vector3 direction, float raycastDistance, LayerMask hitMask, List<LagCompensatedHit> validHits)
|
|
{
|
|
return ProjectileCast(runner, owner, ownerObjectInstanceID, fromTick, toTick, alpha, firePosition, direction, 0f, raycastDistance, hitMask, validHits);
|
|
}
|
|
|
|
public static bool ProjectileCast(NetworkRunner runner, PlayerRef owner, int ownerObjectInstanceID, int fromTick, int toTick, float alpha, Vector3 firePosition, Vector3 direction, float distanceToTarget, float raycastDistance, LayerMask hitMask, List<LagCompensatedHit> validHits)
|
|
{
|
|
List<LagCompensatedHit> hits = ListPool.Get<LagCompensatedHit>(16);
|
|
|
|
int hitCount = runner.LagCompensation.RaycastAll(firePosition, direction, raycastDistance, fromTick, toTick, alpha, hits, hitMask, true, HitOptions.IncludePhysX | HitOptions.SubtickAccuracy);
|
|
if (hitCount <= 0)
|
|
{
|
|
ListPool.Return(hits);
|
|
validHits.Clear();
|
|
return false;
|
|
}
|
|
|
|
for (int i = hitCount - 1; i >= 0; --i)
|
|
{
|
|
LagCompensatedHit hit = hits[i];
|
|
if (hit.Hitbox != null && hit.Hitbox.Root != null && hit.Hitbox.Root.Object != null && hit.Hitbox.Root.Object.InputAuthority == owner)
|
|
{
|
|
hits.RemoveAt(i);
|
|
--hitCount;
|
|
}
|
|
}
|
|
|
|
if (hitCount <= 0)
|
|
{
|
|
ListPool.Return(hits);
|
|
validHits.Clear();
|
|
return false;
|
|
}
|
|
|
|
ProcessHits(hits, hitCount, ownerObjectInstanceID, distanceToTarget, validHits);
|
|
|
|
ListPool.Return(hits);
|
|
|
|
return validHits.Count > 0;
|
|
}
|
|
|
|
private static void ProcessHits(List<LagCompensatedHit> hits, int hitCount, int ownerObjectInstanceID, float distanceToTarget, List<LagCompensatedHit> validHits)
|
|
{
|
|
validHits.Clear();
|
|
|
|
var hitRoots = ListPool.Get<int>(16);
|
|
|
|
float ignoreDistanceMin = 3f;
|
|
float ignoreDistanceMax = Mathf.Max(distanceToTarget - 1f, ignoreDistanceMin);
|
|
|
|
Sort(hits, hitCount);
|
|
|
|
for (int i = 0; i < hits.Count; i++)
|
|
{
|
|
var hit = hits[i];
|
|
|
|
if (distanceToTarget > 0f)
|
|
{
|
|
// For 3rd person cast it is possible that we want to shoot through environment objects a little bit if we already know the destination point
|
|
// => ray from camera is different than ray from 3rd person character
|
|
if (hit.Distance >= ignoreDistanceMin && hit.Distance < ignoreDistanceMax && hit.GameObject != null && ObjectLayerMask.Environment.value.IsBitSet(hit.GameObject.layer))
|
|
continue;
|
|
}
|
|
|
|
int hitRootID = hit.Hitbox != null ? hit.Hitbox.Root.gameObject.GetInstanceID() : 0;
|
|
|
|
if (hitRootID != 0)
|
|
{
|
|
if (hitRootID == ownerObjectInstanceID)
|
|
continue; // Owner was hit
|
|
|
|
if (hitRoots.Contains(hitRootID) == true)
|
|
continue; // Same object was hit multiple times
|
|
|
|
hitRoots.Add(hitRootID);
|
|
}
|
|
|
|
validHits.Add(hits[i]);
|
|
}
|
|
|
|
ListPool.Return(hitRoots);
|
|
}
|
|
|
|
private static void Sort(List<LagCompensatedHit> hits, int maxHits)
|
|
{
|
|
while (true)
|
|
{
|
|
bool swap = false;
|
|
|
|
for (int i = 0; i < maxHits; ++i)
|
|
{
|
|
for (int j = i + 1; j < maxHits; ++j)
|
|
{
|
|
if (hits[j].Distance < hits[i].Distance)
|
|
{
|
|
LagCompensatedHit hit = hits[i];
|
|
hits[i] = hits[j];
|
|
hits[j] = hit;
|
|
|
|
swap = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (swap == false)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|