private static void conversation_set_up_safe_passage_barter_on_consequence(DialogueParams param)
        {
            BarterManager instance = BarterManager.Instance;
            Hero          oneToOneConversationHero = Hero.OneToOneConversationHero;
            PartyBase     mainParty  = PartyBase.MainParty;
            PartyBase     otherParty = MobileParty.ConversationParty?.Party;

            BarterManager.BarterContextInitializer initContext =
                new BarterManager.BarterContextInitializer(BarterManager.Instance.InitializeSafePassageBarterContext);
            int  persuasionCostReduction = 0;
            bool isAIBarter = false;


            if (Hero.OneToOneConversationHero == null)
            {
                Barterable[] array = new Barterable[1];
                array[0] = new SafePassageBarterable(null, Hero.MainHero, otherParty, PartyBase.MainParty);
                instance.StartBarterOffer(Hero.MainHero, oneToOneConversationHero, mainParty, otherParty, null, initContext,
                                          persuasionCostReduction, isAIBarter, array);
            }
            else
            {
                Barterable[] array = new Barterable[2];
                array[0] = new SafePassageBarterable(oneToOneConversationHero, Hero.MainHero, otherParty, PartyBase.MainParty);
                array[1] = new NoAttackBarterable(Hero.MainHero, oneToOneConversationHero, mainParty,
                                                  otherParty, CampaignTime.Days(5f));
                instance.StartBarterOffer(Hero.MainHero, oneToOneConversationHero, mainParty, otherParty, null,
                                          initContext, persuasionCostReduction, isAIBarter, array);
            }
        }
        /// <summary>
        /// Show an text popup listing Hero current loans.
        /// </summary>
        private void ShowLoans()
        {
            string text = "";

            foreach (var loan in BankAccount.Loans)
            {
                text += $"~ Loan took on {CampaignTime.Days(loan.Date)} for <b>{loan.Amount}</b><img src=\"Icons\\Coin@2x\">\n";
                text += (loan.Remaining == loan.Total)
                    ? $"Daily payments will start on {CampaignTime.Days(loan.PaymentsStartDate)}\n"
                    : $"Daily payments started on {CampaignTime.Days(loan.PaymentsStartDate)}\n";
                text += $"Daily payments will end on {CampaignTime.Days(loan.PaymentsEndDate)}\n";
                text += $"Daily payments: <b>{loan.Payments * -1}</b><img src=\"Icons\\Coin@2x\">\n";
                text += $"Remaining to pay: <b>{loan.Remaining}</b><img src=\"Icons\\Coin@2x\">\n";
                text += $" \n";
                text += $" \n";
            }

            InformationManager.ShowInquiry(new InquiryData(
                                               titleText: $"Your current loans.",
                                               text: text,
                                               isAffirmativeOptionShown: true,
                                               isNegativeOptionShown: false,
                                               affirmativeText: "Ok",
                                               negativeText: "Back",
                                               affirmativeAction: new Action(() => { }),
                                               negativeAction: new Action(() => { })
                                               ), true);
        }
示例#3
0
        private void OnDailyTick()
        {
            bool adultAafEnabled = Main.Settings !.AdultAgeFactor > 1.02f;
            bool childAafEnabled = Main.Settings !.ChildAgeFactor > 1.02f;

            if (CampaignOptions.IsLifeDeathCycleDisabled)
            {
                return;
            }

            PeriodicDeathProbabilityUpdate(adultAafEnabled);

            /* Send childhood growth stage transition events & perform AAF if enabled */

            // Subtract 1 for the daily tick's implicitly-aged day & the rest is
            // explicit, incremental age to add.
            var adultAgeDelta = CampaignTime.Days(Main.Settings.AdultAgeFactor - 1f);
            var childAgeDelta = CampaignTime.Days(Main.Settings.ChildAgeFactor - 1f);

            var oneDay = CampaignTime.Days(1f);

            foreach (var hero in Hero.All)
            {
                if (!hero.IsAlive)
                {
                    continue;
                }

                // When calculating the prevAge, we must take care to include the day
                // which the daily tick implicitly aged us since we last did this, or
                // else we could miss age transitions. Ergo, prevAge is the age we
                // were as if we were one day younger than our current BirthDay.
                int prevAge = (int)(hero.BirthDay + oneDay).ElapsedYearsUntilNow;

                if (adultAafEnabled && !hero.IsChild)
                {
                    hero.SetBirthDay(hero.BirthDay - adultAgeDelta);
                }
                else if (childAafEnabled && hero.IsChild)
                {
                    hero.SetBirthDay(hero.BirthDay - childAgeDelta);
                }

                hero.CharacterObject.Age = hero.Age;

                // And our new age, if different.
                int newAge = (int)hero.Age;

                // Did a relevant transition in age(s) occur?
                if (newAge > prevAge && prevAge < adultAge && !hero.IsTemplate)
                {
                    ProcessAgeTransition(hero, prevAge, newAge);
                }
            }
        }
