Ejemplo n.º 1
0
    void UpdateDoMovement(float deltaTime)
    {
        if (currentTile == destinationTile)
        {
            pathAStar = null;
            return;
        }

        if (nextTile == null || nextTile == currentTile)
        {
            if (pathAStar == null || pathAStar.count() == 0)
            {
                pathAStar = new Path_AStar(World.worldInstance, currentTile, destinationTile);

                if (pathAStar.count() == 0)
                {
                    Debug.LogError("Path_AStar -- returned (0) no path to destinationTile");
                    AbbandonJob();
                    return;
                }

                pathAStar.Dequeue();
            }

            nextTile = pathAStar.Dequeue();

            /*if (nextTile == destinationTile) {
             *      nextTile = currentTile;
             *      destinationTile = currentTile;
             * }*/
        }

        float distanceToTravel = Mathf.Sqrt(Mathf.Pow(currentTile.X - nextTile.X, 2) + Mathf.Pow(currentTile.Y - nextTile.Y, 2));

        if (nextTile.isAccessible() == Accessiblity.NEVER)
        {
            Debug.LogError("Charcter tried to enter in unwalkable tile");
            nextTile  = null;
            pathAStar = null;
            return;
        }
        else if (nextTile.isAccessible() == Accessiblity.SOON)
        {
            return;
        }

        float distanceThisFrame   = speed / nextTile.movementCost * deltaTime;
        float percentageThisFrame = distanceThisFrame / distanceToTravel;

        movementPercentage += percentageThisFrame;

        if (movementPercentage >= 1)
        {
            currentTile        = nextTile;
            movementPercentage = 0;
        }
    }
Ejemplo n.º 2
0
    void Update_DoMovement(float deltaTime)
    {
        if (CurrentTile == _destTile)
        {
            CurrentTile.SetUnit(this);
            _pathAStar = null;
            return; // We're already were we want to be.
        }

        if (_nextTile == null || _nextTile == CurrentTile)
        {
            // Get the next tile from the pathfinder.
            if (_pathAStar == null || _pathAStar.Length() == 0)
            {
                // Generate a path to our destination
                CurrentTile.SetUnit(null);
                _pathAStar = new Path_AStar(CurrentTile.World, CurrentTile, _destTile); // This will calculate a path from curr to dest.
                if (_pathAStar.Length() == 0)
                {
                    Debug.LogError("Path_AStar returned no path to destination!");
                    _destTile  = CurrentTile;
                    _pathAStar = null;
                    return;
                }
            }

            // Grab the next waypoint from the pathing system!
            _nextTile = _pathAStar.Dequeue();
        }

        float distToTravel = Mathf.Sqrt(
            Mathf.Pow(CurrentTile.X - _nextTile.X, 2) +
            Mathf.Pow(CurrentTile.Y - _nextTile.Y, 2)
            );
        // How much distance can be travel this Update?
        float distThisFrame = Speed * deltaTime;

        // How much is that in terms of percentage to our destination?
        float percThisFrame = distThisFrame / distToTravel;

        // Add that to overall percentage travelled.
        _movementPercentage += percThisFrame;

        if (_movementPercentage >= 1)
        {
            // We have reached our destination

            //       If there are no more tiles, then we have TRULY
            //       reached our destination.

            CurrentTile         = _nextTile;
            _movementPercentage = 0;
        }
    }
Ejemplo n.º 3
0
        private void OnCharacterChanged(Character character)
        {
            if (_characterGameObjectMap.ContainsKey(character) == false)
            {
                Debug.LogError("OnCharacterChanged failed - Character requested that is not in the map!");
                return;
            }

            var charGo = _characterGameObjectMap[character];

            charGo.transform.position = new Vector3(character.X, character.Y, 0);

            // Draw 'footsteps' for any current path on this character
            if (character.CurrentTile != null && character.Path != null && character.Path.Length() > 0)
            {
                var  p = new Path_AStar(character.Path);
                Tile t;
                do
                {
                    t = p.Dequeue();
                    if (t != null)
                    {
                        var go = new GameObject();
                        go.name = "footstep";
                        go.transform.position = new Vector3(t.X, t.Y, 0);
                        var sprite = go.AddComponent <SpriteRenderer>();
                        sprite.sprite           = SpriteManager.Instance.GetSprite("colonist", "footstep");
                        sprite.sortingLayerName = "Characters";
                        sprite.enabled          = true;
                        Destroy(go, 1);
                    }
                } while (t != null);
            }

            // Set the various subsprite visibility depending on what the situation is for this character.
            _characterSpriteParts[character]["working"].enabled = character.CurrentState == Character.State.WorkingJob;
            _characterSpriteParts[character]["shield"].enabled  = character.ShieldStatus;
        }
