Esempio n. 1
0
        // This is actually much more like unit broken but oh well!
        public static List <EncounterAction> ActionsForUnitRetreat(EncounterState state, Entity parent, Unit unit)
        {
            var parentPos = parent.GetComponent <PositionComponent>().EncounterPosition;

            EncounterPosition targetEndPos = parentPos;
            var backwardsPositions         = new List <EncounterPosition>()
            {
                AIUtils.RotateAndProject(parentPos, 0, 1, unit.UnitFacing),
                AIUtils.RotateAndProject(parentPos, 1, 1, unit.UnitFacing),
                AIUtils.RotateAndProject(parentPos, -1, 1, unit.UnitFacing),
            };

            GameUtils.Shuffle(state.EncounterRand, backwardsPositions);
            foreach (var position in backwardsPositions)
            {
                if (state.EntitiesAtPosition(position.X, position.Y).Count == 0)
                {
                    targetEndPos = position;
                    break;
                }
            }
            if (targetEndPos == parentPos)
            {
                targetEndPos = backwardsPositions[0];
            }
            return(new List <EncounterAction>()
            {
                new MoveAction(parent.EntityId, targetEndPos)
            });
        }
Esempio n. 2
0
        private List <EncounterAction> MoveAndAttack(EncounterState state, int dx, int dy)
        {
            var positionComponent = state.Player.GetComponent <PositionComponent>();
            var oldPos            = positionComponent.EncounterPosition;
            var newPos            = new EncounterPosition(oldPos.X + dx, oldPos.Y + dy);

            // TODO: maybe not hostile?
            var hostiles = AIUtils.HostilesInPosition(state, FactionName.PLAYER, newPos.X, newPos.Y);

            if (hostiles.Count > 0)
            {
                var attackAction = new MeleeAttackAction(state.Player.EntityId, hostiles[state.EncounterRand.Next(hostiles.Count)]);
                return(new List <EncounterAction>()
                {
                    attackAction
                });
            }
            else
            {
                var moveAction = new MoveAction(state.Player.EntityId, newPos);
                return(new List <EncounterAction>()
                {
                    moveAction
                });
            }
        }
Esempio n. 3
0
        public static bool IsPositionTooFarBehind(EncounterPosition position, Unit unit)
        {
            var behindVec = AIUtils.VectorFromCenterRotated(unit.AveragePosition, position.X, position.Y, unit.UnitFacing);

            // This can't be too restrictive or it stops you from sitting at the back of the line when rotating.
            return(behindVec.Item2 > -Mathf.CeilToInt(unit.Depth / 2) + 5);
        }
Esempio n. 4
0
        public static Tuple <int, int> VectorFromCenterRotated(EncounterPosition center, int tx, int ty, FormationFacing facing)
        {
            int dx = tx - center.X;
            int dy = ty - center.Y;

            return(ToNorthCoordinates(dx, dy, facing));
        }
Esempio n. 5
0
        public static bool IsNextRowTooFarAhead(EncounterPosition parentPos, Unit unit)
        {
            var directlyInFrontPosition = AIUtils.RotateAndProject(parentPos, 0, -1, unit.UnitFacing);
            var forwardVec = AIUtils.VectorFromCenterRotated(unit.AveragePosition, directlyInFrontPosition.X, directlyInFrontPosition.Y, unit.UnitFacing);

            return(forwardVec.Item2 < -Mathf.CeilToInt(unit.Depth / 2) - 1);
        }
Esempio n. 6
0
        private bool ShouldHighlightEntity(EncounterState state, Entity entity, EncounterPosition entityPos, int nextPlayerTick)
        {
            var aiComponent = entity.GetComponent <AIComponent>();

            return(aiComponent != null &&
                   !(aiComponent is PathAIComponent) &&
                   state.FoVCache.IsVisible(entityPos) &&
                   entity.GetComponent <ActionTimeComponent>().NextTurnAtTick < nextPlayerTick);
        }
