Exemple #1
0
        private static ActionChosen AICombatActionMeleeOnly(EcsRegistrar rgs, long globalId, long attackerId, List <long> battlefieldEntityIds)
        {
            var action = new ActionChosen {
                Action = Vals.CombatAction.DoNothing, AgentId = attackerId
            };

            var naturalWeaponsMap = rgs.GetPartSingle <Parts.NaturalWeaponsMap>(globalId);

            var targetIdsToWeights = battlefieldEntityIds
                                     .Select(id => new { Id = id, Agent = rgs.GetPartSingleOrDefault <Parts.Agent>(id) })
                                     .Where(a => a.Id != attackerId && a.Agent != null && !Vals.CombatStatusTag.CombatTerminalStatuses.Intersect(a.Agent.CombatStatusTags).Any())
                                     .ToDictionary(a => a.Id, a => 0);

            var attackerFaction     = rgs.GetPartSingle <Parts.Faction>(attackerId);
            var factionInteractions = rgs.GetPartSingle <Parts.FactionInteractionSet>(globalId);

            //eventually we have to figure out how to weight faction relative to everything else.
            var possibleTargetIds = targetIdsToWeights.Keys.ToArray();

            foreach (var possibleTargetId in possibleTargetIds)
            {
                var targetFaction = rgs.GetPartSingle <Parts.Faction>(possibleTargetId);
                targetIdsToWeights[possibleTargetId] = factionInteractions.Interactions
                                                       .SingleOrDefault(i => i.SourceFaction == attackerFaction.CurrentPublicFaction && i.TargetFaction == targetFaction.CurrentPublicFaction)
                                                       ?.Disposition ?? 0;
            }

            var minWeight = targetIdsToWeights.Values.Any() ? targetIdsToWeights.Values.Min() : 0;

            if (minWeight < 0)
            {
                var targetId = targetIdsToWeights.First(kvp => kvp.Value == minWeight).Key;

                var attackerAnatomy = rgs.GetPartSingle <Parts.Anatomy>(attackerId);

                //MWCTODO++: yaaaah this is way too human centric.
                var weaponId = attackerAnatomy.SlotsEquipped.GetValueOrDefault(Vals.BodySlots.WieldHandRight, 0);
                if (weaponId == 0)
                {
                    weaponId = attackerAnatomy.SlotsEquipped.GetValueOrDefault(Vals.BodySlots.WieldHandLeft, 0);
                }

                if (weaponId == 0)
                {
                    var nwmap = naturalWeaponsMap.NaturalWeaponSets.GetValueOrDefault(attackerAnatomy.NaturalWeaponsCategory, null);

                    if (nwmap != null && nwmap.Keys.Any())
                    {
                        //MWCTODO: and this isn't great.
                        weaponId = nwmap.First().Value;
                    }
                }

                action.Action         = Vals.CombatAction.AttackWeaponMelee;
                action.TargetEntityId = targetId;
                action.WeaponEntityId = weaponId;
            }

            return(action);
        }
        internal static IEnumerable <List <Output> > RunBattlefield(EcsRegistrar rgs, long globalId, long battlefieldId, Func <CombatChoicesAndTargets, ActionChosen> receivePlayerInput)
        {
            while (true)
            {
                var battlefieldContainer = rgs.GetPartSingle <Parts.Container>(battlefieldId);
                var battlefieldEntityIds = battlefieldContainer.EntityIds.ToList();

                foreach (var agentId in battlefieldEntityIds)
                {
                    var battlefieldAgent = rgs.GetPartSingleOrDefault <Parts.Agent>(agentId);

                    if (battlefieldAgent == null)
                    {
                        continue;
                    }
                    if (battlefieldAgent.CombatStatusTags.Intersect(Vals.CombatStatusTag.CombatTerminalStatuses).Any())
                    {
                        continue;
                    }

                    ActionChosen agentActionChosen;
                    if (battlefieldAgent.ActiveCombatAI == Vals.AI.PlayerChoice)
                    {
                        var possibleActions = Agent.GetPossibleActions(rgs, globalId, agentId, battlefieldEntityIds);
                        agentActionChosen = receivePlayerInput(possibleActions);
                    }
                    else
                    {
                        agentActionChosen = Agent.GetAgentAICombatAction(rgs, globalId, battlefieldAgent.ActiveCombatAI, agentId, battlefieldEntityIds);
                    }

                    var results = Combat.ProcessAgentAction(rgs, agentId, agentActionChosen);

                    var output = Narrator.OutputForCombatMessages(rgs, results);

                    yield return(output);
                }

                var endOfBattleOutputs = GetEndOfBattleOutputs(rgs, battlefieldEntityIds);
                if (endOfBattleOutputs.Any())
                {
                    yield return(endOfBattleOutputs);

                    yield break;
                }
            }
        }