示例#4
0
        private static bool GetRandomBirthDayForAge(float age, ref CampaignTime __result)
        {
            var   now           = CampaignTime.Now;
            float birthYear     = now.GetYear - age;
            float randDayOfYear = MBRandom.RandomFloatRanged(1, Main.TimeParam.DayPerYear);

            if (randDayOfYear > now.GetDayOfYear)
            {
                --birthYear;
            }

            __result = CampaignTime.Years(birthYear) + CampaignTime.Days(randDayOfYear);
            return(false);
        }
        private void SetStoryVisibleTimeoutIfNeeded(QuestBase quest)
        {
            if (!IsFirstStoryPhase() || !quest.IsSpecialQuest || !quest.IsOngoing)
            {
                return;
            }

            // set visible timeout to be when vanilla would have (silently) timed
            // out the quest,  minus a day to make very sure the quest doesn't
            // somehow trigger vanilla's silent timeout too early.
            CampaignTime newDueTime = FirstPhase.Instance.FirstPhaseStartTime
                                      + CampaignTime.Years(FirstPhaseTimeLimitInYears)
                                      - CampaignTime.Days(1);

            if (quest.QuestDueTime != newDueTime)
            {
                quest.ChangeQuestDueTime(newDueTime);
                ShowNotification(new TextObject("{=QuestTimeRemainingUpdated}Quest time remaining was updated."), "event:/ui/notification/quest_update");
            }
        }
示例#6
0
        private static void Postfix(PregnancyCampaignBehavior __instance)
        {
            CampaignEvents.DailyTickEvent.AddNonSerializedListener(__instance, () =>
            {
                var pregnancies = AccessTools.Field(typeof(PregnancyCampaignBehavior), "_heroPregnancies")
                                  .GetValue(__instance) as IReadOnlyList <object>;
                float timeShiftDays = 1 * LifeIsShortConfig.Instance.AgeMultiplier - 1;

                if (timeShiftDays > 0)
                {
                    foreach (var pregnancy in pregnancies)
                    {
                        var dateField = pregnancy.GetType().GetField("DueDate");
                        var date      = (CampaignTime)dateField.GetValue(pregnancy);
                        var newDate   = CampaignTime.Days((float)date.ToDays - timeShiftDays);
                        dateField.SetValue(pregnancy, newDate);
                    }
                }
            });
        }