Esempio n. 7
0
        public override EncounterPosition PositionInFormation(int formationNumber, Unit unit)
        {
            EncounterPosition center = unit.RallyPoint;

            int dx = formationNumber % 10;
            int dy = Mathf.FloorToInt(formationNumber / 10) - 1;
            Tuple <int, int> rotated = AIUtils.RotateForFormation(dx, dy, unit.UnitFacing);

            return(new EncounterPosition(center.X + rotated.Item1, center.Y + rotated.Item2));
        }
Esempio n. 8
0
 public static FireProjectileAction CreateRailgunAction(string actorId, EncounterPosition targetPosition)
 {
     return(new FireProjectileAction(
                actorId,
                ProjectileType.RAILGUN,
                power: 15,
                (sourcePos) => EncounterPathBuilder.BuildStraightLinePath(sourcePos, targetPosition, maxSteps: 40),
                speed: 20
                ));
 }
Esempio n. 9
0
 public static FireProjectileAction CreateReverserAction(string actorId, EncounterPosition targetPosition)
 {
     return(new FireProjectileAction(
                actorId,
                ProjectileType.REVERSER,
                power: 2,
                (sourcePos) => EncounterPathBuilder.BuildReverseLinePath(sourcePos, targetPosition, overshoot: 4),
                speed: 33
                ));
 }
Esempio n. 10
0
 private static FireProjectileAction CreateSmallShotgunAction(string actorId, EncounterPosition targetPosition)
 {
     return(new FireProjectileAction(
                actorId,
                ProjectileType.SMALL_SHOTGUN,
                power: 1,
                (sourcePos) => EncounterPathBuilder.BuildStraightLinePath(sourcePos, targetPosition, maxSteps: 25),
                speed: 25
                ));
 }
Esempio n. 11
0
 public static FireProjectileAction CreateSmallGatlingAction(string actorId, EncounterPosition targetPosition)
 {
     return(new FireProjectileAction(
                actorId,
                ProjectileType.SMALL_GATLING,
                power: 2,
                (sourcePos) => EncounterPathBuilder.BuildStraightLinePath(sourcePos, targetPosition, maxSteps: 25),
                speed: 50
                ));
 }
Esempio n. 12
0
 public Lane(int laneIdx, EncounterPosition laneCenter)
 {
     this.LaneIdx          = laneIdx;
     this.LaneCenter       = laneCenter;
     this._UnitsForFaction = new Dictionary <FactionName, List <UnitAtLanePosition> >()
     {
         { FactionName.ENEMY, new List <UnitAtLanePosition>() },
         { FactionName.NEUTRAL, new List <UnitAtLanePosition>() },
         { FactionName.PLAYER, new List <UnitAtLanePosition>() }
     };
 }
Esempio n. 13
0
        private static void TryAddAttackAdjacent(EncounterState state, Entity parent, List <EncounterAction> actions,
                                                 FactionName parentFaction, EncounterPosition targetEndPos)
        {
            var adjacentHostiles = AIUtils.AdjacentHostiles(state, parentFaction, targetEndPos);

            if (adjacentHostiles.Count > 0)
            {
                // TODO: don't attack randomly
                var target = adjacentHostiles[state.EncounterRand.Next(adjacentHostiles.Count)];
                actions.Add(new MeleeAttackAction(parent.EntityId, target));
            }
        }
Esempio n. 14
0
        private Label CreateLabel(int power, EncounterPosition position)
        {
            var label = new Label();

            label.Text = power.ToString();
            var numCenterPos = PositionComponent.IndexToVector(position.X, position.Y);

            label.AddFontOverride("font", this._damageFont);
            label.AddColorOverride("font_color", new Color(1f, 0f, 0f));
            // The size isn't determined until after it's first placed, so we place, then reposition according to size to center it.
            label.SetPosition(numCenterPos);
            var size = label.RectSize;

            label.SetPosition(new Vector2(numCenterPos.x - size.x / 2, numCenterPos.y - size.y / 2));
            return(label);
        }