Exemple #3
0
        public static CombatChoicesAndTargets GetPossibleActions(EcsRegistrar rgs, long globalId, long agentId, List <long> battlefieldEntityIds)
        {
            var possibleCombatActions = new CombatChoicesAndTargets();

            var naturalWeaponsMap = rgs.GetPartSingle <Parts.NaturalWeaponsMap>(globalId);

            var agentAnatomy = rgs.GetPartSingle <Parts.Anatomy>(agentId);

            //var agentWieldingDisabled = agentAnatomyModifers
            //    .Where(m => m.EquipmentSlotDisabled == Vals.BodyEquipmentSlots.WieldObjectAppendage)
            //    .Select(m => m.EquipmentSlotDisabled)
            //    .ToList();

            var agentWieldedIds = agentAnatomy.SlotsEquipped
                                  .Where(s => s.Key == Vals.BodySlots.WieldHandLeft || s.Key == Vals.BodySlots.WieldHandRight || s.Key == Vals.BodySlots.WieldTwoHanded)
                                  .Select(s => s.Value)
                                  .ToList();
            var agentWieldedIdToWeaponEntityName = agentWieldedIds
                                                   .Where(id => id != 0)
                                                   .Distinct()
                                                   .Select(id => new { Id = id, Name = rgs.GetPartSingle <Parts.EntityName>(id) })
                                                   .ToDictionary(n => n.Id, n => n.Name);

            var agentNaturalWeaponSlots = naturalWeaponsMap.NaturalWeaponSets[agentAnatomy.NaturalWeaponsCategory];
            //MWCTODO: some magic happens here and we find out a wristblade or a laser eye has been equipped, and add that to the slots.
            // also any quickslots that might have attack items in them. we want quickslots. maybe a wristblade or a laser eye automatically adds a new, fixed quickslot for itself? i like this idea upon first think!
            var recordedIds = new HashSet <long>();

            foreach (var slot in agentNaturalWeaponSlots.Keys)
            {
                var weaponId = agentAnatomy.SlotsEquipped[slot];
                if (weaponId == 0L)
                {
                    weaponId = agentNaturalWeaponSlots[slot];
                }

                if (recordedIds.Contains(weaponId))
                {
                    continue;
                }

                var weapon = Bundle.GetWeaponBundle(rgs, weaponId);
                var choice = new AgentActionChoice
                {
                    AgentId        = agentId,
                    Category       = Vals.CombatCategory.TopLevelAction,
                    Description    = $"Melee {weapon.EntityName.GeneralName}",
                    Action         = Vals.CombatAction.AttackWeaponMelee,
                    WeaponBodySlot = slot,
                    WeaponEntityId = weaponId,
                    NextCategory   = Vals.CombatCategory.MeleeTarget
                };

                possibleCombatActions.Choices.Add(choice);
                recordedIds.Add(weaponId);
            }

            foreach (long id in battlefieldEntityIds)
            {
                if (id == agentId)
                {
                    continue;
                }

                var entityName  = rgs.GetPartSingleOrDefault <Parts.EntityName>(id);
                var entityAgent = rgs.GetPartSingleOrDefault <Parts.Agent>(id);

                if (entityName == null || entityAgent == null)
                {
                    continue;
                }

                if (entityAgent.CombatStatusTags.Intersect(Vals.CombatStatusTag.CombatTerminalStatuses).Any())
                {
                    continue;
                }

                possibleCombatActions.MeleeTargets.Add(id, entityName.ProperName);
            }

            //add stances
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId     = agentId,
                Category    = Vals.CombatCategory.AllStances,
                Description = "Stance (Defensive)",
                Action      = Vals.CombatAction.StanceDefensive
            });
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId     = agentId,
                Category    = Vals.CombatCategory.AllStances,
                Description = "Stance (Stand Ground)",
                Action      = Vals.CombatAction.StanceStandGround
            });
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId     = agentId,
                Category    = Vals.CombatCategory.AllStances,
                Description = "Stance (Aggressive)",
                Action      = Vals.CombatAction.StanceAggressive
            });

            //add top-level choices that we know are present: note that we already did NextCategory = primary-melee because the description there is context dependent.
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId      = agentId,
                Category     = Vals.CombatCategory.TopLevelAction,
                Description  = "All Melee Options",
                NextCategory = Vals.CombatCategory.AllMelee
            });
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId      = agentId,
                Category     = Vals.CombatCategory.TopLevelAction,
                Description  = "Change Stance",
                NextCategory = Vals.CombatCategory.AllStances
            });
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId     = agentId,
                Category    = Vals.CombatCategory.TopLevelAction,
                Description = "Run Away",
                Action      = Vals.CombatAction.RunAway
            });
            possibleCombatActions.Choices.Add(new AgentActionChoice
            {
                AgentId     = agentId,
                Category    = Vals.CombatCategory.TopLevelAction,
                Description = "Do Nothing",
                Action      = Vals.CombatAction.DoNothing
            });


            return(possibleCombatActions);
        }