public Job TakeClosestJobToTile(Tile t) { Job found = null; int distance = int.MaxValue; foreach (var job in _jobQueue) { var route = new Path_AStar() { World = World.Instance, Start = t, End = job.Tile }; route.Calculate(); if (found == null || route.Length() < distance) { found = job; distance = route.Length(); } } if (found != null) { _jobQueue.Remove(found); } return(found); }
public Path_AStar GetClosestPathToInventoryOfType(string objectType, Tile t, int desiredQty, bool searchInStockpiles) { if (Inventories.ContainsKey(objectType) == false) { return(null); } var path = new Path_AStar() { World = World.Instance, Start = t, ObjectType = objectType, CanTakeFromStockpile = true }; path.Calculate(); return(path); }
private BehaviourTreeStatus SetupMoveToJobSite_Action() { if (CurrentJob == null) { Debug.LogFormat("{0}: SetupMoveToJobSite_Action returning failure due to no job", Name); AbandonJob(); AbandonMove(); return(BehaviourTreeStatus.Failure); } if (DestinationTile == CurrentJob.Tile) { // Already moving towards job, so just carry on. return(BehaviourTreeStatus.Success); } // Make sure we're heading for the site. DestinationTile = CurrentJob.Tile; // See if we're already stood on the tile. if (CurrentTile == DestinationTile) { Debug.LogFormat("{0}: SetupMoveToJobSite_Action returning success due to being at the job", Name); return(BehaviourTreeStatus.Success); } // Make sure we have a route to the job. if (_path == null || _path.EndTile() != DestinationTile) { _path = new Path_AStar() { World = World.Instance, Start = CurrentTile, End = DestinationTile }; _path.Calculate(); } // If we still don't have a path, there is no path. if (_path.IsUnReachable) { Debug.LogFormat("{0}: SetupMoveToJobSite_Action returning failure due to not being able to find a route", Name); AbandonJob(); return(BehaviourTreeStatus.Failure); } // See if we're "close enough" to the job. // _path.Debug(); if ((_path.Length()) <= CurrentJob.MinRange) { // Debug.LogFormat("{0}: Close enough to job (is {1} needs to be <= {2})", Name, (_path.Length()), CurrentJob.MinRange); // Set dest to current, just in case it was the proximity-check that got us here DestinationTile = CurrentTile; return(BehaviourTreeStatus.Success); } else { Debug.LogFormat("{0}: Distance to job is {1}, needs to be <={2}", Name, (_path.Length()), CurrentJob.MinRange); } // At this point we should have a valid _nextTile to move to. return(BehaviourTreeStatus.Success); }
private BehaviourTreeStatus MoveTowardsDestination_Action(float deltaTime) { // If we've already arrived at our destination, just continue. if (CurrentTile == _destinationTile) { // Debug.Log("MoveTowardsDestination_Action: Destination Reached"); return(BehaviourTreeStatus.Success); } // If we don't have a next tile yet, get one. if (_nextTile == null || _nextTile == CurrentTile) { // If we don't have a route to the current destination, plan one. if (_path == null || _path.Length() == 0 || _path.EndTile() != DestinationTile) { _path = new Path_AStar() { World = World.Instance, Start = CurrentTile, End = DestinationTile }; _path.Calculate(); } // If Path is still null, we were not able to find a route to our goal if (_path == null) { AbandonJob(); Debug.LogFormat("MoveTowardsDestination_Action: Could not find a route to the next tile!"); return(BehaviourTreeStatus.Failure); } // See if we're "close enough" to the job. // _path.Debug(); if ((_path.Length()) <= CurrentJob.MinRange) { Debug.LogFormat("{0}: Close enough to job (is {1} needs to be <= {2})", Name, (_path.Length()), CurrentJob.MinRange); // Set dest to current, just in case it was the proximity-check that got us here DestinationTile = CurrentTile; return(BehaviourTreeStatus.Success); } else { Debug.LogFormat("{0}: Distance to job is {1}, needs to be <={2}", Name, (_path.Length()), CurrentJob.MinRange); } _nextTile = _path.Dequeue(); } if (_nextTile == null) { _nextTile = CurrentTile; // TODO: Not sure when this might apply } // What's the total distance from point A to point B? // We are going to use Euclidean distance FOR NOW... // But when we do the pathfinding system, we'll likely // switch to something like Manhattan or Chebyshev distance float distToTravel = 0; if (_nextTile != CurrentTile) { distToTravel = Mathf.Sqrt( Mathf.Pow(CurrentTile.X - _nextTile.X, 2) + Mathf.Pow(CurrentTile.Y - _nextTile.Y, 2) ); } // Before entering a Tile, make sure it is not impassable. // This might happen if the Tile is changed (e.g. wall built) after the pathfinder runs. if (_nextTile.IsEnterable() == Enterability.Never) { _nextTile = null; _path = null; Debug.LogFormat("{0}: MoveTowardsDestination_Action failed trying to move into a blocked tile.", Name); return(BehaviourTreeStatus.Failure); } if (_nextTile.IsEnterable() == Enterability.Soon) { // The next Tile we're trying to enter is walkable, but maybe for some reason // cannot be entered right now. Perhaps it is occupied, or contains a closed door. CurrentState = State.WaitingForAccess; return(BehaviourTreeStatus.Running); } // How much distance can be travel this Update? if (_nextTile == null) { _nextTile = CurrentTile; } var distThisFrame = 0f; try { distThisFrame = (_speed / _nextTile.MovementCost) * deltaTime; } catch (Exception e) { Debug.LogError(e.Message); } // How much is that in terms of percentage to our destination? float percThisFrame; if (Mathf.Approximately(distToTravel, 0f)) { percThisFrame = 1f; } else { percThisFrame = distThisFrame / distToTravel; } // Add that to overall percentage travelled. _movementPercentage += percThisFrame; if (_movementPercentage >= 1) { // We have reached our (current) destination CurrentTile = _nextTile; _movementPercentage = 0; } // Debug.LogFormat("MoveTowardsDestination_Action: Character at [{0:F2},{1:F2}] {2:P2}", this.X, this.Y, _movementPercentage); return(BehaviourTreeStatus.Running); }