Esempio n. 15
0
        private bool positionNotTooFarAheadAndMovable(EncounterState state, EncounterPosition parentPos, Unit unit, EncounterPosition possible)
        {
            var entitiesAtPos = state.EntitiesAtPosition(possible.X, possible.Y);

            if (!AIUtils.IsNextRowTooFarAhead(parentPos, unit) && entitiesAtPos.Count == 0)
            {
                return(true);
            }

            var hostilesAtPos = AIUtils.HostilesInPosition(state, FactionName.PLAYER, possible.X, possible.Y);

            if (hostilesAtPos.Count > 0)
            {
                return(true);
            }

            return(false);
        }
Esempio n. 16
0
        public static FoVCache ComputeFoV(EncounterState state, EncounterPosition center, int radius)
        {
            int _x = center.X - radius;
            int _y = center.Y - radius;

            bool[,] visibleCells = new bool[radius * 2 + 1, radius * 2 + 1];

            var visible = rpasCalc.CalcVisibleCellsFrom(center.X, center.Y, radius, state.IsPositionVisible);

            foreach ((int, int)pos in visible)
            {
                if (state.IsInBounds(pos.Item1, pos.Item2))
                {
                    visibleCells[pos.Item1 - _x, pos.Item2 - _y] = true;
                }
            }

            return(new FoVCache(_x, _y, visibleCells));
        }