示例#7
0
        private void AdjustPregnanciesOnLoad(List <string> trace)
        {
            if (!Main.Settings !.EnablePregnancyTweaks ||
                !Main.Settings.AdjustPregnancyDueDates ||
                (SavedValues.PregnancyDuration == default && !WasVanilla))
            {
                return;
            }

            var pregnancyModel = Campaign.Current.Models.PregnancyModel;
            var newDuration    = pregnancyModel.PregnancyDurationInDays;
            var ourDuration    = Main.Settings.ScaledPregnancyDuration * Main.TimeParam.DayPerYear;
            var oldDuration    = WasVanilla ? VanillaPregnancyDuration : SavedValues.PregnancyDuration;

            // Check whether our pregnancy duration is actually in force (i.e., no interference from other mods).
            if (!Util.NearEqual(ourDuration, newDuration))
            {
                trace.Add($"WARNING: {Main.Name}'s pregnancy duration setting has no effect due to at least " +
                          "one other mod overriding the pregnancy model in a conflicting manner.");
                trace.Add($"Type of pregnancy model: {pregnancyModel.GetType().AssemblyQualifiedName}");
            }

            // Don't bother if the effective old and new durations barely differ if at all.
            if (Util.NearEqual(oldDuration, newDuration, 1e-3f))
            {
                return;
            }

            trace.Add("\nAuto-adjusting in-progress pregnancy due dates due to change in pregnancy duration...\n");

            var dueDateDelta = newDuration - oldDuration;

            trace.Add($"Prior pregnancy duration (days):   {oldDuration:F2}");
            trace.Add($"Current pregnancy duration (days): {newDuration:F2}");
            trace.Add($"Pregnancy due dates will change by {dueDateDelta:F2} days.");

            // We need to iterate over the global List<PregnancyCampaignBehavior.Pregnancy> (Pregnancy is a private
            // nested class) stored in that behavior's private instance field _heroPregnancies. We'll then need to
            // access the Pregnancy.DueDate, a private instance field, for all of those. So let's do some reflection.

            var bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
            var pregListFI   = typeof(PregnancyCampaignBehavior).GetField("_heroPregnancies", bindingFlags);

            if (pregListFI is null)
            {
                trace.Add($"Could not resolve {typeof(PregnancyCampaignBehavior).FullName}._heroPregnancies field! Aborting.");
                return;
            }

            var pregT = typeof(PregnancyCampaignBehavior).GetNestedType("Pregnancy", bindingFlags);

            if (pregT is null)
            {
                trace.Add($"Could not resolve {typeof(PregnancyCampaignBehavior).FullName}.Pregnancy type! Aborting.");
                return;
            }

            var pregDueDateFI = pregT.GetField("DueDate", bindingFlags);

            if (pregDueDateFI is null)
            {
                trace.Add($"Could not resolve {pregT.FullName}.DueDate field! Aborting.");
                return;
            }

            // OK, done setting up reflection info. Start by grabbing the instance of the behavior (gee, a public API!):
            var pregBehavior = GetCampaignBehavior <PregnancyCampaignBehavior>();

            if (pregBehavior is null)
            {
                trace.Add($"Could not find campaign behavior {typeof(PregnancyCampaignBehavior).FullName}! Aborting.");
                return;
            }

            if (pregListFI.GetValue(pregBehavior) is not IReadOnlyList <object> pregList)
            {
                trace.Add($"Could not access {pregListFI.Name} as IReadOnlyList<object>! Aborting.");
                return;
            }

            if (pregList.Count == 0)
            {
                trace.Add("No pregnancies are in-progress. Aborting.");
                return;
            }

            var  dueDateDeltaCT = CampaignTime.Days(dueDateDelta);
            uint nPregs         = 0;

            foreach (var preg in pregList)
            {
                var dueDateCT = (CampaignTime)pregDueDateFI.GetValue(preg);
                pregDueDateFI.SetValue(preg, dueDateCT + dueDateDeltaCT);
                ++nPregs;
            }

            trace.Add($"Adjusted {nPregs} in-progress pregnancies.");
        }
