Пример #1
0
 public static void GetGoldCostForUpgrade(ref PartyBase party, ref CharacterObject characterObject, ref CharacterObject upgradeTarget, ref int __result)
 {
     try
     {
         if (party.IsPlayerParty() &&
             BannerlordCheatsSettings.Instance?.FreeTroopUpgrades == true)
         {
             __result = 0;
         }
     }
     catch (Exception e)
     {
         SubModule.LogError(e, typeof(FreeTroopUpgrades));
     }
 }
 public static void GetPartyMemberSizeLimit(ref PartyBase party, ref bool includeDescriptions, ref ExplainedNumber __result)
 {
     try
     {
         if (party.IsPlayerParty() &&
             BannerlordCheatsSettings.Instance?.ExtraPartyMemberSize > 0)
         {
             __result.Add(BannerlordCheatsSettings.Instance.ExtraPartyMemberSize);
         }
     }
     catch (Exception e)
     {
         SubModule.LogError(e, typeof(ExtraPartyMemberSize));
     }
 }
        internal SimulationModel(MapEvent mapEvent, PartyBase attackerParty, PartyBase defenderParty)
        {
            BattleId         = mapEvent.Id;
            EventDescription = mapEvent.ToString();

            bool isSiegeBattle = mapEvent.EventType == BattleTypes.Siege;

            Parties = new ReadOnlyCollection <Party>(new List <Party> {
                new Party(defenderParty, isSiegeBattle), new Party(attackerParty)
            });                                                                                                                             // do not change the order of the list
            IsPlayerInvolved = Hero.MainHero.Id == attackerParty.LeaderHero?.Id || Hero.MainHero.Id == defenderParty.LeaderHero?.Id;

            Terrain = (attackerParty.IsMobile && defenderParty.IsMobile) ? Parties[1].TerrainType : TerrainType.Water;
            Battle  = mapEvent;
        }
        private static bool StrikeOnce(MapEvent mapEvent,
                                       IBattleObserver battleObserver,
                                       MapEventSide strikerSide,
                                       MapEventSide strikedSide,
                                       PartyAttackComposition attack,
                                       out float totalDamageDone)
        {
            int strikerNumber = strikerSide.NumRemainingSimulationTroops;
            int strikedNumber = strikedSide.NumRemainingSimulationTroops;

            totalDamageDone = 0;
            if (strikerNumber == 0 || strikedNumber == 0)
            {
                return(true);
            }

            MapEventState mapEventState  = MapEventState.GetMapEventState(mapEvent);
            bool          finishedAnyone = false;

            for (int index = strikedNumber - 1; index >= 0; index--)
            {
                UniqueTroopDescriptor strikerTroopDescriptor = strikerSide.SelectRandomSimulationTroop();
                CharacterObject       strikerTroop           = strikerSide.GetAllocatedTroop(strikerTroopDescriptor);
                PartyBase             strikerTroopParty      = strikerSide.GetAllocatedTroopParty(strikerTroopDescriptor);

                UniqueTroopDescriptor strikedTroopDescriptor = MapEventSideHelper.SelectSimulationTroopAtIndex(strikedSide, index, out List <UniqueTroopDescriptor> strikedTroopList);
                CharacterObject       strikedTroop           = strikedSide.GetAllocatedTroop(strikedTroopDescriptor);
                PartyBase             strikedTroopParty      = strikedSide.GetAllocatedTroopParty(strikedTroopDescriptor);

                // MapEvents.GetSimulatedDamage and CombatSimulationModel.SimulateHit
                if (mapEvent.IsPlayerSimulation && strikedTroopParty == PartyBase.MainParty)
                {
                    float damageMultiplier = Campaign.Current.Models.DifficultyModel.GetPlayerTroopsReceivedDamageMultiplier();
                    attack *= damageMultiplier;
                }
                DamageTypes damageType = (double)MBRandom.RandomFloat < 0.15 ? DamageTypes.Blunt : DamageTypes.Cut;

                bool isFinishingStrike = MapEventSideHelper.ApplySimulationDamageToSelectedTroop(
                    strikedSide, strikedTroop, strikedTroopParty, strikedTroopDescriptor, index, strikedTroopList,
                    attack, damageType, strikerTroopParty, mapEventState, battleObserver, out float damage);
                totalDamageDone += damage;

                strikerSide.ApplySimulatedHitRewardToSelectedTroop(strikedTroop, 0, isFinishingStrike);
                finishedAnyone = finishedAnyone || isFinishingStrike;
            }

            return(finishedAnyone);
        }
