Пример #1
0
    protected TileFunctions FindEndTile(TileFunctions t)
    {
        Stack<TileFunctions> tempPath = new Stack<TileFunctions>();

        TileFunctions next = t.parent;

        while (next != null)
        {
            tempPath.Push(next);
            next = next.parent;
        }

        if (tempPath.Count <= move)
        {
            //if the tile is within range this is the tile we move towards
            return t.parent;
        }

        TileFunctions endTile = null;
        for (int i = 0; i <= move; i++)
        {
            //if the tile is out of range use this tile
            endTile = tempPath.Pop();
        }
        return endTile;
    }
Пример #2
0
/*    public void DetectCharacter()
 *  {
 *      Collider2D DetectedObject = Physics2D.OverlapBox(transform.position, new Vector2(0.8f, 0.8f), 1f);
 *
 *      if (DetectedObject.gameObject.tag != "Tile")
 *      {
 *          occupied = true;
 *          detectedEnemy = DetectedObject;
 *      }
 *      else
 *      {
 *          occupied = false;
 *          detectedEnemy = null;
 *      }
 *  }*/

    public void CheckTile(Vector3 direction, TileFunctions target, bool attackable)
    {
        Vector3 halfExtents = new Vector3(0.25f, 0.25f);

        //creates a box to detect any objects with colliders, not sure what angle parameter does
        Collider2D[] colliders = Physics2D.OverlapBoxAll(transform.position + direction, halfExtents, 1f);

        foreach (Collider2D item in colliders)
        {
            TileFunctions tile = item.GetComponent <TileFunctions>();

            if (tile != null && tile.walkable)
            {
                RaycastHit2D hit = Physics2D.Raycast(tile.transform.position, new Vector3(0, 0, -1), 1);

                if (hit.collider.tag == "Tile" || tile == target)
                {
                    adjacencyList.Add(tile);
                }
                else
                {
                    tile.occupied = true;
                    adjacencyList.Add(tile);
                }
            }
        }
    }
Пример #3
0
    public void FindNeighbors(TileFunctions target, bool attackable)
    {
        //TODO need to change how it resets so you can click on an enemy and player unit at the same time
        Reset();

        CheckTile(new Vector2(0, 1), target, attackable);
        CheckTile(new Vector2(0, -1), target, attackable);
        CheckTile(Vector3.right, target, attackable);
        CheckTile(Vector3.left, target, attackable);
    }
Пример #4
0
    public void ShowAttackRange(bool detectable, bool enemyRangeTile)
    {
        float rng = ((float)move + (float)attackRange) * 2.4f;

        Collider2D[] tilesInRange = Physics2D.OverlapBoxAll(gameObject.transform.position, new Vector2(rng, rng), 1f);

        Queue <TileFunctions> borderTiles = new Queue <TileFunctions>();

        foreach (Collider2D tile in tilesInRange)
        {
            if (tile.gameObject.GetComponent <TileFunctions>())
            {
                if (tile.gameObject.GetComponent <TileFunctions>().borderTile == true)
                {
                    borderTiles.Enqueue(tile.gameObject.GetComponent <TileFunctions>());
                }
            }
        }

        while (borderTiles.Count > 0)
        {
            TileFunctions dequeuedTile = borderTiles.Dequeue();
            selectableTiles.Add(dequeuedTile);

            foreach (TileFunctions tile in dequeuedTile.adjacencyList)
            {
                if (!tile.visited)
                {
                    tile.selectAttackable = true;
                    if (dequeuedTile.borderTile || dequeuedTile.distance < attackRange)
                    {
                        if (tile.detectedEnemy && detectable && tile.detectedEnemy.gameObject.tag != gameObject.tag)
                        {
                            enemyDetected        = true;
                            tile.colorAttackable = true;
                        }
                        //TODO needs to be refactored
                        if (dequeuedTile.borderTile == true)
                        {
                            TileFunctions ModifiedTile = TileSetFlags(tile, dequeuedTile, 1, true, false, true);
                            borderTiles.Enqueue(ModifiedTile);
                        }
                        else
                        {
                            TileFunctions ModifiedTile = TileSetFlags(tile, dequeuedTile, 1 + dequeuedTile.distance, true, false, true);
                            borderTiles.Enqueue(ModifiedTile);
                        }
                    }
                }
            }
        }
    }