Ejemplo n.º 4
0
        private void Update_DoMovement(float deltaTime)
        {
            if (currTile == destTile)
            {
                pathAStar = null;
                return; // We're already were we want to be.
            }

            if (nextTile == null || nextTile == currTile)
            {
                // Get the next tile from the pathfinder.
                if (pathAStar == null || pathAStar.Length() == 0)
                {
                    // Generate a path to our destination
                    pathAStar = new Path_AStar(currTile.World, currTile, destTile);
                    // This will calculate a path from curr to dest.
                    if (pathAStar.Length() == 0)
                    {
                        //Debug.LogError("Path_AStar returned no path to destination!");
                        AbandonJob();
                        pathAStar = null;
                        return;
                    }

                    // Ignore the first tile in the path, as that's the tile we are currently in,
                    // and we can always move out of our current tile.
                    nextTile = pathAStar.Dequeue();
                }

                // Grab the next waypoint from the pathing system!
                nextTile = pathAStar.Dequeue();


                if (nextTile == currTile)
                {
                    //Debug.LogError("Update_DoMovement - nextTile is currTile?");
                }
            }

            /*		if(pathAStar.Length() == 1) {
             *          return;
             *      }
             */
            // At this point we should have a valid nextTile to move to.

            // 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 != currTile)
            {
                distToTravel = (float)Math.Sqrt(
                    Math.Pow(currTile.X - nextTile.X, 2) +
                    Math.Pow(currTile.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)
            {
                // Debug.LogError("Error - character was strying to enter an impassable tile!");
                nextTile  = currTile;
                pathAStar = null;
            }
            else 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.
                return;
            }

            // How much distance can be travel this Update?
            var distThisFrame = (speed / nextTile.MovementCost) * deltaTime;

            // How much is that in terms of percentage to our destination?
            var percThisFrame = distThisFrame / distToTravel;

            // Add that to overall percentage travelled.
            movementPercentage += percThisFrame;

            if (movementPercentage >= 1)
            {
                // We have reached our destination

                // TODO: Get the next tile from the pathfinding system.
                //       If there are no more tiles, then we have TRULY
                //       reached our destination.

                currTile           = nextTile;
                movementPercentage = 0;
                // FIXME?  Do we actually want to retain any overshot movement?
            }
        }
Ejemplo n.º 5
0
    void Update_DoMovement(float deltaTime)
    {
        if (currTile == destTile)
        {
            pathAStar = null;
            return;            //we're already were we want to be.
        }

        if (nextTile == null || nextTile == currTile)
        {
            //get the next tile from the pathfinder
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                //calculate a path from curr to dest
                pathAStar = new Path_AStar(currTile.world, currTile, destTile);
                if (pathAStar.Length() == 0)
                {
                    Debug.LogError("Path_AStar returned no path to destination !");
                    AbandonJob();
                    pathAStar = null;
                    return;
                }
            }
            //grab the next waypoint from the pathfinding system
            nextTile = pathAStar.Dequeue();

            if (nextTile == currTile)
            {
                Debug.LogError("Update_DoMovement - nextTile is currTile ?");
            }
        }

/*		if(pathAStar.Length() == 1 ){
 *                      return;
 *              }
 */
        //at this point we should have a valid nextTile  to move to !



        //on détermnie la distance entre les deux points theoreme de pythagore mec ??
        //for now it is euclidian, but when pathfinding system we do, manhattan or chebyshev system BRO !!
        //Pow !!!
        //public static float Pow(float f, float p);
        //Returns f raised to power p.
        //public static float Sqrt(float f); -- Returns square root of f.
        float distToTravel = Mathf.Sqrt(Mathf.Pow(currTile.X - nextTile.X, 2) + Mathf.Pow(currTile.Y - nextTile.Y, 2));

        //on détermine la distance par frame pour qu'elle soit égale quelque que soit le nombre de fps
        //how much distance can be traveled this update
        float distThisFrame = speed * deltaTime;

        // how much is that in terms of percentage to our destination ? (de 0 a 1)
        float percThisFrame = distThisFrame / distToTravel;

        //add that overall poercentage travelled
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            //we have reached our destination

            //TODO : get the next tile from the pathfinding system
            //If there are no more tiles, then we have TRULKY reach our destination

            currTile           = nextTile;
            movementPercentage = 0;
            //FIXME do we actually want to retain any overshot movement ?
        }
    }
    void Update_DoMovement(float deltaTime)
    {
        if (currTile == destTile)
        {
            pathAStar = null;
            return;
        }

        if (nextTile == null || nextTile == currTile)
        {
            //Get the next tile from the pathfinder
            if (pathAStar == null)
            {
                //Generate a path to our destination
                pathAStar = new Path_AStar(currTile.world, currTile, destTile);
                if (pathAStar.Length() == 0 && currTile != destTile)
                {
                    Debug.LogError("Path_AStar returned no path to destination!");
                    //FIXME: Job should maybe be re-enqued instead?
                    AbandonJob();
                    pathAStar = null;
                    return;
                }

                //nextTile = pathAStar.Dequeue();
            }


            nextTile = pathAStar.Dequeue();

            if (nextTile == currTile)
            {
                Debug.LogError("Update_DoMovement - nextTile is currTile?");
            }
        }

        if (nextTile.GetEnterability() == Enterability.Never)
        {
            //Most likely wall got built, so we just need to reset our pathfinding information.
            //FIXME: Ideally, when a wall gets spawned, we should invalidate our path immediately, so that we dont waste a bunch of time walking towards a dead end. To save CPU, maybe we can only check every so often? Or maybe we should register a callback to the OnTileChanged event?
            Debug.LogError("FIXME: A character was trying to enter an unwalkable tile!");
            nextTile  = null;
            pathAStar = null;
            return;
        }
        else if (nextTile.GetEnterability() == Enterability.Soon)
        {
            // We can't enter the tile NOW, but we should be able to do so in the future
            //This is likely a door.
            //We dont bail out our movement path but we do return now and don't actually process movement
            return;
        }

        float distToTravel  = Mathf.Sqrt(Mathf.Pow(currTile.X - nextTile.X, 2) + Mathf.Pow(currTile.Y - nextTile.Y, 2));
        float distThisFrame = (speed / nextTile.MovementCost) * deltaTime;
        float percThisFrame = distToTravel <= 0 ? 1 - movementPercentage : distThisFrame / distToTravel;

        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            //TODO: Get the next tile from the pathfinding system.
            //If there are no more tiles, then we have truly reached our destination.


            currTile           = nextTile;
            movementPercentage = 0;
        }



        return;
    }
Ejemplo n.º 7
0
    private void Update_DoMovement(float deltaTime)
    {
        if (CurrTile == DestTile)
        {
            // We're already were we want to be.
            pathAStar = null;
            IsWalking = false;
            VisualPath.Instance.RemoveVisualPoints(name);
            return;
        }

        if (nextTile == null || nextTile == CurrTile)
        {
            // Get the next tile from the pathfinder.
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                // Generate a path to our destination.
                // This will calculate a path from current tile to destination tile.
                pathAStar = new Path_AStar(World.Current, CurrTile, DestTile);
                if (pathAStar.Length() == 0)
                {
                    Debug.ULogErrorChannel("Character", "Path_AStar returned no path to destination!");
                    AbandonJob(false);
                    return;
                }

                // Let's ignore the first tile, because that's the tile we're currently in.
                nextTile = pathAStar.Dequeue();
            }

            if (IsSelected)
            {
                VisualPath.Instance.SetVisualPoints(name, pathAStar.GetList());
            }

            IsWalking = true;

            // Grab the next waypoint from the pathing system!
            nextTile = pathAStar.Dequeue();

            if (nextTile == CurrTile)
            {
                IsWalking = false;
            }
        }

        if (nextTile.IsEnterable() == Enterability.Never)
        {
            //// Most likely a wall got built, so we just need to reset our pathfinding information.
            //// FIXME: Ideally, when a wall gets spawned, we should invalidate our path immediately,
            ////            so that we don't waste a bunch of time walking towards a dead end.
            ////            To save CPU, maybe we can only check every so often?
            ////            Or maybe we should register a callback to the OnTileChanged event?
            //// Debug.ULogErrorChannel("FIXME", "A character was trying to enter an unwalkable tile.");
            nextTile  = null;   // our next tile is a no-go
            pathAStar = null;   // clearly our pathfinding info is out of date.
            return;
        }
        else if (nextTile.IsEnterable() == Enterability.Soon)
        {
            // We can't enter the NOW, but we should be able to in the
            // future. This is likely a DOOR.
            // So we DON'T bail on our movement/path, but we do return
            // now and don't actually process the movement.
            return;
        }

        CharacterFacing();

        // At this point we should have a valid nextTile to move to.
        // 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 = Mathf.Sqrt(
            Mathf.Pow(CurrTile.X - nextTile.X, 2) +
            Mathf.Pow(CurrTile.Y - nextTile.Y, 2));

        // How much distance can be travel this Update?
        float distThisFrame = speed / nextTile.MovementCost * deltaTime;

        // How much is that in terms of percentage to our destination?
        float percThisFrame = distThisFrame / distToTravel;

        // Add that to overall percentage travelled.
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            // We have reached our destination

            //// TODO: Get the next tile from the pathfinding system.
            ////       If there are no more tiles, then we have TRULY
            ////       reached our destination.

            CurrTile           = nextTile;
            movementPercentage = 0;

            // FIXME?  Do we actually want to retain any overshot movement?
        }
    }
