diff --git a/About/About.xml b/About/About.xml index f7db2b21..0d87b41a 100644 --- a/About/About.xml +++ b/About/About.xml @@ -19,7 +19,7 @@ - Version 1.1.9 + Version 1.1.10 This mod force prisoners to work. To enable this feature prisoners must have "Force to work" option checked ("Prisoner" tab). Prison labor needs management that consist: - Motivation - prisoners need to be motivated by presence of colonists. Wardens have new job - supervising prisoners. Low motivation can lead to revolts. diff --git a/Assemblies/PrisonLabor.dll b/Assemblies/PrisonLabor.dll index cbd6e551..43d4f7c7 100644 Binary files a/Assemblies/PrisonLabor.dll and b/Assemblies/PrisonLabor.dll differ diff --git a/Languages/English/Keyed/Keys.xml b/Languages/English/Keyed/Keys.xml index e7b61e7a..e5276874 100644 --- a/Languages/English/Keyed/Keys.xml +++ b/Languages/English/Keyed/Keys.xml @@ -80,4 +80,7 @@ Enable prisoner suicide Enables suicide of prisoners when they aren't very happy + + Enable prisoner full heal rest + Prisoner will stay in bed until fully healed diff --git a/README.md b/README.md index fb990668..806862c4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

- v1.1.9 + v1.1.10