示例#8
0
        public void Import(Hero character, bool updateAppearance)
        {
            string filename = GetSaveName(character);
            bool   isPlayer = Helper.CharacterHasTraitDeveloper(character);
            int?   year = null, season = null, day = null, hour = null;
            long?  remaining = null;
            int?   mercy = null, valor = null, honor = null, generosity = null, calculating = null;
            string culture = null;

            foreach (var keyValuePair in Helper.ReadFile(filename))
            {
                var key   = keyValuePair.Key;
                var value = keyValuePair.Value;

                // Parse
                try
                {
                    // Birthday
                    if (key.Equals("Year"))
                    {
                        year = Convert.ToInt32(value);
                    }
                    else if (key.Equals("Season"))
                    {
                        season = Convert.ToInt32(value);
                    }
                    else if (key.Equals("Day"))
                    {
                        day = Convert.ToInt32(value);
                    }
                    else if (key.Equals("Hour"))
                    {
                        hour = Convert.ToInt32(value);
                    }
                    else if (key.Equals("RemainingTicks"))
                    {
                        remaining = Convert.ToInt64(value);
                    }

                    // Culture
                    else if (key.Equals("Culture"))
                    {
                        culture = value;
                    }

                    // Traits
                    // if the character is the player (who has a trait developer), read the XP
                    else if (isPlayer)
                    {
                        if (key.Equals("MercyXP"))
                        {
                            mercy = Convert.ToInt32(value);
                        }
                        else if (key.Equals("ValorXP"))
                        {
                            valor = Convert.ToInt32(value);
                        }
                        else if (key.Equals("HonorXP"))
                        {
                            honor = Convert.ToInt32(value);
                        }
                        else if (key.Equals("GenerosityXP"))
                        {
                            generosity = Convert.ToInt32(value);
                        }
                        else if (key.Equals("CalculatingXP"))
                        {
                            calculating = Convert.ToInt32(value);
                        }
                    }
                    else
                    {
                        // The character doesn't not have a trait developer (non-player). Directly read the traits.
                        if (key.Equals("Mercy"))
                        {
                            mercy = Convert.ToInt32(value);
                        }
                        else if (key.Equals("Valor"))
                        {
                            valor = Convert.ToInt32(value);
                        }
                        else if (key.Equals("Honor"))
                        {
                            honor = Convert.ToInt32(value);
                        }
                        else if (key.Equals("Generosity"))
                        {
                            generosity = Convert.ToInt32(value);
                        }
                        else if (key.Equals("Calculating"))
                        {
                            calculating = Convert.ToInt32(value);
                        }
                    }
                }
                catch { Helper.ShowAndLog($"Failed to parse {key} for {character}"); return; }
            }

            bool readBirthdaySuccess = false;
            bool readCultureSuccess  = false;
            bool readTraitsSuccess   = false;

            // Read Birthday
            if (year.HasValue &&
                season.HasValue &&
                day.HasValue &&
                hour.HasValue &&
                remaining.HasValue)
            {
                var b = CampaignTime.Years(year.Value) +
                        CampaignTime.Seasons(season.Value) +
                        CampaignTime.Days(day.Value) +
                        CampaignTime.Hours(hour.Value);
                long newTicks = b.GetTicks();
                newTicks += remaining.Value;

                var newBirthDay = Helper.CreateCampaignTime(newTicks);
                character.BirthDay = newBirthDay;
                // Update character model
                if (updateAppearance)
                {
                    var dps = character.BodyProperties.DynamicProperties;
                    dps.Age = character.Age;

                    typeof(BodyProperties)
                    .GetField("_dynamicBodyProperties", BindingFlags.Instance | BindingFlags.NonPublic)
                    .SetValue(character.BodyProperties, dps);
                }

                readBirthdaySuccess = true;
            }

            // Read Culture
            if (culture != null)
            {
                CultureCode c;
                if (Enum.TryParse(culture, true, out c) == false)
                {
                    c = CultureCode.Invalid;
                }

                if (c != CultureCode.Invalid)
                {
                    var heroOfThisCulture = Hero.FindFirst((h) => h.Culture.GetCultureCode() == c);
                    if (heroOfThisCulture != null)
                    {
                        character.CharacterObject.Culture = heroOfThisCulture.CharacterObject.Culture;
                        if (character.Clan.Leader == character)
                        {
                            character.Clan.Culture = character.CharacterObject.Culture; // Clan culture changes too
                        }
                        readCultureSuccess = true;
                    }
                    else
                    {
                        //Helper.ShowAndLog($"{character.Name}'s culture not imported: Can't set to culture \"{c.ToString()}\"!");
                    }
                }
                else
                {
                    //Helper.ShowAndLog($"{character.Name}'s culture not imported: Invalid culture \"{culture}\"!");
                }
            }
            else
            {
                //Helper.ShowAndLog($"{character.Name}'s culture not imported: culture value is empty!");
            }

            // Read Traits
            if (mercy.HasValue &&
                valor.HasValue &&
                honor.HasValue &&
                generosity.HasValue &&
                calculating.HasValue)
            {
                if (isPlayer)
                {
                    var ptd              = Campaign.Current.PlayerTraitDeveloper;
                    var deltaMercy       = mercy.Value - ptd.GetPropertyValue(DefaultTraits.Mercy);
                    var deltaValor       = valor.Value - ptd.GetPropertyValue(DefaultTraits.Valor);
                    var deltaHonor       = honor.Value - ptd.GetPropertyValue(DefaultTraits.Honor);
                    var deltaGenerosity  = generosity.Value - ptd.GetPropertyValue(DefaultTraits.Generosity);
                    var deltaCalculating = calculating.Value - ptd.GetPropertyValue(DefaultTraits.Calculating);

                    if (deltaMercy != 0)
                    {
                        ptd.AddTraitXp(DefaultTraits.Mercy, deltaMercy);
                    }
                    if (deltaValor != 0)
                    {
                        ptd.AddTraitXp(DefaultTraits.Valor, deltaValor);
                    }
                    if (deltaHonor != 0)
                    {
                        ptd.AddTraitXp(DefaultTraits.Honor, deltaHonor);
                    }
                    if (deltaGenerosity != 0)
                    {
                        ptd.AddTraitXp(DefaultTraits.Generosity, deltaGenerosity);
                    }
                    if (deltaCalculating != 0)
                    {
                        ptd.AddTraitXp(DefaultTraits.Calculating, deltaCalculating);
                    }
                }
                else
                {
                    // It will clamp to min max value in SetTraitLevel()
                    character.SetTraitLevel(DefaultTraits.Mercy, mercy.Value);
                    character.SetTraitLevel(DefaultTraits.Valor, valor.Value);
                    character.SetTraitLevel(DefaultTraits.Honor, honor.Value);
                    character.SetTraitLevel(DefaultTraits.Generosity, generosity.Value);
                    character.SetTraitLevel(DefaultTraits.Calculating, calculating.Value);
                }

                readTraitsSuccess = true;
            }

            string msg = $"Imported {character.Name}'s ";

            if (readBirthdaySuccess && readCultureSuccess && readTraitsSuccess)
            {
                msg += "birthday, culture and traits.";
            }
            else if (readBirthdaySuccess && readCultureSuccess && !readTraitsSuccess)
            {
                msg += "birthday and culture.";
            }
            else if (readBirthdaySuccess && !readCultureSuccess && readTraitsSuccess)
            {
                msg += "birthday and traits.";
            }
            else if (!readBirthdaySuccess && readCultureSuccess && readTraitsSuccess)
            {
                msg += "culture and traits.";
            }
            else if (readBirthdaySuccess && !readCultureSuccess && !readTraitsSuccess)
            {
                msg += "birthday.";
            }
            else if (!readBirthdaySuccess && readCultureSuccess && !readTraitsSuccess)
            {
                msg += "culture.";
            }
            else if (!readBirthdaySuccess && !readCultureSuccess && readTraitsSuccess)
            {
                msg += "traits.";
            }
            else
            {
                msg = null;
            }
            if (msg != null)
            {
                Helper.ShowAndLog(msg + $" Appearance {(updateAppearance ? string.Empty : "not")} updated.", new Color(0, 1, 0));
            }
        }