Ejemplo n.º 8
0
    /// <summary>
    /// Checks weather the current job has all the materials in place and if not instructs the working character to get the materials there first.
    /// Only ever returns true if all materials for the job are at the job location and thus signals to the calling code, that it can proceed with job execution.
    /// </summary>
    /// <returns></returns>
    bool CheckForJobMaterials()
    {
        if (myJob.HasAllMaterial())
        {
            return(true); //we can return early
        }
        // Job still needs materials
        // Am I carrying anything the job location wants?
        if (inventory != null)
        {
            if (myJob.DesiresInventoryType(inventory) > 0)
            {
                // If so, deliver
                // Walk to the job tile then drop off the stack into the job
                if (CurrTile == myJob.tile)
                {
                    // We are at the job site so drop the inventory
                    World.Current.inventoryManager.PlaceInventory(myJob, inventory);
                    myJob.DoWork(0);  // This will call all cbJobWorked callbacks

                    //at this point we should dump anything in our inventory
                    DumpExcessInventory();
                }
                else
                {
                    // Walk to job site
                    DestTile = myJob.tile;
                    return(false);
                }
            }
            else
            {
                // We are carrying something but the job doesn't want it
                // Dump it
                DumpExcessInventory();
            }
        }
        else
        {
            // At this point, the job still requires inventory but we aren't carrying it
            // Are we standing on a tile with goods desired by job?
            if (CurrTile.inventory != null &&
                myJob.DesiresInventoryType(CurrTile.inventory) > 0 &&
                (myJob.canTakeFromStockpile || CurrTile.furniture == null || CurrTile.furniture.IsStockpile() == false))
            {
                // Pick up the stuff
                World.Current.inventoryManager.PlaceInventory(
                    this,
                    CurrTile.inventory,
                    myJob.DesiresInventoryType(CurrTile.inventory)
                    );
            }
            else
            {
                // If not, walk towards a tile containing the required goods

                // Find the first thing in the job that isn't satisfied
                Inventory desired = myJob.GetFirstDesiredInventory();

                if (CurrTile != NextTile)
                {
                    // We are still moving somewhere so just bail out
                    return(false);
                }

                // Any chance we already have a path that leads to the items we want?
                if (pathAStar != null && pathAStar.EndTile() != null && pathAStar.EndTile().inventory != null && pathAStar.EndTile().inventory.objectType == desired.objectType)
                {
                    // We are already moving towards a tile that we want so do nothing
                }
                else
                {
                    Path_AStar newPath = World.Current.inventoryManager.GetPathToClosestInventoryOfType(
                        desired.objectType,
                        CurrTile,
                        desired.maxStackSize - desired.stackSize,
                        myJob.canTakeFromStockpile
                        );

                    if (newPath == null || newPath.Length() == 0)
                    {
                        Debug.Log("No tile contains objects of type " + desired.objectType + "to satisfy job requirements");
                        AbandonJob();
                        return(false);
                    }

                    Debug.Log("pathAStar returned with length of: " + newPath.Length());

                    DestTile = newPath.EndTile();

                    // Since we already have a path calculated let's just save that
                    pathAStar = newPath;

                    // Ignore the first tile because that's the tile we're already in
                    NextTile = newPath.Dequeue();
                }

                // One way or the other, we are now on route to an object of the right type
                return(false);
            }
        }

        return(false); // Can't continue until all materials are satisifed
    }
Ejemplo n.º 9
0
    /// <summary>
    /// Checks weather the current job has all the materials in place and if not instructs the working character to get the materials there first.
    /// Only ever returns true if all materials for the job are at the job location and thus signals to the calling code, that it can proceed with job execution.
    /// </summary>
    /// <returns></returns>
    bool CheckForJobMaterials()
    {
        if (myJob.HasAllMaterial())
        {
            return(true); //we can return early
        }
        // At this point we know, that the job still needs materials.
        // First we check if we carry any materials the job wants by chance.
        if (inventory != null)
        {
            if (myJob.DesiresInventoryType(inventory) > 0)
            {
                // If so, deliver the goods.
                // Walk to the job tile, then drop off the stack into the job.
                if (CurrTile == myJob.tile)
                {
                    // We are at the job's site, so drop the inventory
                    World.current.inventoryManager.PlaceInventory(myJob, inventory);
                    myJob.DoWork(0); // This will call all cbJobWorked callbacks, because even though
                                     // we aren't progressing, it might want to do something with the fact
                                     // that the requirements are being met.

                    //at this point we should dump anything in our inventory
                    DumpExcessInventory();
                }
                else
                {
                    // We still need to walk to the job site.
                    DestTile = myJob.tile;
                    return(false);
                }
            }
            else
            {
                // We are carrying something, but the job doesn't want it!
                // Dump the inventory so we can be ready to carry what the job actually wants.
                DumpExcessInventory();
            }
        }
        else
        {
            // At this point, the job still requires inventory, but we aren't carrying it!

            // Are we standing on a tile with goods that are desired by the job?
            Debug.Log("Standing on Tile check");
            if (CurrTile.inventory != null &&
                myJob.DesiresInventoryType(CurrTile.inventory) > 0 &&
                (myJob.canTakeFromStockpile || CurrTile.furniture == null || CurrTile.furniture.IsStockpile() == false))
            {
                // Pick up the stuff!
                Debug.Log("Pick up the stuff");

                World.current.inventoryManager.PlaceInventory(
                    this,
                    CurrTile.inventory,
                    myJob.DesiresInventoryType(CurrTile.inventory)
                    );
            }
            else
            {
                // Walk towards a tile containing the required goods.
                Debug.Log("Walk to the stuff");
                Debug.Log(myJob.canTakeFromStockpile);


                // Find the first thing in the Job that isn't satisfied.
                Inventory desired = myJob.GetFirstDesiredInventory();

                if (CurrTile != NextTile)
                {
                    // We are still moving somewhere, so just bail out.
                    return(false);
                }

                // Any chance we already have a path that leads to the items we want?
                if (pathAStar != null && pathAStar.EndTile() != null && pathAStar.EndTile().inventory != null && (pathAStar.EndTile().furniture != null && !(myJob.canTakeFromStockpile == false && pathAStar.EndTile().furniture.IsStockpile() == true)) && pathAStar.EndTile().inventory.objectType == desired.objectType)
                {
                    // We are already moving towards a tile that contains what we want!
                    // so....do nothing?
                }
                else
                {
                    Path_AStar newPath = World.current.inventoryManager.GetPathToClosestInventoryOfType(
                        desired.objectType,
                        CurrTile,
                        desired.maxStackSize - desired.stackSize,
                        myJob.canTakeFromStockpile
                        );

                    if (newPath == null || newPath.Length() < 1)
                    {
                        //Debug.Log("pathAStar is null and we have no path to object of type: " + desired.objectType);
                        // Cancel the job, since we have no way to get any raw materials!
                        Debug.Log("No tile contains objects of type '" + desired.objectType + "' to satisfy job requirements.");
                        AbandonJob();
                        return(false);
                    }

                    Debug.Log("pathAStar returned with length of: " + newPath.Length());

                    DestTile = newPath.EndTile();

                    // Since we already have a path calculated, let's just save that.
                    pathAStar = newPath;

                    // Ignore first tile, because that's what we're already in.
                    NextTile = newPath.Dequeue();
                }

                // One way or the other, we are now on route to an object of the right type.
                return(false);
            }
        }

        return(false); // We can't continue until all materials are satisfied.
    }
