| | | 1 | | using Godot; |
| | | 2 | | |
| | | 3 | | |
| | | 4 | | namespace Safarimacik.Model; |
| | | 5 | | |
| | | 6 | | |
| | | 7 | | /// <summary> |
| | | 8 | | /// A ranger that regulates predators. |
| | | 9 | | /// </summary> |
| | | 10 | | /// Its purpose is to be able to regulate the number of predators. |
| | | 11 | | /// It needs to be paid a wage every day. |
| | | 12 | | public class Ranger : Purchasable { |
| | | 13 | | public const int Wage = 30; |
| | | 14 | | public const int Price = 95; |
| | | 15 | | |
| | | 16 | | private Predator? _target; |
| | | 17 | | private Predator? _lastKilled; |
| | 1 | 18 | | private float _moveSpeed = 25f; |
| | 0 | 19 | | private Func<Vector2, float> _tileSpeed = _ => 0.0f; |
| | | 20 | | private Vector2 _position; |
| | 1 | 21 | | private RangerState _state = null!; |
| | | 22 | | |
| | | 23 | | public event Action<List<(Vector2, float)>>? StepsTaken; |
| | | 24 | | public event Action? StateChanged; |
| | | 25 | | |
| | 1 | 26 | | public Predator? LastKilled => _lastKilled; |
| | 1 | 27 | | public Predator? Target => _target; |
| | 1 | 28 | | int Purchasable.Price => Price; |
| | 1 | 29 | | public Vector2 Position => _position; |
| | 1 | 30 | | public Vector2I TilePosition => new((int)_position.X / 16, (int)_position.Y / 16); |
| | | 31 | | public Func<Vector2, float> TileSpeed { |
| | 1 | 32 | | set { _tileSpeed = value; } |
| | | 33 | | } |
| | | 34 | | public RangerState State { |
| | 1 | 35 | | get => _state; |
| | 1 | 36 | | set { |
| | 1 | 37 | | _state = value; |
| | 1 | 38 | | OnStateChanged(); |
| | 1 | 39 | | } |
| | | 40 | | } |
| | | 41 | | |
| | 1 | 42 | | public Ranger(Vector2 position) { |
| | 1 | 43 | | _position = position; |
| | 1 | 44 | | State = new IdleRangerState(this); // this sets _state |
| | 1 | 45 | | } |
| | | 46 | | |
| | | 47 | | /// <summary> |
| | | 48 | | /// Moves the ranger through the given route, taking the tilespeed into account. (Should be called each tick.) |
| | | 49 | | /// </summary> |
| | | 50 | | /// <param name="path">List of points the ranger moves through</param> |
| | | 51 | | /// <remarks> |
| | | 52 | | /// The method removes points from 'path' that have been reached by the ranger during it's movement. |
| | | 53 | | /// </remarks> |
| | 1 | 54 | | public void Move(List<Vector2> path) { |
| | 1 | 55 | | float distanceRemaining = _moveSpeed; |
| | | 56 | | |
| | 1 | 57 | | List<(Vector2, float)> stepsTaken = []; |
| | | 58 | | |
| | 1 | 59 | | while (distanceRemaining > 0 && path.Count > 0) { |
| | 0 | 60 | | Vector2 nextPoint = path[0]; |
| | 0 | 61 | | Vector2 toNext = nextPoint - _position; |
| | | 62 | | |
| | 0 | 63 | | if (distanceRemaining >= toNext.Length() / _tileSpeed(_position)) { |
| | 0 | 64 | | _position = nextPoint; |
| | 0 | 65 | | path.RemoveAt(0); |
| | 0 | 66 | | distanceRemaining -= toNext.Length() / _tileSpeed(_position); |
| | 0 | 67 | | } else { |
| | 0 | 68 | | Vector2 direction = toNext.Normalized(); |
| | 0 | 69 | | _position += direction * distanceRemaining * _tileSpeed(_position); |
| | 0 | 70 | | distanceRemaining = 0; |
| | 0 | 71 | | } |
| | 0 | 72 | | stepsTaken.Add((_position, _moveSpeed * _tileSpeed(_position))); |
| | 0 | 73 | | } |
| | 1 | 74 | | OnStepsTaken(stepsTaken); |
| | 1 | 75 | | } |
| | | 76 | | |
| | | 77 | | /// <summary> |
| | | 78 | | /// Sets the provided animal (if it's a predator) as this ranger's target. |
| | | 79 | | /// </summary> |
| | | 80 | | /// <param name="target">The target animal</param> |
| | 1 | 81 | | public void SelectTarget(Animal target) { |
| | 1 | 82 | | if (target is Predator predator) { |
| | 1 | 83 | | _target = predator; |
| | 1 | 84 | | } |
| | 1 | 85 | | } |
| | | 86 | | |
| | 1 | 87 | | public void CancelTargetSelection() { |
| | 1 | 88 | | _target = null; |
| | 1 | 89 | | State = new IdleRangerState(this); |
| | 1 | 90 | | } |
| | | 91 | | |
| | 1 | 92 | | public void KillTarget() { |
| | 1 | 93 | | _target?.Kill(); |
| | 1 | 94 | | _lastKilled = _target; |
| | 1 | 95 | | _target = null; |
| | 1 | 96 | | } |
| | | 97 | | |
| | 1 | 98 | | private void OnStepsTaken(List<(Vector2, float)> steps) { |
| | 1 | 99 | | StepsTaken?.Invoke(steps); |
| | 1 | 100 | | } |
| | | 101 | | |
| | 1 | 102 | | private void OnStateChanged() { |
| | 1 | 103 | | StateChanged?.Invoke(); |
| | 1 | 104 | | } |
| | | 105 | | } |