diff --git a/1.3/Assemblies/PrisonLabor.dll b/1.3/Assemblies/PrisonLabor.dll index ff89f24a..1f8f602e 100644 Binary files a/1.3/Assemblies/PrisonLabor.dll and b/1.3/Assemblies/PrisonLabor.dll differ diff --git a/1.3/Defs/WorkGiverDef.xml b/1.3/Defs/WorkGiverDef.xml index a70ddb87..533c17ab 100644 --- a/1.3/Defs/WorkGiverDef.xml +++ b/1.3/Defs/WorkGiverDef.xml @@ -1,17 +1,33 @@ - - PrisonLabor_SupervisePrisonLabor - - PrisonLabor.Core.AI.WorkGivers.WorkGiver_Supervise - PrisonLabor_Jailor - 5 - watch prisoner - watching prisoner - -
  • Talking
  • -
    -
    + + PrisonLabor_SupervisePrisonLabor + + PrisonLabor.Core.AI.WorkGivers.WorkGiver_Supervise + PrisonLabor_Jailor + 5 + watch prisoner + watching prisoner + +
  • Manipulation
  • +
    + +
  • Violent
  • +
    +
    + + + PrisonLabor_ChatWithPrisoner + + PrisonLabor.Core.AI.WorkGivers.WorkGivers_ManipulatePrisoner + Warden + chat with + chatting with + 61 + +
  • Talking
  • +
    +
    PrisonLabor_HandleChains diff --git a/1.3/Defs/WorkTypes.xml b/1.3/Defs/WorkTypes.xml index c84ec975..056f766b 100644 --- a/1.3/Defs/WorkTypes.xml +++ b/1.3/Defs/WorkTypes.xml @@ -9,11 +9,8 @@ Supervise 1099 true - -
  • Social
  • -
    -
  • Social
  • +
  • Violent
  • diff --git a/1.3/Patches/Designators.xml b/1.3/Patches/Designators.xml index e6155876..4b696ade 100644 --- a/1.3/Patches/Designators.xml +++ b/1.3/Patches/Designators.xml @@ -1,7 +1,7 @@ - Always + Normal
  • Always diff --git a/1.3/Patches/SetJailorJobsPatch.xml b/1.3/Patches/SetJailorJobsPatch.xml new file mode 100644 index 00000000..81ab1099 --- /dev/null +++ b/1.3/Patches/SetJailorJobsPatch.xml @@ -0,0 +1,33 @@ + + + + Normal + +
  • + */WorkGiverDef[defName="DoExecution"]/workType + + PrisonLabor_Jailor + +
  • +
  • + */WorkGiverDef[defName="ExecuteGuiltyColonist"]/workType + + PrisonLabor_Jailor + +
  • +
  • + */WorkGiverDef[defName="ReleasePrisoner"]/workType + + PrisonLabor_Jailor + +
  • +
  • + */WorkGiverDef[defName="TakePrisonerToBed"]/workType + + PrisonLabor_Jailor + +
  • +
    +
    + +
    \ No newline at end of file diff --git a/About/About.xml b/About/About.xml index ca2a7736..93c1a78a 100644 --- a/About/About.xml +++ b/About/About.xml @@ -25,7 +25,7 @@ - Version 1.3.5 + Version 1.3.6 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/Ideology/Patches/JailorForSlavesPatch.xml b/Ideology/Patches/JailorForSlavesPatch.xml new file mode 100644 index 00000000..06935517 --- /dev/null +++ b/Ideology/Patches/JailorForSlavesPatch.xml @@ -0,0 +1,14 @@ + + + + Normal + +
  • + */WorkGiverDef[defName="ExecuteSlave"]/workType + + PrisonLabor_Jailor + +
  • +
    +
    +
    \ No newline at end of file diff --git a/README.md b/README.md index 3af25f5b..189018c3 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

    - v1.3.5 + v1.3.6

    diff --git a/Source/CompatibilityPatches/CashRegister.cs b/Source/CompatibilityPatches/CashRegister.cs new file mode 100644 index 00000000..c2380bd8 --- /dev/null +++ b/Source/CompatibilityPatches/CashRegister.cs @@ -0,0 +1,68 @@ +using CashRegister.Shifts; +using HarmonyLib; +using PrisonLabor.Core.Other; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Verse; + +namespace PrisonLabor.CompatibilityPatches +{ + static class CashRegister + { + private static ModSearcher modSeeker; + internal static void Init() + { + ModSearcher modSeeker = new ModSearcher("Cash Register"); + if (modSeeker.LookForMod()) + { + Patch(); + } + } + + private static void Patch() + { + try + { + MethodBase methodBase = GetTargetMethod(); + if (methodBase != null) + { + var harmony = new Harmony("Harmony_PrisonLabor_CashRegister"); + harmony.Patch(methodBase, postfix: new HarmonyMethod(typeof(CashRegister).GetMethod("PostFixCandidates"))); + Log.Message("Prison Labor: Cash Register mod patched"); + } + } + catch (Exception e) + { + Log.Error($"PrisonLaborException: failed to proceed Cash Register mod patches: {e.ToString()}"); + } + + } + + public static IEnumerable PostFixCandidates(IEnumerable __result, CompAssignableToPawn __instance) + { + foreach(Pawn pawn in __result) + { + yield return pawn; + } + + if (__instance.parent.Spawned && __instance is CompAssignableToPawn_Shifts) + { + foreach(Pawn pawn in __instance.parent.Map.mapPawns.PrisonersOfColonySpawned) + { + yield return pawn; + } + } + } + + private static MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(CompAssignableToPawn), "get_AssigningCandidates"); + } + } + +} diff --git a/Source/CompatibilityPatches/Initialization.cs b/Source/CompatibilityPatches/Initialization.cs index 127c50cf..7ba42af7 100644 --- a/Source/CompatibilityPatches/Initialization.cs +++ b/Source/CompatibilityPatches/Initialization.cs @@ -12,6 +12,7 @@ internal static void Run() //NoWaterNoLife.Init(); Quarry.Init(); Kajin2.Init(); + CashRegister.Init(); } } } diff --git a/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs b/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs index 3d2ccdef..9a8fc517 100644 --- a/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs +++ b/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs @@ -25,12 +25,6 @@ public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) if (!PrisonLaborUtility.LaborEnabled(prisoner) && prisonerComp != null && !prisonerComp.EscapeTracker.CanEscape) return null; - if (PrisonLaborUtility.RecruitInLaborEnabled(prisoner)) - return new Job(JobDefOf.PrisonerAttemptRecruit, t); - if (PrisonLaborUtility.ConvertInLaborEnabled(prisoner)) - return new Job(JobDefOf.PrisonerConvert, t); - if (PrisonLaborUtility.EnslaveInLaborEnabled(prisoner)) - return new Job(JobDefOf.PrisonerEnslave, t); if ((!PrisonLaborUtility.WorkTime(prisoner) || !need.ShouldBeMotivated) && prisonerComp != null && !prisonerComp.EscapeTracker.CanEscape) return null; diff --git a/Source/Core/AI/WorkGivers/WorkGivers_ManipulatePrisoner.cs b/Source/Core/AI/WorkGivers/WorkGivers_ManipulatePrisoner.cs new file mode 100644 index 00000000..fcad9aa9 --- /dev/null +++ b/Source/Core/AI/WorkGivers/WorkGivers_ManipulatePrisoner.cs @@ -0,0 +1,45 @@ +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.Core.AI.WorkGivers +{ + class WorkGivers_ManipulatePrisoner : WorkGiver_Warden + { + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + var prisoner = t as Pawn; + + if (prisoner == null) + return null; + if (!ShouldTakeCareOfPrisoner(pawn, prisoner)) + return null; + if (prisoner.Downed || !pawn.CanReserve(t, 1, -1, null, false) || !prisoner.Awake()) + return null; + if (pawn.IsPrisoner) + return null; + + + if (PrisonLaborUtility.RecruitInLaborEnabled(prisoner)) + { + return new Job(JobDefOf.PrisonerAttemptRecruit, t); + } + if (PrisonLaborUtility.ConvertInLaborEnabled(prisoner)) + { + return new Job(JobDefOf.PrisonerConvert, t); + } + if (PrisonLaborUtility.EnslaveInLaborEnabled(prisoner)) + { + return new Job(JobDefOf.PrisonerEnslave, t); + } + + return null; + } + } +} + diff --git a/Source/Core/Meta/Version.cs b/Source/Core/Meta/Version.cs index f0bff914..b82204f6 100644 --- a/Source/Core/Meta/Version.cs +++ b/Source/Core/Meta/Version.cs @@ -73,6 +73,7 @@ public enum Version v1_3_2, v1_3_3, v1_3_4, - v1_3_5 + v1_3_5, + v1_3_6 } } diff --git a/Source/Core/Meta/VersionUtility.cs b/Source/Core/Meta/VersionUtility.cs index 8628415f..27ffbe3d 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_3_5; - public const string versionString = "1.3.5"; + public const Version versionNumber = Version.v1_3_6; + public const string versionString = "1.3.6"; public static Version VersionOfSaveFile { get; set; } diff --git a/Source/Core/PrisonLaborUtility.cs b/Source/Core/PrisonLaborUtility.cs index cb52ffa4..6fbf0caa 100644 --- a/Source/Core/PrisonLaborUtility.cs +++ b/Source/Core/PrisonLaborUtility.cs @@ -9,7 +9,7 @@ namespace PrisonLabor.Core { - internal static class PrisonLaborUtility + public static class PrisonLaborUtility { public static bool LaborEnabled(this Pawn pawn) { @@ -83,7 +83,7 @@ public static bool IsDisabledByLabor(IntVec3 pos, Pawn pawn, WorkTypeDef workTyp return false; } - public static bool canWorkHere(IntVec3 pos, Pawn pawn, WorkTypeDef workType) + public static bool CanWorkHere(IntVec3 pos, Pawn pawn, WorkTypeDef workType) { if (!pawn.IsPrisonerOfColony && pos != null && pawn.Map.areaManager.Get() != null && !WorkSettings.WorkDisabled(workType)) @@ -101,5 +101,10 @@ public static bool canWorkHere(IntVec3 pos, Pawn pawn, WorkTypeDef workType) } return true; } + + public static Faction GetPawnFaction(Pawn pawn) + { + return pawn.IsPrisonerOfColony ? Faction.OfPlayer : pawn.Faction; + } } } \ No newline at end of file diff --git a/Source/Core/Settings/CleanSaveDialog.cs b/Source/Core/Settings/CleanSaveDialog.cs index 97fc3e6c..28f38521 100644 --- a/Source/Core/Settings/CleanSaveDialog.cs +++ b/Source/Core/Settings/CleanSaveDialog.cs @@ -1,5 +1,4 @@ using PrisonLabor.Core.GameSaves; -using PrisonLabor.Tweaks; using UnityEngine; using Verse; diff --git a/Source/Core/Settings/SelectSaveForCleaningDialog.cs b/Source/Core/Settings/SelectSaveForCleaningDialog.cs index 3a7d59de..bddbd2ae 100644 --- a/Source/Core/Settings/SelectSaveForCleaningDialog.cs +++ b/Source/Core/Settings/SelectSaveForCleaningDialog.cs @@ -1,5 +1,4 @@ -using PrisonLabor.Tweaks; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_RoofReservation.cs b/Source/HarmonyPatches/Patches_Construction/Patch_RoofReservation.cs deleted file mode 100644 index 22d7b30e..00000000 --- a/Source/HarmonyPatches/Patches_Construction/Patch_RoofReservation.cs +++ /dev/null @@ -1,36 +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_Construction -{ - [HarmonyPatch()] - [HarmonyPatch(typeof(WorkGiver_BuildRoof), "HasJobOnCell")] - class Patch_RoofReservation - { - public static bool Postfix(bool __result, WorkGiver_BuildRoof __instance, Pawn pawn, IntVec3 c, bool forced) - { - if (__result && pawn.IsPrisonerOfColony) - { - try - { - System.Reflection.MethodInfo methodInfo = AccessTools.Method(typeof(WorkGiver_BuildRoof), "BuildingToTouchToBeAbleToBuildRoof"); - Building building = methodInfo.Invoke(__instance, new object[] { c, pawn }) as Building; - if (building != null) - { - return pawn.CanReach(building, Verse.AI.PathEndMode.Touch, pawn.NormalMaxDanger()); - } - } catch(Exception e) - { - Verse.Log.Message($"Exception in roof patch{e}"); - } - } - return __result; - } - } -} diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs index 19fd9221..4eb471dc 100644 --- a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs +++ b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_ConstructDeliverResourcesToFrames.cs @@ -44,7 +44,7 @@ static IEnumerable Transpiler(IEnumerable inst //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.Call, typeof(ConstructionUtils).GetMethod(nameof(ConstructionUtils.IsPrisonerWork))); yield return new CodeInstruction(OpCodes.Brtrue, label); foreach (var instr in instructions) diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Deconstruct.cs b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Deconstruct.cs new file mode 100644 index 00000000..e0c8314d --- /dev/null +++ b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Deconstruct.cs @@ -0,0 +1,41 @@ +using HarmonyLib; +using PrisonLabor.Core; +using PrisonLabor.Core.Other; +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; + +namespace PrisonLabor.HarmonyPatches.Patches_Construction +{ + [HarmonyPatch(typeof(WorkGiver_Deconstruct), "HasJobOnThing")] + class Patch_WorkGiver_Deconstruct + { + static IEnumerable Transpiler(ILGenerator gen, MethodBase mBase, IEnumerable inst) + { + var codes = new List(inst); + for (int i = 0; i < codes.Count(); i++) + { + if (i > 0 && ShouldPatch(codes[i], codes[i - 1])) + { + DebugLogger.debug($"Deconstruct HasJobOnThing patch: {mBase.ReflectedType.Name}.{mBase.Name}"); + yield return new CodeInstruction(OpCodes.Call, typeof(PrisonLaborUtility).GetMethod(nameof(PrisonLaborUtility.GetPawnFaction))); + } + else + { + yield return codes[i]; + } + } + } + + private static bool ShouldPatch(CodeInstruction actual, CodeInstruction prev) + { + return prev.opcode == OpCodes.Ldarg_1 && actual.opcode == OpCodes.Callvirt && actual.operand != null && actual.operand.ToString().Contains("RimWorld.Faction get_Faction()"); + } + } +} diff --git a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs index 58ee8166..f0b4effb 100644 --- a/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs +++ b/Source/HarmonyPatches/Patches_Construction/Patch_WorkGiver_Repair.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using PrisonLabor.Core; using PrisonLabor.WorkUtils; using RimWorld; using System; @@ -14,34 +15,6 @@ 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")] diff --git a/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs b/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs index a81d74fe..ce294029 100644 --- a/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs +++ b/Source/HarmonyPatches/Patches_Construction/WorkGiver_ConstructDeliverResourcesToBlueprints.cs @@ -44,7 +44,7 @@ static IEnumerable Transpiler(IEnumerable inst //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.Call, typeof(ConstructionUtils).GetMethod(nameof(ConstructionUtils.IsPrisonerWork))); yield return new CodeInstruction(OpCodes.Brtrue, label); foreach (var instr in instructions) diff --git a/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Position.cs b/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Position.cs index 38aa96d2..ba08b052 100644 --- a/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Position.cs +++ b/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Position.cs @@ -39,7 +39,7 @@ private static IEnumerable checkFields(IEnumerable __result, W { foreach (IntVec3 pos in __result) { - if (PrisonLaborUtility.canWorkHere(pos, pawn, __instance.def.workType)) + if (PrisonLaborUtility.CanWorkHere(pos, pawn, __instance.def.workType)) { yield return pos; } diff --git a/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Thing.cs b/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Thing.cs index abd32070..4e55a3aa 100644 --- a/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Thing.cs +++ b/Source/HarmonyPatches/Patches_LaborArea/Patch_Labor_Thing.cs @@ -16,13 +16,13 @@ class Patch_Labor_Thing { static IEnumerable TargetMethods() { - foreach(var method in getBaseMethods()) + foreach(var method in GetBaseMethods()) { yield return method; } // yield return getCleanMethod(); } - static IEnumerable getBaseMethods() { + static IEnumerable GetBaseMethods() { return Assembly.GetAssembly(typeof(WorkGiver_Scanner)).GetTypes() .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(WorkGiver_Scanner))) .SelectMany(type => type.GetMethods()) @@ -41,7 +41,7 @@ static IEnumerable Postfix(IEnumerable __result, WorkGiver_Scanner { if (__result != null && __instance != null) { - return checkFields(__result, __instance, pawn); + return CheckFields(__result, __instance, pawn); } else { @@ -49,12 +49,12 @@ static IEnumerable Postfix(IEnumerable __result, WorkGiver_Scanner } } - private static IEnumerable checkFields(IEnumerable __result, WorkGiver_Scanner __instance, Pawn pawn) + private static IEnumerable CheckFields(IEnumerable __result, WorkGiver_Scanner __instance, Pawn pawn) { foreach (Thing thing in __result) { //Log.Message($"Work type: { __instance.def.workType}, thing is {thing}, value: {PrisonLaborUtility.canWorkHere(thing.Position, pawn, __instance.def.workType)}"); - if (thing != null && PrisonLaborUtility.canWorkHere(thing.Position, pawn, __instance.def.workType)) + if (thing != null && PrisonLaborUtility.CanWorkHere(thing.Position, pawn, __instance.def.workType)) { // Log.Message($"Work type { __instance.def.workType}, value: {PrisonLaborUtility.canWorkHere(thing.Position, pawn, __instance.def.workType)}"); yield return thing; diff --git a/Source/HarmonyPatches/Patches_LaborArea/Patch_Scanner_HasJob.cs b/Source/HarmonyPatches/Patches_LaborArea/Patch_Scanner_HasJob.cs index 87a407ac..376c13b9 100644 --- a/Source/HarmonyPatches/Patches_LaborArea/Patch_Scanner_HasJob.cs +++ b/Source/HarmonyPatches/Patches_LaborArea/Patch_Scanner_HasJob.cs @@ -28,7 +28,7 @@ static bool Postfix(bool __result, WorkGiver_Scanner __instance, Pawn pawn, Thin { if (__result && t != null ) { - return PrisonLaborUtility.canWorkHere(t.Position, pawn, __instance.def.workType); + return PrisonLaborUtility.CanWorkHere(t.Position, pawn, __instance.def.workType); } return __result; } diff --git a/Source/HarmonyPatches/Patches_Work/Patch_JobDriver_Mine.cs b/Source/HarmonyPatches/Patches_Work/Patch_JobDriver_Mine.cs index 4f1afec8..2ca3a70b 100644 --- a/Source/HarmonyPatches/Patches_Work/Patch_JobDriver_Mine.cs +++ b/Source/HarmonyPatches/Patches_Work/Patch_JobDriver_Mine.cs @@ -22,7 +22,7 @@ static IEnumerable Postfix(IEnumerable toilList, JobDriver_Mine __in { if (counter == count) { - toil.AddFinishAction(createDelegate(__instance)); + toil.AddFinishAction(CreateDelegate(__instance)); } counter++; yield return toil; @@ -30,7 +30,7 @@ static IEnumerable Postfix(IEnumerable toilList, JobDriver_Mine __in } - static private Action createDelegate(JobDriver_Mine __instance) + static private Action CreateDelegate(JobDriver_Mine __instance) { return delegate { diff --git a/Source/HarmonyPatches/Patches_Work/Patch_JobGiver_Repair.cs b/Source/HarmonyPatches/Patches_Work/Patch_JobGiver_Repair.cs deleted file mode 100644 index 1774d0a7..00000000 --- a/Source/HarmonyPatches/Patches_Work/Patch_JobGiver_Repair.cs +++ /dev/null @@ -1,65 +0,0 @@ -using HarmonyLib; -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_Work -{ - [HarmonyPatch(typeof(WorkGiver_Repair))] - class Patch_JobGiver_Repair - { - [HarmonyPrefix] - [HarmonyPatch("ShouldSkip")] - static bool shouldSkipPrefix(ref bool __result, Pawn pawn, bool forced) - { - if (pawn != null && pawn.IsPrisonerOfColony) - { - __result = pawn.Map.listerBuildingsRepairable.RepairableBuildings(Faction.OfPlayer).Count == 0; - return false; - } - - return true; - } - - [HarmonyPrefix] - [HarmonyPatch("PotentialWorkThingsGlobal")] - static bool PotentialWorkThingsGlobalPrefix(ref IEnumerable __result, Pawn pawn) - { - if (pawn != null && pawn.IsPrisonerOfColony) - { - __result = pawn.Map.listerBuildingsRepairable.RepairableBuildings(Faction.OfPlayer); - return false; - } - - return true; - } - - [HarmonyPrefix] - [HarmonyPatch("HasJobOnThing")] - static bool HasJobOnThingPrefix(ref bool __result, Pawn pawn, Thing t, bool forced) - { - if(pawn != null && pawn.IsPrisonerOfColony) - { - Building building = t as Building; - // Fuckin monster yeah I know. All negated values from oryginal method only for prisoners - if (building != null && pawn.Map.listerBuildingsRepairable.Contains(Faction.OfPlayer, building) - && building.def.building.repairable && (t.def.useHitPoints || t.HitPoints != t.MaxHitPoints) && pawn.Map.areaManager.Home[t.Position] - && pawn.CanReserveAndReach(t, PathEndMode.ClosestTouch, pawn.NormalMaxDanger(), 1, -1, null, forced) - && building.Map.designationManager.DesignationOn(building, DesignationDefOf.Deconstruct) == null - && (!building.def.mineable && building.Map.designationManager.DesignationAt(building.Position, DesignationDefOf.Mine) == null) - && building.IsBurning() - ) - { - __result = true; - return false; - } - } - return true; - } - } -} diff --git a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_CleanFilth.cs b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_CleanFilth.cs index 5ed003b8..52a3ed32 100644 --- a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_CleanFilth.cs +++ b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_CleanFilth.cs @@ -35,7 +35,7 @@ static bool Postfix(bool __result, Pawn pawn, Thing t, bool forced) return t is Filth filth && filth.Map.areaManager.Home[filth.Position] && pawn.CanReserveAndReach(t, PathEndMode.ClosestTouch, pawn.NormalMaxDanger(), 1, -1, null, forced) && filth.TicksSinceThickened >= MinTicksSinceThickened - && PrisonLaborUtility.canWorkHere(filth.Position, pawn, workGiverDef.workType); + && PrisonLaborUtility.CanWorkHere(filth.Position, pawn, workGiverDef.workType); } return __result; } diff --git a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_PrisonerFaction.cs b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_PrisonerFaction.cs new file mode 100644 index 00000000..3c41048c --- /dev/null +++ b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_PrisonerFaction.cs @@ -0,0 +1,51 @@ +using HarmonyLib; +using PrisonLabor.Core; +using PrisonLabor.Core.Other; +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; + +namespace PrisonLabor.HarmonyPatches.Patches_Work +{ + [HarmonyPatch] + class Patch_WorkGiver_PrisonerFaction + { + static IEnumerable TargetMethods() + { + return Assembly.GetAssembly(typeof(WorkGiver_Scanner)).GetTypes() + .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(WorkGiver_Scanner))) + .SelectMany(type => type.GetMethods()) + .Where(method => method.Name.Equals("PotentialWorkThingsGlobal") || method.Name.Equals("ShouldSkip")) + .Distinct() + .Cast(); + } + + static IEnumerable Transpiler(ILGenerator gen, MethodBase mBase, IEnumerable inst) + { + var codes = new List(inst); + for (int i = 0; i < codes.Count(); i++) + { + if (i > 0 && ShouldPatch(codes[i], codes[i - 1])) + { + DebugLogger.debug($"WorkThingsGlobal & ShouldSkip patch: {mBase.ReflectedType.Name}.{mBase.Name}"); + yield return new CodeInstruction(OpCodes.Call, typeof(PrisonLaborUtility).GetMethod(nameof(PrisonLaborUtility.GetPawnFaction))); + } + else + { + yield return codes[i]; + } + } + } + + private static bool ShouldPatch(CodeInstruction actual, CodeInstruction prev) + { + return prev.opcode == OpCodes.Ldarg_1 && actual.opcode == OpCodes.Callvirt && actual.operand != null && actual.operand.ToString().Contains("RimWorld.Faction get_Faction()"); + } + } +} diff --git a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_RescueDowned.cs b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_RescueDowned.cs index 46b1fb5f..dfe8e2f6 100644 --- a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_RescueDowned.cs +++ b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_RescueDowned.cs @@ -1,36 +1,58 @@ using HarmonyLib; +using PrisonLabor.Core; +using PrisonLabor.Core.Other; 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_Work { - [HarmonyPatch(typeof(WorkGiver_RescueDowned), "ShouldSkip")] + [HarmonyPatch(typeof(RestUtility), "FindBedFor", new Type[] { typeof(Pawn), typeof(Pawn), typeof(bool), typeof(bool), typeof(GuestStatus) } )] + class Patch_RestUtility + { + //Don't try to take wounded to unreachable bed + static Building_Bed Postfix(Building_Bed __result, Pawn sleeper, Pawn traveler, bool checkSocialProperness, bool ignoreOtherReservations, GuestStatus? guestStatus) + { + if(__result != null && traveler.IsPrisonerOfColony && !traveler.CanReach(__result, PathEndMode.ClosestTouch, traveler.NormalMaxDanger())) + { + return null; + } + return __result; + } + } + + + [HarmonyPatch(typeof(WorkGiver_RescueDowned), "HasJobOnThing")] class Patch_WorkGiver_RescueDowned { - static bool Prefix(ref bool __result, Pawn pawn, bool forced) + static IEnumerable Transpiler(ILGenerator gen, MethodBase mBase, IEnumerable inst) { - if(pawn != null && pawn.IsPrisonerOfColony) + var codes = new List(inst); + for (int i = 0; i < codes.Count(); i++) { - List list = pawn.Map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer); - for (int i = 0; i < list.Count; i++) + if (i > 0 && ShouldPatch(codes[i], codes[i - 1])) + { + DebugLogger.debug($"WorkGiver_RescueDowned patch: {mBase.ReflectedType.Name}.{mBase.Name}"); + yield return new CodeInstruction(OpCodes.Call, typeof(PrisonLaborUtility).GetMethod(nameof(PrisonLaborUtility.GetPawnFaction))); + } + else { - if (list[i].Downed && !list[i].InBed()) - { - __result = false; - return false; - } + yield return codes[i]; } - __result = true; - return false; } + } - return true; + private static bool ShouldPatch(CodeInstruction actual, CodeInstruction prev) + { + return prev.opcode == OpCodes.Ldarg_1 && actual.opcode == OpCodes.Callvirt && actual.operand != null && actual.operand.ToString().Contains("RimWorld.Faction get_Faction()"); } } } diff --git a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_TakeToPen.cs b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_TakeToPen.cs deleted file mode 100644 index 974dc37b..00000000 --- a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_TakeToPen.cs +++ /dev/null @@ -1,26 +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_Work -{ - [HarmonyPatch(typeof(WorkGiver_TakeToPen), "PotentialWorkThingsGlobal")] - class Patch_WorkGiver_TakeToPen - { - static bool Prefix(ref IEnumerable __result, Pawn pawn) - { - if (pawn != null && pawn.IsPrisonerOfColony) - { - __result = pawn.Map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer); - return false; - } - - return true; - } - } -} diff --git a/Source/Initialization.cs b/Source/Initialization.cs index 3733a310..1388c708 100644 --- a/Source/Initialization.cs +++ b/Source/Initialization.cs @@ -3,7 +3,6 @@ using PrisonLabor.Core.Meta; using PrisonLabor.Core.Settings; using PrisonLabor.HarmonyPatches; -using PrisonLabor.Tweaks; using RimWorld; using System; using System.Collections.Generic; @@ -18,10 +17,9 @@ internal class Initialization static Initialization() { try - { + { PrisonLaborPrefs.Init(); HPatcher.Init(); - ClassInjector.Init(); SettingsMenu.Init(); VersionUtility.CheckVersion(); CompatibilityPatches.Initialization.Run(); diff --git a/Source/Organizer/NewsFeed.xml b/Source/Organizer/NewsFeed.xml index 233c1ca9..df2a8683 100644 --- a/Source/Organizer/NewsFeed.xml +++ b/Source/Organizer/NewsFeed.xml @@ -4,6 +4,7 @@ + diff --git a/Source/PrisonLabor.csproj b/Source/PrisonLabor.csproj index afae8daf..4f036344 100644 --- a/Source/PrisonLabor.csproj +++ b/Source/PrisonLabor.csproj @@ -42,6 +42,10 @@ packages\RimWorld.MultiplayerAPI.0.3.0\lib\net472\0MultiplayerAPI.dll + + False + False + @@ -75,12 +79,14 @@ + + @@ -136,8 +142,8 @@ - + @@ -186,12 +192,11 @@ - - + @@ -229,7 +234,6 @@ - @@ -241,6 +245,9 @@ + + CashRegister.dll + Defs\ConceptDef.xml @@ -274,6 +281,15 @@ Defs\WorkTypes.xml + + Patches\AddPrisonerComp.xml + + + Patches\Designators.xml + + + Patches\SetJailorJobsPatch.xml + Organizer\About.xml Designer @@ -284,6 +300,9 @@ Ideology\Defs\PrisonersInteractionMode.xml + + Ideology\Patches\JailorForSlavesPatch.xml + Language\Keys.xml Designer diff --git a/Source/Tweaks/ClassInjector.cs b/Source/Tweaks/ClassInjector.cs deleted file mode 100644 index eecfef0f..00000000 --- a/Source/Tweaks/ClassInjector.cs +++ /dev/null @@ -1,31 +0,0 @@ -using PrisonLabor.Constants; -using RimWorld; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Verse; - -namespace PrisonLabor.Tweaks -{ - public static class ClassInjector - { - public static void Init() - { - SplitWardenType(); - } - - private static void SplitWardenType() - { - DefDatabase.GetNamed("DoExecution").workType = PL_DefOf.PrisonLabor_Jailor; - DefDatabase.GetNamed("ReleasePrisoner").workType = PL_DefOf.PrisonLabor_Jailor; - DefDatabase.GetNamed("TakePrisonerToBed").workType = PL_DefOf.PrisonLabor_Jailor; - //DefDatabase.GetNamed("FeedPrisoner").workType = PrisonLaborDefOf.PrisonLabor_Jailor; - //DefDatabase.GetNamed("DeliverFoodToPrisoner").workType = PrisonLaborDefOf.PrisonLabor_Jailor; - WorkTypeDefOf.Warden.workGiversByPriority.Clear(); - WorkTypeDefOf.Warden.ResolveReferences(); - PL_DefOf.PrisonLabor_Jailor.workGiversByPriority.Clear(); - PL_DefOf.PrisonLabor_Jailor.ResolveReferences(); - } - } -} diff --git a/Source/Tweaks/MainTabWindow_Assign_Tweak.cs b/Source/Tweaks/MainTabWindow_Assign_Tweak.cs deleted file mode 100644 index 46cfed0a..00000000 --- a/Source/Tweaks/MainTabWindow_Assign_Tweak.cs +++ /dev/null @@ -1,109 +0,0 @@ -using RimWorld; -using RimWorld.Planet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using Verse; - -namespace PrisonLabor.Tweaks -{ - public class MainTabWindow_Assign_Tweak : MainTabWindow_PawnTable - { - #region Original/Vanilla content of class - protected override PawnTableDef PawnTableDef - { - get - { - return PawnTableDefOf.Assign; - } - } - #endregion - - private PawnTable prisonersTable; - - public const int ColonistsTabIndex = 0; - public const int PrisonersTabIndex = 1; - private int currentTabIndex = 0; - - protected virtual IEnumerable Prisoners - { - get - { - foreach (var pawn in Find.CurrentMap.mapPawns.PrisonersOfColony) - { - if (PrisonLaborUtility.LaborEnabled(pawn)) - { - WorkSettings.InitWorkSettings(pawn); - yield return pawn; - } - } - } - } - - public override void DoWindowContents(Rect rect) - { - string[] tabs; - if (Prisoners.Count() > 0) - tabs = new string[] { "PrisonLabor_ColonistsOnlyShort".Translate(), "PrisonLabor_PrisonersOnlyShort".Translate() }; - else - tabs = new string[] { "PrisonLabor_ColonistsOnlyShort".Translate() }; - - PrisonLaborWidgets.BeginTabbedView(rect, tabs, ref currentTabIndex); - if (currentTabIndex == ColonistsTabIndex) - { - base.DoWindowContents(rect); - } - else if (currentTabIndex == PrisonersTabIndex) - { - SetInitialSizeAndPosition(); - prisonersTable.PawnTableOnGUI(new Vector2(rect.x, rect.y + this.ExtraTopSpace)); - } - PrisonLaborWidgets.EndTabbedView(); - } - - private PawnTable CreatePrisonerTable() - { - return new PawnTable( - PawnTableDef, - new Func>(() => Prisoners), - UI.screenWidth - (int)(this.Margin * 2f), - (int)((float)(UI.screenHeight - 35) - this.ExtraBottomSpace - this.ExtraTopSpace - this.Margin * 2f) - ); - } - - public override void Notify_ResolutionChanged() - { - prisonersTable = CreatePrisonerTable(); - base.Notify_ResolutionChanged(); - } - - public override void PostOpen() - { - if (this.prisonersTable == null) - { - this.prisonersTable = this.CreatePrisonerTable(); - } - base.PostOpen(); - Find.World.renderer.wantedMode = WorldRenderMode.None; - } - - public override Vector2 RequestedTabSize - { - get - { - if (prisonersTable != null) - { - var pTableSize = new Vector2(this.prisonersTable.Size.x + this.Margin * 2f, this.prisonersTable.Size.y + this.ExtraBottomSpace + this.ExtraTopSpace + this.Margin * 2f); - var cTableSize = base.RequestedTabSize; - var maxTableSize = new Vector2(Math.Max(pTableSize.x, cTableSize.x), Math.Max(pTableSize.y, cTableSize.y) + PrisonLaborWidgets.TabHeight); - return maxTableSize; - } - else - return base.RequestedTabSize; - } - } - - } -} diff --git a/Source/WorkUtils/ConstructionUtils.cs b/Source/WorkUtils/ConstructionUtils.cs index 74229fd4..9b608e0b 100644 --- a/Source/WorkUtils/ConstructionUtils.cs +++ b/Source/WorkUtils/ConstructionUtils.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using PrisonLabor.Core; using RimWorld; using System; using System.Collections.Generic; @@ -15,55 +16,35 @@ class ConstructionUtils { public static bool HasJobOnThingFixed(Pawn pawn, Thing t, bool forced) { - Building building = t as Building; - if (building == null) - { + if (!PawnCanRepairNow(pawn, t)) return false; - } - if (!pawn.Map.listerBuildingsRepairable.Contains(Faction.OfPlayer, 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.IsPrisonerOfColony && !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)) + Building t1 = t as Building; + if (PrisonLaborUtility.GetPawnFaction(pawn) == Faction.OfPlayer && !pawn.Map.areaManager.Home[t.Position]) { + JobFailReason.Is(WorkGiver_FixBrokenDownBuilding.NotInHomeAreaTrans, null); 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; + return pawn.CanReserveAndReach(t1, PathEndMode.ClosestTouch, pawn.NormalMaxDanger(), 1, -1, null, forced) && + t1.Map.designationManager.DesignationOn(t1, DesignationDefOf.Deconstruct) == null && + (!t1.def.mineable || t1.Map.designationManager.DesignationAt(t1.Position, DesignationDefOf.Mine) == null) && + !t1.IsBurning(); + } - public static bool isPrisonerWork(Thing t, Pawn pawn) + public static bool IsPrisonerWork(Thing t, Pawn pawn) { return pawn.IsPrisonerOfColony && t.Faction == Faction.OfPlayer; } + + private static bool PawnCanRepairEver(Pawn pawn, Thing t) + { + return t is Building building && t.def.useHitPoints && (building.def.building.repairable && t.Faction == PrisonLaborUtility.GetPawnFaction(pawn)); + } + + private static bool PawnCanRepairNow(Pawn pawn, Thing t) + { + return PawnCanRepairEver(pawn, t) && pawn.Map.listerBuildingsRepairable.Contains(PrisonLaborUtility.GetPawnFaction(pawn), (Building)t) && t.HitPoints != t.MaxHitPoints; + } } } diff --git a/changelog.txt b/changelog.txt index c934c97e..2cce50ce 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,9 @@ Changelog: +1.3.6 +- CashRegister compatibility patch +- Jailor is now only responsible for supervising and executing prisoners +- Warden is responsible for recruting, converting and providing food for prisoners +- Various patches for workgiver regarding prisoners. 1.3.5 - Unlocked taking prisoners to their bed at any place - Removed default interaction NRE in UI