Ejemplo n.º 10
0
    void Update_DoJob(float deltaTime)
    {
        // Do I have a job?
        jobSearchCooldown -= Time.deltaTime;
        if (myJob == null)
        {
            if (jobSearchCooldown > 0)
            {
                // Don't look for job now.
                return;
            }


            GetNewJob();

            if (myJob == null)
            {
                // There was no job on the queue for us, so just return.
                jobSearchCooldown = UnityEngine.Random.Range(0.1f, 0.5f);
                DestTile          = currTile;
                return;
            }
        }

        // We have a job! (And the job tile is reachable)

        // STEP 1: Does the job have all the materials it needs?
        if (myJob.HasAllMaterial() == false)
        {
            // No, we are missing something!

            // STEP 2: Are we CARRYING anything that the job location wants?
            if (inventory != null)
            {
                if (myJob.DesiresInventoryType(inventory) > 0)
                {
                    // If so, deliver the goods.
                    //  Walk to the job tile, then drop off the stack into the job.
                    if (currTile == myJob.tile)
                    {
                        // We are at the job's site, so drop the inventory
                        World.current.inventoryManager.PlaceInventory(myJob, inventory);
                        myJob.DoWork(0);                         // This will call all cbJobWorked callbacks, because even though
                        // we aren't progressing, it might want to do something with the fact
                        // that the requirements are being met.

                        // Are we still carrying things?
                        if (inventory.stackSize == 0)
                        {
                            inventory = null;
                        }
                        else
                        {
                            Debug.LogError("Character is still carrying inventory, which shouldn't be. Just setting to NULL for now, but this means we are LEAKING inventory.");
                            inventory = null;
                        }
                    }
                    else
                    {
                        // We still need to walk to the job site.
                        DestTile = myJob.tile;
                        return;
                    }
                }
                else
                {
                    // We are carrying something, but the job doesn't want it!
                    // Dump the inventory at our feet
                    // TODO: Actually, walk to the nearest empty tile and dump it there.
                    if (World.current.inventoryManager.PlaceInventory(currTile, inventory) == false)
                    {
                        Debug.LogError("Character tried to dump inventory into an invalid tile (maybe there's already something here.");
                        // FIXME: For the sake of continuing on, we are still going to dump any
                        // reference to the current inventory, but this means we are "leaking"
                        // inventory.  This is permanently lost now.
                        inventory = null;
                    }
                }
            }
            else
            {
                // At this point, the job still requires inventory, but we aren't carrying it!

                // Are we standing on a tile with goods that are desired by the job?
                Debug.Log("Standing on Tile check");
                if (currTile.inventory != null &&
                    (myJob.canTakeFromStockpile || currTile.furniture == null || currTile.furniture.IsStockpile() == false) &&
                    myJob.DesiresInventoryType(currTile.inventory) > 0)
                {
                    // Pick up the stuff!
                    Debug.Log("Pick up the stuff");

                    World.current.inventoryManager.PlaceInventory(
                        this,
                        currTile.inventory,
                        myJob.DesiresInventoryType(currTile.inventory)
                        );
                }
                else
                {
                    // Walk towards a tile containing the required goods.
                    Debug.Log("Walk to the stuff");
                    Debug.Log(myJob.canTakeFromStockpile);


                    // Find the first thing in the Job that isn't satisfied.
                    Inventory desired = myJob.GetFirstDesiredInventory();

                    if (currTile != nextTile)
                    {
                        // We are still moving somewhere, so just bail out.
                        return;
                    }

                    // Any chance we already have a path that leads to the items we want?
                    if (pathAStar != null && pathAStar.EndTile() != null && pathAStar.EndTile().inventory != null && pathAStar.EndTile().inventory.objectType == desired.objectType)
                    {
                        // We are already moving towards a tile that contains what we want!
                        // so....do nothing?
                    }
                    else
                    {
                        Path_AStar newPath = World.current.inventoryManager.GetPathToClosestInventoryOfType(
                            desired.objectType,
                            currTile,
                            desired.maxStackSize - desired.stackSize,
                            myJob.canTakeFromStockpile
                            );

                        if (newPath == null)
                        {
                            //Debug.Log("pathAStar is null and we have no path to object of type: " + desired.objectType);
                            // Cancel the job, since we have no way to get any raw materials!
                            AbandonJob();
                            return;
                        }


                        Debug.Log("pathAStar returned with length of: " + newPath.Length());

                        if (newPath == null || newPath.Length() == 0)
                        {
                            Debug.Log("No tile contains objects of type '" + desired.objectType + "' to satisfy job requirements.");
                            AbandonJob();
                            return;
                        }

                        DestTile = newPath.EndTile();

                        // Since we already have a path calculated, let's just save that.
                        pathAStar = newPath;

                        // Ignore first tile, because that's what we're already in.
                        nextTile = newPath.Dequeue();
                    }

                    // One way or the other, we are now on route to an object of the right type.
                    return;
                }
            }

            return;             // We can't continue until all materials are satisfied.
        }

        // If we get here, then the job has all the material that it needs.
        // Lets make sure that our destination tile is the job site tile.
        DestTile = myJob.tile;

        // Are we there yet?
        if (currTile == myJob.tile)
        {
            // We are at the correct tile for our job, so
            // execute the job's "DoWork", which is mostly
            // going to countdown jobTime and potentially
            // call its "Job Complete" callback.
            myJob.DoWork(deltaTime);
        }

        // Nothing left for us to do here, we mostly just need Update_DoMovement to
        // get us where we want to go.
    }
Ejemplo n.º 11
0
    void Update_DoMovement(float deltaTime) {
        if (currTile == destTile) {
            pathAStar = null;
            return; // We're already where we want to be.
        }

        // currTile = Tile I'm in and in process of leaving.
        // nextTile = Tile I'm currently entering.
        // destTile = Our final destination -- we never walk here directly but use it for the pathfinding.

        if (nextTile == null || nextTile == currTile) {
            // I don't have a nextTile so I get it from the pathfinder.
            if (pathAStar == null || pathAStar.Lenght() == 0){
                // I don't have a pathfinder so I create one.
                pathAStar = new Path_AStar(WorldController.Instance.world,currTile, destTile);
                if (pathAStar.Lenght() == 0) {
                    // Pathfinding couldn't get a path to the destination.
                    Debug.LogError("Path_AStar returned no path to destination!");

                    // Re-enqueue Job and set current to null.
                    AbandonJob();
                    return;
                }
                // Let's ignore the first tile, because that's the tile we're currently in.
                nextTile = pathAStar.Dequeue();
            } // Now we have a path.

            // Grab next waypoint from the path system
            nextTile = pathAStar.Dequeue();

            if (nextTile == currTile) {
                Debug.LogError("Update_DoMovement -- nextTile is currTile?");
            }
        }

        // At this point we have a valid nextTile

        // Total distance.
        float distToTravel = Mathf.Sqrt(Mathf.Pow(currTile.X - nextTile.X, 2f) + Mathf.Pow(currTile.Y - nextTile.Y, 2f));

        if (nextTile.IsEnterable() == ENTERABILITY.Never) {
            // Most likely a wall got built after path creation.
            // FIXME: When a wall gets spawned we should invalidate our pathfinding imediatale
            Debug.LogError("Update_DoMovement -- Trying to move to an unwalkable tile or walkable tile with moveCost of 0.");
            nextTile = null;   // Our next tile is a no-go.
            pathAStar = null;  // clearly our pathfinding info is out of date.
            return;
        } else if (nextTile.IsEnterable() == ENTERABILITY.Soon) {
            // The tile we are trying to enter is technically walkable (i.e. not a wall),
            // but are we allowed to enter it right now.
            // We return without processing the movement.
            return;
        }

        // Distance travelled this update.
        float distThisFrame = speed/nextTile.movementCost * deltaTime;

        // Percentage to destination this frame.
        float percThisFrame = distThisFrame / distToTravel;

        // Add that to overall percentage travelled.
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1) {
            // We have reached our destination

            // TODO: Get next destination tile from pathfinding system. 
            // TODO: If there are no more tiles, we are in the real destination
            currTile = nextTile;
            movementPercentage = 0;
        }

        if (cbCharacterChanged != null) {
            cbCharacterChanged(this);
        }
    }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        private BehaviourTreeStatus FindRequiredStock_Action()
        {
            //Debug.Log("FindRequiredStock_Action");

            // If the current job has all the materials it needs already, we can just skip this step.
            if (CurrentJob.HasAllMaterial())
            {
                AbandonMove();
                return(BehaviourTreeStatus.Success);
            }

            // The job needs some more materials, perhaps we're holding them already so don't need to go anywhere.
            if (Inventory != null && CurrentJob.NeedsMaterial(Inventory) > 0)
            {
                // We are carrying at least some of what the current job needs, so continue on our merry way.
                AbandonMove();
                return(BehaviourTreeStatus.Success);
            }

            // The job needs some more materials, and we're not carrying it already, so we need to move to where there are some.

            // Perhaps the stock is right where we're stood?
            if (CurrentTile.Inventory != null &&
                (CurrentJob.CanTakeFromStockpile || CurrentTile.Furniture == null || CurrentTile.Furniture.IsStockpile() == false) &&
                (CurrentJob.NeedsMaterial(CurrentTile.Inventory) != 0))
            {
                // The materials we need are right where we're stood!
                AbandonMove();
                return(BehaviourTreeStatus.Success);
            }

            // The Job needs some of this:
            var unsatisfied = CurrentJob.GetFirstRequiredInventory();

            // We might have a path to the item we need already
            var endTile = _path == null ? null : _path.EndTile();

            if (_path != null && endTile != null && endTile.Inventory != null && endTile.Inventory.ObjectType == unsatisfied.ObjectType)
            {
                // We are already moving towards a tile with the items we want, just keep going.
                return(BehaviourTreeStatus.Success);
            }

            // Look for the first item that matches.
            _path = World.Instance.InventoryManager.GetClosestPathToInventoryOfType(
                objectType: unsatisfied.ObjectType,
                t: CurrentTile,
                desiredQty: unsatisfied.MaxStackSize - unsatisfied.StackSize,
                searchInStockpiles: CurrentJob.CanTakeFromStockpile);


            // If there are no items anywhere that satisfy the requirements, we have to give up on this job.
            if (_path == null || _path.Length() == 0)
            {
                //// Debug.LogFormat("No Tile found containing the desired type ({0}).", unsatisfied.ObjectType);
                AbandonJob();
                return(BehaviourTreeStatus.Failure);
            }

            // We've identified where the missing items can be found, so head there.
            _destinationTile = _path.EndTile();
            _nextTile        = _path.Dequeue();
            return(BehaviourTreeStatus.Success);
        }
