public ItemTeleporter(XElement element) : base(element)
        {
            var typeElement = element.Element("type");
            var failElement = element.Element("fail");

            if (typeElement != null)
            {
                Type = (string)typeElement;
            }

            if (failElement != null)
            {
                OnFail = (PathingResult)Enum.Parse(typeof(PathingResult), (string)failElement);
            }
            else
            {
                OnFail = PathingResult.Interrupted;
            }
        }
Exemple #2
0
    public PathingResult FindPath(object fromObject, object toObject, bool drawDebug = false)
    {
        PathingResult result = new PathingResult();

        result.isValid = false;

        float       debugDelay = 0f;
        const float debugTime  = 20000000f;

        if (drawDebug)
        {
            DebugDrawers.Clear();
        }

        if (
            fromObject == null ||
            toObject == null ||
            fromObject == toObject
            )
        {
            return(result);
        }

        // Result node variables.
        foreach (DictionaryEntry entry in this.nodes)
        {
            Node node = (Node)entry.Value;
            node.isQueued    = false;
            node.minDistance = Mathf.Infinity;
        }

        Node fromNode = (Node)this.nodes[fromObject];
        Node toNode   = (Node)this.nodes[toObject];

        if (fromNode == null || toNode == null || !fromNode.isEnabled || !toNode.isEnabled)
        {
            return(result);
        }

        fromNode.minDistance = 0f;

        Queue <Node> nodesToTest = new Queue <Node>();

        nodesToTest.Enqueue(fromNode);

        Node currentNode;

        while (true)
        {
            // Tested all nodes we can reach.
            if (nodesToTest.Count == 0)
            {
                break;
            }

            currentNode = nodesToTest.Dequeue();

            foreach (Connection connection in currentNode.connections)
            {
                Node node = connection.node;

                if (node.isEnabled == false)
                {
                    continue;
                }

                node.minDistance = Mathf.Min(
                    node.minDistance,
                    currentNode.minDistance + connection.distance
                    );

                if (node.isQueued == false)
                {
                    nodesToTest.Enqueue(node);
                    node.isQueued = true;
                }

                if (drawDebug)
                {
                    DebugDrawers.SpawnLine(
                        currentNode.pos,
                        node.pos,
                        Color.blue,
                        debugTime - debugDelay,
                        debugDelay
                        );
                    debugDelay += 0.02f;
                }
            }

            if (currentNode == toNode)
            {
                break;
            }
        }

        // No path.
        if (toNode.isQueued == false)
        {
            return(result);
        }

        result.distance = toNode.minDistance;
        result.isValid  = true;
        result.nodes    = new List <object>();

        result.nodes.Add(toNode.o);

        // Trace toNode to fromNode, following the shortest path.
        currentNode = toNode;
        Node lastNode = null;

        while (true)
        {
            float minMinDistance = Mathf.Infinity;
            Node  bestNode       = null;
            foreach (Connection connection in currentNode.connections)
            {
                if (connection.node.isEnabled == false)
                {
                    continue;
                }

                if (connection.node.minDistance < minMinDistance)
                {
                    minMinDistance = connection.node.minDistance;
                    bestNode       = connection.node;
                }
            }

            if (drawDebug)
            {
                foreach (Connection connection in currentNode.connections)
                {
                    if (connection.node.isEnabled == false)
                    {
                        continue;
                    }

                    if (connection.node != bestNode && connection.node != lastNode)
                    {
                        DebugDrawers.SpawnLine(
                            currentNode.pos,
                            connection.node.pos,
                            Color.yellow,
                            debugTime - debugDelay,
                            debugDelay
                            );
                    }
                }

                DebugDrawers.SpawnLine(
                    currentNode.pos,
                    bestNode.pos,
                    Color.green,
                    debugTime - debugDelay,
                    debugDelay
                    );

                debugDelay += 0.33f;
            }

            lastNode = currentNode;

            result.nodes.Add(bestNode.o);

            if (bestNode == fromNode)
            {
                break;
            }
            else
            {
                currentNode = bestNode;
            }
        }

        result.nodes.Reverse();

        return(result);
    }