diff --git a/Source/Core/AI/JobGivers/JobGiver_Labor.cs b/Source/Core/AI/JobGivers/JobGiver_Labor.cs index 2fe65c5a..f76e92a4 100644 --- a/Source/Core/AI/JobGivers/JobGiver_Labor.cs +++ b/Source/Core/AI/JobGivers/JobGiver_Labor.cs @@ -35,8 +35,13 @@ public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobPara if (pawn.timetable == null) WorkSettings.InitWorkSettings(pawn); - if (HealthAIUtility.ShouldHaveSurgeryDoneNow(pawn) || HealthAIUtility.ShouldBeTendedNowByPlayer(pawn) || HealthAIUtility.ShouldSeekMedicalRest(pawn)) + if (HealthAIUtility.ShouldHaveSurgeryDoneNow(pawn)) return ThinkResult.NoJob; + + if(PrisonLaborPrefs.EnableFullHealRest && (HealthAIUtility.ShouldBeTendedNowByPlayer(pawn) || HealthAIUtility.ShouldSeekMedicalRest(pawn))) + { + return ThinkResult.NoJob; + } //Check medical assistance, fed, and rest if not override if (!PrisonLaborUtility.WorkTime(pawn)) { diff --git a/Source/Core/Meta/Prefs.cs b/Source/Core/Meta/Prefs.cs index 84dc0ebe..78fb1e20 100644 --- a/Source/Core/Meta/Prefs.cs +++ b/Source/Core/Meta/Prefs.cs @@ -154,6 +154,17 @@ public static string AllowedWorkTypes } } + public static bool EnableFullHealRest + { + get { return data.enable_full_heal_rest; } + + set + { + data.enable_full_heal_rest = value; + Apply(); + } + } + public static void Init() { var flag = !new FileInfo(prefsFilePath).Exists; diff --git a/Source/Core/Meta/PrefsData.cs b/Source/Core/Meta/PrefsData.cs index 018039ff..cbdcfb35 100644 --- a/Source/Core/Meta/PrefsData.cs +++ b/Source/Core/Meta/PrefsData.cs @@ -14,6 +14,7 @@ public class PrisonLaborPrefsData public bool enable_revolts = true; public bool show_treatment_happiness = false; public bool enable_suicide = true; + public bool enable_full_heal_rest = true; public Version last_version = Version.v0_0; public bool show_news = true; diff --git a/Source/Core/Meta/Version.cs b/Source/Core/Meta/Version.cs index b16d338f..d9de4093 100644 --- a/Source/Core/Meta/Version.cs +++ b/Source/Core/Meta/Version.cs @@ -59,6 +59,7 @@ public enum Version v1_1_6, v1_1_7, v1_1_8, - v1_1_9 + v1_1_9, + v1_1_10 } } diff --git a/Source/Core/Meta/VersionUtility.cs b/Source/Core/Meta/VersionUtility.cs index ff82ffc0..e4a6ab83 100644 --- a/Source/Core/Meta/VersionUtility.cs +++ b/Source/Core/Meta/VersionUtility.cs @@ -5,8 +5,8 @@ namespace PrisonLabor.Core.Meta { class VersionUtility { - public const Version versionNumber = Version.v1_1_9; - public const string versionString = "1.1.9"; + public const Version versionNumber = Version.v1_1_10; + public const string versionString = "1.1.10"; public static Version VersionOfSaveFile { get; set; } diff --git a/Source/Core/Settings/SettingsMenu.cs b/Source/Core/Settings/SettingsMenu.cs index d5636961..b50e5991 100644 --- a/Source/Core/Settings/SettingsMenu.cs +++ b/Source/Core/Settings/SettingsMenu.cs @@ -19,6 +19,7 @@ internal class SettingsMenu : Mod private static bool enableRevolts; private static bool showTreatmentHappiness; private static bool enableSuicide; + private static bool enableFullHealRest; private static bool advancedGrowing; private static int defaultInteractionMode; @@ -38,6 +39,7 @@ public static void Init() enableRevolts = PrisonLaborPrefs.EnableRevolts; enableSuicide = PrisonLaborPrefs.EnableSuicide; showTreatmentHappiness = PrisonLaborPrefs.ShowTreatmentHappiness; + enableFullHealRest = PrisonLaborPrefs.EnableFullHealRest; interactionModeList = new List(DefDatabase.AllDefs); defaultInteractionMode = interactionModeList.IndexOf(DefDatabase.GetNamed(PrisonLaborPrefs.DefaultInteractionMode)); @@ -102,6 +104,10 @@ public override void DoSettingsWindowContents(Rect inRect) listing_options.CheckboxLabeled("PrisonLabor_EnableSuicide".Translate(), ref enableSuicide, "PrisonLabor_EnableSuicideDesc".Translate()); + listing_options.CheckboxLabeled("PrisonLabor_EnableFullHealRest".Translate(), ref enableFullHealRest, + "PrisonLabor_EnableFullHealRestDesc".Translate()); + + listing_options.GapLine(); listing_options.CheckboxLabeled("PrisonLabor_ShowTreatmentHappiness".Translate(), ref showTreatmentHappiness, @@ -169,6 +175,7 @@ public override void WriteSettings() PrisonLaborPrefs.ShowTreatmentHappiness = showTreatmentHappiness; PrisonLaborPrefs.AdvancedGrowing = advancedGrowing; PrisonLaborPrefs.EnableSuicide = enableSuicide; + PrisonLaborPrefs.EnableFullHealRest = enableFullHealRest; PrisonLaborPrefs.DefaultInteractionMode = interactionModeList[defaultInteractionMode].defName; PrisonLaborPrefs.Save(); Log.Message("Prison Labor settings saved"); diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_BlueprintsForPlayerFAction.cs b/Source/HarmonyPatches/Patches_Construction/Patch_BlueprintsForPlayerFAction.cs new file mode 100644 index 00000000..82cebc91 --- /dev/null +++ b/Source/HarmonyPatches/Patches_Construction/Patch_BlueprintsForPlayerFAction.cs @@ -0,0 +1,32 @@ +using HarmonyLib; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Management.Instrumentation; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Verse; + +namespace PrisonLabor.HarmonyPatches.Patches_Construction +{ + [HarmonyPatch(typeof(Blueprint), "TryReplaceWithSolidThing")] + class Patch_BlueprintsForPlayerFaction + { + + public static void Postfix(Pawn workerPawn, Thing createdThing, bool __result) + { + + if (__result && createdThing != null && createdThing.def.CanHaveFaction && workerPawn.IsPrisonerOfColony) + { +#if DEBUG + Log.Message($"Setting faction for: {createdThing}"); +#endif + createdThing.SetFactionDirect(Faction.OfPlayer); + } + + } + + } +} diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_Smoothing.cs b/Source/HarmonyPatches/Patches_Construction/Patch_Smoothing.cs new file mode 100644 index 00000000..a9a60a26 --- /dev/null +++ b/Source/HarmonyPatches/Patches_Construction/Patch_Smoothing.cs @@ -0,0 +1,33 @@ +using HarmonyLib; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; + +namespace PrisonLabor.HarmonyPatches.Patches_Construction +{ + [HarmonyPatch()] + class Patch_Smoothing + { + static IEnumerable TargetMethods() + { + yield return (MethodBase)typeof(WorkGiver_ConstructSmoothWall).GetMethod("HasJobOnCell"); + yield return (MethodBase)typeof(WorkGiver_ConstructAffectFloor).GetMethod("HasJobOnCell"); + } + + public static bool Postfix(bool __result, Pawn pawn, IntVec3 c) + { + if(__result && pawn.IsPrisonerOfColony) + { + return pawn.CanReach(c, PathEndMode.Touch, pawn.NormalMaxDanger()); + } + + return __result; + } + } +} diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs new file mode 100644 index 00000000..19fd9221 --- /dev/null +++ b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs @@ -0,0 +1,57 @@ +using HarmonyLib; +using PrisonLabor.WorkUtils; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; + +namespace PrisonLabor.HarmonyPatches.Patches_Construction +{ + [HarmonyPatch(typeof(WorkGiver_ConstructDeliverResourcesToFrames))] + [HarmonyPatch("JobOnThing")] + [HarmonyPatch(new[] { typeof(Pawn), typeof(Thing), typeof(bool) })] + class Patch_WorkGiver_ConstructDeliverResourcesToFrames + { + static IEnumerable Transpiler(IEnumerable instructions) + { + + OpCode[] opCodes1 = + { + OpCodes.Ldarg_2, + OpCodes.Callvirt, + OpCodes.Ldarg_1, + OpCodes.Callvirt, + OpCodes.Beq_S, + }; + string[] operands1 = + { + "", + "RimWorld.Faction get_Faction()", + "", + "RimWorld.Faction get_Faction()", + "System.Reflection.Emit.Label", + }; + + + var label = HPatcher.FindOperandAfter(opCodes1, operands1, instructions, true); + + //Add If(pawn.IsPrisonerOfColony) {jump next condition} + yield return new CodeInstruction(OpCodes.Ldarg_2); + yield return new CodeInstruction(OpCodes.Ldarg_1); + yield return new CodeInstruction(OpCodes.Call, typeof(ConstructionUtils).GetMethod("isPrisonerWork")); + yield return new CodeInstruction(OpCodes.Brtrue, label); + + foreach (var instr in instructions) + { + yield return instr; + } + + } + } +} diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs new file mode 100644 index 00000000..58ee8166 --- /dev/null +++ b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs @@ -0,0 +1,60 @@ +using HarmonyLib; +using PrisonLabor.WorkUtils; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; + +namespace PrisonLabor.HarmonyPatches.Patches_Construction +{ + [HarmonyPatch(typeof(WorkGiver_Repair))] + class Patch_WorkGiver_Repair + { + [HarmonyPrefix] + [HarmonyPatch("ShouldSkip")] + [HarmonyPatch(new[] { typeof(Pawn), typeof(bool) })] + static bool ShouldSKipPrefix(ref bool __result, Pawn pawn, bool forced) + { + if(pawn.IsPrisonerOfColony) + { + __result = pawn.Map.listerBuildingsRepairable.RepairableBuildings(Faction.OfPlayer).Count == 0; + return false; + } + return true; + + } + + [HarmonyPrefix] + [HarmonyPatch("PotentialWorkThingsGlobal")] + [HarmonyPatch(new[] { typeof(Pawn) })] + static bool PotentialWorkThingsGlobalPrefix(ref IEnumerable __result, Pawn pawn) + { + if (pawn.IsPrisonerOfColony) + { + __result = pawn.Map.listerBuildingsRepairable.RepairableBuildings(Faction.OfPlayer); + return false; + } + return true; + + } + + + [HarmonyPrefix] + [HarmonyPatch("HasJobOnThing")] + [HarmonyPatch(new[] { typeof(Pawn), typeof(Thing), typeof(bool) })] + static bool HasJobOnThingPrefix(ref bool __result, Pawn pawn,Thing t, bool forced) + { + if (pawn.IsPrisonerOfColony) + { + __result = ConstructionUtils.HasJobOnThingFixed(pawn, t, forced); + return false; + } + return true; + + } + } +} diff --git a/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs b/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs new file mode 100644 index 00000000..a81d74fe --- /dev/null +++ b/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs @@ -0,0 +1,57 @@ +using HarmonyLib; +using PrisonLabor.WorkUtils; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; + +namespace PrisonLabor.HarmonyPatches.Patches_Construction +{ + [HarmonyPatch(typeof(WorkGiver_ConstructDeliverResourcesToBlueprints))] + [HarmonyPatch("JobOnThing")] + [HarmonyPatch(new[] { typeof(Pawn), typeof(Thing), typeof(bool) })] + class Patch_WorkGiver_ConstructDeliverResourcesToBlueprints + { + static IEnumerable Transpiler(IEnumerable instructions) + { + + OpCode[] opCodes1 = + { + OpCodes.Ldarg_2, + OpCodes.Callvirt, + OpCodes.Ldarg_1, + OpCodes.Callvirt, + OpCodes.Beq_S, + }; + string[] operands1 = + { + "", + "RimWorld.Faction get_Faction()", + "", + "RimWorld.Faction get_Faction()", + "System.Reflection.Emit.Label", + }; + + + var label = HPatcher.FindOperandAfter(opCodes1, operands1, instructions, true); + + //Add If(pawn.IsPrisonerOfColony) {jump next condition} + yield return new CodeInstruction(OpCodes.Ldarg_2); + yield return new CodeInstruction(OpCodes.Ldarg_1); + yield return new CodeInstruction(OpCodes.Call, typeof(ConstructionUtils).GetMethod("isPrisonerWork")); + yield return new CodeInstruction(OpCodes.Brtrue, label); + + foreach (var instr in instructions) + { + yield return instr; + } + + } + } +} diff --git a/Source/HarmonyPatches/Patches_NPR/ListerBuildingsRepairable_Patch.cs b/Source/HarmonyPatches/Patches_NPR/ListerBuildingsRepairable_Patch.cs deleted file mode 100644 index 3c8d1e6a..00000000 --- a/Source/HarmonyPatches/Patches_NPR/ListerBuildingsRepairable_Patch.cs +++ /dev/null @@ -1,29 +0,0 @@ -using HarmonyLib; -using RimWorld; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Verse; - -namespace PrisonLabor.HarmonyPatches.Patches_NPR -{ - [HarmonyPatch(typeof(WorkGiver_Repair))] - [HarmonyPatch("ShouldSkip")] - [HarmonyPatch(new[] { typeof(Pawn), typeof(bool) })] - class ListerBuildingsRepairable_Patch - { - - static bool Prefix(ref bool __result, Pawn pawn, bool forced) - { - if(pawn.Faction == null && pawn.IsPrisonerOfColony) - { - __result = pawn.Map.listerBuildingsRepairable.RepairableBuildings(Faction.OfPlayer).Count == 0; - return false; - } - return true; - - } - } -} diff --git a/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs b/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs index 091abd65..e163bedd 100644 --- a/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs +++ b/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs @@ -19,7 +19,7 @@ private static void Prefix(Pawn __instance, Faction newFaction, Pawn recruiter) { if(__instance.IsPrisonerOfColony && newFaction == Faction.OfPlayer) { - __instance.workSettings = null; + __instance.workSettings = new Pawn_WorkSettings(__instance); } } } diff --git a/Source/WorkUtils/ConstructionUtils.cs b/Source/WorkUtils/ConstructionUtils.cs new file mode 100644 index 00000000..98d8ccbd --- /dev/null +++ b/Source/WorkUtils/ConstructionUtils.cs @@ -0,0 +1,69 @@ +using HarmonyLib; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using Verse; +using Verse.AI; + +namespace PrisonLabor.WorkUtils +{ + class ConstructionUtils + { + public static bool HasJobOnThingFixed(Pawn pawn, Thing t, bool forced) + { + Building building = t as Building; + if (building == null) + { + return false; + } + if (!pawn.Map.listerBuildingsRepairable.Contains(pawn.Faction, building)) + { + return false; + } + if (!building.def.building.repairable) + { + return false; + } + if (t.Faction != Faction.OfPlayer) + { + return false; + } + if (!t.def.useHitPoints || t.HitPoints == t.MaxHitPoints) + { + return false; + } + if (pawn.Faction == Faction.OfPlayer && !pawn.Map.areaManager.Home[t.Position]) + { + JobFailReason.Is(WorkGiver_FixBrokenDownBuilding.NotInHomeAreaTrans); + return false; + } + if (!pawn.CanReserveAndReach(building, PathEndMode.ClosestTouch, pawn.NormalMaxDanger(), 1, -1, null, forced)) + { + return false; + } + if (building.Map.designationManager.DesignationOn(building, DesignationDefOf.Deconstruct) != null) + { + return false; + } + if (building.def.mineable && building.Map.designationManager.DesignationAt(building.Position, DesignationDefOf.Mine) != null) + { + return false; + } + if (building.IsBurning()) + { + return false; + } + return true; + } + + + public static bool isPrisonerWork(Thing t, Pawn pawn) + { + return pawn.IsPrisonerOfColony && t.Faction == Faction.OfPlayer; + } + } +} diff --git a/changelog.txt b/changelog.txt index 1647d054..033346e5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,8 @@ Changelog: +1.1.10 +- Fixes for construction job. Repairing, hauling resources to frame and blueprint, building frame, smoothing wall and floor should now work correctly. +- Fix for disappearing work tab. Request from Simple slavery mod author. Simple slavery finally compatible? +- Added option in menu to allow prisoners rest until fully healed. 1.1.9 - NPR fix for previus optimization 1.1.8