Ejemplo n.º 14
0
    // World calls this to update the character
    public void Update(float deltaTime)
    {
        // Check if I have a job
        // If I don't have a job..
        if (myJob == null)
        {
            // Try to pull a job
            myJob = WorldController.Instance.World.jobQueue.Dequeue();
            // Did that pull succeed?
            // If I still don't have a job
            if (myJob == null)
            {
                // Pullout, I don't have a job and can't get one. I don't want to do anything else
                return;
            }
            // If I did get a job...
            else
            {
                jobTile = myJob.buildTile;                     // set the job tile as my jobtile
                myJob.RegisterJobCanceledCallback(OnJobEnded); // we want to know if the job is completed or canceled, so we can discard it and do something else
                myJob.RegisterJobCompleteCallback(OnJobEnded);

                // It's a new job, reset everything as we'll have to work out pathfinding again
                destTile = null;
                nextTile = currTile;
            }
        }

        // At this stage I should have a job
        // Am I at the job site?

        if (destTile != null && currTile == destTile)
        {
            // If I'm at the job site, work on the job
            myJob.DoWork(deltaTime);
        }

        else
        {
            // Do I have my next step (nextTile) ?
            // If I don't have my next step or are on it
            if (nextTile == null || currTile == nextTile)
            {
                // Check if I have a path to follow
                // If I don't have a path...
                if (mainPath == null || mainPath.Length() == 0)
                {
                    // Check all neighbours
                    // Get a list of all the neighbouring tiles to the jobTile
                    Tile[] neighbourList = jobTile.GetNeighbours(true);
                    // Local lists to hold possilbe paths and tile destinations.
                    // Won't need these after we have worked out the one we want
                    potentialPathList = new List <Path_AStar>();
                    pathToDestTileMap = new Dictionary <Path_AStar, Tile>();


                    // Check each tile adjacent to the job tile, and if it's standable generate a path to it and add that path to the list of potental paths
                    foreach (Tile t in neighbourList)
                    {
                        if (t.IsStandable() == true)
                        {
                            Path_AStar PTemp = new Path_AStar(t.world, currTile, t);
                            // check that there is a legitimate path before adding it to the list of potential paths
                            if (PTemp.Length() != 0)
                            {
                                potentialPathList.Add(PTemp);
                                pathToDestTileMap.Add(PTemp, t);
                            }
                        }
                    }

                    // Check that we have at least one potential path
                    // If we don't, bail out as pathing is impossible
                    if (potentialPathList.Count <= 0)
                    {
                        //Debug.LogError("No Potential Paths found");
                        AbandonJob();   // Pull out of job and put job back on queue
                        mainPath = null;
                        potentialPathList.Clear();
                        pathToDestTileMap.Clear();
                        return;
                    }


                    // We should now have at least one potential path, so we will see which one is the shortest
                    // Set first on list at the shortest, and check each path agaisnt it, a shorter path becoming the new shortest
                    Path_AStar shortestPath = potentialPathList.First();

                    foreach (Path_AStar path in potentialPathList)
                    {
                        if (path.Length() < shortestPath.Length())
                        {
                            shortestPath = path;
                        }
                    }

                    // We now have a path to use that will take us to a legitmate building spot\
                    // And also the tile we are trying to get to

                    mainPath = shortestPath;
                    destTile = pathToDestTileMap[shortestPath];
                }
                // At this stage we should have a path
                nextTile = mainPath.Dequeue();
            }
            // At this stage we should have a nextTile
            // If I'm not at the jobsite, move towards it
            MoveToNextTile(deltaTime);
        }



        if (cbCharacterChanged != null)     // Let other objects know that we have changed -- TODO: don't want to run every tick???
        {
            cbCharacterChanged(this);
        }
    }