Exemple #3
0
    void HexTileHovered()
    {
        bool isHoveredTileGOActive = this.hoveredTile != null;

        if (this.state == BattleState.AiControl)
        {
            isHoveredTileGOActive = false;
        }
        else if (this.state == BattleState.MoveAction)
        {
            foreach (BattleTile tile in this.moveActionData.ghostMechTiles)
            {
                tile.mapTile.RemoveLayer(MapTile.Layer.GhostSprite);
            }
            this.moveActionData.ghostMechTiles.Clear();

            if (this.moveActionData.losLinesGO)
            {
                Destroy(this.moveActionData.losLinesGO);
            }
            this.moveActionData.losLinesGO = new GameObject("LOS lines");
            this.moveActionData.losLinesGO.transform.parent = this.worldGO.transform;

            this.ResetActionPointsPreview();

            this.moveActionData.pathingResult = this.pathNetwork.FindPath(
                this.selectedTile,
                this.hoveredTile
                );

            if (this.CanClickTile() == false)
            {
                goto end;
            }

            PathingResult result = this.moveActionData.pathingResult.Value;

            if (result.isValid == false)
            {
                goto end;
            }

            // Create ghost mechs

            this.moveActionData.ghostMechTiles.Capacity = result.nodes.Count - 1;

            GameObject prevGO = this.selectedTile.gameObject;
            GameObject currentGO;
            for (int n = 1; n < result.nodes.Count; ++n)
            {
                BattleTile tile = (BattleTile)result.nodes[n];

                this.moveActionData.ghostMechTiles.Add(tile);

                currentGO = tile.gameObject;

                bool right = currentGO.transform.position.x > prevGO.transform.position.x;
                tile.mapTile.SetLayer(
                    MapTile.Layer.GhostSprite,
                    sprite: this.selectedTile.mech.data.sprite,
                    flipX: right,
                    color: new Color(1.0f, 1.0f, 1.0f, 0.5f)
                    );

                prevGO = currentGO;
            }

            // Create LOS lines from each tile to the target

            BattleMech target = this.selectedTile.mech.target;
            if (target && this.selectedTile.mech.fireAuto)
            {
                for (int n = 1; n < result.nodes.Count; ++n)
                {
                    BattleTile tile = (BattleTile)result.nodes[n];

                    GameObject go = (GameObject)Instantiate(Resources.Load("Prefabs/LOS line"));
                    go.transform.parent = this.moveActionData.losLinesGO.transform;

                    float   offsetOutward = 0.33f;
                    Vector3 dir           = (target.tile.transform.position - tile.transform.position).normalized;
                    Vector3 pos1          = tile.transform.position + dir * offsetOutward;
                    Vector3 pos2          = target.tile.transform.position - dir * offsetOutward;

                    float height = 0.25f;
                    pos1.y += height;
                    pos2.y += height;

                    LineRenderer lr = go.GetComponent <LineRenderer>();
                    lr.SetPositions(new Vector3[] { pos1, pos2 });

                    bool  canSee    = this.TestLOS(tile, target.tile);
                    Color lineColor = canSee ? Color.green : Color.red;
                    lr.startColor = lineColor;
                    lr.endColor   = lineColor;
                }
            }

            // Update action point UI element.

            float apRequired = this.selectedTile.mech.GetAPCostForMove(result.nodes).ap;
            this.UpdateActionPointsPreview(this.selectedTile.mech.actionPoints - apRequired);
        }

end:

        if (isHoveredTileGOActive)
        {
            this.mapDisplay.SetHoveredTile(this.hoveredTile.mapTile);
            this.mapDisplay.SetHoveredTileValid(this.CanClickTile());
        }
        else
        {
            this.mapDisplay.DisableHoveredTile();
        }
    }
