private void OnDailyHeroTick(Hero hero)
        {
            // We only evaluate marriage once per human year, and we use an offset to distribute hero
            // marriages more evenly throughout that year:
            int daysOffset  = hero.Id.GetHashCode() % daysPerHumanYear;
            int daysElapsed = (int)Campaign.Current.CampaignStartTime.ElapsedDaysUntilNow;

            // Is this not the right day to do our yearly marriage tick?
            if ((daysElapsed + daysOffset) % daysPerHumanYear != 0)
            {
                return;
            }

            // Does this hero even qualify for a marriage evaluation?
            if (!SuitorQualifiesForNobleMarriageSystem(hero))
            {
                return;
            }

            var clanFitness    = GetClanFitness(hero.Clan);
            var marriageChance = GetAnnualMarriageChance(clanFitness);

            Util.Log.Print($"[{CampaignTime.Now}] {GetHeroTrace(hero, clanFitness)}: Considering marriage ({marriageChance * 100:F1}% chance)...");

            if (MBRandom.RandomFloat > marriageChance)
            {
                Util.Log.Print(" -> Decided not to marry for now.");
                return;
            }

            // Find eligible candidates for marriage in order of preference
            var wife    = FindBestNobleMaiden(hero);
            var spawned = false;

            // Were there no eligible female nobles?
            if (wife is null)
            {
                wife = ConsiderMaidenOfLesserNobility(hero, clanFitness);

                if (wife is null)
                {
                    return;
                }
                else
                {
                    spawned = true;
                }
            }

            // Get married!
            Util.Log.Print($" -> MARRIAGE ({(spawned ? "spawned" : "regular")}): {GetHeroTrace(wife, spawned ? -1 : GetClanFitness(wife.Clan))}");
            MarriageAction.Apply(hero, wife);
        }
        private static void MarryHero(Hero hero)
        {
            if (Hero.MainHero.Spouse == hero || Hero.MainHero.ExSpouses.Contains(hero))
            {
                return;
            }
            //1.4.3 结婚后,第二个英雄状态会变成逃亡状态,并且会被所在部队移除, 所在部队还会解散。

            Hero mainSpouse = Hero.MainHero.Spouse;

            bool needAddPlayerTroop = true;

            if (Hero.MainHero.PartyBelongedTo.MemberRoster.Contains(hero.CharacterObject))
            {
                Hero.MainHero.PartyBelongedTo.MemberRoster.RemoveTroop(hero.CharacterObject, 1);
            }
            if (hero.PartyBelongedTo != null)
            {
                MobileParty partyBelongedTo = hero.PartyBelongedTo;
                partyBelongedTo.MemberRoster.RemoveTroop(hero.CharacterObject, 1);
                partyBelongedTo.RemoveParty();
                //partyBelongedTo.Party.Owner = partyBelongedTo.MemberRoster.First().Character;
            }



            if (null == hero.Clan)
            {
                hero.Clan = Hero.MainHero.Clan;
            }
            MarriageAction.Apply(Hero.MainHero, hero);
            hero.ChangeState(Hero.CharacterStates.Active);
            if (needAddPlayerTroop)
            {
                Hero.MainHero.PartyBelongedTo.MemberRoster.AddToCounts(hero.CharacterObject, 1);
            }


            SpouseOperation.RemoveRepeatExspouses(Hero.MainHero, Hero.MainHero.Spouse);

            TextObject textObject = GameTexts.FindText("sue_more_spouses_marry_target", null);

            StringHelpers.SetCharacterProperties("SUE_HERO", hero.CharacterObject, null, textObject);
            InformationManager.AddQuickInformation(textObject, 0, null, "event:/ui/notification/quest_finished");

            if (null != mainSpouse)
            {
                SpouseOperation.SetPrimarySpouse(mainSpouse);
            }
        }