Пример #5
0
    public TileFunctions TileSetFlags(TileFunctions t, TileFunctions dequeuedTile, int distance, bool attackable = false, bool selectable = false, bool showAttackableTiles = false)
    {
        TileFunctions tile = t;

        tile.selectable      = selectable;
        tile.attackable      = attackable;
        tile.colorAttackable = showAttackableTiles;
        tile.visited         = true;
        tile.parent          = dequeuedTile;
        tile.distance        = distance;

        return(tile);
    }
Пример #6
0
    public void ShowEnemyAttackRangeTiles()
    {
        float rng = ((float)move + (float)attackRange) * 2.4f;
        Collider2D[] tilesInRange = Physics2D.OverlapBoxAll(gameObject.transform.position, new Vector2(rng, rng), 1f);

        Queue<TileFunctions> borderTiles = new Queue<TileFunctions>();

        foreach (Collider2D tile in tilesInRange)
        {
            if (tile.gameObject.GetComponent<TileFunctions>())
            {
                if (tile.gameObject.GetComponent<TileFunctions>().erBorderTile == true)
                {
                    borderTiles.Enqueue(tile.gameObject.GetComponent<TileFunctions>());
                }
            }
        }

        while (borderTiles.Count > 0)
        {
            TileFunctions dequeuedTile = borderTiles.Dequeue();
            EnemyRangeTiles.Add(dequeuedTile);

            foreach (TileFunctions tile in dequeuedTile.adjacencyList)
            {
                if (!tile.erVisited)
                {
                    if (dequeuedTile.erBorderTile || dequeuedTile.distance < attackRange)
                    {
                        if (dequeuedTile.erBorderTile == true)
                        {
                            tile.colorEnemyRange = true;
                            tile.erVisited = true;
                            tile.distance = 1;
                            //tile.enemiesUsingTile.Add(gameObject);
                            borderTiles.Enqueue(tile);
                        }
                        else
                        {
                            tile.colorEnemyRange = true;
                            tile.erVisited = true;
                            tile.distance = 1 + dequeuedTile.distance;
                            //tile.enemiesUsingTile.Add(gameObject);
                            borderTiles.Enqueue(tile);
                        }
                    }
                }
            }
        }
    }
Пример #7
0
    public void RemoveAttackableTiles()
    {
        if (currentTile != null)
        {
            currentTile.current = false;
            currentTile         = null;
        }
        foreach (TileFunctions tile in attackableTiles)
        {
            tile.ResetAttackable();
        }

        attackableTiles.Clear();
    }
Пример #8
0
    public void RemoveSelectableTiles()
    {
        if (currentTile != null)
        {
            currentTile.current = false;
            currentTile         = null;
        }
        foreach (TileFunctions tile in selectableTiles)
        {
            tile.Reset();
        }

        selectableTiles.Clear();
    }
Пример #9
0
    public void MoveToTile(TileFunctions tile)
    {
        path.Clear();
        tile.target = true;
        moving      = true;

        TileFunctions next = tile;

        while (next != null)
        {
            path.Push(next);
            next = next.parent;
        }
    }
