vampire-like/Assets/GameMain/Scripts/Simulation/Jobs/SimulationWorld.CollisionRe...

127 lines
4.6 KiB
C#

using Entity;
using Entity.Weapon;
using UnityEngine;
namespace Simulation
{
public sealed partial class SimulationWorld
{
#region Collision Requests
public bool TryRequestAreaCollision(int sourceEntityId, int sourceOwnerEntityId, in Vector3 center,
float radius, int maxTargets = 16)
{
return TryRequestAreaCollisionInternal(sourceEntityId, sourceOwnerEntityId, in center, radius,
maxTargets, CollisionShapeCircle, Vector3.forward, 180f, 0f, 0f);
}
public bool TryRequestSectorCollision(int sourceEntityId, int sourceOwnerEntityId, in Vector3 center,
float radius, in Vector3 direction, float halfAngleDeg, int maxTargets = 16)
{
return TryRequestAreaCollisionInternal(sourceEntityId, sourceOwnerEntityId, in center, radius,
maxTargets, CollisionShapeSector, direction, halfAngleDeg, 0f, 0f);
}
public bool TryRequestRectangleCollision(int sourceEntityId, int sourceOwnerEntityId, in Vector3 center,
float halfWidth, float halfLength, in Vector3 direction, int maxTargets = 16)
{
float safeHalfWidth = Mathf.Max(0.01f, halfWidth);
float safeHalfLength = Mathf.Max(0.01f, halfLength);
float boundingRadius = Mathf.Sqrt(safeHalfWidth * safeHalfWidth + safeHalfLength * safeHalfLength);
return TryRequestAreaCollisionInternal(sourceEntityId, sourceOwnerEntityId, in center, boundingRadius,
maxTargets, CollisionShapeRectangle, direction, 0f, safeHalfWidth, safeHalfLength);
}
private bool TryRequestAreaCollisionInternal(int sourceEntityId, int sourceOwnerEntityId,
in Vector3 center, float radius, int maxTargets, int shapeType, in Vector3 direction, float halfAngleDeg,
float halfWidth, float halfLength)
{
if (!_useSimulationMovement)
{
return false;
}
if (sourceEntityId == 0 || radius <= 0f || maxTargets <= 0)
{
return false;
}
int resolvedOwnerEntityId = sourceOwnerEntityId != 0 ? sourceOwnerEntityId : sourceEntityId;
bool sourceWasActiveAtQueryTime = WasCollisionSourceActiveAtQueryTime(sourceEntityId);
Vector3 normalizedDirection = direction;
normalizedDirection.y = 0f;
if (normalizedDirection.sqrMagnitude <= Mathf.Epsilon)
{
normalizedDirection = Vector3.forward;
}
else
{
normalizedDirection.Normalize();
}
_areaCollisionRequests.Add(new AreaCollisionRequestData
{
SourceEntityId = sourceEntityId,
SourceOwnerEntityId = resolvedOwnerEntityId,
SourceWasActiveAtQueryTime = sourceWasActiveAtQueryTime,
Center = center,
Radius = Mathf.Max(0.01f, radius),
MaxTargets = Mathf.Max(1, maxTargets),
ShapeType = shapeType,
Direction = normalizedDirection,
HalfAngleDeg = Mathf.Clamp(halfAngleDeg, 0f, 180f),
HalfWidth = Mathf.Max(0f, halfWidth),
HalfLength = Mathf.Max(0f, halfLength)
});
return true;
}
private int GetPendingAreaCollisionRequestCount()
{
return _areaCollisionRequests.Count;
}
private int EstimatePendingAreaCollisionCandidateCountFromRequests()
{
int expectedCount = 0;
for (int i = 0; i < _areaCollisionRequests.Count; i++)
{
expectedCount += Mathf.Max(1, _areaCollisionRequests[i].MaxTargets);
}
return expectedCount;
}
private void ClearAreaCollisionTransientBuffers()
{
_areaCollisionRequests.Clear();
_areaCollisionHitEvents.Clear();
_areaCollisionHitDedupKeys.Clear();
}
private static bool WasCollisionSourceActiveAtQueryTime(int sourceEntityId)
{
EntityBase sourceEntity = TryGetEntityById(sourceEntityId);
if (sourceEntity == null || !sourceEntity.Available)
{
return false;
}
if (sourceEntity is WeaponBase weapon)
{
return weapon.IsAttacking;
}
if (sourceEntity is EnemyProjectile projectile)
{
return projectile.IsActive;
}
return true;
}
#endregion
}
}