Exemple #1
0
        public static List <EncounterAction> ActionsForUnitReform(EncounterState state, Entity parent, int formationNumber, Unit unit)
        {
            var actions = new List <EncounterAction>();

            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            var targetPosition = AIUtils._DecideFormationPosition(formationNumber, playerPos, unit);

            if (parentPos != targetPosition)
            {
                // TODO: We may want to make pathfinding stateful/cache it or something, to save on turn times
                var path = Pathfinder.AStarWithNewGrid(parentPos, targetPosition, state);
                if (path != null)
                {
                    actions.Add(new MoveAction(parent.EntityId, path[0]));
                }
                else
                {
                    actions.Add(new WaitAction(parent.EntityId));
                }
            }
            else
            {
                actions.Add(new WaitAction(parent.EntityId));
            }

            return(actions);
        }
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions   = new List <EncounterAction>();
            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            // Close distance if further than 5
            if (parentPos.DistanceTo(playerPos) >= 5f)
            {
                // PERF: We may want to make pathfinding stateful/cache it or something, to save on turn times
                var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);
                if (path != null)
                {
                    actions.Add(new MoveAction(parent.EntityId, path[0]));
                }
            }
            // Fire shotgun pellets=5, spread=5 every 4th turn, else fire single cannon (this is honestly a comical amount of spread though)
            if (this.CurrentShotgunCooldown == 0)
            {
                actions.AddRange(FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 5, spread: 5, state.EncounterRand));
                this.CurrentShotgunCooldown += this.ShotgunCooldown;
            }
            else
            {
                actions.Add(FireProjectileAction.CreateSmallCannonAction(parent.EntityId, playerPos));
                if (this.CurrentShotgunCooldown > 0)
                {
                    this.CurrentShotgunCooldown -= 1;
                }
            }


            return(actions);
        }
Exemple #3
0
        private static bool ResolveAutopilotBeginTravel(AutopilotBeginAction action, EncounterState state)
        {
            var           playerPosition = state.Player.GetComponent <PositionComponent>().EncounterPosition;
            EncounterZone zone           = state.GetZoneById(action.ZoneId);

            var foundPath      = Pathfinder.AStarWithNewGrid(playerPosition, zone.Center, state, 9000);
            int autopilotTries = 0;

            while (foundPath == null && autopilotTries < 5)
            {
                foundPath = Pathfinder.AStarWithNewGrid(playerPosition, zone.RandomEmptyPosition(state.EncounterRand, state), state, 9000);
                autopilotTries++;
            }
            if (foundPath != null && autopilotTries > 0)
            {
                state.LogMessage(String.Format("Autopilot could not find path to center of [b]{0}[/b]; autopiloting to randomly chosen position in [b]{0}[/b].", zone.ZoneName));
                state.Player.GetComponent <PlayerComponent>().LayInAutopilotPathForTravel(new EncounterPath(foundPath));
                return(true);
            }
            else if (foundPath != null)
            {
                state.LogMessage(String.Format("Autopiloting to [b]{0}[/b]", zone.ZoneName));
                state.Player.GetComponent <PlayerComponent>().LayInAutopilotPathForTravel(new EncounterPath(foundPath));
                return(true);
            }
            else
            {
                state.LogMessage(String.Format("Autopilot failed to plot course to to [b]{0}[/b]", zone.ZoneName), failed: true);
                return(false);
            }
        }
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions   = new List <EncounterAction>();
            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            // Always attempt to close distance
            var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);

            if (path != null)
            {
                actions.Add(new MoveAction(parent.EntityId, path[0]));
            }
            // Fire reverser + cannon every 3rd turn, and shotgun + secondary batteries otherwise
            if (this.CurrentReverserCooldown == 0)
            {
                actions.Add(FireProjectileAction.CreateReverserAction(parent.EntityId, playerPos));
                actions.Add(FireProjectileAction.CreateSmallCannonAction(parent.EntityId, playerPos));
                this.CurrentReverserCooldown += ReverserCooldown;
            }
            else
            {
                actions.Add(FireProjectileAction.CreateSmallCannonAction(parent.EntityId, playerPos));
                actions.Add(FireProjectileAction.CreateSmallCannonAction(parent.EntityId, playerPos));
                actions.AddRange(FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 2, spread: 3, state.EncounterRand));
                if (this.CurrentReverserCooldown > 0)
                {
                    this.CurrentReverserCooldown -= 1;
                }
            }

            return(actions);
        }
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions   = new List <EncounterAction>();
            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            // Always attempt to close distance
            var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);

            if (path != null)
            {
                actions.Add(new MoveAction(parent.EntityId, path[0]));
            }
            // Fire comically dense & inaccurate shotgun volley every 4 turns, and shotgun otherwise
            if (this.CurrentVolleyCooldown == 0)
            {
                actions.AddRange(FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 30, spread: 7, state.EncounterRand));
                actions.Add(FireProjectileAction.CreateSmallCannonAction(parent.EntityId, playerPos));
                this.CurrentVolleyCooldown += VolleyCooldown;
            }
            else
            {
                actions.AddRange(FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 2, spread: 1, state.EncounterRand));
                if (this.CurrentVolleyCooldown > 0)
                {
                    this.CurrentVolleyCooldown -= 1;
                }
            }

            return(actions);
        }