Пример #10
0
    public void ShowEnemyRangeTiles(int range)
    {
        ComputeAdjacencyLists(null, false);

        GetCurrentTile();

        Queue<TileFunctions> process = new Queue<TileFunctions>();

        process.Enqueue(currentTile);

        currentTile.erVisited = true;

        while (process.Count > 0)
        {
            TileFunctions dequeuedTile = process.Dequeue();

            EnemyRangeTiles.Add(dequeuedTile);

            if (dequeuedTile.distance < range && !dequeuedTile.borderTile)
            {
                foreach (TileFunctions tile in dequeuedTile.adjacencyList)
                {
                    if (!tile.erVisited)
                    {
                        if (tile.occupied)
                        {
                            dequeuedTile.erBorderTile = true;
                        }
                        if (!tile.occupied)
                        {
                            tile.colorEnemyRange = true;
                            tile.erVisited = true;
                            tile.distance = 1 + dequeuedTile.distance;

                            if (tile.distance == move)
                            {
                                tile.erBorderTile = true;
                            }
                            process.Enqueue(tile);
                        }
                    }
                }
            }
        }
        if (process.Count == 0)
        {
           ShowEnemyAttackRangeTiles();
        }
    }
Пример #11
0
    public void ComputeAdjacencyLists(TileFunctions target, bool attackable)
    {
        float rng = ((float)move + (float)attackRange) * 2.4f;

        Collider2D[] tilesInRange = Physics2D.OverlapBoxAll(gameObject.transform.position, new Vector2(rng, rng), 1f);

        foreach (Collider2D tile in tilesInRange)
        {
            if (tile.gameObject.GetComponent <TileFunctions>())
            {
                TileFunctions startTile = tile.gameObject.GetComponent <TileFunctions>();
                startTile.FindNeighbors(target, attackable);
            }
        }
    }
Пример #12
0
    protected TileFunctions FindLowestF(List<TileFunctions> list)
    {
        TileFunctions lowest = list[0];
        foreach (TileFunctions t in list)
        {
            if (t.f < lowest.f)
            {
                lowest = t;
            }

        }
        list.Remove(lowest);

        //returns tile with shortest distance
        return lowest;
    }
Пример #13
0
    public TileFunctions GetTargetTile(GameObject target)
    {
        Vector3 playerTilePos = new Vector3(target.transform.position.x, target.transform.position.y, target.transform.position.z + 1);

        //Casts a ray from under the board to tile player character is standing on.
        //Only works because it ignores character layer, cant get raycast to not hit player character
        RaycastHit2D hit = Physics2D.Raycast(playerTilePos, new Vector3(0, 0, 1), 1f, 9);

        TileFunctions tile = null;

        if (hit.collider != null)
        {
            tile = hit.collider.GetComponent <TileFunctions>();
        }

        return(tile);
    }
Пример #14
0
    public void Reset()
    {
        actionColor.GetComponent <SpriteRenderer>().color = new Color32(0, 0, 0, 0);
        adjacencyList.Clear();
        walkable   = true;
        current    = false;
        target     = false;
        selectable = false;
        if (selectAttackable)
        {
            ResetAttackable();
        }

        selectAttackable = false;
        borderTile       = false;
        visited          = false;
        parent           = null;
        distance         = 0;

        f = g = h = 0;
    }
Пример #15
0
    public void TargetTileToTravel()
    {
        if (Input.GetMouseButtonUp(0) && !actionCompleted)
        {
            Ray          ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit2D hit = Physics2D.Raycast(ray.origin, Vector2.up);

            if (hit)
            {
                if (hit.collider.tag == "Tile")
                {
                    TileFunctions clickedTile = hit.collider.GetComponent <TileFunctions>();

                    if (clickedTile.selectable)
                    {
                        MoveToTile(clickedTile);
                    }
                }
            }
        }
    }
Пример #16
0
    //public bool selectableReady = true;

    public void SetTileDetectCharacter()
    {
        //reset = false;
        if (detectedTile == null)
        {
            //TODO give tiles their own layer
            detectedTile = Physics2D.OverlapBox(transform.position, new Vector3(0.8f, 0.8f, 0), 1f, 1);
            TileFunctions tile = detectedTile.gameObject.GetComponent <TileFunctions>();
            tile.detectedEnemy = gameObject.GetComponent <Collider2D>();
        }
        else if (new Vector2(detectedTile.transform.position.x, detectedTile.transform.position.y) != new Vector2(gameObject.transform.position.x, gameObject.transform.position.y))
        {
            TileFunctions tileDetected = detectedTile.gameObject.GetComponent <TileFunctions>();

            //needed for ai to turn occupied false for some reason
            tileDetected.occupied = false;

            tileDetected.detectedEnemy = null;
            detectedTile = null;
        }
        reset = true;
    }