Пример #5
0
        public static bool IsPlayerParty(this PartyBase party)
        {
            // Workaround for crash on accessing BanditPartyComponent.Owner
            Hero owner;

            try
            {
                owner = party?.Owner;
            }
            catch (NullReferenceException)
            {
                return(false);
            }

            return(owner?.IsHumanPlayerCharacter ?? false);
        }
Пример #6
0
        private static void OnMilitiaRemoved(PartyBase partyBase)
        {
            if (!IsBM(partyBase.MobileParty))
            {
                return;
            }

            Mod.Log($">>> OnMilitiaRemoved - {partyBase.Name}.");
            if (partyBase.MobileParty.LeaderHero?.CurrentSettlement != null)
            {
                Traverse.Create(HeroesWithoutParty(partyBase.MobileParty.LeaderHero?.CurrentSettlement)).Field <List <Hero> >("_list").Value.Remove(partyBase.MobileParty.LeaderHero);
                Mod.Log($">>> FLUSH OnMilitiaRemoved bandit hero without party - {partyBase.MobileParty.LeaderHero.Name} at {partyBase.MobileParty.LeaderHero?.CurrentSettlement}.");
            }

            PartyMilitiaMap.Remove(partyBase.MobileParty);
        }
 public static void  CalculateRecruitableNumber(ref PartyBase party, ref CharacterObject character, ref int __result)
 {
     try
     {
         if (party.IsPlayerParty() &&
             !character.IsHero() &&
             BannerlordCheatsSettings.Instance?.InstantPrisonerRecruitment == true)
         {
             __result = party.PrisonRoster.GetTroopCount(character);
         }
     }
     catch (Exception e)
     {
         SubModule.LogError(e, typeof(InstantPrisonerRecruitment));
     }
 }
Пример #8
0
        static void Postfix(PartyBase party, CharacterObject troopToBoost, ref int __result)
        {
            if (BannerlordTweaksSettings.Instance is { } settings&& settings.PrisonerConformityTweaksEnabled && !(party.LeaderHero is null))
            {
                float num;
                if (party.LeaderHero == Hero.MainHero ||
                    (!(party.Owner is null) && party.Owner.Clan == Hero.MainHero.Clan && settings.PrisonerConformityTweaksApplyToClan) ||
                    (settings.PrisonerConformityTweaksApplyToAi))
                {
                    num = __result * (1 + settings.PrisonerConformityTweakBonus);
                    party.MobileParty.EffectiveQuartermaster.AddSkillXp(DefaultSkills.Charm, (num * .05f));
                    __result = MBMath.Round(num);
                }
            }

            // Add Tier-Specific Boosts?
        }