Exemple #6
0
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions          = new List <EncounterAction>();
            var parentPos        = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos        = state.Player.GetComponent <PositionComponent>().EncounterPosition;
            var distanceToPlayer = parentPos.DistanceTo(playerPos);

            // Only attempt to close distance if >=7 squares away
            if (distanceToPlayer >= 7f)
            {
                var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);
                if (path != null)
                {
                    actions.Add(new MoveAction(parent.EntityId, path[0]));
                }
            }

            // Always fire cannon
            actions.Add(FireProjectileAction.CreateSmallCannonAction(parent.EntityId, playerPos));

            // Fire railgun on cooldown (every 3rd turn)
            if (this.CurrentRailgunCooldown == 0)
            {
                actions.Add(FireProjectileAction.CreateRailgunAction(parent.EntityId, playerPos));
                this.CurrentRailgunCooldown += this.RailgunCooldown;
            }
            else if (this.CurrentRailgunCooldown > 0)
            {
                this.CurrentRailgunCooldown -= 1;
            }

            // If player is close and flak is off cooldown, fire
            if (distanceToPlayer <= 4 && this.CurrentFlakCooldown == 0)
            {
                actions.AddRange(FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 30, spread: 5, state.EncounterRand));
                this.CurrentFlakCooldown = this.FlakCooldown;
            }
            else if (this.CurrentFlakCooldown > 0)
            {
                this.CurrentFlakCooldown -= 1;
            }

            return(actions);
        }
Exemple #7
0
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions   = new List <EncounterAction>();
            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            // Always close distance
            var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);

            if (path != null)
            {
                actions.Add(new MoveAction(parent.EntityId, path[0]));
            }
            // Always fire
            actions.Add(FireProjectileAction.CreateSmallGatlingAction(parent.EntityId, playerPos));
            actions.Add(FireProjectileAction.CreateSmallGatlingAction(parent.EntityId, playerPos));
            actions.Add(FireProjectileAction.CreateSmallGatlingAction(parent.EntityId, playerPos));

            return(actions);
        }
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions   = new List <EncounterAction>();
            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            // Carrier never moves

            // Always launch randomly chosen strike craft - immediately paths one square to get it out of the carrier's square
            var chosenEntityDef = this.LaunchTable[state.EncounterRand.Next(3)];
            var strikeCraft     = EntityBuilder.CreateEnemyByEntityDefId(chosenEntityDef, this.ActivationGroupId, state.CurrentTick);

            actions.Add(new SpawnEntityAction(parent.EntityId, strikeCraft, parentPos, true));
            var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);

            // TODO: If you park adjacent the carrier, spawns will try to path literally into you and be stuck on the carrier square.
            // Won't crash anything it'll just put some error logs out and be deeply comical.
            if (path != null)
            {
                actions.Add(new MoveAction(strikeCraft.EntityId, path[0]));
            }

            // If player is close and flak is off cooldown, fire (comically this can, and will, friendly-fire its fighter wing)
            // TODO: friendly fire, maybe? It is a bit silly.
            if (parentPos.DistanceTo(playerPos) <= 4 && this.CurrentFlakCooldown == 0)
            {
                actions.AddRange(FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 30, spread: 5, state.EncounterRand));
                this.CurrentFlakCooldown = this.FlakCooldown;
            }
            else if (this.CurrentFlakCooldown > 0)
            {
                this.CurrentFlakCooldown -= 1;
            }

            return(actions);
        }
Exemple #9
0
        public override List <EncounterAction> _DecideNextAction(EncounterState state, Entity parent)
        {
            var actions = new List <EncounterAction>();

            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;
            var playerPos = state.Player.GetComponent <PositionComponent>().EncounterPosition;

            // Close distance if further than 5
            if (parentPos.DistanceTo(playerPos) >= 5f)
            {
                // TODO: We may want to make pathfinding stateful/cache it or something, to save on turn times
                var path = Pathfinder.AStarWithNewGrid(parentPos, playerPos, state);
                if (path != null)
                {
                    actions.Add(new MoveAction(parent.EntityId, path[0]));
                }
            }
            // Always fire shotgun (spread=2, pellets=3)
            var fire = FireProjectileAction.CreateSmallShotgunAction(parent.EntityId, playerPos, numPellets: 3, spread: 2, state.EncounterRand);

            actions.AddRange(fire);

            return(actions);
        }