Пример #17
0
    public void Move()
    {
        if (attacking) { return; }

        //FindAttackAbleTiles(); //works just as well as AIDetectPlayers, but I think AiDetectPlayers might be less costly
        DetectPcsInAttackRange();
        if (path.Count > 0)
        {
            //returns obj at the top of the stack without removing;
            TileFunctions nextTileInPath = path.Peek();
            Vector3 target = nextTileInPath.transform.position;

            if (Vector3.Distance(transform.position, target) >= 0.05f)
            {
                //TODO find a way to travel to point without affecting z axis
                var targetPos = new Vector3(target.x, target.y, -1f);
                gameObject.transform.position = Vector2.MoveTowards(gameObject.transform.position, targetPos, moveSpeed * Time.deltaTime);
            }
            else
            {
                //temporary fix for z axis
                transform.position = new Vector3(target.x, target.y, -1f);
                path.Pop();

                //so ai attacks player when in range
                if (detectedEnemies.Count > 0)
                {
                    AiAttackAction();
                }
            }
        }
        else
        {
            RemoveSelectableTiles();
            moving = false;

            EndTurn();
        }
    }
Пример #18
0
    public void Move()
    {
        if (path.Count > 0)
        {
            //returns obj at the top of the stack without removing;
            TileFunctions nextTileInPath = path.Peek();
            Vector3       target         = nextTileInPath.transform.position;

            if (Vector3.Distance(transform.position, target) >= 0.05f)
            {
                //TODO find a way to travel to point without affecting z axis
                var targetPos = new Vector3(target.x, target.y, -1f);
                gameObject.transform.position = Vector2.MoveTowards(gameObject.transform.position, targetPos, moveSpeed * Time.deltaTime);
            }
            else
            {
                //temporary fix for z axis
                transform.position = new Vector3(target.x, target.y, -1f);
                path.Pop();
            }
        }
        else
        {
            RemoveSelectableTiles();
            moving = false;
            var unitMenu = unitMenuController.transform.GetChild(0).GetComponent <UnitMenu>();

            turnManager.characterSelected = true;
            if (!attacking)
            {
                ToggleUnitMenu(true);
            }


            unitMenu.SetUnit(gameObject);
        }
    }
Пример #19
0
    public void BFSTileMap(int range, bool detectable = false, bool selectable = false, bool attackable = false, bool enemyRangeTile = false)
    {
        if (detectable && enemyDetected)
        {
            return;
        }

        ComputeAdjacencyLists(null, attackable);
        GetCurrentTile();

        Queue <TileFunctions> process = new Queue <TileFunctions>();

        process.Enqueue(currentTile);

        currentTile.visited = true;

        while (process.Count > 0)
        {
            //remove and return the tile
            TileFunctions dequeuedTile = process.Dequeue();

            selectableTiles.Add(dequeuedTile);

            if (attackable)
            {
                attackableTiles.Add(dequeuedTile);
            }

            if (dequeuedTile.distance < range && !dequeuedTile.borderTile)
            {
                //if unit is on border tile need to check both of its adjacency lists
                foreach (TileFunctions tile in dequeuedTile.adjacencyList)
                {
                    if (!tile.visited)
                    {
                        if (tile.detectedEnemy != null && tile.detectedEnemy.tag != gameObject.tag && !tile.enemyAdded)
                        {
                            if (detectable)
                            {
                                enemyDetected        = true;
                                tile.colorAttackable = true;
                            }
                            if (attackable)
                            {
                                tile.enemyAdded = true;
                                detectedEnemies.Add(tile);
                            }
                        }

                        if (tile.occupied)
                        {
                            dequeuedTile.borderTile = true;
                        }
                        if (!tile.occupied || attackable)
                        {
                            TileFunctions ModifiedTile = TileSetFlags(tile, dequeuedTile, 1 + dequeuedTile.distance, attackable, selectable, false);

                            if (ModifiedTile.distance == move)
                            {
                                ModifiedTile.borderTile = true;
                            }
                            process.Enqueue(ModifiedTile);
                        }
                    }
                }
            }
        }
        if (process.Count == 0)
        {
            ShowAttackRange(detectable, enemyRangeTile);
        }
    }