Пример #9
0
 private void GetBattleXpBonusFromPerks(PartyBase party, ref ExplainedNumber xpToGain, CharacterObject troop)
 {
     if (party.IsMobile && party.MobileParty.LeaderHero != null)
     {
         if (!troop.IsArcher && party.MobileParty.HasPerk(DefaultPerks.OneHanded.Trainer, true))
         {
             xpToGain.AddFactor(DefaultPerks.OneHanded.Trainer.SecondaryBonus * 0.01f, DefaultPerks.OneHanded.Trainer.Name);
         }
         if (troop.IsInfantry)
         {
             if (party.MobileParty.HasPerk(DefaultPerks.OneHanded.CorpsACorps, false))
             {
                 xpToGain.AddFactor(DefaultPerks.OneHanded.CorpsACorps.PrimaryBonus * 0.01f, DefaultPerks.OneHanded.CorpsACorps.Name);
             }
             if (party.MobileParty.HasPerk(DefaultPerks.TwoHanded.BaptisedInBlood, true))
             {
                 xpToGain.AddFactor(DefaultPerks.TwoHanded.BaptisedInBlood.SecondaryBonus * 0.01f, DefaultPerks.TwoHanded.BaptisedInBlood.Name);
             }
         }
         if (party.MobileParty.HasPerk(DefaultPerks.OneHanded.LeadByExample, false))
         {
             xpToGain.AddFactor(DefaultPerks.OneHanded.LeadByExample.PrimaryBonus * 0.01f, DefaultPerks.OneHanded.LeadByExample.Name);
         }
         if (party.MobileParty.HasPerk(DefaultPerks.Leadership.Companions, false))
         {
             xpToGain.AddFactor(DefaultPerks.Leadership.Companions.PrimaryBonus * 0.01f, DefaultPerks.Leadership.Companions.Name);
         }
         if (troop.IsArcher && party.MobileParty.HasPerk(DefaultPerks.Crossbow.MountedCrossbowman, true))
         {
             xpToGain.AddFactor(DefaultPerks.Crossbow.MountedCrossbowman.SecondaryBonus * 0.01f, DefaultPerks.Crossbow.MountedCrossbowman.Name);
         }
     }
     if (party.IsMobile && party.MobileParty.IsGarrison)
     {
         Settlement currentSettlement = party.MobileParty.CurrentSettlement;
         if (((currentSettlement != null) ? currentSettlement.Town.Governor : null) != null)
         {
             PerkHelper.AddPerkBonusForTown(DefaultPerks.TwoHanded.Yadomejutsu, party.MobileParty.CurrentSettlement.Town, ref xpToGain);
             if (troop.IsMounted)
             {
                 PerkHelper.AddPerkBonusForTown(DefaultPerks.Polearm.Guards, party.MobileParty.CurrentSettlement.Town, ref xpToGain);
             }
         }
     }
 }
Пример #10
0
 private PartyState GetPartyState(PartyBase party)
 {
     if (!PartyStates.TryGetValue(party.Id, out PartyState partyState))
     {
         partyState            = new PartyState(this, party.Side == BattleSideEnum.Attacker);
         PartyStates[party.Id] = partyState;
         for (int index = 0; index < party.MemberRoster.Count; ++index)
         {
             TroopRosterElement elementCopyAtIndex = party.MemberRoster.GetElementCopyAtIndex(index);
             CharacterObject    troop = elementCopyAtIndex.Character;
             if (troop != null)
             {
                 partyState.RegisterTroops(troop, (elementCopyAtIndex.Number - elementCopyAtIndex.WoundedNumber));
             }
         }
     }
     return(partyState);
 }
 public static void CalculateRenownGain(
     ref PartyBase party,
     ref float renownValueOfBattle,
     ref float contributionShare,
     ref ExplainedNumber __result)
 {
     try
     {
         if (party.IsPlayerParty() &&
             BannerlordCheatsSettings.Instance?.RenownRewardMultiplier > 1f)
         {
             __result.AddMultiplier(BannerlordCheatsSettings.Instance.RenownRewardMultiplier);
         }
     }
     catch (Exception e)
     {
         SubModule.LogError(e, typeof(RenownRewardMultiplierBattle));
     }
 }
Пример #12
0
        private static TroopRoster ConstructTroopRoster(PartyTemplateObject pt, PartyBase ownerParty, int troopNumberLimit = -1) //TODO implement troop number limit.
        {
            TroopRoster returned     = new TroopRoster(ownerParty);
            float       gameProcess  = MiscHelper.GetGameProcess();
            float       num          = 0.25f + 0.75f * gameProcess;
            int         num2         = MBRandom.RandomInt(2);
            float       num3         = (num2 == 0) ? MBRandom.RandomFloat : (MBRandom.RandomFloat * MBRandom.RandomFloat * MBRandom.RandomFloat * 4f);
            float       num4         = (num2 == 0) ? (num3 * 0.8f + 0.2f) : (1f + num3);
            float       randomFloat  = MBRandom.RandomFloat;
            float       randomFloat2 = MBRandom.RandomFloat;
            float       randomFloat3 = MBRandom.RandomFloat;

            for (int i = 0; i < pt.Stacks.Count; i++)
            {
                float f = (pt.Stacks.Count > 0) ? ((float)pt.Stacks[i].MinValue + num * num4 * randomFloat * (float)(pt.Stacks[i].MaxValue - pt.Stacks[i].MinValue)) : 0f;
                returned.AddToCounts(pt.Stacks[i].Character, MBRandom.RoundRandomized(f), false);
            }
            return(returned);
        }