Exemple #4
0
    // Note: this will be used for replays and maybe save files, so only use data from the move data
    // and the current state of the map.
    // Hmmmm, this is starting to seem very independent from the rest of this file.
    public void ExecuteMove(object o)
    {
        if (o.GetType() == typeof(BattleMove.Move))
        {
            var move = (BattleMove.Move)o;

            Assert.IsTrue(
                this.GetTile(move.mechIndex).mech != null &&
                this.GetTile(move.newIndex).mech == null &&
                (move.isFiring == false || this.GetTile(move.targetMechIndex).mech != null)
                );

            BattleMech mech       = this.GetTile(move.mechIndex).mech;
            BattleMech targetMech = move.isFiring ? this.GetTile(move.targetMechIndex).mech : null;
            BattleTile fromTile   = mech.tile;
            BattleTile toTile     = this.GetTile(move.newIndex);

            this.pathNetwork.SetNodeEnabled(fromTile, true);

            PathingResult result = this.pathNetwork.FindPath(fromTile, toTile);
            Assert.IsTrue(result.isValid);

            bool       isFiring = move.isFiring;
            BattleTile prevTile = (BattleTile)result.nodes[0];
            for (int n = 1; n < result.nodes.Count; ++n)
            {
                BattleTile currentTile = (BattleTile)result.nodes[n];

                prevTile.mech    = null;
                currentTile.mech = mech;
                mech.tile        = currentTile;

                if (isFiring)
                {
                    bool canSeeTarget = this.TestLOS(currentTile, targetMech.tile);
                    if (canSeeTarget)
                    {
                        this.MechAttack(mech, targetMech);
                        if (targetMech.isDestroyed)
                        {
                            isFiring = false;
                        }
                    }
                }

                prevTile = currentTile;
            }

            mech.PlaceAtMapTile(toTile.mapTile);

            BattleTile    lastTile1 = (BattleTile)result.nodes[result.nodes.Count - 2];
            BattleTile    lastTile2 = (BattleTile)result.nodes[result.nodes.Count - 1];
            bool          right     = lastTile2.transform.position.x > lastTile1.transform.position.x;
            MechDirection newDir    = right ? MechDirection.Right : MechDirection.Left;
            mech.SetDirection(newDir);

            var apCostResult = mech.GetAPCostForMove(result.nodes);
            Assert.IsTrue(mech.actionPoints > 0);
            mech.actionPoints -= apCostResult.ap;

            this.pathNetwork.SetNodeEnabled(toTile, false);

            this.UpdateFogOfWar();
        }
        else if (o.GetType() == typeof(BattleMove.StandingFire))
        {
            var move = (BattleMove.StandingFire)o;

            Assert.IsTrue(
                this.GetTile(move.mechIndex).mech != null &&
                this.GetTile(move.targetMechIndex).mech != null
                );

            BattleMech mech       = this.GetTile(move.mechIndex).mech;
            BattleMech targetMech = this.GetTile(move.targetMechIndex).mech;

            this.MechAttack(mech, targetMech);

            var apCostResult = mech.GetAPCostForStandingFire();
            mech.actionPoints -= apCostResult.ap;
        }
        else if (o.GetType() == typeof(BattleMove.SetTarget))
        {
            var move = (BattleMove.SetTarget)o;

            Assert.IsTrue(
                this.GetTile(move.mechIndex).mech != null &&
                (move.hasTarget == false || this.GetTile(move.targetMechIndex).mech != null)
                );

            BattleMech mech = this.GetTile(move.mechIndex).mech;

            if (move.hasTarget)
            {
                mech.target = this.GetTile(move.targetMechIndex).mech;
            }
            else
            {
                mech.target = null;
            }
        }
        else
        {
            throw new UnityException();
        }

        // Add to battle history.
        this.history.moves.Add(o);

        // Determine if this team's turn is over so we can advance the turn.
        bool hasAP = false;

        foreach (BattleMech mech in this.currentTeam.mechs)
        {
            if (mech.actionPoints > 0)
            {
                hasAP = true;
                break;
            }
        }
        if (hasAP == false)
        {
            this.AdvanceTurn();
        }
    }