Пример #20
0
        private void OnGameUpdate(EventArgs args)
        {
            Utils.TrySpawnForEachPlayer(TrySpawnCustomNpc);

            foreach (var npc in Main.npc.Where(n => n?.active == true))
            {
                var customNpc = GetCustomNpc(npc);
                if (customNpc?.Definition.ShouldAggressivelyUpdate == true)
                {
                    npc.netUpdate = true;
                }

                if (customNpc?.HasChildren == true)
                {
                    customNpc?.UpdateChildren();
                }

                if (customNpc?.HasTransformed == true)
                {
                    var id = customNpc.Npc.whoAmI;
                    customNpc.HasTransformed = false;

                    var definition = customNpc.Definition;

                    if (definition.OnTransformed != null)
                    {
                        try
                        {
                            CustomIDFunctions.CurrentID = definition.Name;
                            definition.OnTransformed(customNpc);
                        }
                        catch (Exception ex)
                        {
                            Utils.LogScriptRuntimeError(ex);
                            definition.OnTransformed = null;
                        }

                        TSPlayer.All.SendData(PacketTypes.NpcUpdate, "", id);
                        TSPlayer.All.SendData(PacketTypes.UpdateNPCName, "", id);
                    }
                }

                var npcId = npc.whoAmI;
                if (_checkNpcForReplacement[npcId])
                {
                    TryReplaceNpc(npc);
                    _checkNpcForReplacement[npcId] = false;
                }
            }

            //player - npc collisions
            foreach (var player in TShock.Players.Where(p => p?.Active == true))
            {
                var tplayer      = player.TPlayer;
                var playerHitbox = tplayer.Hitbox;
                if (!tplayer.immune)
                {
                    player.SetData(IgnoreCollisionKey, false);
                }

                foreach (var npc in Main.npc.Where(n => n?.active == true))
                {
                    var customNpc = GetCustomNpc(npc);
                    if (customNpc != null)
                    {
                        var definition = customNpc.Definition;

                        if (definition.OnCollision != null)
                        {
                            if (npc.Hitbox.Intersects(playerHitbox) && !player.GetData <bool>(IgnoreCollisionKey))
                            {
                                try
                                {
                                    CustomIDFunctions.CurrentID = definition.Name;
                                    definition.OnCollision(customNpc, player);
                                }
                                catch (Exception ex)
                                {
                                    Utils.LogScriptRuntimeError(ex);
                                    definition.OnCollision = null;
                                }

                                //player.SetData(IgnoreCollisionKey, true);
                                //break;//should this be a continue instead??
                            }
                        }
                    }
                }

                if (!tplayer.immune)
                {
                    player.SetData(IgnoreCollisionKey, true);
                }
            }

            //npc - tile collisions
            foreach (var npc in Main.npc.Where(n => n?.active == true))
            {
                var customNpc = GetCustomNpc(npc);
                if (customNpc != null)
                {
                    var definition = customNpc.Definition;

                    if (definition.OnTileCollision != null)
                    {
                        var tileCollisions = TileFunctions.GetOverlappedTiles(npc.Hitbox);
                        if (tileCollisions.Count > 0)
                        {
                            try
                            {
                                CustomIDFunctions.CurrentID = definition.Name;
                                definition.OnTileCollision(customNpc, tileCollisions);
                            }
                            catch (Exception ex)
                            {
                                Utils.LogScriptRuntimeError(ex);
                                definition.OnTileCollision = null;
                            }
                        }
                    }
                }
            }
        }