Ejemplo n.º 15
0
//	Job myJob;
//
//	void Update_DoJob (float deltaTime) {
//		if (myJob == null) {
//			myJob = currTile.world.jobQueue.Dequeue ();
//
//			if (myJob != null) {
//				// I got a job!
//				destTile = myJob.tile;
//
//				// Register the ended job callback
//				myJob.RegisterJobCompleteCallback (OnJobEnded);
//				myJob.RegisterJobCancelCallback (OnJobEnded);
//			}
//		}
//
//		// moving the character
//		if (myJob != null && currTile == myJob.tile) {
//			myJob.DoJob(deltaTime);
//		}
//
//	}
//
//	public void AbandonJob() {
//		nextTile = destTile = currTile;
//		pathAStar = null;
//		currTile.world.jobQueue.Enqueue(myJob);
//		myJob = null;
//	}

    void Update_DoMovement(float deltaTime)
    {
        if (currTile == destTile)
        {
            pathAStar = null;
            return;             // where are already where we want to be
        }

        if (nextTile == null || nextTile == currTile)
        {
            // get the next tile from the pathfinder
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                // generate a new path to our destination
                pathAStar = new Path_AStar(WorldController.Instance.world, currTile, destTile);
                if (pathAStar.Length() == 0)
                {
                    //Debug.LogError ("pathAStar returned no path to destination");
                    // FIXME: the job should be re-enqued
//					AbandonJob ();
                    pathAStar = null;
                    return;
                }
                nextTile = pathAStar.Dequeue();
            }
            // FIXME: discarding the first node, the current tile of the character
            // from the pathfinding system. Maybe there's a better way?


            nextTile = pathAStar.Dequeue();

            if (nextTile == currTile)
            {
                Debug.LogError("Update_DoMovement: nextTile is currTile?");
            }
        }

        float distToTravel = Vector2.Distance(new Vector2(currTile.X, currTile.Y), new Vector2(nextTile.X, nextTile.Y));

        // float distToTravel = Mathf.Sqrt (Mathf.Pow (currTile.X - nextTile.X, 2) + Mathf.Pow (currTile.Y - nextTile.Y, 2));


        if (nextTile.movementCost == 0)
        {
            //FIXME : this is getting called too much. shouldnt be at all?
            Debug.LogError("character trying to traverse an unwalkble tile");
            nextTile  = null;
            pathAStar = null;
            return;
        }
        float percThisFram = (speed * deltaTime) / (distToTravel * nextTile.movementCost);

        movementPercentage += percThisFram;

        if (movementPercentage >= 1)
        {
            // get the next destination tile from the pathfinding system

            currTile           = nextTile;
            movementPercentage = 0;
        }
    }
Ejemplo n.º 16
0
    void DoMovement()
    {
        if (curTile == DestTile)
        {
            // We made it
            StopMove();
            return;
        }


        if (nextTile == null || nextTile == curTile)
        {
            // Get the next tile
            if (path == null || path.Length() == 0)
            {
                // Generate path
                path = new Path_AStar(activeArea, curTile, DestTile);
                if (path.Length() == 0)
                {
                    StopMove();
                    // Debug.LogError("Enemy's PathAStar did not return a path!");
                    return;
                }

                // Ignore the first tile since we are on it
                nextTile = path.Dequeue();
            }

            nextTile = path.Dequeue();

            SetDirection();

            ENTERABILITY nextTileEnterability = nextTile.CanEnter();
            switch (nextTileEnterability)
            {
            case ENTERABILITY.Never:
                // Cant go on
                StopMove();
                return;
            }

            if (nextTile == curTile)
            {
                StopMove();
                return;
            }
        }
        // How much distance can we travel this frame?
        float distToTravel = Mathf.Sqrt(
            Mathf.Pow(curTile.X - nextTile.X, 2) +
            Mathf.Pow(curTile.Y - nextTile.Y, 2));

        // How much distance can we travel this frame?
        float distThisFrame = speed.GetValue() / nextTile.MovementCost * Time.deltaTime;

        float perThisFrame = distThisFrame / distToTravel;

        movePercent += perThisFrame;

        if (movePercent >= 1)
        {
            movePercent = 0;
            curTile     = nextTile;
        }
    }
Ejemplo n.º 17
0
    public void Update_Movement(float deltaTime)
    {
        //Debug.Log("Character UpdateMovement");
        if (currTile == destTile)
        {
            pather = null;
            return; // We're already were we want to be.
        }

        if (nextTile == null || nextTile == currTile)
        {
            // Get the next tile from the pathfinder.
            if (pather == null || pather.Length() == 0)
            {
                // Generate a path to our destination
                pather = new Path_AStar(currTile.world, currTile, destTile); // This will calculate a path from curr to dest.
                if (pather.Length() == 0)
                {
                    Debug.LogError("Path_AStar returned no path to destination!");
                    AbandonJob();
                    pather = null;
                    return;
                }
            }

            // Grab the next waypoint from the pathing system!
            nextTile = pather.Dequeue();

            if (nextTile == currTile)
            {
                //Debug.LogError("Update_DoMovement - nextTile is currTile?");
            }
        }

        /*		if(pathAStar.Length() == 1) {
         *          return;
         *      }
         */
        // At this point we should have a valid nextTile to move to.

        // 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 = Mathf.Sqrt(
            Mathf.Pow(currTile.x - nextTile.x, 2) +
            Mathf.Pow(currTile.y - nextTile.y, 2)
            );


        // How much distance can be travel this Update?
        float distThisFrame = speed * deltaTime;

        // How much is that in terms of percentage to our destination?
        float percThisFrame = distThisFrame / distToTravel;

        // Add that to overall percentage travelled.
        movementPercentage += (percThisFrame * currTile.MoveCost);
        Debug.Log("movementPercentage:" + movementPercentage + ". percThisFrame:" + percThisFrame + ". currTile.Movecost" + currTile.MoveCost);
        if (movementPercentage >= 1)
        {
            // We have reached our destination

            // TODO: Get the next tile from the pathfinding system.
            //       If there are no more tiles, then we have TRULY
            //       reached our destination.

            currTile           = nextTile;
            movementPercentage = 0;
            // FIXME?  Do we actually want to retain any overshot movement?
        }

        //Debug.Log("Character End Movement");
    }
Ejemplo n.º 18
0
    void Update_DoMovement(float deltaTime)
    {
        if (CurrTile == DestTile)
        {
            pathAStar = null;
            return;     // We're already were we want to be.
        }

        // currTile = The tile I am currently in (and may be in the process of leaving)
        // nextTile = The tile I am currently entering
        // destTile = Our final destination -- we never walk here directly, but instead use it for the pathfinding

        if (NextTile == null || NextTile == CurrTile)
        {
            // Get the next tile from the pathfinder.
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                // Generate a path to our destination
                pathAStar = new Path_AStar(World.current, CurrTile, DestTile);  // This will calculate a path from curr to dest.
                if (pathAStar.Length() == 0)
                {
                    Debug.LogError("Path_AStar returned no path to destination!");
                    AbandonJob();
                    return;
                }

                // Let's ignore the first tile, because that's the tile we're currently in.
                NextTile = pathAStar.Dequeue();
            }


            // Grab the next waypoint from the pathing system!
            NextTile = pathAStar.Dequeue();

            if (NextTile == CurrTile)
            {
                //Debug.LogError("Update_DoMovement - nextTile is currTile?");
            }
        }

        // At this point we should have a valid nextTile to move to.

        // 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 = Mathf.Sqrt(
            Mathf.Pow(CurrTile.X - NextTile.X, 2) +
            Mathf.Pow(CurrTile.Y - NextTile.Y, 2)
            );

        if (NextTile.IsEnterable() == ENTERABILITY.Never)
        {
            // Most likely a wall got built, so we just need to reset our pathfinding information.
            // FIXME: Ideally, when a wall gets spawned, we should invalidate our path immediately,
            //		  so that we don't waste a bunch of time walking towards a dead end.
            //		  To save CPU, maybe we can only check every so often?
            //		  Or maybe we should register a callback to the OnTileChanged event?
            Debug.LogError("FIXME: A character was trying to enter an unwalkable tile.");
            NextTile  = null;   // our next tile is a no-go
            pathAStar = null;   // clearly our pathfinding info is out of date.
            return;
        }
        else if (NextTile.IsEnterable() == ENTERABILITY.Soon)
        {
            // We can't enter the NOW, but we should be able to in the
            // future. This is likely a DOOR.
            // So we DON'T bail on our movement/path, but we do return
            // now and don't actually process the movement.
            return;
        }

        // How much distance can be travel this Update?
        float distThisFrame = speed / NextTile.movementCost * deltaTime;

        // How much is that in terms of percentage to our destination?
        float percThisFrame = distThisFrame / distToTravel;

        // Add that to overall percentage travelled.
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            // We have reached our destination

            // TODO: Get the next tile from the pathfinding system.
            //       If there are no more tiles, then we have TRULY
            //       reached our destination.

            CurrTile           = NextTile;
            movementPercentage = 0;
            // FIXME?  Do we actually want to retain any overshot movement?
        }
    }