Exemple #5
0
    void Update()
    {
        if (hardInput.GetKeyDown("Test LOS"))
        {
            // Draw a LOS test line from the selected tile to all other tiles.

            Debug.Log("Testing LOS");

            if (this.selectedTile == null)
            {
                return;
            }

            foreach (BattleTile tile in this.tiles)
            {
                bool canSee = this.TestLOS(this.selectedTile, tile);

                DebugDrawers.SpawnLine(
                    this.selectedTile.transform.position,
                    tile.transform.position,
                    canSee ? Color.green : Color.red,
                    2f
                    );
            }
        }
        else if (hardInput.GetKeyDown("Test pathing"))
        {
            Debug.Log("Testing pathing");

            if (this.selectedTile == null || this.hoveredTile == null)
            {
                return;
            }

            if (this.selectedTile.mech)
            {
                this.pathNetwork.SetNodeEnabled(this.selectedTile, true);
            }

            PathingResult result = this.pathNetwork.FindPath(
                this.selectedTile,
                this.hoveredTile,
                true
                );

            if (this.selectedTile.mech)
            {
                this.pathNetwork.SetNodeEnabled(this.selectedTile, false);
            }

            if (result.isValid)
            {
                Debug.Log(result.nodes.Count + " nodes in path " + result.distance + " units long.");
            }
            else
            {
                Debug.Log("Invalid path!");
            }
        }
        else if (hardInput.GetKeyDown("Test saving"))
        {
            Debug.Log("Testing saving");

            string jsonText = this.history.ToJSON();
            string path     = "TestSave.json";

            using (StreamWriter sw = new StreamWriter(path)){
                sw.WriteLine(jsonText);
            }

            Debug.Log("Wrote save to " + path);
        }
    }
Exemple #6
0
    public void Update()
    {
        // Test: path to a target mech, stop when we can see it and keep firing.
        BattleMech target = null;

        foreach (BattleTeam team in this.battle.teams)
        {
            foreach (BattleMech mech in team.mechs)
            {
                if (team != this.ourMech.team)
                {
                    target = mech;
                    break;
                }
            }
        }

        if (target == null)
        {
            return;
        }

        BattleTile ourTile    = this.ourMech.tile;
        BattleTile targetTile = target.tile;

        bool canSeeTarget = this.battle.TestLOS(ourTile, targetTile);

        // TODO: this is really stupid
        this.battle.pathNetwork.SetNodeEnabled(ourTile, true);
        this.battle.pathNetwork.SetNodeEnabled(targetTile, true);
        PathingResult result = this.battle.pathNetwork.FindPath(ourTile, targetTile);

        this.battle.pathNetwork.SetNodeEnabled(ourTile, false);
        this.battle.pathNetwork.SetNodeEnabled(targetTile, false);

        if (result.isValid == false)
        {
            return;
        }

        BattleTile nextTile = (BattleTile)result.nodes[1];

        if (canSeeTarget && result.distance <= 5)
        {
            var move = new BattleMove.StandingFire();
            move.mechIndex       = ourTile.index;
            move.targetMechIndex = targetTile.index;
            this.battle.ExecuteMove(move);
        }
        else
        {
            var move = new BattleMove.Move();
            move.mechIndex = ourTile.index;
            move.newIndex  = nextTile.index;
            if (canSeeTarget)
            {
                move.isFiring        = true;
                move.targetMechIndex = targetTile.index;
            }
            else
            {
                move.isFiring = false;
            }
            this.battle.ExecuteMove(move);
        }

        this.battle.SetState(BattleState.EndOfAction);
    }