Пример #13
0
        private bool patrol_talk_start_on_conditional()
        {
            PartyBase encounteredParty = PlayerEncounter.EncounteredParty;

            try
            {
                if (PlayerEncounter.Current != null && Campaign.Current.CurrentConversationContext == ConversationContext.PartyEncounter &&
                    encounteredParty.IsMobile && encounteredParty.Name.Contains("Patrol") && encounteredParty.IsActive && encounteredParty.MobileParty.HomeSettlement.OwnerClan == Clan.PlayerClan)
                {
                    return(true);
                }
                return(false);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                return(false);
            }
        }
Пример #14
0
        public void SpawnTheTroops(SpawnTroop[] variables, PartyBase party)
        {
            foreach (SpawnTroop troop in variables)
            {
                try
                {
                    int             num             = new CEVariablesLoader().GetIntFromXML(troop.Number);
                    int             numWounded      = new CEVariablesLoader().GetIntFromXML(troop.WoundedNumber);
                    CharacterObject characterObject = MBObjectManager.Instance.GetObject <CharacterObject>(troop.Id);

                    if (characterObject == null)
                    {
                        foreach (CharacterObject characterObject2 in MBObjectManager.Instance.GetObjectTypeList <CharacterObject>())
                        {
                            if (characterObject2.Occupation == Occupation.Soldier && string.Equals(characterObject2.Name.ToString(), troop.Id, StringComparison.OrdinalIgnoreCase))
                            {
                                characterObject = characterObject2;
                                break;
                            }
                        }
                    }

                    if (characterObject != null)
                    {
                        if (num > 0)
                        {
                            if (troop.Ref != null && troop.Ref.ToLower() == "troop")
                            {
                                party.MemberRoster.AddToCounts(characterObject, num, false, numWounded, 0, true, -1);
                            }
                            else
                            {
                                party.PrisonRoster.AddToCounts(characterObject, num, false, numWounded, 0, true, -1);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    CECustomHandler.ForceLogToFile("Failed to SpawnTheTroops : " + e);
                }
            }
        }
Пример #15
0
        private static string?GetEncounterMenu(PartyBase attackerParty, PartyBase defenderParty, PartyBase encounteredPartyBase)
        {
            if (!FastDialogueSubModule.Instance.running)
            {
                return(null);
            }

            if (encounteredPartyBase.IsSettlement || encounteredPartyBase.MapEvent != null)
            {
                return(null);
            }

            if (!FastDialogueSubModule.Instance.IsPatternWhitelisted(encounteredPartyBase.Leader.StringId))
            {
                return(null);
            }

            var inOwnedKingdom = encounteredPartyBase.MapFaction == PartyBase.MainParty.MapFaction && PartyBase.MainParty.MapFaction.Leader.CharacterObject == PartyBase.MainParty.Leader;

            if (inOwnedKingdom)
            {
                return(null);
            }

            if (encounteredPartyBase.MobileParty?.IsCurrentlyUsedByAQuest == true && encounteredPartyBase.Leader.StringId.Contains("villager"))
            {
                return(null);
            }

            if (!encounteredPartyBase.IsMobile)
            {
                return(FastDialogueSubModule.FastEncounterMenu);
            }

            var notGarrisonOrSiege = !encounteredPartyBase.MobileParty.IsGarrison || MobileParty.MainParty.BesiegedSettlement == null;
            var notOwnSettlementOrNotOwnBesiegedSettlement = MobileParty.MainParty.CurrentSettlement == null || encounteredPartyBase.MobileParty.BesiegedSettlement != MobileParty.MainParty.CurrentSettlement;

            if (notGarrisonOrSiege && notOwnSettlementOrNotOwnBesiegedSettlement)
            {
                return(FastDialogueSubModule.FastEncounterMenu);
            }
            return(null);
        }
Пример #16
0
            private static void Postfix(PartyBase party)
            {
                if (party?.MobileParty is null ||
                    !party.MobileParty.IsBM() ||
                    party.PrisonRoster is not null &&
                    party.PrisonRoster.Contains(Hero.MainHero.CharacterObject))
                {
                    return;
                }

                if (party.MemberRoster.TotalManCount <= Globals.Settings.MinPartySize)
                {
                    Mod.Log($">>> Dispersing {party.Name} of {party.MemberRoster.TotalHealthyCount}+{party.MemberRoster.TotalWounded}w+{party.PrisonRoster?.Count}p");
                    Trash(party.MobileParty);
                    return;
                }

                RemoveUndersizedTracker(party);
            }
        private void OnSaveStart()
        {
            //deal with corrupted settlement parties from pre-1.4.1
            foreach (Settlement s in Settlement.All)
            {
                if (!s.IsTown && !s.IsCastle)
                {
                    continue;
                }
                PartyBase settlementParty = null, garrisonParty = null;
                settlementParty = s.Town.Owner;
                foreach (var party in ((SettlementComponent)s.Town).Settlement.Parties)
                {
                    if (party.IsGarrison)
                    {
                        garrisonParty = party.Party;
                    }
                    if (party.Party.IsSettlement)
                    {
                        settlementParty = party.Party;
                    }
                }

                if (settlementParty == null || garrisonParty == null)
                {
                    continue;
                }

                List <TroopRosterElement> elements = new List <TroopRosterElement>();

                foreach (var troopRosterElement in settlementParty.MemberRoster.GetTroopRoster())
                {
                    elements.Add(troopRosterElement);
                }

                foreach (var troopRosterElement in elements)
                {
                    settlementParty.MemberRoster.RemoveTroop(troopRosterElement.Character, troopRosterElement.Number);
                    garrisonParty.MemberRoster.AddToCounts(troopRosterElement.Character, troopRosterElement.Number);
                }
            }
        }
Пример #18
0
        static bool Prefix(PartyBase party, float renownValueOfBattle, float contributionShare, StatExplainer explanation, ref float __result)
        {
            bool patched = false;

            try
            {
                var battleRenownMultiplier = 1f;

                if (Settings.Instance.BattleRewardApplyToAI || party.LeaderHero != null && party.LeaderHero == Hero.MainHero)
                {
                    battleRenownMultiplier = Settings.Instance.BattleRenownMultiplier;
                }

                var stat = new ExplainedNumber((renownValueOfBattle * contributionShare) * battleRenownMultiplier, explanation);

                /* Debug to test complaint of Battle Renown multiplier not being calculated right.
                 * if (party.LeaderHero == Hero.MainHero)
                 * {
                 *  MessageBox.Show($"DefaultBattleRewardModelRenownPatch. renownValueOfBattle is: "+ renownValueOfBattle+"\nbattleRenownMultiplier is:" + battleRenownMultiplier + "\nexplanation:"+ explanation+"\n");
                 * }
                 */

                //TODO:: Implement this the same as native in next game update
                //if (party.IsMobile && party.MobileParty.HasPerk(DefaultPerks.Charm.ShowYourScars))
                //{
                //        PerkHelper.AddPerkBonusForParty(DefaultPerks.Charm.ShowYourScars, party.MobileParty, ref stat);
                //}
                if (party.IsMobile && party.Leader != null && party.Leader.HeroObject != null && party.LeaderHero.GetPerkValue(DefaultPerks.Charm.ShowYourScars))
                {
                    PerkHelper.AddPerkBonusForParty(DefaultPerks.Charm.ShowYourScars, party.MobileParty, true, ref stat);
                }

                __result = stat.ResultNumber;
                patched  = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An error occurred during DefaultBattleRewardModelRenownPatch. Reverting to original behaviour...\n\nException:\n{ex.Message}\n\n{ex.InnerException?.Message}\n\n{ex.InnerException?.InnerException?.Message}");
            }

            return(!patched);
        }
        public void CheckForBarters(BarterData args)
        {
            PartyBase offererParty = args.OffererParty;
            PartyBase otherParty   = args.OtherParty;

            if (offererParty == null || otherParty == null)
            {
                return;
            }

#if BETA
            foreach (CharacterObject characterObject in offererParty.PrisonerHeroes)
#else
            foreach (CharacterObject characterObject in offererParty.PrisonerHeroes())
#endif
            {
                if (characterObject.IsHero && !FactionManager.IsAtWarAgainstFaction(characterObject.HeroObject.MapFaction, otherParty.MapFaction))
                {
                    if (CESettings.Instance != null && ((CESettings.Instance.EscapeAutoRansom.SelectedIndex != 0) || !(CESettings.Instance.EscapeAutoRansom.SelectedIndex == 1) && (!characterObject.IsPlayerCharacter || offererParty != PartyBase.MainParty)))
                    {
                        Barterable barterable = new SetPrisonerFreeBarterable(characterObject.HeroObject, args.OffererHero, args.OffererParty, args.OtherHero);
                        args.AddBarterable <PrisonerBarterGroup>(barterable);
                    }
                }
            }

#if BETA
            foreach (CharacterObject characterObject2 in otherParty.PrisonerHeroes)
#else
            foreach (CharacterObject characterObject2 in otherParty.PrisonerHeroes())
#endif
            {
                if (characterObject2.IsHero && !FactionManager.IsAtWarAgainstFaction(characterObject2.HeroObject.MapFaction, offererParty.MapFaction))
                {
                    if (CESettings.Instance != null && ((CESettings.Instance.EscapeAutoRansom.SelectedIndex != 0) || !(CESettings.Instance.EscapeAutoRansom.SelectedIndex == 1) && (!characterObject2.IsPlayerCharacter || otherParty != PartyBase.MainParty)))
                    {
                        Barterable barterable2 = new SetPrisonerFreeBarterable(characterObject2.HeroObject, args.OtherHero, args.OtherParty, args.OffererHero);
                        args.AddBarterable <PrisonerBarterGroup>(barterable2);
                    }
                }
            }
        }
Пример #20
0
        //deal with our parties being removed! Also this is more efficient ;)
        private void OnPartyRemoved(PartyBase p)
        {
            MobileParty mb = p.MobileParty;

            if (mb == null)
            {
                return;
            }

            CSPartyData partyData = DynamicSpawnData.Instance.GetDynamicSpawnData(mb);

            if (partyData != null)
            {
                partyData.spawnBaseData.DecrementNumberSpawned();
                //this is a custom spawns party!!
                OnPartyDeath(mb, partyData);
                ModDebug.ShowMessage(mb.StringId + " has died at " + partyData.latestClosestSettlement + ", reducing the total number to: " + partyData.spawnBaseData.GetNumberSpawned(), DebugMessageType.DeathTrack);
                DynamicSpawnData.Instance.RemoveDynamicSpawnData(mb);
            }
        }
Пример #21
0
            public static CharacterObject GetCharacterWithHighestSkill(PartyBase party, SkillObject skill)
            {
                CharacterObject heroObject = null;
                int             num        = 0;

                for (int i = 0; i < party.MemberRoster.Count; i++)
                {
                    CharacterObject characterAtIndex = party.MemberRoster.GetCharacterAtIndex(i);
                    if (characterAtIndex.IsHero && !characterAtIndex.HeroObject.IsWounded)
                    {
                        int skillValue = characterAtIndex.GetSkillValue(skill);
                        if (skillValue >= num)
                        {
                            num        = skillValue;
                            heroObject = characterAtIndex;
                        }
                    }
                }
                return(heroObject ?? party.LeaderHero.CharacterObject);
            }
Пример #22
0
        public static SPCombatant CreateParty(PartyBase party, BattleSideEnum side, BasicCultureObject culture,
                                              TeamConfig teamConfig, bool isPlayerTeam)
        {
            party.Owner = null;
            if (teamConfig.HasGeneral)
            {
                var characterObject = (teamConfig.General as SPCharacterConfig)?.ActualCharacterObject;
                if (characterObject?.IsHero ?? false)
                {
                    party.Owner = characterObject.HeroObject;
                }
            }
            Utility.FillPartyMembers(party, side, culture, teamConfig, isPlayerTeam);
            bool isAttacker = side == BattleSideEnum.Attacker;
            var  combatant  = new SPCombatant(party, side, teamConfig.TacticLevel, culture,
                                              new Tuple <uint, uint>(teamConfig.Color1, teamConfig.Color2),
                                              teamConfig.Banner);

            if (teamConfig.HasGeneral)
            {
                if (teamConfig.General is SPCharacterConfig general)
                {
                    combatant.AddCharacter(
                        new SPSpawnableCharacter(general, (int)general.CharacterObject.DefaultFormationGroup,
                                                 general.FemaleRatio > 0.5, isPlayerTeam), 1);
                }
            }
            for (int i = 0; i < teamConfig.Troops.Troops.Length; ++i)
            {
                var troopConfig = teamConfig.Troops.Troops[i];
                if (troopConfig.Character is SPCharacterConfig spCharacter)
                {
                    var femaleCount = (int)(troopConfig.Number * spCharacter.FemaleRatio + 0.49);
                    var maleCount   = troopConfig.Number - femaleCount;
                    combatant.AddCharacter(new SPSpawnableCharacter(spCharacter, i, true), femaleCount);
                    combatant.AddCharacter(new SPSpawnableCharacter(spCharacter, i, false), maleCount);
                }
            }

            return(combatant);
        }
Пример #23
0
        internal static TroopRoster[] MergeRosters(MobileParty sourceParty, PartyBase targetParty)
        {
            var troopRoster    = TroopRoster.CreateDummyTroopRoster();
            var prisonerRoster = TroopRoster.CreateDummyTroopRoster();
            var rosters        = new List <TroopRoster>
            {
                sourceParty.MemberRoster,
                targetParty.MemberRoster
            };

            var prisoners = new List <TroopRoster>
            {
                sourceParty.PrisonRoster,
                targetParty.PrisonRoster
            };

            // dumps all bandit heroes (shouldn't be more than 2 though...)
            foreach (var roster in rosters)
            {
                foreach (var troopRosterElement in roster.GetTroopRoster().Where(x => x.Character?.HeroObject == null))
                {
                    troopRoster.AddToCounts(troopRosterElement.Character, troopRosterElement.Number,
                                            woundedCount: troopRosterElement.WoundedNumber, xpChange: troopRosterElement.Xp);
                }
            }

            foreach (var roster in prisoners)
            {
                foreach (var troopRosterElement in roster.GetTroopRoster().Where(x => x.Character?.HeroObject == null))
                {
                    prisonerRoster.AddToCounts(troopRosterElement.Character, troopRosterElement.Number,
                                               woundedCount: troopRosterElement.WoundedNumber, xpChange: troopRosterElement.Xp);
                }
            }

            return(new[]
            {
                troopRoster,
                prisonerRoster
            });
        }
        private void AddSettlementProjectBonuses(PartyBase party, ref ExplainedNumber result)
        {
            if (party?.Owner?.HomeSettlement == null)
            {
                return;
            }
            Settlement homeSettlement = party.Owner.HomeSettlement;

            if (!homeSettlement.IsTown && !homeSettlement.IsCastle)
            {
                return;
            }
            foreach (Building building in homeSettlement.Town.Buildings)
            {
                int buildingEffectAmount = building.GetBuildingEffectAmount(DefaultBuildingEffects.GarrisonCapacity);
                if (buildingEffectAmount > 0)
                {
                    result.Add((float)buildingEffectAmount, building.Name);
                }
            }
        }
Пример #25
0
        /// <summary>
        /// Tries to get the PartyBase of the Agent origin being evaluated
        /// </summary>
        /// <param name="origin">The Agent origin to evaluate</param>
        /// <param name="party">The Agent's party or null</param>
        /// <returns>Returns true if the Agent's party was found</returns>
        public static bool TryGetParty(this IAgentOriginBase origin, out PartyBase party)
        {
            switch (origin)
            {
            case PartyAgentOrigin partyAgentOrigin:
                party = partyAgentOrigin.Party;
                return(party != null);

            case PartyGroupAgentOrigin partyGroupAgentOrigin:
                party = partyGroupAgentOrigin.Party;
                return(party != null);

            case SimpleAgentOrigin simpleAgentOrigin:
                party = simpleAgentOrigin.Party;
                return(party != null);

            default:
                party = null;
                return(false);
            }
        }
Пример #26
0
        private void StartMarriageBarter()
        {
            Hero        offererHero     = Hero.MainHero;
            MobileParty partyBelongedTo = offererHero.PartyBelongedTo;
            PartyBase   offererParty    = (partyBelongedTo != null) ? partyBelongedTo.Party : null;

            Hero otherHero = Hero.OneToOneConversationHero;

            partyBelongedTo = otherHero.PartyBelongedTo;
            PartyBase otherParty = (partyBelongedTo != null) ? partyBelongedTo.Party : null;

            Barterable barterable = new MarriageBarterable(otherHero, otherParty, proposedSpouseForPlayerRelative, playerProposalHero);

            barterable.SetIsOffered(true);
            List <Barterable> offer = new List <Barterable>()
            {
                barterable
            };

            BarterManager.Instance.StartBarterOffer(offererHero, otherHero, offererParty, otherParty, null, null, 0, false, offer);
        }
Пример #27
0
            private static void Postfix(MapEventSide __instance, PartyBase party, Hero __state)
            {
                if (__state == null ||
                    party?.MobileParty == null ||
                    !IsBM(party.MobileParty) ||
                    party.PrisonRoster != null &&
                    party.PrisonRoster.Contains(Hero.MainHero.CharacterObject))
                {
                    return;
                }

                if (party.MemberRoster?.TotalHealthyCount == 0 ||
                    party.MemberRoster?.TotalHealthyCount < Globals.Settings.MinPartySize &&
                    party.PrisonRoster?.Count < Globals.Settings.MinPartySize &&
                    __instance.Casualties > party.MemberRoster?.TotalHealthyCount * 2)
                {
                    Mod.Log($">>> Dispersing {party.Name} of {party.MemberRoster.TotalHealthyCount}+{party.MemberRoster.TotalWounded}w+{party.PrisonRoster?.Count}p");
                    __state.KillHero();
                    Trash(party.MobileParty);
                }
            }
Пример #28
0
        internal void AddTroopsFromParty(PartyBase party)
        {
            var troops = party.MemberRoster;

            foreach (var troop in troops)
            {
                int totalNumber = troop.Number - troop.WoundedNumber;
                var troopType   = troop.Character.DecideTroopType();

                while (totalNumber-- > 0)
                {
                    Troops.Add(new Troop(troop.Character, this, troopType));
                }
            }
            if (party.MobileParty != null && party.MobileParty.AttachedParties != null)
            {
                foreach (var attachedParty in party.MobileParty.AttachedParties)
                {
                    AddTroopsFromParty(attachedParty.Party);
                }
            }
        }
        private static void SortAnyParty(MBBindingList <PartyCharacterVM> toSort, PartyBase party,
                                         TroopRoster rosterToSort, PartySort sorter)
        {
            if (rosterToSort == null || rosterToSort.Count == 0 || toSort == null || toSort.IsEmpty())
            {
                return;
            }

            CharacterObject leaderOfParty = party?.LeaderHero?.CharacterObject;

            // Sort the list, this is done for the visual unit cards to be properly positioned after the sort
            // This is not yet persisted to the actual roster, that is done after this.
            toSort.StableSort(sorter);

            // Sanity check to ensure the leader is *always* at the top of the party.
            if (leaderOfParty != null)
            {
                var index = toSort.FindIndex((character) => character.Character.Equals(leaderOfParty));
                PartyCharacterVM leaderVm = toSort[index];
                toSort.RemoveAt(index);
                toSort.Insert(0, leaderVm);
            }

            // Here we manually clear the roster while ignoring the party leader.
            // Don't use `rosterToSort.Clear()` as that seems to cause the party leader to get unset permanently afterward, which stops upgrades from working.
            rosterToSort.RemoveIf((item) => item.Character != leaderOfParty);

            // Re-add the correctly sorted troops to the roster. We need to do it in this janky way due to the fact that we can't easily sort
            // the underlying roster array.
            foreach (PartyCharacterVM character in toSort)
            {
                if (character.Character != leaderOfParty)
                {
                    rosterToSort.AddToCounts(
                        character.Troop.Character, character.Troop.Number, false, character.Troop.WoundedNumber,
                        character.Troop.Xp);
                }
            }
        }
Пример #30
0
        public static Hero FindHero(PartyBase party)
        {
            bool flag   = false;
            Hero result = null;
            bool flag2  = party.Owner != null;

            if (flag2)
            {
                result = party.Owner;
                flag   = true;
            }
            bool flag3 = !flag;

            if (flag3)
            {
                bool flag4 = party.Leader != null;
                if (flag4)
                {
                    bool flag5 = party.Leader.HeroObject != null;
                    if (flag5)
                    {
                        result = party.Leader.HeroObject;
                        flag   = true;
                    }
                }
            }
            bool flag6 = !flag;

            if (flag6)
            {
                bool flag7 = party.LeaderHero != null;
                if (flag7)
                {
                    result = party.LeaderHero;
                }
            }
            return(result);
        }