using System; using System.Collections.Generic; using System.Linq; using System.Numerics; namespace Mappy.Data; /// Single point on the movement trail (Carbonite-style). public record MovementTrailPoint(uint Territory, uint Map, float X, float Y, double TimeStamp); /// Config and storage for the movement trail (where you've been on the map). public class MovementTrailConfig { private readonly List _points = []; private int _nextIndex; private float _lastX = float.MinValue; private float _lastY = float.MinValue; private uint _lastTerritory; public int MaxPoints { get; set; } = 100; public float MinDistance { get; set; } = 2f; public float FadeTimeSeconds { get; set; } = 60f; public Vector4 TrailColor { get; set; } = new(1f, 0f, 0f, 0.9f); // Red like Carbonite public IReadOnlyList Points => _points; private float EffectiveMinDistance => Mappy.System.SystemConfig?.MovementTrailMinDistance ?? MinDistance; private float EffectiveFadeTime => Mappy.System.SystemConfig?.MovementTrailFadeTimeSeconds ?? FadeTimeSeconds; private int EffectiveMaxPoints => Mappy.System.SystemConfig?.MovementTrailMaxPoints ?? MaxPoints; public void Clear() { _points.Clear(); _nextIndex = 0; _lastX = float.MinValue; _lastY = float.MinValue; } /// Record a new trail point if the player has moved enough. Call from Framework.Update. public void TryAddPoint(uint territory, uint map, float x, float y) { // Reset when changing territory if (territory != _lastTerritory) { Clear(); _lastTerritory = territory; } var dx = x - _lastX; var dy = y - _lastY; var moveDist = MathF.Sqrt(dx * dx + dy * dy); if (moveDist < EffectiveMinDistance && _lastX > float.MinValue) return; _lastX = x; _lastY = y; var now = DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalSeconds; var max = EffectiveMaxPoints; if (_points.Count < max) { _points.Add(new MovementTrailPoint(territory, map, x, y, now)); } else { _points[_nextIndex] = new MovementTrailPoint(territory, map, x, y, now); _nextIndex = (_nextIndex + 1) % max; } } /// Get points for the current map that haven't faded yet. public IEnumerable GetVisiblePoints(uint territoryId, uint mapId) { var now = DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalSeconds; var fade = EffectiveFadeTime; return _points .Where(p => p.Territory == territoryId && p.Map == mapId && (now - p.TimeStamp) < fade) .ToList(); } }