Beispiel #3
0
        internal void ChangeSpouse(Hero hero, Hero spouseHero)
        {
            try
            {
                if (hero == null)
                {
                    return;
                }
                Hero heroSpouse = hero.Spouse;

                if (!hero.IsHumanPlayerCharacter && hero.IsFactionLeader)
                {
                    RemoveFactionLeader(hero);
                }
                else if (!spouseHero.IsHumanPlayerCharacter && spouseHero.IsFactionLeader)
                {
                    RemoveFactionLeader(spouseHero);
                }

                if (heroSpouse != null)
                {
                    TextObject textObject = GameTexts.FindText("str_CE_spouse_leave");
                    textObject.SetTextVariable("HERO", hero.Name);
                    textObject.SetTextVariable("SPOUSE", heroSpouse.Name);
                    InformationManager.DisplayMessage(new InformationMessage(textObject.ToString(), Colors.Magenta));

                    if (heroSpouse.Father != null)
                    {
                        heroSpouse.Clan = heroSpouse.Father.Clan;
                    }
                    else if (heroSpouse.Mother != null)
                    {
                        heroSpouse.Clan = heroSpouse.Mother.Clan;
                    }
                    hero.Spouse = null;
                }

                if (spouseHero == null)
                {
                    return;
                }

                if (hero.Clan == spouseHero.Clan)
                {
                    return;
                }

                Hero spouseHeroSpouse = spouseHero.Spouse;

                if (spouseHeroSpouse != null)
                {
                    TextObject textObject3 = GameTexts.FindText("str_CE_spouse_leave");
                    textObject3.SetTextVariable("HERO", hero.Name);
                    textObject3.SetTextVariable("SPOUSE", spouseHeroSpouse.Name);
                    InformationManager.DisplayMessage(new InformationMessage(textObject3.ToString(), Colors.Magenta));

                    if (spouseHeroSpouse.Father != null)
                    {
                        spouseHeroSpouse.Clan = spouseHeroSpouse.Father.Clan;
                    }
                    else if (spouseHeroSpouse.Mother != null)
                    {
                        spouseHeroSpouse.Clan = spouseHeroSpouse.Mother.Clan;
                    }
                    spouseHero.Spouse = null;
                }

                MarriageAction.Apply(hero, spouseHero);
            }
            catch (Exception e)
            {
                CECustomHandler.ForceLogToFile("Failed ChangeSpouse " + e + " HERO1: " + hero + " HERO2: " + spouseHero);
            }
        }