Ejemplo n.º 19
0
    /// <summary>
    /// 更新移动
    /// </summary>
    /// <param name="deltaTime"></param>
    void Update_DoMovement(float deltaTime)
    {
        if (currTile == destTile)
        {
            path_AStar = null;
            return;
        }
        if (nextTile == null || nextTile == currTile)
        {
            //获取下一个寻路点
            if (path_AStar == null || path_AStar.Length() == 0)
            {
                //生存到目的地寻路
                path_AStar = new Path_AStar(currTile.world, currTile, destTile);
                if (path_AStar.Length() == 0)
                {
                    AbandonJob();
                    path_AStar = null;
                    return;
                }
                //获取下一个路径tile
                nextTile = path_AStar.Dequeue();
            }
            //获取下一个路径tile
            nextTile = path_AStar.Dequeue();
        }
        if (nextTile.IsEnterable() == Enterability.Never)
        {
            //很可能是墙建成了,所以我们只需要重置我们的寻路信息。
            // FIXME:理想情况下,当墙壁产生时,我们应立即使路径无效,
            //这样我们就不会浪费一大堆时间走向死胡同。
            //为了节省CPU,也许我们只能经常检查?
            //或者我们应该注册OnTileChanged事件的回调?
            nextTile   = null;
            path_AStar = null;
            return;
        }
        else if (nextTile.IsEnterable() == Enterability.Soon)
        {
            //我们现在无法进入,但我们应该可以进入
            //未来 这可能是一个DOOR。
            //所以我们不要保佑我们的运动/路径,但我们确实会回来
            //现在并不实际处理运动。
            return;
        }
        //从A点到B点的总距离是多少?
        //我们将使用欧几里德距离现在......
        //但是当我们进行寻路系统时,我们很可能会这样做
        //切换到曼哈顿或切比雪夫的距离
        float distToTravel = Mathf.Sqrt(
            Mathf.Pow(currTile.x - nextTile.x, 2)
            + Mathf.Pow(currTile.y - nextTile.y, 2)
            );

        // 移动速度(通过门的时 缓慢通过)
        float distThisFrame = speed / nextTile.movementCost * deltaTime;

        // 到目的地的需要多久?
        float percThisFrame = distThisFrame / distToTravel;

        //
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            // TODO:从寻路系统中获取下一个图块。
            //如果没有更多的瓷砖,那么我们就有了TRULY
            //到达目的地

            // 我们到达了目的地
            currTile           = nextTile;
            movementPercentage = 0;
            // 我们真的想保留任何超车运动吗?
        }
        if (cbCharacterChanged != null)
        {
            cbCharacterChanged(this);
        }
    }
Ejemplo n.º 20
0
    void Update_DoMovement(float deltaTime)
    {
        if (CurrTile == DestTile)
        {
            pathAStar = null;
            return; // Already there
        }

        // currTile = the tile I'm currently in (and may be leaving)
        // nextTile = the tile I'm currently entering
        // destTile = Our final destination -- we never walk here directly, but instead use it for the pathfinder

        if (NextTile == null || NextTile == CurrTile)
        {
            // Get the next tile from the pathfinder
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                // Generate a path to our destination
                pathAStar = new Path_AStar(World.Current, CurrTile, DestTile);  // This will calculate path from curr to dest
                if (pathAStar.Length() == 0)
                {
                    Debug.LogError("Path_AStar returned no path to destination!");
                    AbandonJob();
                    return;
                }

                // Let's ignore the first tile because that's the tile we're currently in
                NextTile = pathAStar.Dequeue();
            }

            // Grab the next waypoint from the pathing system!
            NextTile = pathAStar.Dequeue();

            if (NextTile == CurrTile)
            {
                Debug.LogError("Update_DoMovement - nextTile is currTile?");
            }
        }

        // At this point we should have a valid nextTile to move to

        // Total distance between A and B
        // Euclidean distance for now; for pathfinding change to Manhattan or something else
        float distToTravel = Mathf.Sqrt(
            Mathf.Pow(CurrTile.X - NextTile.X, 2) +
            Mathf.Pow(CurrTile.Y - NextTile.Y, 2)
            );

        if (NextTile.IsEnterable() == ENTERABILITY.Never)
        {
            // Most likely a wall got built, so we need to reset pathfinding
            // FIXME: when a wall gets spanwed, invalidate path immediately. or check sometimes to save CPU.
            // or register a callback to ontilechanged event
            Debug.LogError("Fix me - character trying to walk through unwalkable  tile");
            NextTile  = null;   // our next tile is a no-go
            pathAStar = null;   // pathfinding info is out of date
            return;
        }
        else if (NextTile.IsEnterable() == ENTERABILITY.Soon)
        {
            // Can't enter now but should be able to in the future.(Door?)
            // Don't bail on movement path but return now and don't process movement.
            return;
        }

        // How much distance can be travelled this Update
        float distThisFrame = speed / NextTile.movementCost * deltaTime;

        // How much is that in terms of percentage
        float percThisFrame = distThisFrame / distToTravel;

        // Add that to overall percentage travelled
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            // Reached destination

            // TODO: get the next tile from pathfinding system

            CurrTile           = NextTile;
            movementPercentage = 0;

            // FIXME: Overshot movement?
        }
    }
Ejemplo n.º 21
0
    void Update_DoMovement(float _deltaTime)
    {
        //if we don't need to move, don't move, we're already here
        if (currentTile == DestinationTile)
        {
            pathAStar = null;
            return;
        }

        if (nextTile == null || nextTile == currentTile)
        {
            //Get next tile from pathfinder
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                //generate a path
                pathAStar = new Path_AStar(currentTile.World, currentTile, DestinationTile); //calculate a path from the current tile to the destination tile
                if (pathAStar.Length() == 0)
                {
                    Debug.LogError("Character -- Update_DoMovement: Path_AStar returned no path to destination");
                    AbandonJob();
                    return;
                }
                //ignore the first tile, it is what we're on
                nextTile = pathAStar.Dequeue();
            }


            //Grab next waypoint
            nextTile = pathAStar.Dequeue();
            if (nextTile == currentTile)
            {
                Debug.LogError("Character-- Update_DoMovement: nextTile is equal to currentTile");
            }
        }

        //if (pathAStar.Length() == 1)
        //    return;

        //At this point we should have a valid nextTile


        //total distance from point A to point B
        float distanceToTravel = Mathf.Sqrt(Mathf.Pow(currentTile.X - nextTile.X, 2) + Mathf.Pow(currentTile.Y - nextTile.Y, 2));

        if (nextTile.IsEnterable() == ENTERABILITY.Never)
        {
            Debug.LogError("Character -- Update_DoMovement: A character tried to enter an unwalkable tile");
            //the next tile shouldn't be walked on, so the path info is outdated and need to be updated (e.g. a wall was built here after the path was made)
            nextTile  = null;
            pathAStar = null;
            return;
        }
        else if (nextTile.IsEnterable() == ENTERABILITY.Soon)
        {
            //We can't enter the tile now, but we should be able to in the near future. This tile is likely a door, so we will return until the tile is enterable
            //then we process the movement and move thrugh the tile

            return;
        }

        //How much distance can we travel this update
        float distanceThisFrame = speed / nextTile.MovementCost * _deltaTime;


        //How mush is that in terms of percentage to our destination
        float percentageThisFrame = distanceThisFrame / distanceToTravel;

        //add to overall percentage travel
        movementPercentage += percentageThisFrame;

        //if we have reached the destination
        if (movementPercentage >= 1)
        {
            currentTile        = nextTile;
            movementPercentage = 0;
        }
    }
