예제 #1
0
        MovementCost GetRulesMoveCost(
            TileComponentRules TileRules,
            UnitMovementRules MovementRules,
            bool Adjacent,
            bool UnitMoved,
            bool Road,
            bool UseRoad,
            Unit Unit)
        {
            if (TileRules == null)
            {
                return(new MovementCost(0f));
            }

            var cost = TileRules.GetAttributes()
                       .Where(i => i == TerrainAttribute.ROADED ? UseRoad : !Road)
                       .Select(i => MovementRules[i].GetMoveCost(Adjacent, UnitMoved))
                       .Aggregate(new MovementCost(0f), (i, j) => i + j);

            if (!Unit.Configuration.CanCarryInWater &&
                !Road &&
                (TileRules.HasAttribute(TerrainAttribute.WATER) || TileRules.HasAttribute(TerrainAttribute.SWAMP)))
            {
                cost = new MovementCost(OrderInvalidReason.UNIT_NO_CARRY_IN_WATER);
            }

            if (!TileRules.OverrideBaseMovement && cost.UnableReason == OrderInvalidReason.NONE)
            {
                return(new MovementCost(0f));
            }
            return(cost);
        }
예제 #2
0
        public MovementCost GetMoveCost(Unit Unit, Tile To, bool RoadMovement, bool IgnoreOccupyingUnits = false)
        {
            if (!IgnoreOccupyingUnits && Unit.CanEnter(To) == OrderInvalidReason.TILE_ENEMY_OCCUPIED)
            {
                return(new MovementCost(OrderInvalidReason.TILE_ENEMY_OCCUPIED));
            }

            var toBlock   = To.GetUnitBlockType();
            var fromBlock = Tile.GetUnitBlockType();

            bool unitMoved = Unit.Moved || !Tile.Units.Contains(Unit);
            bool adjacent  = !unitMoved && !Unit.Moved && To.NeighborTiles.Any(i => i != null && i.Units.Contains(Unit));

            if (!Unit.Configuration.IsAircraft())
            {
                if (toBlock == BlockType.HARD_BLOCK && !adjacent)
                {
                    return(new MovementCost(OrderInvalidReason.UNIT_NO_MOVE));
                }
                if ((fromBlock == BlockType.HARD_BLOCK || fromBlock == BlockType.SOFT_BLOCK) && unitMoved)
                {
                    return(new MovementCost(OrderInvalidReason.UNIT_NO_MOVE));
                }
            }

            bool useRoadMovement = RoadMovement &&
                                   !Tile.Map.Environment.IsRoadMovementRestricted(Unit.Configuration.UnitClass) &&
                                   !Unit.Configuration.MovementRules.CannotUseRoadMovement &&
                                   !(toBlock == BlockType.STANDARD && (!To.Units.Contains(Unit) || To.Units.Count() > 1)) &&
                                   !(fromBlock == BlockType.STANDARD &&
                                     (!Tile.Units.Contains(Unit) || Tile.Units.Count() > 1)) &&
                                   !(Unit.Configuration.CannotUseRoadMovementWithOversizedPassenger &&
                                     Unit.Passenger != null &&
                                     Unit.Passenger.Configuration.IsOversizedPassenger);

            var edge = Tile.GetEdgeRules(To);
            var path = Tile.GetPathOverlayRules(To);

            bool roaded = path != null && path.RoadMove;

            var fromBridged = Tile.Units.Any(
                i => i.Configuration.UnitClass == UnitClass.BRIDGE &&
                i.Emplaced &&
                (!Unit.Configuration.IsArmored || i.Configuration.CanSupportArmored));
            var toBridged = Tile.Units.Any(
                i => i.Configuration.UnitClass == UnitClass.BRIDGE &&
                i.Emplaced &&
                (!Unit.Configuration.IsArmored || i.Configuration.CanSupportArmored));

            bool leavingDepressed = Tile.Rules.Depressed &&
                                    (path == null || !path.HasAttribute(TerrainAttribute.DEPRESSED)) &&
                                    (path == null || !path.DepressedTransition) &&
                                    !roaded;

            UnitMovementRules movementRules = Unit.Configuration.MovementRules;
            var leaveCost = new MovementCost(0f);

            if (leavingDepressed && !fromBridged)
            {
                leaveCost = movementRules.BaseCost + LEAVING_DEPRESSED_ATTRIBUTES
                            .Select(i => movementRules[i].GetMoveCost(adjacent, unitMoved))
                            .Aggregate((i, j) => i + j);
            }

            var crossCost = GetRulesMoveCost(
                edge, movementRules, adjacent, unitMoved, roaded, useRoadMovement, Unit);

            var enterCost = new MovementCost(0f);

            if (!toBridged)
            {
                enterCost = GetRulesMoveCost(
                    To.GetBaseRules(), movementRules, adjacent, unitMoved, roaded, useRoadMovement, Unit);

                var edgeCost      = new MovementCost(0f);
                var intersectCost = new MovementCost(0f);
                for (int i = 0; i < 6; ++i)
                {
                    var eMove = GetRulesMoveCost(
                        To.GetEdgeRules(i), movementRules, adjacent, unitMoved, roaded, useRoadMovement, Unit);
                    if (eMove.IsSet())
                    {
                        if (edgeCost.IsSet())
                        {
                            edgeCost = MovementCost.Min(edgeCost, eMove);
                        }
                        else
                        {
                            edgeCost = eMove;
                        }
                    }

                    var pMove = GetRulesMoveCost(
                        To.GetPathOverlayRules(i), movementRules, adjacent, unitMoved, roaded, useRoadMovement, Unit);
                    if (pMove.IsSet())
                    {
                        if (intersectCost.IsSet())
                        {
                            intersectCost = MovementCost.Min(intersectCost, pMove);
                        }
                        else
                        {
                            intersectCost = pMove;
                        }
                    }
                }

                enterCost = (edgeCost.IsSet() ? MovementCost.Min(edgeCost, enterCost) : enterCost) + intersectCost;
            }

            if (path != null && path.OverrideBaseMovement && (!path.RoadMove || useRoadMovement))
            {
                enterCost = GetRulesMoveCost(
                    path, movementRules, adjacent, unitMoved, roaded, useRoadMovement, Unit);
                crossCost = new MovementCost(0f);
            }
            if (Tile.Rules.TieredElevation < To.Rules.TieredElevation)
            {
                enterCost += movementRules[TerrainAttribute.UP_HILL].GetMoveCost(adjacent, unitMoved);
            }
            if (Tile.Configuration.Elevation > To.Configuration.Elevation)
            {
                enterCost += movementRules[TerrainAttribute.DOWN_HILL].GetMoveCost(adjacent, unitMoved);
            }

            float multiplier = Unit.Passenger != null && Unit.Passenger.Configuration.IsOversizedPassenger
                                                                   ? Unit.Configuration.OversizedPassengerMovementMultiplier : 1;

            return(multiplier * (movementRules.BaseCost + enterCost + leaveCost + crossCost));
        }