Esempio n. 17
0
        public string ToCardinalDirection(EncounterPosition parentPos, EncounterPosition adjacentPos)
        {
            int dx = adjacentPos.X - parentPos.X;
            int dy = adjacentPos.Y - parentPos.Y;

            if (dx == 0 && dy == -1)
            {
                return(InputHandler.ActionMapping.MOVE_N);
            }
            else if (dx == 1 && dy == -1)
            {
                return(InputHandler.ActionMapping.MOVE_NE);
            }
            else if (dx == 1 && dy == 0)
            {
                return(InputHandler.ActionMapping.MOVE_E);
            }
            else if (dx == 1 && dy == 1)
            {
                return(InputHandler.ActionMapping.MOVE_SE);
            }
            else if (dx == 0 && dy == 1)
            {
                return(InputHandler.ActionMapping.MOVE_S);
            }
            else if (dx == -1 && dy == 1)
            {
                return(InputHandler.ActionMapping.MOVE_SW);
            }
            else if (dx == -1 && dy == 0)
            {
                return(InputHandler.ActionMapping.MOVE_W);
            }
            else if (dx == -1 && dy == -1)
            {
                return(InputHandler.ActionMapping.MOVE_NW);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Esempio n. 18
0
        public override EncounterPosition PositionInFormation(int formationNumber, Unit unit)
        {
            EncounterPosition center = unit.RallyPoint;
            int halfFormation        = unit.NumInFormation / 2 + 1;

            if (formationNumber < halfFormation)
            {
                int dx      = formationNumber % 10;
                int dy      = Mathf.FloorToInt(formationNumber / 10) - 1;
                var rotated = AIUtils.RotateForFormation(dx, dy, unit.UnitFacing);
                return(new EncounterPosition(center.X + rotated.Item1, center.Y + rotated.Item2));
            }
            else
            {
                int dx      = formationNumber % 10 - 10;
                int dy      = Mathf.FloorToInt((formationNumber - halfFormation) / 10) - 1;
                var rotated = AIUtils.RotateForFormation(dx, dy, unit.UnitFacing);
                return(new EncounterPosition(center.X + rotated.Item1, center.Y + rotated.Item2));
            }
        }
Esempio n. 19
0
 public SpawnEntityAction(string spawnerId, Entity entityToSpawn, EncounterPosition position, bool ignoreCollision) : base(spawnerId, ActionType.SPAWN_ENTITY)
 {
     this.EntityToSpawn   = entityToSpawn;
     this.Position        = position;
     this.IgnoreCollision = ignoreCollision;
 }
Esempio n. 20
0
 // Last 5 items are "retreat zone" - TODO: color them yellow, or something
 private static bool IsInRetreatZone(EncounterState state, EncounterPosition position)
 {
     return(!(5 <= position.X && state.MapWidth - 5 >= position.X && 5 <= position.Y && state.MapHeight - 5 >= position.Y));
 }
Esempio n. 21
0
        /**
         * Fires a spread of shotgun pellets in a box formation around the centerpoint. Spread is half the width/height of the box.
         */
        public static List <FireProjectileAction> CreateSmallShotgunAction(string actorId, EncounterPosition targetPosition, int numPellets, int spread, Random seededRand)
        {
            if (spread == 0)
            {
                throw new NotImplementedException("shotguns can't have 0 spread what is this");
            }

            List <FireProjectileAction> pellets = new List <FireProjectileAction>();

            for (int i = 0; i < numPellets; i++)
            {
                var dx = seededRand.Next(spread * 2 + 1) - spread;
                var dy = seededRand.Next(spread * 2 + 1) - spread;
                pellets.Add(CreateSmallShotgunAction(actorId, new EncounterPosition(targetPosition.X + dx, targetPosition.Y + dy)));
            }

            return(pellets);
        }
Esempio n. 22
0
 public bool IsVisible(EncounterPosition position)
 {
     return(this.IsVisible(position.X, position.Y));
 }
Esempio n. 23
0
        public static void PopulateStateForLevel(Entity player, int dungeonLevel, EncounterState state, Random seededRand,
                                                 int width = 300, int height = 300, int maxZoneGenAttempts = 100)
        {
            InitializeMapAndAddBorderWalls(state, width, height);

            // Place each empty zone onto the map
            int zoneGenAttemps         = 0;
            List <EncounterZone> zones = new List <EncounterZone>();

            while (zoneGenAttemps < maxZoneGenAttempts && zones.Count < LevelData.GetNumberOfZones(dungeonLevel))
            {
                int zoneWidth  = seededRand.Next(ZONE_MIN_SIZE, ZONE_MAX_SIZE + 1);
                int zoneHeight = seededRand.Next(ZONE_MIN_SIZE, ZONE_MAX_SIZE + 1);
                int zoneX      = seededRand.Next(1, state.MapWidth - zoneWidth);
                int zoneY      = seededRand.Next(1, state.MapHeight - zoneHeight);

                var newZone = new EncounterZone(Guid.NewGuid().ToString(), new EncounterPosition(zoneX, zoneY), zoneWidth, zoneHeight,
                                                "Zone " + zones.Count.ToString());

                bool overlaps = zones.Any(existing => existing.Intersects(newZone));
                if (!overlaps)
                {
                    zones.Add(newZone);
                }
            }
            state._zones = zones;

            // Add the player to the map
            var playerZoneIdx = seededRand.Next(0, zones.Count);

            state.PlaceEntity(player, zones[playerZoneIdx].Center);

            /*
             * var nextToPlayer = new EncounterPosition(zones[playerZoneIdx].Center.X + 2, zones[playerZoneIdx].Center.Y + 1);
             * state.PlaceEntity(EntityBuilder.CreateItemByEntityDefId(EntityDefId.ITEM_RED_PAINT), nextToPlayer);
             * nextToPlayer = new EncounterPosition(zones[playerZoneIdx].Center.X + 1, zones[playerZoneIdx].Center.Y + 1);
             * state.PlaceEntity(EntityBuilder.CreateItemByEntityDefId(EntityDefId.ITEM_EMP), nextToPlayer);
             * for (int i = 0; i < 26; i++) {
             * nextToPlayer = new EncounterPosition(zones[playerZoneIdx].Center.X + i, zones[playerZoneIdx].Center.Y + 3);
             * state.PlaceEntity(EntityBuilder.CreateItemByEntityDefId(EntityDefId.ITEM_EXTRA_BATTERY), nextToPlayer);
             * }
             */

            var nextToPlayer = new EncounterPosition(zones[playerZoneIdx].Center.X + 2, zones[playerZoneIdx].Center.Y + 2);

            //string[] defs = new string[] { EntityDefId.SCOUT, EntityDefId.FIGHTER, EntityDefId.GUNSHIP, EntityDefId.FRIGATE, EntityDefId.DESTROYER, EntityDefId.CRUISER, EntityDefId.CARRIER, EntityDefId.DIPLOMAT };
            string[] defs = new string[] { EntityDefId.ITEM_DUCT_TAPE, EntityDefId.ITEM_EMP, EntityDefId.ITEM_EXTRA_BATTERY, EntityDefId.ITEM_RED_PAINT };
            for (int x = 0; x < defs.Length; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    var pos = new EncounterPosition(nextToPlayer.X + x, nextToPlayer.Y + y);
                    //state.PlaceEntity(EntityBuilder.CreateEnemyByEntityDefId(defs[x], "12345", 0), pos, ignoreCollision: true);
                    state.PlaceEntity(EntityBuilder.CreateItemByEntityDefId(defs[x]), pos, ignoreCollision: true);
                }
            }

            // Add all the various zone features to the map
            // TODO: Draw this from LevelData instead of literally special-casing level 10 here
            if (dungeonLevel != 10)
            {
                // Generate the stairs (maybe we should refer interally as something more themetically appropriate?)
                // You can get stairs in your starting zone, but you probably shouldn't take them...
                // var stairsZone = zones[playerZoneIdx]; // For testing
                var stairsZone     = zones[seededRand.Next(0, zones.Count)];
                var stairsPosition = stairsZone.RandomEmptyPosition(seededRand, state);
                var stairs         = EntityBuilder.CreateStairsEntity();
                state.PlaceEntity(stairs, stairsPosition);
                stairsZone.AddFeatureToReadout(stairs);

                // Generate intel
                // var intelZone = zones[playerZoneIdx]; // For testing
                var intelZone     = zones[seededRand.Next(0, zones.Count)];
                var intelPosition = intelZone.RandomEmptyPosition(seededRand, state);
                var intel         = EntityBuilder.CreateIntelEntity(dungeonLevel + 1);
                state.PlaceEntity(intel, intelPosition);
                intelZone.AddFeatureToReadout(intel);
            }

            // Populate each zone with an encounter
            foreach (EncounterZone zone in zones)
            {
                if (zone == zones[playerZoneIdx])
                {
                    PopulateZone(zone, dungeonLevel, seededRand, state, safe: true);
                }
                else
                {
                    PopulateZone(zone, dungeonLevel, seededRand, state);
                }
            }
        }
Esempio n. 24
0
 private static EncounterPosition _DecideFormationPosition(int formationNumber, EncounterPosition center, Unit unit)
 {
     return(AIUtils.FormationDictionary[unit.UnitFormation].PositionInFormation(formationNumber, unit));
 }
Esempio n. 25
0
 public MoveAction(string actorId, EncounterPosition targetPosition) : base(actorId, ActionType.MOVE)
 {
     TargetPosition = targetPosition;
 }
Esempio n. 26
0
        public static List <Entity> AdjacentHostiles(EncounterState state, FactionName parentFaction, EncounterPosition position)
        {
            var adjacentHostiles = new List <Entity>();

            foreach (var newpos in state.AdjacentPositions(position))
            {
                adjacentHostiles.AddRange(AIUtils.HostilesInPosition(state, parentFaction, newpos.X, newpos.Y));
            }
            return(adjacentHostiles);
        }
Esempio n. 27
0
 public static FireProjectileAction CreateCuttingLaserAction(string playerId, int playerPower, EncounterPosition targetPosition)
 {
     return(new FireProjectileAction(
                playerId,
                ProjectileType.CUTTING_LASER,
                power: playerPower,
                (sourcePos) => EncounterPathBuilder.BuildStraightLinePath(sourcePos, targetPosition, endsAtTarget: true),
                speed: 0
                ));
 }
Esempio n. 28
0
        public static EncounterPosition RotateAndProject(EncounterPosition origin, int x, int y, FormationFacing facing)
        {
            var vec = Rotate(x, y, facing);

            return(new EncounterPosition(origin.X + vec.Item1, origin.Y + vec.Item2));
        }