示例#9
0
        public void Export(Hero character)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("//Lines started with // are comments.");
            sb.AppendLine(string.Empty);
            sb.AppendLine("//Readme:");
            sb.AppendLine("//Season ranges from 0 to 3. Spring is 0 and Autumn is 2, for example.");
            sb.AppendLine("//Day starts with 0. So if your birthday is Summer 11, Day should be 10.");
            sb.AppendLine("//Use the field \"FormattedBirthday\" to check what your birthday is, after export.");
            sb.AppendLine("//If you want to modify RemainingTicks, remember there are 10000 ticks per game second.");
            sb.AppendLine("//Traits range from -2 to 2.");
            sb.AppendLine(Environment.NewLine);
            sb.AppendLine($"//{character.Name}'s birthday:");
            sb.AppendLine($"Year={character.BirthDay.GetYear}");
            sb.AppendLine($"Season={character.BirthDay.GetSeasonOfYear}");
            sb.AppendLine($"Day={character.BirthDay.GetDayOfSeason}");
            sb.AppendLine($"Hour={character.BirthDay.GetHourOfDay}");
            // Get remaining ticks so we don't lose any milliseconds.
            var b = CampaignTime.Years(character.BirthDay.GetYear) +
                    CampaignTime.Seasons(character.BirthDay.GetSeasonOfYear) +
                    CampaignTime.Days(character.BirthDay.GetDayOfSeason) +
                    CampaignTime.Hours(character.BirthDay.GetHourOfDay);

            sb.AppendLine($"RemainingTicks={(character.BirthDay - b).GetTicks()}");
            sb.AppendLine(Environment.NewLine);

            // Culture
            sb.AppendLine("//Culture:");
            sb.AppendLine($"Culture={character.Culture.GetName()}");
            sb.AppendLine(Environment.NewLine);

            // Is this character the player?
            bool isPlayer = Helper.CharacterHasTraitDeveloper(character);

            // Traits
            string traitPromptStr = isPlayer ? " (Read only. Modify Trait XP to change traits)" : string.Empty;

            sb.AppendLine($"//Traits{traitPromptStr}:");
            var traits = character.GetHeroTraits();

            sb.AppendLine($"Mercy={traits.Mercy}");
            sb.AppendLine($"Valor={traits.Valor}");
            sb.AppendLine($"Honor={traits.Honor}");
            sb.AppendLine($"Generosity={traits.Generosity}");
            sb.AppendLine($"Calculating={traits.Calculating}");
            sb.AppendLine(Environment.NewLine);

            // Trait XP
            if (isPlayer)
            {
                sb.AppendLine("//Trait XP:");
                sb.AppendLine($"MercyXP={Campaign.Current.PlayerTraitDeveloper.GetPropertyValue(DefaultTraits.Mercy)}");
                sb.AppendLine($"ValorXP={Campaign.Current.PlayerTraitDeveloper.GetPropertyValue(DefaultTraits.Valor)}");
                sb.AppendLine($"HonorXP={Campaign.Current.PlayerTraitDeveloper.GetPropertyValue(DefaultTraits.Honor)}");
                sb.AppendLine($"GenerosityXP={Campaign.Current.PlayerTraitDeveloper.GetPropertyValue(DefaultTraits.Generosity)}");
                sb.AppendLine($"CalculatingXP={Campaign.Current.PlayerTraitDeveloper.GetPropertyValue(DefaultTraits.Calculating)}");
                sb.AppendLine(Environment.NewLine);
            }

            // Output.
            sb.AppendLine("//Don't modify this field as it will not be read.");
            sb.AppendLine($"FormattedBirthday={character.BirthDay.ToString()}");
            for (int i = DefaultTraits.Mercy.MinValue; i <= DefaultTraits.Mercy.MaxValue; ++i)
            {
                sb.AppendLine($"MercyXPRequired{i}={Campaign.Current.Models.CharacterDevelopmentModel.GetTraitXpRequiredForTraitLevel(DefaultTraits.Mercy, i)}");
            }
            for (int i = DefaultTraits.Valor.MinValue; i <= DefaultTraits.Valor.MaxValue; ++i)
            {
                sb.AppendLine($"ValorXPRequired{i}={Campaign.Current.Models.CharacterDevelopmentModel.GetTraitXpRequiredForTraitLevel(DefaultTraits.Valor, i)}");
            }
            for (int i = DefaultTraits.Honor.MinValue; i <= DefaultTraits.Honor.MaxValue; ++i)
            {
                sb.AppendLine($"HonorXPRequired{i}={Campaign.Current.Models.CharacterDevelopmentModel.GetTraitXpRequiredForTraitLevel(DefaultTraits.Honor, i)}");
            }
            for (int i = DefaultTraits.Generosity.MinValue; i <= DefaultTraits.Generosity.MaxValue; ++i)
            {
                sb.AppendLine($"GenerosityXPRequired{i}={Campaign.Current.Models.CharacterDevelopmentModel.GetTraitXpRequiredForTraitLevel(DefaultTraits.Generosity, i)}");
            }
            for (int i = DefaultTraits.Calculating.MinValue; i <= DefaultTraits.Calculating.MaxValue; ++i)
            {
                sb.AppendLine($"CalculatingXPRequired{i}={Campaign.Current.Models.CharacterDevelopmentModel.GetTraitXpRequiredForTraitLevel(DefaultTraits.Calculating, i)}");
            }
            File.WriteAllText(this.GetSaveName(character), sb.ToString());

            Helper.ShowAndLog($"Exported {character.Name}'s birthday, culture and traits.");
        }