Пример #21
0
 public void GetCurrentTile()
 {
     currentTile         = GetTargetTile(gameObject);
     currentTile.current = true;
 }
Пример #22
0
        //private void onProjectileSetDefaults(SetDefaultsEventArgs<Projectile,int> args)
        //{
        //	var projectile = args.Object;

        //	var customProjectile = GetCustomProjectile(projectile);
        //	if(customProjectile!=null)
        //	{
        //		Debug.Print("onProjectileSetDefaults!");
        //		var definition = customProjectile.Definition;

        //		definition.ApplyTo(projectile);

        //		lock( locker )
        //		{
        //			Utils.TryExecuteLua(() => definition.OnSpawn?.Call(customProjectile), definition.Name);
        //		}

        //		TSPlayer.All.SendData(PacketTypes.ProjectileNew, "", projectile.whoAmI);

        //		args.Handled = true;
        //	}
        //}

        private HookResult OnProjectilePreUpdate(Projectile projectile, ref int index)
        {
            var result           = HookResult.Continue;
            var customProjectile = GetCustomProjectile(projectile);

            if (customProjectile == null)
            {
                return(HookResult.Continue);
            }

            var definition   = customProjectile.Definition;
            var lastTimeLeft = projectile.timeLeft;             //we capture this to help determine whether we need to decrement timeLeft at the end of this method.
            //terraria has many points where it sets timeLeft internally, but our custom proj modifies whether/when those points run.
            //by the end of this method we hopefully have enough information to tell if terraria modified it, or if we need to do it ourselves.

            //game updates
            var onGameUpdate = definition.OnGameUpdate;

            if (customProjectile.Active && onGameUpdate != null)
            {
                try
                {
                    CustomIDFunctions.CurrentID = definition.Name;
                    var handled = onGameUpdate(customProjectile);
                    result = handled == true ? HookResult.Cancel : HookResult.Continue;

                    if (result == HookResult.Cancel)
                    {
                        //if we dont pass execution onto Terraria's Projectile.Update(), AI() will never get run, so we better run it ourselves.
                        projectile.AI();
                    }

                    customProjectile.SendNetUpdate = true;
                }
                catch (Exception ex)
                {
                    Utils.LogScriptRuntimeError(ex);
                    definition.OnGameUpdate = null;
                }
            }

            //collision tests

            //players
            if (customProjectile.Active && definition.OnCollision != null)
            {
                foreach (var player in TShock.Players)
                {
                    if (player?.Active == true)
                    {
                        var onCollision = definition.OnCollision;
                        if (onCollision != null)
                        {
                            var tplayer      = player.TPlayer;
                            var playerHitbox = tplayer.Hitbox;

                            if (!tplayer.immune && projectile.Hitbox.Intersects(playerHitbox))
                            {
                                try
                                {
                                    CustomIDFunctions.CurrentID = definition.Name;
                                    onCollision(customProjectile, player);
                                    customProjectile.SendNetUpdate = true;
                                }
                                catch (Exception ex)
                                {
                                    Utils.LogScriptRuntimeError(ex);
                                    definition.OnCollision = null;
                                }
                            }
                        }
                    }
                }
            }

            //tiles
            if (customProjectile.Active && projectile.tileCollide)
            {
                // this is a bit convoluted, because of the 2 conditions-- player wants to run custom code on tile collisions and/or player isn't allowing terraria
                // to run Update(), thus the projectile wont be killed in a timely manner. See condition below for result == HookResult.Cancel
                if (definition.OnTileCollision != null || result == HookResult.Cancel)
                {
                    var tileCollisions = TileFunctions.GetOverlappedTiles(projectile.Hitbox);

                    if (tileCollisions.Count > 0)
                    {
                        var killProjectile = false;

                        //if terrarias code won't be running Update(and thus AI() ), we should kill the projectile ourselves if we hit any applicable tile.
                        if (result != HookResult.Continue)
                        {
                            //...we have to scan the list before the player does, to ensure they dont modify anything(we shouldn't have switched from ReadOnlyCollection. )
                            foreach (var hit in tileCollisions)
                            {
                                if (TileFunctions.IsSolidOrSlopedTile(hit.X, hit.Y) ||
                                    (!(definition.BaseOverride.IgnoreWater == true) && TileFunctions.IsLiquidTile(hit.X, hit.Y)))
                                {
                                    killProjectile = true;
                                    break;
                                }
                            }
                        }

                        try
                        {
                            CustomIDFunctions.CurrentID = definition.Name;
                            definition.OnTileCollision?.Invoke(customProjectile, tileCollisions);
                            //customProjectile.SendNetUpdate = true;
                        }
                        catch (Exception ex)
                        {
                            Utils.LogScriptRuntimeError(ex);
                            definition.OnTileCollision = null;
                        }

                        //script hasnt killed projectile, but we did hit a foreground tile, so lets kill it ourselves
                        if (customProjectile.Active && killProjectile == true)
                        {
                            customProjectile.Kill();
                        }
                    }
                }
            }

            //We need to decrement timeLeft ourselves if no other code has, and no code run after this point will do so
            if (customProjectile.Active && result == HookResult.Cancel && customProjectile.TimeLeft == lastTimeLeft)
            {
                customProjectile.TimeLeft--;

                if (customProjectile.TimeLeft < 1)
                {
                    customProjectile.Kill();
                }
            }

            if (customProjectile.Active && customProjectile.SendNetUpdate)
            {
                SendProjectileUpdate(customProjectile.Index);
            }

            return(result);
        }