Beispiel #4
0
        private void OnDailyHeroTick(Hero hero)
        {
            // Very early exit conditions:
            if (hero.IsFemale || !hero.IsNoble)
            {
                return;
            }

            // We only evaluate marriage once per human year, and we use an offset to distribute hero
            // marriages more evenly throughout that year:
            int daysOffset  = hero.Id.GetHashCode() % daysPerHumanYear;
            int daysElapsed = (int)Campaign.Current.CampaignStartTime.ElapsedDaysUntilNow;

            // Is this not the right day to do our yearly marriage tick?
            if ((daysElapsed + daysOffset) % daysPerHumanYear != 0)
            {
                return;
            }

            // Does this hero even qualify for a marriage evaluation?
            if (hero.IsDead ||
                !hero.IsActive ||
                hero.Clan is null ||
                hero.Clan.Kingdom is null ||
                (int)hero.Age < minAgeMale ||
                !Campaign.Current.Models.MarriageModel.IsSuitableForMarriage(hero) ||
                hero.Clan.IsClanTypeMercenary ||
                hero.Clan == Clan.PlayerClan)
            {
                return;
            }

            var clanFitness    = GetClanFitness(hero.Clan);
            var marriageChance = GetAnnualMarriageChance(clanFitness);

            Util.Log.Print($"[{CampaignTime.Now}] {GetHeroTrace(hero, clanFitness)}: Considering marriage ({marriageChance * 100:F1}% chance)...");

            if (MBRandom.RandomFloat > marriageChance)
            {
                Util.Log.Print(" -> Decided not to marry for now.");
                return;
            }

            // Find eligible candidates for marriage in order of preference
            var wife = Kingdom.All
                       .Where(k =>
                              !k.IsEliminated &&
                              IsKingdomAllowedForMarriageByConfig(hero, k))
                       .SelectMany(k => k.Clans)
                       .Where(c =>
                              !c.IsEliminated &&
                              !c.IsClanTypeMercenary &&
                              c != Clan.PlayerClan)
                       .SelectMany(c => c.Lords)
                       .Where(h =>
                              h.IsFemale &&
                              h.IsAlive &&
                              h.IsNoble &&
                              h.IsActive &&
                              h.Spouse is null &&
                              IsMaidenAllowedForMarriageByConfig(hero, h) &&
                              Campaign.Current.Models.MarriageModel.IsCoupleSuitableForMarriage(hero, h))
                       .OrderByDescending(h => GetNobleMatchScore(hero, h))
                       .FirstOrDefault();

            var marriageType = string.Empty;

            // Were there no eligible female nobles?
            if (wife is null)
            {
                string spawnMsg = " -> No eligible noble candidates to marry.";

                if (!Config.SpawnNobleWives || Config.SpawnedMarriageChanceMult < 0.01f)
                {
                    Util.Log.Print(spawnMsg);
                    return;
                }

                // If CF >= 3, then we never spawn a wife.
                if (clanFitness >= 3)
                {
                    Util.Log.Print(spawnMsg + " Can't try to spawn wife (clan fitness is too high).");
                    return;
                }

                // Likewise, at 0 < CF < 3, there are restrictions upon spawning a wife based
                // upon how many preexisting children the hero has sired and/or whether they're
                // too old.
                int childCount     = hero.Children.Count();
                int maleChildCount = hero.Children.Where(h => !h.IsFemale).Count();

                if (clanFitness == 2 && (childCount >= 2 || maleChildCount >= 1 || hero.Age >= 60) ||
                    clanFitness == 1 && (childCount >= 3 || maleChildCount >= 2 || hero.Age >= 65))
                {
                    Util.Log.Print(spawnMsg + " Can't try to spawn wife (clan fitness is too high for our prior children / age).");
                    return;
                }

                // Now, the base chance from here (taking into account that our clan fitness level
                // has already significantly affected the odds of reaching this point) is simply
                // 40%, with up to two +5% bonuses or two -5% maluses for however many children short
                // of 2 we do not already have (i.e., in [30%, 50%]).

                float spawnChance = 0.4f + Math.Max(-0.1f, 0.05f * (2 - childCount));
                spawnChance *= Config.SpawnedMarriageChanceMult; // Modified by our config
                var chanceStr = $" (chance was {spawnChance * 100:F0}%)";

                if (MBRandom.RandomFloat > spawnChance)
                {
                    Util.Log.Print(spawnMsg + $" Decided not to spawn wife{chanceStr}.");
                    return;
                }

                Util.Log.Print(spawnMsg + $" Spawning wife{chanceStr}...");
                marriageType = " (spawned)";

                int wifeAgeMin = Campaign.Current.Models.MarriageModel.MinimumMarriageAgeFemale;
                int wifeAgeMax = Math.Min(maxAgeFemale - 5, wifeAgeMin + 5);

                wife = HeroUtil.SpawnNoble(hero.Clan, wifeAgeMin, wifeAgeMax, isFemale: true);

                if (wife is null)
                {
                    Util.Log.Print(" ---> ERROR: Could not find character template to spawn female noble!");
                    return;
                }

                wife.IsFertile = true;
            }

            // Get married!
            Util.Log.Print($" -> MARRIAGE{marriageType}: {GetHeroTrace(wife, GetClanFitness(wife.Clan))}");
            MarriageAction.Apply(hero, wife);
        }