示例#10
0
 private static void TimeShift(Hero hero, float timeShiftDays)
 {
     hero.BirthDay = CampaignTime.Days((float)hero.BirthDay.ToDays - timeShiftDays);
 }
示例#11
0
        private void OnDailyTick()
        {
            bool aafEnabled = !Util.NearEqual(Main.Settings !.AgeFactor, 1f, 1e-2);

            /* Update Hero Death Probabilities */

            int daysElapsed  = (int)Campaign.Current.CampaignStartTime.ElapsedDaysUntilNow;
            int updatePeriod = !aafEnabled ? Main.TimeParam.DayPerYear : (int)(Main.TimeParam.DayPerYear / Main.Settings.AgeFactor);

            if (updatePeriod <= 0)
            {
                updatePeriod = 1;
            }

            // Globally update death probabilities every year of accumulated age
            if (daysElapsed % updatePeriod == 0)
            {
                UpdateHeroDeathProbabilities !();
            }

            /* Send childhood growth stage transition events & perform AAF if enabled */

            // Subtract 1 for the daily tick's implicitly-aged day & the rest is
            // explicit, incremental age to add.
            var birthDayDelta = CampaignTime.Days(Main.Settings.AgeFactor - 1f);

            // And this is just hoisted.
            var oneDay = CampaignTime.Days(1f);

            foreach (var hero in Hero.All)
            {
                if (hero.IsDead)
                {
                    continue;
                }

                // When calculating the prevAge, we must take care to include the day
                // which the daily tick implicitly aged us since we last did this, or
                // else we could miss age transitions. Ergo, prevAge is the age we
                // were as if we were one day younger than our current BirthDay.
                int prevAge = (int)(hero.BirthDay + oneDay).ElapsedYearsUntilNow;

                if (aafEnabled)
                {
                    hero.BirthDay           -= birthDayDelta;
                    hero.CharacterObject.Age = hero.Age;
                }

                // And our new age, if different.
                int newAge = (int)hero.Age;

                // Did a relevant transition in age(s) occur?
                if (newAge > prevAge && prevAge < adultAge && !hero.IsTemplate)
                {
                    // Loop over the aged years (extremely aggressive Days Per Season + AAF
                    // could make it multiple), and thus we need to be able to handle the
                    // possibility of multiple growth stage events needing to be fired.

                    for (int age = prevAge + 1; age <= Math.Min(newAge, adultAge); ++age)
                    {
                        // Replacement for EducationCampaignBehavior.OnDailyTick()
                        //
                        // On e1.5.5, they've disabled the EducationCampaignBehavior, but I'm going to
                        // continue calling DoEducation so long as the child isn't yet of age, because
                        // that seems at worst harmless. What crashes (and not in e1.5.5 because they
                        // removed all of the behavior's event listeners, which is what we'll do for
                        // our e1.5.4 version) is when their OnHeroComesOfAge event listener runs.
                        if (hero.Clan == Clan.PlayerClan && GetChildAgeState(age) != ChildAgeState.Invalid)
                        {
                            DoEducation !(hero);

                            // WTF is this doing after the DoEducation call? Magic, or TaleWorlds f*****g up?
                            new TextObject("{=Z5qYQV08}Your kin has reached the age of {CHILD.AGE} and needs your guidance on "
                                           + "{?CHILD.GENDER}her{?}his{\\?} development.", null)
                            .SetCharacterProperties("CHILD", hero.CharacterObject, null, false);
                        }

                        // This replaces AgingCampaignBehavior.OnDailyTick's campaign event triggers:

                        if (age == childAge)
                        {
                            OnHeroGrowsOutOfInfancy(hero);
                        }

                        if (age == teenAge)
                        {
                            OnHeroReachesTeenAge(hero);
                        }

                        if (age == adultAge && !hero.IsActive)
                        {
                            OnHeroComesOfAge(hero);
                        }
                    }
                }
            }
        }