Exemple #10
0
        /**
         * A zone is considered "explored" when:
         * 1: All storables have been found
         *   1a: If your inventory is not full, all storable items have been picked up
         * 2: All non-storable features have been seen
         *
         * Actual % of FoW revealed is not important. This is kinda cheaty, because it implies the autopilot knows intel for the
         * area, but also, who cares? It's fine. Likewise it doesn't factor into account having destroyed the enemies because if
         * there is an encounter, you'll definitely run into it!
         */
        private static bool ResolveAutopilotContinueExplore(EncounterState state)
        {
            var player          = state.Player;
            var playerComponent = player.GetComponent <PlayerComponent>();
            var playerPos       = player.GetComponent <PositionComponent>().EncounterPosition;
            var path            = playerComponent.AutopilotPath;

            var zone = state.GetZoneById(playerComponent.AutopilotZoneId);
            var nextUngottenStorable =
                zone.ReadoutItems.Concat(zone.ReadoutFeatures)
                .FirstOrDefault(i => state.GetEntityById(i.EntityId) != null &&
                                state.GetEntityById(i.EntityId).GetComponent <StorableComponent>() != null);
            // We rely on the fact that there's no ungettable features other than stairs, and that there's only one stair, to make this
            // work. If there were multiple ungettable features you'd want to put them into a list and autopilot between them so you
            // could cycle the 'x' button to find the one you want.
            var stairs = zone.ReadoutFeatures.FirstOrDefault(r =>
                                                             state.GetEntityById(r.EntityId).GetComponent <StairsComponent>() != null &&
                                                             state.GetEntityById(r.EntityId).GetComponent <PositionComponent>().EncounterPosition != playerPos
                                                             );

            if (PlayerSeesEnemies(state))
            {
                ResolveAction(new AutopilotEndAction(player.EntityId, AutopilotEndReason.ENEMY_DETECTED), state);
                return(false);
            } // If you are already on a path, progress on the path
            else if (path != null)
            {
                if (path.AtEnd)
                {
                    playerComponent.ClearAutopilotPath();
                    return(false);
                }
                else
                {
                    Rulebook.ResolveAction(new MoveAction(player.EntityId, path.Step()), state);
                    return(true);
                }
            } // If you're on top of a storable item, get it
            else if (state.EntitiesAtPosition(playerPos.X, playerPos.Y).Any(e => e.GetComponent <StorableComponent>() != null))
            {
                var nextStorable = state.EntitiesAtPosition(playerPos.X, playerPos.Y).First(e => e.GetComponent <StorableComponent>() != null);
                if (ResolveAction(new GetItemAction(player.EntityId), state))
                {
                    return(true);
                }
                else
                {
                    ResolveAction(new AutopilotEndAction(player.EntityId, AutopilotEndReason.INVENTORY_FULL), state);
                    return(false);
                }
            } // If there are any storable items, move towards them
            else if (nextUngottenStorable != null)
            {
                var nextPos   = state.GetEntityById(nextUngottenStorable.EntityId).GetComponent <PositionComponent>().EncounterPosition;
                var foundPath = Pathfinder.AStarWithNewGrid(playerPos, nextPos, state, 900);
                if (foundPath == null)
                {
                    ResolveAction(new AutopilotEndAction(player.EntityId, AutopilotEndReason.NO_PATH), state);
                    return(false);
                }
                else
                {
                    foundPath.Add(nextPos);
                    playerComponent.LayInAutopilotPathForExploration(new EncounterPath(foundPath));
                    return(true);
                }
            } // If this is the stairs zone, go to the stairs
            else if (stairs != null)
            {
                var nextPos   = state.GetEntityById(stairs.EntityId).GetComponent <PositionComponent>().EncounterPosition;
                var foundPath = Pathfinder.AStarWithNewGrid(playerPos, nextPos, state, 900);
                if (foundPath == null)
                {
                    ResolveAction(new AutopilotEndAction(player.EntityId, AutopilotEndReason.NO_PATH), state);
                    return(false);
                }
                else
                {
                    foundPath.Add(nextPos);
                    playerComponent.LayInAutopilotPathForExploration(new EncounterPath(foundPath));
                    return(true);
                }
            } // Otherwise you're done!
            else
            {
                ResolveAction(new AutopilotEndAction(player.EntityId, AutopilotEndReason.TASK_COMPLETED), state);
                return(false);
            }
        }