diff --git a/Changelog.txt b/Changelog.txt index d7847dd..3906979 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,4 +1,9 @@ -Version 1.6.5 +Version 1.6.6 + +- Rework OutsideConnectionAI patch for greater robustness + + +Version 1.6.5 - Add support for wall-to-wall residential buildings as separate transport mode probability category - Mod conflict detection now takes place on enabling the mod (so you don't have to load a city to find out if there's a conflict) diff --git a/Code/Loading.cs b/Code/Loading.cs index 247a1c0..07bbc29 100644 --- a/Code/Loading.cs +++ b/Code/Loading.cs @@ -31,6 +31,8 @@ protected override void LoadedActions(LoadMode mode) // Prime Threading.counter to continue from frame index. int temp = (int)(Singleton.instance.m_currentFrameIndex / 4096u); Threading.Counter = temp % DataStore.LifeSpanMultiplier; + + PatcherManager.Instance.ListMethods(); } } } diff --git a/Code/Patches/OutsideConnectionAIPatches.cs b/Code/Patches/OutsideConnectionAIPatches.cs index 7256c81..c6834ca 100644 --- a/Code/Patches/OutsideConnectionAIPatches.cs +++ b/Code/Patches/OutsideConnectionAIPatches.cs @@ -11,6 +11,7 @@ namespace LifecycleRebalance using System.Reflection.Emit; using AlgernonCommons; using ColossalFramework; + using ColossalFramework.Math; using HarmonyLib; /// @@ -31,15 +32,12 @@ public static class OutsideConnectionAIPatches public static IEnumerable Transpiler(MethodBase original, IEnumerable instructions, ILGenerator generator) { // Local variable ILCode indexes (original method). - const int EducationVarIndex = 3; + const int EducationVarIndex = 2; const int NumVarIndex = 3; const int ILoopVarIndex = 17; const int AgeVarIndex = 21; const int Education2VarIndex = 22; - // Not used in patch - for determining patch location. - const int flag4VarIndex = 23; - Logging.Message("starting StartConnectionTransferImpl transpiler"); // Local variables used by the patch. @@ -100,7 +98,7 @@ public static IEnumerable Transpiler(MethodBase original, IEnum { instruction = instructionsEnumerator.Current; } - while ((instruction.opcode != OpCodes.Stloc_S || !(instruction.operand is LocalBuilder builder && builder.LocalIndex == flag4VarIndex)) && instructionsEnumerator.MoveNext()); + while ((instruction.opcode != OpCodes.Stloc_S || !(instruction.operand is LocalBuilder builder && builder.LocalIndex == Education2VarIndex)) && instructionsEnumerator.MoveNext()); // Load required variables for patch method onto stack. yield return new CodeInstruction(OpCodes.Ldloc_S, ILoopVarIndex) { labels = startForLabels }; @@ -179,59 +177,66 @@ public static void RandomizeImmigrants(int i, Citizen.Education education, int[] // Set default eductation output to what the game has already determined. resultEducation = education; - // Apply education level randomisation if that option is selected. - if (ModSettings.Settings.RandomImmigrantEd) + if (education < Citizen.Education.Uneducated || resultEducation > Citizen.Education.ThreeSchools) + { + Logging.Error("invalid starting education level ", education); + } + + // Calculate education levels. + if (i < 2) { - if (i < 2) + // Adults (set education levels). + // Local references. + ref Randomizer simulationRandomizer = ref Singleton.instance.m_randomizer; + ModSettings settings = ModSettings.Settings; + + // 24% different education levels. + int eduModifier = settings.RandomImmigrantEd ? simulationRandomizer.Int32(-12, 12) / 10 : 0; + + if (settings.ImmiEduBoost) { - // Adults. - // 24% different education levels - int eduModifier = Singleton.instance.m_randomizer.Int32(-12, 12) / 10; - resultEducation += eduModifier; - if (resultEducation < Citizen.Education.Uneducated) - { - resultEducation = Citizen.Education.Uneducated; - } - else if (resultEducation > Citizen.Education.ThreeSchools) - { - resultEducation = Citizen.Education.ThreeSchools; - } - - // Apply education boost, if enabled, and if we're not already at the max. - if (ModSettings.Settings.ImmiEduBoost && resultEducation < Citizen.Education.ThreeSchools) - { - ++resultEducation; - } + // Education boost - 50% chance. + eduModifier += simulationRandomizer.Int32(0, 1); } - else + else if (settings.ImmiEduDrag) { - // Children. - switch (Citizen.GetAgeGroup(resultAge)) - { - case Citizen.AgeGroup.Child: - resultEducation = Citizen.Education.Uneducated; - break; - case Citizen.AgeGroup.Teen: - resultEducation = Citizen.Education.OneSchool; - break; - default: - // Make it that 80% graduate from high school - resultEducation = (Singleton.instance.m_randomizer.Int32(0, 100) < 80) ? Citizen.Education.TwoSchools : Citizen.Education.OneSchool; - break; - } + // Education drag - 50% chance. + eduModifier -= simulationRandomizer.Int32(0, 1); } - } - // Apply education suppression, if enabled, and if we're not already at the min. - if (ModSettings.Settings.ImmiEduDrag && resultEducation > Citizen.Education.Uneducated) + // Apply education modifier and clamp bounds. + resultEducation += eduModifier; + if (resultEducation < Citizen.Education.Uneducated) + { + resultEducation = Citizen.Education.Uneducated; + } + else if (resultEducation > Citizen.Education.ThreeSchools) + { + resultEducation = Citizen.Education.ThreeSchools; + } + } + else { - --resultEducation; + // Children (set education levels). + switch (Citizen.GetAgeGroup(resultAge)) + { + case Citizen.AgeGroup.Child: + resultEducation = Citizen.Education.Uneducated; + break; + case Citizen.AgeGroup.Teen: + resultEducation = Citizen.Education.OneSchool; + break; + default: + // Make it that 80% graduate from high school + resultEducation = (Singleton.instance.m_randomizer.Int32(0, 100) < 80) ? Citizen.Education.TwoSchools : Citizen.Education.OneSchool; + break; + } } // Write to immigration log if that option is selected. if (LifecycleLogging.UseImmigrationLog) { - LifecycleLogging.WriteToLog(LifecycleLogging.ImmigrationLogName, "Family member ", i, " immigrating with age ", resultAge, " (" + (int)(resultAge / ModSettings.AgePerYear), " years old) and education level ", education); + LifecycleLogging.WriteToLog(LifecycleLogging.ImmigrationLogName, "Family member ", i, " immigrating with age ", resultAge, " (" + (int)(resultAge / ModSettings.AgePerYear), " years old) and education level ", resultEducation, " from original education level ", education); } } diff --git a/Lifecycle Rebalance Revisited.csproj b/Lifecycle Rebalance Revisited.csproj index 1b833fb..08e6602 100644 --- a/Lifecycle Rebalance Revisited.csproj +++ b/Lifecycle Rebalance Revisited.csproj @@ -7,7 +7,7 @@ algernon Copyright © 2022 algernon $(Title) - 1.6.5 + 1.6.5.1 $(MSBuildProgramFiles32)/Steam/steamapps/common/Cities_Skylines/Cities_Data/Managed $(AssemblySearchPaths);