Ejemplo n.º 22
0
    /// <summary>
    /// Checks whether the current job has all the materials in place and if not instructs the working character to get the materials there first.
    /// Only ever returns true if all materials for the job are at the job location and thus signals to the calling code, that it can proceed with job execution.
    /// </summary>
    /// <returns></returns>
    private bool CheckForJobMaterials()
    {
        List <string> fulfillableInventoryRequirements = new List <string>();

        if (MyJob != null && MyJob.IsNeed && MyJob.Critical == false)
        {
            MyJob.tile = jobTile = new Path_AStar(World.Current, CurrTile, null, MyJob.JobObjectType, 0, false, true).EndTile();
        }

        if (MyJob == null || MyJob.MaterialNeedsMet())
        {
            // We can return early.
            return(true);
        }
        else
        {
            fulfillableInventoryRequirements = MyJob.FulfillableInventoryRequirements();

            // If we somehow get here and fulfillableInventoryRequirements is empty then there is a problem!
            if (fulfillableInventoryRequirements == null || fulfillableInventoryRequirements.Count() == 0)
            {
                Debug.ULogChannel("Character", "CheckForJobMaterials: no fulfillable inventory requirements");
                AbandonJob(true);
                return(false);
            }
        }

        // At this point we know that the job still needs materials and these needs are satisfiable.
        // First we check if we carry any materials the job wants by chance.
        if (inventory != null)
        {
            if (MyJob.AmountDesiredOfInventoryType(inventory) > 0)
            {
                // If so, deliver the goods.
                // Walk to the job tile, then drop off the stack into the job.
                if (CurrTile == JobTile)
                {
                    // We are at the job's site, so drop the inventory
                    World.Current.inventoryManager.PlaceInventory(MyJob, inventory);
                    MyJob.DoWork(0); // This will call all cbJobWorked callbacks, because even though
                    // we aren't progressing, it might want to do something with the fact
                    // that the requirements are being met.

                    // at this point we should dump anything in our inventory
                    DumpExcessInventory();
                }
                else
                {
                    // We still need to walk to the job site.
                    DestTile = JobTile;
                    return(false);
                }
            }
            else
            {
                // We are carrying something, but the job doesn't want it!
                // Dump the inventory so we can be ready to carry what the job actually wants.
                DumpExcessInventory();
            }
        }
        else
        {
            // At this point, the job still requires inventory, but we aren't carrying it!
            // Are we standing on a tile with goods that are desired by the job?
            if (CurrTile.Inventory != null &&
                MyJob.AmountDesiredOfInventoryType(CurrTile.Inventory) > 0 && !CurrTile.Inventory.Locked &&
                (MyJob.canTakeFromStockpile || CurrTile.Furniture == null || CurrTile.Furniture.IsStockpile() == false))
            {
                // Pick up the stuff!
                World.Current.inventoryManager.PlaceInventory(
                    this,
                    CurrTile.Inventory,
                    MyJob.AmountDesiredOfInventoryType(CurrTile.Inventory));
            }
            else
            {
                // Walk towards a tile containing the required goods.
                if (CurrTile != nextTile)
                {
                    // We are still moving somewhere, so just bail out.
                    return(false);
                }

                // Any chance we already have a path that leads to the items we want?
                // Check that we have an end tile and that it has content.
                // Check if contains the desired objectType�.
                if (WalkingToUsableInventory() && fulfillableInventoryRequirements.Contains(pathAStar.EndTile().Inventory.ObjectType))
                {
                    // We are already moving towards a tile that contains what we want!
                    // so....do nothing?
                    return(false);
                }
                else
                {
                    Inventory  desired = null;
                    Path_AStar newPath = null;
                    foreach (string itemType in fulfillableInventoryRequirements)
                    {
                        desired = MyJob.inventoryRequirements[itemType];
                        newPath = World.Current.inventoryManager.GetPathToClosestInventoryOfType(
                            desired.ObjectType,
                            CurrTile,
                            desired.MaxStackSize - desired.StackSize,
                            MyJob.canTakeFromStockpile);

                        if (newPath == null || newPath.Length() < 1)
                        {
                            // Try the next requirement
                            Debug.ULogChannel("Character", "No tile contains objects of type '" + desired.ObjectType + "' to satisfy job requirements.");
                            continue;
                        }

                        // else, there is a valid path to an item that will satisfy the job
                        break;
                    }

                    if (newPath == null || newPath.Length() < 1)
                    {
                        // tried all requirements and found no path
                        Debug.ULogChannel("Character", "No reachable tile contains objects able to satisfy job requirements.");
                        AbandonJob(true);
                        return(false);
                    }

                    Debug.ULogChannel("Character", "pathAStar returned with length of: " + newPath.Length());

                    DestTile = newPath.EndTile();

                    // Since we already have a path calculated, let's just save that.
                    pathAStar = newPath;

                    // Ignore first tile, because that's what we're already in.
                    nextTile = newPath.Dequeue();
                }

                // One way or the other, we are now on route to an object of the right type.
                return(false);
            }
        }

        return(false); // We can't continue until all materials are satisfied.
    }
Ejemplo n.º 23
0
    void Update_DoMovement(float deltaTime)
    {
        if (CurrTile == destTile)
        {
            pathAStar = null;
            return;
        }

        if (nextTile == null || nextTile == CurrTile)
        {
            //get the next tile from the pathfinder
            if (pathAStar == null || pathAStar.Length() == 0)
            {
                //gen a path to dest
                pathAStar = new Path_AStar(CurrTile.World, CurrTile, destTile);
                if (pathAStar.Length() == 0)
                {
                    Debug.LogError($"Path A star returned no path to destination");
                    AbandonJob();
                    pathAStar = null;
                    return;
                }
                nextTile = pathAStar.Dequeue(); //burning through the first tile, as that is the tile we are currently in
            }


            nextTile = pathAStar.Dequeue();

            if (nextTile == CurrTile)
            {
                Debug.Log($"Update_DoMovement - nexttile is currtile??");
            }
        }

        //get distance from a to b
        float distToTravel = Mathf.Sqrt(
            Mathf.Pow(CurrTile.X - nextTile.X, 2) +
            Mathf.Pow(CurrTile.Y - nextTile.Y, 2));

        if (nextTile.IsEnterable() == Enterability.Never)
        {
            Debug.LogError($"FIXME: a character was trying to enter an unwalkable tile");
            nextTile  = null;
            pathAStar = null;
            return;
        }
        else if (nextTile.IsEnterable() == Enterability.Soon)
        {
            return;
        }

        //how much distance are we travelling this update cycle
        float distThisFrame = speed / nextTile.movementCost * deltaTime;

        //how much is that in terms of percentage to our destination
        float percThisFrame = distThisFrame / distToTravel;

        // add that to overall percentage travelled
        movementPercentage += percThisFrame;

        if (movementPercentage >= 1)
        {
            //we have reached out destination

            //todo: get the next destinatnion from the pathfinding system
            //if there are no more tiles then we have truly reached the destination

            CurrTile           = nextTile;
            movementPercentage = 0;
        }
    }