Пример #23
0
    public void FindPath(TileFunctions target)
    {
        ComputeAdjacencyLists(target, false);
        GetCurrentTile();

        List<TileFunctions> openList = new List<TileFunctions>();
        List<TileFunctions> closedList = new List<TileFunctions>();

        openList.Add(currentTile);

        currentTile.h = Vector3.Distance(currentTile.transform.position, target.transform.position);
        currentTile.f = currentTile.h;

        //29:14 part 6: explains the three steps of A*

        while (openList.Count > 0)
        {
            TileFunctions lowest = FindLowestF(openList);

            closedList.Add(lowest);

            if (lowest == target)
            {
                actualTargetTile = FindEndTile(lowest);
                MoveToTile(actualTargetTile);
                return;
            }
            foreach (TileFunctions tile in lowest.adjacencyList)
            {
                if (tile == target || !tile.occupied)
                {
                    if (closedList.Contains(tile))
                    {
                        //do nothing, already processed
                    }
                    else if (openList.Contains(tile))
                    {

                        //this case is triggered when multiple paths exist in the open list, and compares them to find the shortest path among them
                        //determines which path is better if multiple exists
                        float tempG = lowest.g + Vector3.Distance(tile.transform.position, lowest.transform.position);

                        if (tempG < tile.g)
                        {
                            tile.parent = lowest;

                            tile.g = tempG;
                            tile.f = tile.g + tile.h;
                        }
                    }
                    else
                    {
                        tile.parent = lowest;

                        //distance to the beginning
                        //the g of the parent plus the distance to the parent
                        tile.g = lowest.g + Vector3.Distance(tile.transform.position, lowest.transform.position);
                        //estimated distance to the end
                        tile.h = Vector3.Distance(tile.transform.position, target.transform.position);
                        tile.f = tile.g + tile.h;

                        openList.Add(tile);
                    }
                }
            }
        }

        //18:20 part 6
        //triggers when there is no path to the target
        //TODO need to modify so that player gets as close as possible even when there is no path
        EndTurn();
        Debug.Log("Path not found");
    }
Пример #24
0
 public void CalculatePath()
 {
     TileFunctions targetTile = GetTargetTile(target);
     FindPath(targetTile);
 }