示例#12
0
        private void OnDailyTickClan(Clan clan)
        {
            if (!SeparatismConfig.Settings.AnarchyRebellionsEnabled)
            {
                return;
            }

            var clanFiefsAmount = clan.GetFiefsAmount();

            if (clanFiefsAmount < SeparatismConfig.Settings.CriticalAmountOfFiefsPerSingleClan)
            {
                return;
            }
            var anarchySettlements = clan.Settlements.Where(x => x.IsTown &&
                                                            CampaignTime.Hours(x.LastVisitTimeOfOwner) + CampaignTime.Days(SeparatismConfig.Settings.NumberOfDaysAfterOwnerVisitToKeepOrder) < CampaignTime.Now).ToArray();

            if (anarchySettlements.Length == 0)
            {
                return;
            }

            var availableClans = Clan.All.ReadyToGo().ToArray();

            foreach (var settlement in anarchySettlements.OrderByDescending(x => x.Position2D.Distance(clan.FactionMidPoint)))
            {
                var newRulerClan = availableClans
                                   .Where(x => x.Culture == settlement.Culture)
                                   .OrderByDescending(x => x.TotalStrength)
                                   .FirstOrDefault();
                var rebelRightNow = SeparatismConfig.Settings.DailyAnarchyRebellionChance >= 1 ||
                                    (MBRandom.RandomFloat <= SeparatismConfig.Settings.DailyAnarchyRebellionChance);

                if (newRulerClan != null && rebelRightNow)
                {
                    var rebelSettlements = new List <Settlement>();
                    rebelSettlements.Add(settlement);
                    int bonusSettlements = (SeparatismConfig.Settings.BonusRebelFiefForHighTierClan && newRulerClan.Tier > 4) ? 1 : 0;
                    if (bonusSettlements > 0)
                    {
                        var neighborClanFiefs = new Queue <Settlement>(Settlement
                                                                       .FindSettlementsAroundPosition(settlement.Position2D, 50, x => x.OwnerClan == clan)
                                                                       .Where(x => x.IsCastle)
                                                                       .Except(rebelSettlements)
                                                                       .OrderBy(x => x.Position2D.Distance(settlement.Position2D)));
                        while (bonusSettlements > 0 && neighborClanFiefs.Count > 0)
                        {
                            var nextFief = neighborClanFiefs.Dequeue();
                            if (nextFief.Culture == settlement.Culture)
                            {
                                rebelSettlements.Add(nextFief);
                                bonusSettlements--;
                            }
                        }
                    }

                    var rebelKingdom = GoRebelKingdom(newRulerClan, rebelSettlements);
                    var textObject   = new TextObject("{=Separatism_Anarchy_Rebel}People of {Settlement} have broken from {Kingdom} to call {Ruler} on rulership and found the {RebelKingdom}.", null);
                    textObject.SetTextVariable("Settlement", settlement.Name);
                    textObject.SetTextVariable("Kingdom", clan.Kingdom.Name);
                    textObject.SetTextVariable("Ruler", newRulerClan.Leader.Name);
                    textObject.SetTextVariable("RebelKingdom", rebelKingdom.Name);
                    GameLog.Warn(textObject.ToString());
                    return;
                }
            }
        }