Ejemplo n.º 1
0
 public GameFormationActor(GameFormation f, IServiceProvider services)
     : base(services)
 {
     this.formation     = f;
     this.formationId   = f.FormationId;
     this.formationName = f.FormationName;
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Generates a <see cref="GameFormation"/> with a single <see cref="GameUnit"/> via <see cref="GenerateTestUnit"/>
        ///   and assigns a default, simple set of <see cref="VolleyOrders"/> to it for Volley 1; also assigns the new GameUnit
        ///   a set of <see cref="GameUnitFireAllocation"/> orders to match up with the <see cref="FireOrder"/>s.
        /// </summary>
        /// <param name="id">Desired ID of the new formation</param>
        /// <param name="name">Desired name of the new formation</param>
        /// <param name="unitList">Reference to a list of GameUnits, so that the Formation's new GameUnit can be added to it.</param>
        /// <param name="targetFormationId">Optionally, specify the ID of a target Formation for this Formation's Orders to specify. Default is 0.</param>
        /// <returns>The new Formation with included <see cref="GameUnitFormationInfo"/> for the new GameUnit. Side Effect: adds the new GameUnit to <paramref name="unitList"/></returns>
        public static GameFormation GenerateTestFormation(int id, string name, ref List <GameUnit> unitList, int targetFormationId = 0)
        {
            GameUnit u = GenerateTestUnit(id: 1, name: $"{name}-1");

            unitList.Add(u);

            var f = new GameFormation()
            {
                FormationId   = id,
                FormationName = name,
                MaxThrust     = 99,
                Orders        = new List <VolleyOrders>(),
                PlayerId      = 0,
            };

            f.Units = new List <GameUnitFormationInfo>()
            {
                new GameUnitFormationInfo(u, f)
            };

            var fOrder = new VolleyOrders()
            {
                Volley       = 1,
                EvasionDice  = 2,
                SpeedDice    = 4,
                FiringOrders = new List <FireOrder>()
                {
                    new FireOrder()
                    {
                        TargetID            = targetFormationId,
                        FireType            = "Normal",
                        Priority            = "Primary",
                        TargetFormationName = string.Empty,
                        DiceAssigned        = 0
                    }
                },
                ManeuveringOrders = new List <ManeuverOrder>()
                {
                    new ManeuverOrder()
                    {
                        TargetID     = targetFormationId,
                        ManeuverType = "Close",
                        Priority     = "Primary"
                    }
                }
            };

            u.FireAllocation = new List <GameUnitFireAllocation>()
            {
                new GameUnitFireAllocation(volley: 1, fireConId: u.Electronics.OfType <FireControlSystem>().First().Id, fireMode: "Normal", priority: "Primary", weaponIds: u.Weapons.Select(w => w.Id).ToList())
            };

            f.Orders.Add(fOrder);

            return(f);
        }
        private static List <string> GenerateOrdersReadout(GameFormation f, List <GameUnit> allUnits, List <GameFormation> formations)
        {
            List <string> readout = new List <string>();

            foreach (var volleyOrder in f.Orders)
            {
                readout.AddRange(WrapDecorated(volleyOrder.ToString(), ReadoutWidth, "* ", " *", 5));
                readout.AddRange(PrintReadoutCollection(string.Empty, volleyOrder.ManeuveringOrders, true));

                foreach (var fire in volleyOrder.FiringOrders)
                {
                    var leadString      = itemLeadString;
                    var fireOrderString = ToTitleCase($"{fire.FireType} Order: '{fire.Priority}' -- Target: [{fire.TargetID}] {fire.TargetFormationName}{(fire.DiceAssigned > 0 ? $" ({fire.DiceAssigned}D)" : string.Empty)}");
                    readout.AddRange(WrapDecorated(fireOrderString, ReadoutWidth, itemLeadString, " *", 5));
                    foreach (var unit in f.Units)
                    {
                        var unitForOrder = allUnits.FirstOrDefault(x => x.IdNumeric == unit.UnitId);
                        if (unitForOrder != null)
                        {
                            var unitOrderFireAllocations = unitForOrder.FireAllocation.Where(fireAlloc => (fireAlloc.Volley == volleyOrder.Volley || fireAlloc.Volley == 0) && fireAlloc.Priority.ToLowerInvariant() == fire.Priority.ToLowerInvariant());
                            foreach (var allocation in unitOrderFireAllocations)
                            {
                                var fc = unitForOrder.AllSystems.FirstOrDefault(afc => afc.Id == allocation.FireConId) ?? new FireControlSystem()
                                {
                                    Status = UnitSystemStatus.Operational
                                };

                                // TODO: BUG: reporting "Operational" even for damaged FireCon sometimes, see default XML: ANS Glory, Volley 2, Secondary / FireCon ID 6 should be Damaged
                                var line = new List <string>()
                                {
                                    $">     {unit.UnitName} -- FC{fc.Id}({fc.StatusString})"
                                };
                                foreach (var w in allocation.WeaponIDs)
                                {
                                    var wep = unitForOrder.Weapons.First(uw => uw.Id == w);
                                    line.Add($">>     {wep.ToString()}");
                                }

                                readout.AddRange(PrintReadoutCollection(string.Empty, line, true));
                            }
                        }
                    }
                }
            }

            return(readout);
        }
        private static List <string> GenerateFormationReadout(GameFormation f, List <GameUnit> allUnits, List <GamePlayer> players)
        {
            var readout = new List <string>();

            var player = players.Where(p => p.Id == f.PlayerId.ToString()).FirstOrDefault() ?? new GamePlayer()
            {
                Name = "Unknown Player"
            };

            var playerStrings = new List <string>()
            {
                $"Player {player.Id}",
                player.Team,
                (player.Key <= 0 ? player.Name : $"{player.Name} [{player.Key}]"),
                player.Email,
                string.IsNullOrWhiteSpace(player.Objectives) ? null : $"\"{player.Objectives}\""
            }.Where(s => !string.IsNullOrWhiteSpace(s));

            readout.AddRange(WrapDecorated(string.Join(" -- ", playerStrings), ReadoutWidth, "* ", " *", 5));

            readout.AddRange(WrapDecorated($"Area Screen Rating '{f.GetFormationAreaScreenRating()}'", ReadoutWidth, "* ", " *"));
            readout.AddRange(WrapDecorated($"MaxThrust '{f.MaxThrust}'", ReadoutWidth, "* ", " *"));
            readout.AddRange(WrapDecorated($"Units ({f.Units.Count})", ReadoutWidth, "* ", " *"));
            foreach (var u in f.Units)
            {
                var uR         = allUnits.Where(ur => ur.IdNumeric == u.UnitId).First();
                var unitString = $"- {uR.ToString()} ({uR.Status}) -- Thrust {uR.GetCurrentThrust()}";
                if (uR.GetCurrentThrust() > f.MaxThrust)
                {
                    unitString += $" ({f.MaxThrust}+{u.ExtraThrust})";
                }

                if (u.IsFormationFlag)
                {
                    unitString += $" -- Flagship";
                }

                unitString += $" -- HitChance {f.GetHitChancePercentage(u.UnitId):0.##}%";

                readout.AddRange(WrapDecorated(unitString, ReadoutWidth, "*   ", " *", 5));

                readout.AddRange(PrintReadoutCollection("Fire Allocations", uR.FireAllocation));
            }

            return(readout);
        }
        private static void ExecuteManeuversForFormation(int currentVolley, GameFormation f, GameState gameState)
        {
            VolleyOrders orders = f.GetOrdersForVolley(currentVolley);

            foreach (var o in orders.GetSortedManeuveringOrders())
            {
                var target = gameState.Formations.Where(t => t.FormationId == o.TargetID).FirstOrDefault();

                var speed = Math.Max(0, orders.SpeedSuccesses + ManeuverOrder.GetManeuverModifier(o.Priority));

                if (target == null || o.ManeuverType == Constants.PassiveManeuverType)
                {
                    // Bail early if the maneuver is a passive one, e.g. "Maintain"
                    // Bail early if the maneuver is not against a valid target Id (e.g. "Target 0" default orders or orders against Formations that have been destroyed)
                    continue;
                }

                int rangeShift = o.CalculateRangeShift(currentVolley, f, orders.SpeedSuccesses, target);
                gameState.DistanceGraph.UpdateDistance(f, target, rangeShift);
            }
        }
Ejemplo n.º 6
0
        protected override IList <GameEvent> ReceiveWeaponAttackEvent(GameEvent arg)
        {
            var result = new List <GameEvent>();

            var evt = arg as WeaponAttackEvent ??
                      throw ReceiverArgumentMismatch(nameof(arg), arg.GetType(), MethodBase.GetCurrentMethod().Name, typeof(AttackEvent));

            // Unit receives event if:
            // a) WeaponAttack is assigned to this Unit's Formation
            // b) Attack's percentile roll is within this Unit's PercentileRange
            if (evt.TargetingData.Target.FormationId == this.unitFormationInfo.FormationId &&
                this.unitFormationInfo.CoversPercentile(evt.UnitAssignmentPercentile))
            {
                var           target          = evt.TargetingData.Target.UnitActor.unitFormationInfo;
                GameFormation targetFormation = target.GetFormationReference();
                GameUnit      targetUnit      = target.GetUnitReference();

                GameFormation attackerFormation = this.unitFormationInfo.GetFormationReference();
                GameUnit      attackerUnit      = this.unitFormationInfo.GetUnitReference();
                int           firingRange       = evt.TargetingData.FormationRange;

                result.Add(new UnitStatusEvent()
                {
                    Description = $"UnitStatus: [{this.UnitId}]{this.UnitName}",
                    Message     = $"[{targetFormation.FormationId}]{targetFormation.FormationName}:[{targetUnit.IdNumeric}]{targetUnit.Name}"
                                  + $" covers percentile range {this.unitFormationInfo.PercentileLowerBound}-{this.unitFormationInfo.PercentileUpperBound},"
                                  + $" so incoming attack with percentile roll {evt.UnitAssignmentPercentile} targets it.",
                    Exchange = evt.Exchange,
                    Volley   = evt.Volley
                });

                WeaponSystem weapon = evt.AttackData.Weapon;

                // TODO: Add ability to override this from AttackData and/or TargetingData?
                Constants.DamageType effectiveDamageType = weapon.GetDamageType();

                int evasionDRM = -1 * targetFormation.GetOrdersForVolley(evt.Volley).EvasionSuccesses;

                int otherDRM = targetFormation.GetDRMVersusWeaponType(weapon.GetType())
                               + targetUnit.GetDRMVersusWeaponType(weapon.GetType());

                var localScreens = targetUnit.GetLocalScreenRating();
                var areaScreens  = targetFormation.GetFormationAreaScreenRating();

                ScreenRating totalScreenRating = ScreenRating.Combine(localScreens, areaScreens);

                DamageResult weaponAttackResult = this.ResolveWeaponAttack(weapon, firingRange, totalScreenRating, evasionDRM, otherDRM);

                var statusMsg = $"[{attackerUnit.IdNumeric}]{attackerUnit.Name} fires [{weapon.Id}]{weapon.SystemName} at [{targetUnit.IdNumeric}]{targetUnit.Name}"
                                + $"\n\t\t -- Net modifiers: Range {firingRange}"
                                + $", Screen {weapon.FinalizeScreenValue(totalScreenRating)}"
                                + $", Evasion DRM {weapon.FinalizeEvasionDRM(evasionDRM)}"
                                + $", Other DRM {otherDRM}"
                                + $"\n\t\t -- Rolls {weaponAttackResult.RollString()}"
                                + $"\n\t\t -- Deals {weaponAttackResult.ToString()}";

                result.Add(new UnitStatusEvent()
                {
                    Description = $"UnitStatus: [{this.UnitId}]{this.UnitName}",
                    Message     = statusMsg,
                    Exchange    = evt.Exchange,
                    Volley      = evt.Volley
                });
            }

            return(result);
        }