Beispiel #5
0
        private void CastleAbandonSettlementMenuOption(CampaignGameStarter campaignGameStarter)
        {
            campaignGameStarter.AddGameMenuOption("ruler_castle_menu", "ruler_castle_abandon", "Abandon Rulership of Castle", (GameMenuOption.OnConditionDelegate)(args =>
            {
                args.optionLeaveType = GameMenuOption.LeaveType.Manage;
                if (Settlement.CurrentSettlement.OwnerClan.Kingdom != null && Settlement.CurrentSettlement.OwnerClan.Kingdom.Leader != Hero.MainHero)
                {
                    args.Tooltip   = new TextObject("You must be the faction leader to abandon a settlement");
                    args.IsEnabled = false;
                }

                args.Tooltip = new TextObject("A minor noble will take control of the settlement");

                return(true);
            }), (GameMenuOption.OnConsequenceDelegate)(args => {
                InformationManager.ShowInquiry(new InquiryData("Abandon Castle", "Are you sure you want to abandon this castle?", true, true, "Yes", "No", (Action)(() => {
                    List <CharacterObject> source = new List <CharacterObject>();
                    CultureObject culture = Settlement.CurrentSettlement.Culture;
                    foreach (CharacterObject characterObject in CharacterObject.Templates.Where <CharacterObject>((Func <CharacterObject, bool>)(x => x.Occupation == Occupation.Lord)).ToList <CharacterObject>())
                    {
                        if (characterObject.Culture == culture)
                        {
                            source.Add(characterObject);
                        }
                    }
                    CharacterObject template = source[rng.Next(0, source.Count - 1)];
                    Hero NewHero = HeroCreator.CreateSpecialHero(template, Settlement.CurrentSettlement, null, Hero.MainHero.Clan, rng.Next(25, 30));
                    NewHero.ChangeState(Hero.CharacterStates.Active);
                    HeroCreationCampaignBehavior herocreationbehavior = new HeroCreationCampaignBehavior();
                    herocreationbehavior.DeriveSkillsFromTraits(NewHero, template);

                    List <CharacterObject> source2 = new List <CharacterObject>();
                    foreach (CharacterObject characterObject in CharacterObject.Templates.Where <CharacterObject>((Func <CharacterObject, bool>)(x => x.Occupation == Occupation.Lord)).ToList <CharacterObject>())
                    {
                        if (characterObject.Culture == culture)
                        {
                            source2.Add(characterObject);
                        }
                    }
                    CharacterObject template2 = source2[rng.Next(0, source2.Count - 1)];
                    template2.IsFemale = true;
                    Hero NewHero2 = HeroCreator.CreateSpecialHero(template2, Settlement.CurrentSettlement, null, Hero.MainHero.Clan, rng.Next(25, 30));
                    NewHero2.ChangeState(Hero.CharacterStates.Active);
                    herocreationbehavior.DeriveSkillsFromTraits(NewHero2, template2);
                    template2.IsFemale = false;

                    Clan clan = MBObjectManager.Instance.CreateObject <Clan>();
                    Banner ClanBanner = Banner.CreateRandomClanBanner();
                    TextObject clanName = culture.ClanNameList[rng.Next(0, culture.ClanNameList.Count)];
                    clan.InitializeClan(clanName, clanName, culture, ClanBanner);
                    clan.SetLeader(NewHero);
                    FieldInfo field = clan.GetType().GetField("_tier", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                    if ((FieldInfo)null != field)
                    {
                        field.SetValue((object)clan, rng.Next(2, 4));
                    }

                    NewHero.Clan = clan;
                    NewHero.IsNoble = true;
                    MobileParty newMobileParty1 = clan.CreateNewMobileParty(NewHero);
                    newMobileParty1.ItemRoster.AddToCounts(DefaultItems.Grain, 10);
                    newMobileParty1.ItemRoster.AddToCounts(DefaultItems.Meat, 5);

                    NewHero2.Clan = clan;
                    NewHero2.IsNoble = true;
                    MobileParty newMobileParty2 = clan.CreateNewMobileParty(NewHero2);
                    newMobileParty2.ItemRoster.AddToCounts(DefaultItems.Grain, 10);
                    newMobileParty2.ItemRoster.AddToCounts(DefaultItems.Meat, 5);

                    ChangeOwnerOfSettlementAction.ApplyByKingDecision(NewHero, Settlement.CurrentSettlement);
                    clan.UpdateHomeSettlement(Settlement.CurrentSettlement);

                    MarriageAction.Apply(NewHero, NewHero2);
                    ChangeRelationAction.ApplyPlayerRelation(NewHero, 40);
                }), (Action)(() => {
                    GameMenu.SwitchToMenu("castle");
                })), true);
            }), index: 1);;;
        }