diff --git a/1.3/Assemblies/PrisonLabor.dll b/1.3/Assemblies/PrisonLabor.dll index da7d162f..fa19a5de 100644 Binary files a/1.3/Assemblies/PrisonLabor.dll and b/1.3/Assemblies/PrisonLabor.dll differ diff --git a/1.3/Defs/MainButton.xml b/1.3/Defs/MainButton.xml index d41fee49..7c6c41f8 100644 --- a/1.3/Defs/MainButton.xml +++ b/1.3/Defs/MainButton.xml @@ -5,6 +5,7 @@ Manage your faction prisoners PrisonLabor.Core.MainButton_Window.PrisonerButtonWindow + PL_TabIcon 35 true diff --git a/1.3/Defs/PrisonerInteractionModeDef.xml b/1.3/Defs/PrisonerInteractionModeDef.xml index 1c3052e8..1077ec61 100644 --- a/1.3/Defs/PrisonerInteractionModeDef.xml +++ b/1.3/Defs/PrisonerInteractionModeDef.xml @@ -10,9 +10,4 @@ 6 - - PrisonLabor_workAndConvertOption - - 7 - diff --git a/1.3/Defs/WorkGiverDef.xml b/1.3/Defs/WorkGiverDef.xml index 6c81b193..a70ddb87 100644 --- a/1.3/Defs/WorkGiverDef.xml +++ b/1.3/Defs/WorkGiverDef.xml @@ -19,8 +19,8 @@ PrisonLabor.Core.AI.WorkGivers.WorkGiver_HandleChains PrisonLabor_Jailor 5 - >handle prisoner's chainsr - >handling prisoner's chains + handle prisoner's chains + handling prisoner's chains
  • Manipulation
  • diff --git a/Ideology/Defs/PrisonersInteractionMode.xml b/Ideology/Defs/PrisonersInteractionMode.xml new file mode 100644 index 00000000..000391ae --- /dev/null +++ b/Ideology/Defs/PrisonersInteractionMode.xml @@ -0,0 +1,15 @@ + + + + PrisonLabor_workAndConvertOption + + 7 + + + + PrisonLabor_workAndEnslaveOption + + 8 + + + \ No newline at end of file diff --git a/Languages/English/Keyed/Keys.xml b/Languages/English/Keyed/Keys.xml index 7d779a40..649ee23a 100644 --- a/Languages/English/Keyed/Keys.xml +++ b/Languages/English/Keyed/Keys.xml @@ -3,6 +3,7 @@ Force to work Work and recruit Work and convert + Work and enslave Your prisoner stopped working! Warden response threshold Stopping work threshold diff --git a/LoadFolders.xml b/LoadFolders.xml index ceb87a04..c779be13 100644 --- a/LoadFolders.xml +++ b/LoadFolders.xml @@ -14,5 +14,6 @@
  • /
  • 1.3
  • +
  • Ideology
  • \ No newline at end of file diff --git a/MakeRelease.bat b/MakeRelease.bat index 8dd804f1..04c1d9ac 100644 --- a/MakeRelease.bat +++ b/MakeRelease.bat @@ -39,10 +39,12 @@ xcopy "1.1\*.*" "%target_directory%\1.1" /e mkdir "%target_directory%\1.2" xcopy "1.2\*.*" "%target_directory%\1.2" /e -:: 1.2 +:: 1.3 mkdir "%target_directory%\1.3" xcopy "1.3\*.*" "%target_directory%\1.3" /e +mkdir "%target_directory%\Ideology" +xcopy "Ideology\*.*" "%target_directory%\Ideology" /e :: LoadFolders.xml copy "LoadFolders.xml" "%target_directory%\LoadFolders.xml" diff --git a/Source/Constants/PL_DefOf.cs b/Source/Constants/PL_DefOf.cs index 7ea0aea9..e52c6b68 100644 --- a/Source/Constants/PL_DefOf.cs +++ b/Source/Constants/PL_DefOf.cs @@ -12,8 +12,13 @@ public static class PL_DefOf { public static PrisonerInteractionModeDef PrisonLabor_workOption; public static PrisonerInteractionModeDef PrisonLabor_workAndRecruitOption; + + [MayRequireIdeology] public static PrisonerInteractionModeDef PrisonLabor_workAndConvertOption; + [MayRequireIdeology] + public static PrisonerInteractionModeDef PrisonLabor_workAndEnslaveOption; + public static WorkTypeDef PrisonLabor_Jailor; public static NeedDef PrisonLabor_Motivation; diff --git a/Source/Core/AI/ThinkNodes/ThinkNode_Labor.cs b/Source/Core/AI/ThinkNodes/ThinkNode_Labor.cs index cada9731..5ca8e83a 100644 --- a/Source/Core/AI/ThinkNodes/ThinkNode_Labor.cs +++ b/Source/Core/AI/ThinkNodes/ThinkNode_Labor.cs @@ -1,3 +1,4 @@ +using PrisonLabor.Core.Components; using PrisonLabor.Core.Needs; using PrisonLabor.Core.Other; using PrisonLabor.Core.Trackers; @@ -32,17 +33,18 @@ protected override bool Satisfied(Pawn pawn) // Prisoner will escape if get ready to run. // If he can run he will start ticking impatient, once complete he will get ready. - var escapeTracker = EscapeTracker.Of(pawn, true); + + var prisonerComp = pawn.TryGetComp(); if (pawn.guest.PrisonerIsSecure && RCellFinder.TryFindBestExitSpot(pawn, out c, TraverseMode.ByPawn)) { - if (escapeTracker.ReadyToEscape) + if (prisonerComp.escapeTracker.ReadyToEscape) return false; else - escapeTracker.CanEscape = true; + prisonerComp.escapeTracker.CanEscape = true; } else { - escapeTracker.CanEscape = false; + prisonerComp.escapeTracker.CanEscape = false; } diff --git a/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs b/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs index 22ead048..68c8b824 100644 --- a/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs +++ b/Source/Core/AI/WorkGivers/WorkGiver_Supervise.cs @@ -1,3 +1,4 @@ +using PrisonLabor.Core.Components; using PrisonLabor.Core.Needs; using PrisonLabor.Core.Trackers; using RimWorld; @@ -20,14 +21,17 @@ public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) return null; if (pawn.IsPrisoner) return null; - var escapeTracker = EscapeTracker.Of(prisoner, true); - if (!PrisonLaborUtility.LaborEnabled(prisoner) && !escapeTracker.CanEscape) + var prisonerComp = prisoner.TryGetComp(); ; + + 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.WorkTime(prisoner) || !need.ShouldBeMotivated) && !escapeTracker.CanEscape) + if (PrisonLaborUtility.EnslaveInLaborEnabled(prisoner)) + return new Job(JobDefOf.PrisonerEnslave, t); + if ((!PrisonLaborUtility.WorkTime(prisoner) || !need.ShouldBeMotivated) && prisonerComp != null && !prisonerComp.escapeTracker.CanEscape) return null; return new Job(DefDatabase.GetNamed("PrisonLabor_PrisonerSupervise"), prisoner); diff --git a/Source/Core/Alerts/Alert_EscapingPrisoners.cs b/Source/Core/Alerts/Alert_EscapingPrisoners.cs index 29df2392..7e5fc9c8 100644 --- a/Source/Core/Alerts/Alert_EscapingPrisoners.cs +++ b/Source/Core/Alerts/Alert_EscapingPrisoners.cs @@ -23,10 +23,7 @@ private IEnumerable PotentialEscapingPrisoners { get { - var maps = Find.Maps; - for (var i = 0; i < maps.Count; i++) - foreach (var pawn in maps[i].mapPawns.AllPawns.Where(p=>p.IsPrisoner && EscapeTracker.Of(p, true).CanEscape)) - yield return pawn; + return EscapeTracker.PrisonersReadyToEscape; } } diff --git a/Source/Core/BaseClasses/SimpleTimer.cs b/Source/Core/BaseClasses/SimpleTimer.cs index dadb8fb2..68309719 100644 --- a/Source/Core/BaseClasses/SimpleTimer.cs +++ b/Source/Core/BaseClasses/SimpleTimer.cs @@ -32,7 +32,7 @@ public void Tick() { if (_IsActive) { - Ticks++; + Ticks += 250; } } diff --git a/Source/Core/Components/PrisonerComp.cs b/Source/Core/Components/PrisonerComp.cs index 4470c2f0..ea90ad3a 100644 --- a/Source/Core/Components/PrisonerComp.cs +++ b/Source/Core/Components/PrisonerComp.cs @@ -13,8 +13,10 @@ namespace PrisonLabor.Core.Components { - public class PrisonerComp : ThingComp + public class PrisonerComp : ThingComp { + public EscapeTracker escapeTracker; + private bool Active { get @@ -24,6 +26,14 @@ private bool Active } } + public override void Initialize(CompProperties props) + { + base.Initialize(props); + if (escapeTracker == null) + { + escapeTracker = new EscapeTracker(this.parent as Pawn); + } + } public override void PostDraw() { if (Active && PrisonLaborPrefs.EnableMotivationIcons) @@ -43,10 +53,11 @@ public override void PostDraw() DrawIcon(TexturePool.lazyTexture); } } - + } + private void DrawIcon(Material drawIcon) { var drawPos = parent.DrawPos; @@ -62,5 +73,18 @@ private void DrawIcon(Material drawIcon) var material = FadedMaterialPool.FadedVersionOf(drawIcon, num2); Graphics.DrawMesh(MeshPool.plane05, drawPos, Quaternion.identity, material, 0); } + + public override void PostExposeData() + { + Scribe_Deep.Look(ref escapeTracker, "EscapeTracker", new object[] { this.parent as Pawn }); + } + + public override void CompTickRare() + { + if (Active) + { + escapeTracker?.Tick(); + } + } } } diff --git a/Source/Core/GameSaves/SaveCleaner.cs b/Source/Core/GameSaves/SaveCleaner.cs index 8f978eca..c87b2efc 100644 --- a/Source/Core/GameSaves/SaveCleaner.cs +++ b/Source/Core/GameSaves/SaveCleaner.cs @@ -163,7 +163,7 @@ private static void UpdateData(XmlElement xmlNode) // TODO bills // Interaction Mode - string[] interactions = { PL_DefOf.PrisonLabor_workOption.defName, PL_DefOf.PrisonLabor_workAndRecruitOption.defName, PL_DefOf.PrisonLabor_workAndConvertOption.defName }; + string[] interactions = { PL_DefOf.PrisonLabor_workOption.defName, PL_DefOf.PrisonLabor_workAndRecruitOption.defName, PL_DefOf.PrisonLabor_workAndConvertOption.defName, PL_DefOf.PrisonLabor_workAndEnslaveOption.defName }; foreach (var guestTracker in gameNode.GetEveryNode("guest")) { diff --git a/Source/Core/MainButton_Window/ColumnWorker_EscapeTracker.cs b/Source/Core/MainButton_Window/ColumnWorker_EscapeTracker.cs index 0e9e2bec..262bda6c 100644 --- a/Source/Core/MainButton_Window/ColumnWorker_EscapeTracker.cs +++ b/Source/Core/MainButton_Window/ColumnWorker_EscapeTracker.cs @@ -1,4 +1,5 @@ -using PrisonLabor.Core.Trackers; +using PrisonLabor.Core.Components; +using PrisonLabor.Core.Trackers; using RimWorld; using System; using System.Collections.Generic; @@ -13,24 +14,23 @@ public class ColumnWorker_EscapeTracker : PawnColumnWorker_Text { protected override string GetTextFor(Pawn pawn) { - - var escapeTracker = EscapeTracker.Of(pawn); - if(escapeTracker != null) + var prisonerComp = pawn.TryGetComp(); + if(prisonerComp != null) { - return (escapeTracker.ReadyToEscape ? "ready" : escapeTracker.ReadyToRunPercentage + " %"); + return (prisonerComp.escapeTracker.ReadyToEscape ? "ready" : prisonerComp.escapeTracker.ReadyToRunPercentage + " %"); } - return "0 %"; + return null; } protected override string GetTip(Pawn pawn) { - var escapeTracker = EscapeTracker.Of(pawn); - if (escapeTracker != null) + var prisonerComp = pawn.TryGetComp(); + if (prisonerComp != null) { - return $"(Cap:{ escapeTracker.EscapeLevel})"; + return $"(Cap:{ prisonerComp.escapeTracker.EscapeLevel})"; } - return ""; + return null; } } } diff --git a/Source/Core/MainButton_Window/ColumnWorker_HasHandscuffs.cs b/Source/Core/MainButton_Window/ColumnWorker_HasHandscuffs.cs index 19257991..f166f349 100644 --- a/Source/Core/MainButton_Window/ColumnWorker_HasHandscuffs.cs +++ b/Source/Core/MainButton_Window/ColumnWorker_HasHandscuffs.cs @@ -38,5 +38,10 @@ protected override void SetValue(Pawn pawn, bool value, PawnTable table) } table.SetDirty(); } + + protected override bool HasCheckbox(Pawn pawn) + { + return pawn != null && pawn.health != null; + } } } diff --git a/Source/Core/MainButton_Window/ColumnWorker_HasLegcuffs.cs b/Source/Core/MainButton_Window/ColumnWorker_HasLegcuffs.cs index f44162a7..230cf930 100644 --- a/Source/Core/MainButton_Window/ColumnWorker_HasLegcuffs.cs +++ b/Source/Core/MainButton_Window/ColumnWorker_HasLegcuffs.cs @@ -38,5 +38,10 @@ protected override void SetValue(Pawn pawn, bool value, PawnTable table) } table.SetDirty(); } + + protected override bool HasCheckbox(Pawn pawn) + { + return pawn != null && pawn.health != null; + } } } diff --git a/Source/Core/MainButton_Window/ColumnWorker_Interaction.cs b/Source/Core/MainButton_Window/ColumnWorker_Interaction.cs index f8469f91..c84ebb93 100644 --- a/Source/Core/MainButton_Window/ColumnWorker_Interaction.cs +++ b/Source/Core/MainButton_Window/ColumnWorker_Interaction.cs @@ -1,4 +1,5 @@ -using RimWorld; +using PrisonLabor.Constants; +using RimWorld; using System; using System.Collections.Generic; using System.Linq; @@ -30,6 +31,10 @@ public override void DoCell(Rect rect, Pawn pawn, PawnTable table) option = new FloatMenuOption(intertaction.LabelCap, delegate { pawn.guest.interactionMode = intertaction; + if(intertaction == PrisonerInteractionModeDefOf.Convert || intertaction == PL_DefOf.PrisonLabor_workAndConvertOption) + { + pawn.guest.ideoForConversion = Faction.OfPlayer.ideos.PrimaryIdeo; + } }), payload = intertaction }; diff --git a/Source/Core/MainButton_Window/CustomTabWindow.cs b/Source/Core/MainButton_Window/CustomTabWindow.cs index c686770e..b4d25d6a 100644 --- a/Source/Core/MainButton_Window/CustomTabWindow.cs +++ b/Source/Core/MainButton_Window/CustomTabWindow.cs @@ -54,7 +54,7 @@ public override Vector2 InitialSize return requestedTabSize; } } - protected virtual IEnumerable Pawns => Find.CurrentMap.mapPawns.FreeColonists_NoHusks; + protected virtual IEnumerable Pawns => Find.CurrentMap.mapPawns.FreeColonists; public override void PostOpen() { diff --git a/Source/Core/MainButton_Window/PrisonerButtonWindow.cs b/Source/Core/MainButton_Window/PrisonerButtonWindow.cs index d55facf0..7dddc2aa 100644 --- a/Source/Core/MainButton_Window/PrisonerButtonWindow.cs +++ b/Source/Core/MainButton_Window/PrisonerButtonWindow.cs @@ -84,6 +84,7 @@ public PrisonerButtonWindow() : base() { foreach(var def in DefDatabase.AllDefs) { + Log.Message($"Def: {def.defName}, def.dev: {def.dev}, dev: {Prefs.DevMode}"); if(def.dev == false) { tabsView.Add(def, CreateWindow(def)); @@ -94,9 +95,9 @@ public PrisonerButtonWindow() : base() } } - DebugLogger.debug("Prisoners main windows constructed"); - + DebugLogger.debug("Prisoners main windows constructed"); } + public override void DoWindowContents(Rect inRect) { @@ -113,15 +114,16 @@ public override void PostOpen() { base.PostOpen(); tabs.Clear(); - foreach (PrisonersTabDef tabDef in DefDatabase.AllDefs.OrderBy(def => def.order)) + foreach (PrisonersTabDef tabDef in DefDatabase.AllDefs.Where(def => !def.dev || def.dev == Prefs.DevMode).OrderBy(def => def.order)) { tabs.Add(new PrisonerWindowTab(tabDef, tabDef.LabelCap, delegate { CurTab = tabDef; }, () => CurTab == tabDef)); GetTable(tabDef); + } - CurTab = tabs[0].def; + CurTab = tabs[1].def; foreach(var tab in tabsView.Values) { tab.PostOpen(); diff --git a/Source/Core/Needs/Need_Treatment.cs b/Source/Core/Needs/Need_Treatment.cs index 0b791145..017c523b 100644 --- a/Source/Core/Needs/Need_Treatment.cs +++ b/Source/Core/Needs/Need_Treatment.cs @@ -106,6 +106,7 @@ public override void NeedInterval() var motivation = pawn.needs.TryGetNeed(); if (motivation != null && motivation.IsPrisonerWorking) CurLevel += BGP.LaborRate; + } public override string GetTipString() diff --git a/Source/Core/PrisonLaborUtility.cs b/Source/Core/PrisonLaborUtility.cs index 4948f1af..cb52ffa4 100644 --- a/Source/Core/PrisonLaborUtility.cs +++ b/Source/Core/PrisonLaborUtility.cs @@ -14,8 +14,11 @@ internal static class PrisonLaborUtility public static bool LaborEnabled(this Pawn pawn) { if (pawn.IsPrisoner) - if (pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workOption || pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workAndRecruitOption || pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workAndConvertOption) + if (pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workOption || pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workAndRecruitOption + || pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workAndConvertOption || pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workAndEnslaveOption) + { return true; + } return false; } @@ -36,10 +39,15 @@ public static bool ConvertInLaborEnabled(Pawn pawn) return false; } + public static bool EnslaveInLaborEnabled(Pawn pawn) + { + if (pawn.guest.interactionMode == PL_DefOf.PrisonLabor_workAndEnslaveOption && pawn.guest.ScheduledForInteraction && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Talking)) + return true; + + return false; + } public static bool WorkTime(Pawn pawn) { -/* if (pawn.needs == null || pawn.needs.food == null || pawn.needs.rest == null) - return false;*/ if (pawn.timetable == null) return true; if (pawn.timetable.CurrentAssignment == TimeAssignmentDefOf.Work) diff --git a/Source/Core/Trackers/EscapeTracker.cs b/Source/Core/Trackers/EscapeTracker.cs index 1b66928d..ca1e7f32 100644 --- a/Source/Core/Trackers/EscapeTracker.cs +++ b/Source/Core/Trackers/EscapeTracker.cs @@ -17,31 +17,32 @@ public class EscapeTracker : IExposable * This region is for ensuring that for every pawn there will be only one escape tracker. * It is constructed in this way to prevent heavy modification of Pawn class (on external library). */ - private static Dictionary escapeTimers = new Dictionary(); + private static HashSet prisonersReadyToEscape = new HashSet(); - /// - /// Access EscapeTracker of Pawn - /// - public static EscapeTracker Of(Pawn pawn, bool forced = false) + public static HashSet PrisonersReadyToEscape { - if(!pawn.IsPrisoner && !forced) - { - return null; - } - if (!escapeTimers.ContainsKey(pawn)) + get { - escapeTimers.Add(pawn, new EscapeTracker(pawn)); + return prisonersReadyToEscape; } - return escapeTimers[pawn]; } - public static void Save(Pawn pawn, EscapeTracker tracker) + private static void Register(Pawn pawn) { - if(pawn != null && tracker != null) + if (pawn.IsPrisoner) { - escapeTimers[pawn] = tracker; + prisonersReadyToEscape.Add(pawn); } } + + private static void DeRegister(Pawn pawn) + { + prisonersReadyToEscape.Remove(pawn); + } + + /// + /// Access EscapeTracker of Pawn + /// #endregion private SimpleTimer timer = new SimpleTimer(); @@ -120,12 +121,14 @@ public void Tick() { timer.ResetAndStop(); ReadyToEscape = false; + DeRegister(Pawn); } } // Check if timer should trigger escape else if (timer.Ticks >= EscapeLevel) { ReadyToEscape = true; + Register(Pawn); } // Tick timer diff --git a/Source/Core/Trackers/InspirationTracker.cs b/Source/Core/Trackers/InspirationTracker.cs index 3670e1ea..27090b92 100644 --- a/Source/Core/Trackers/InspirationTracker.cs +++ b/Source/Core/Trackers/InspirationTracker.cs @@ -53,7 +53,7 @@ public static void Calculate(Map map) { if (InspirationTracker.tickCounter >= InspirationTracker.updateInterval) { - if (map.mapPawns.PrisonersOfColonyCount == 0) + if (map.mapPawns.PrisonersOfColonySpawnedCount == 0) { return; } @@ -64,10 +64,10 @@ public static void Calculate(Map map) { var wardens = new List(); - wardens.AddRange(map.mapPawns.FreeColonists); + wardens.AddRange(map.mapPawns.FreeColonistsSpawned); var prisoners = new List(); - prisoners.AddRange(map.mapPawns.PrisonersOfColony); + prisoners.AddRange(map.mapPawns.PrisonersOfColonySpawned); if (wardens.Count == 0 || prisoners.Count == 0) { diff --git a/Source/HarmonyPatches/DevTools.cs b/Source/HarmonyPatches/DevTools.cs index a3d1cb94..46b5a6f8 100644 --- a/Source/HarmonyPatches/DevTools.cs +++ b/Source/HarmonyPatches/DevTools.cs @@ -56,14 +56,20 @@ public static void TreatmentDown(Pawn p) [DebugAction("Prison Labor Tools", "Turn into prisoner", actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] public static void MakePrisoner(Pawn p) { - p.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Prisoner); + if (p.RaceProps.Humanlike) + { + p.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Prisoner); + } } [DebugAction("Prison Labor Tools", "Set free", actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] public static void SetFree(Pawn p) { - p.guest.SetGuestStatus(null, GuestStatus.Guest); + if (p.RaceProps.Humanlike) + { + p.guest.SetGuestStatus(null, GuestStatus.Guest); + } } diff --git a/Source/HarmonyPatches/HPatcher.cs b/Source/HarmonyPatches/HPatcher.cs index 43af874f..9fb68688 100644 --- a/Source/HarmonyPatches/HPatcher.cs +++ b/Source/HarmonyPatches/HPatcher.cs @@ -166,7 +166,7 @@ public static IEnumerable ReplaceFragment(OpCode[] opCodes, Str } // Jump back to begining of fragment - index -= operands.Length; + index -= operands.Length - 1; // If no fragment is found throw exception (or somehow begining of fragment is lower than 0) if (index < 0) @@ -178,7 +178,7 @@ public static IEnumerable ReplaceFragment(OpCode[] opCodes, Str instructions.RemoveRange(index, operands.Length); // Add fragment - instructions.InsertRange(index + 1, newFragment); + instructions.InsertRange(index, newFragment); return instructions; } diff --git a/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs b/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs index 8f1440db..084f4f66 100644 --- a/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs +++ b/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection.Emit; using System.Text; using System.Threading.Tasks; using Verse; @@ -13,57 +14,28 @@ namespace PrisonLabor.HarmonyPatches.Patches_BillAssignation [HarmonyPatch(typeof(Bill_ProductionWithUft), "get_BoundWorker")] class Patch_Bill_ProductionWithUft { - - static void Prefix(Bill_ProductionWithUft __instance, out UnfinishedThing __state) + private static IEnumerable Transpiler(ILGenerator gen, IEnumerable instr) { - UnfinishedThing unfinishedThing = Traverse.Create(__instance).Field("boundUftInt").GetValue(); - - if(unfinishedThing != null && unfinishedThing.Creator != null && unfinishedThing.Creator.IsPrisonerOfColony) + OpCode[] opCodesToFind = { - DebugLogger.debug($"[PL] Saving unfinished thing to state pawn: {unfinishedThing.Creator.LabelShort}, bill: {unfinishedThing.LabelShort}"); - __state = unfinishedThing; - } - else + OpCodes.Ldloc_0, + OpCodes.Callvirt, + OpCodes.Brtrue_S + }; + string[] operandsToFind = { - __state = null; - } - - } - - static Pawn Postfix(Pawn __result, Bill_ProductionWithUft __instance, UnfinishedThing __state) - { - - if (__result == null && __state != null) + "", + "RimWorld.Faction get_HostFaction()", + "System.Reflection.Emit.Label" + }; + Label label = (Label)HPatcher.FindOperandAfter(opCodesToFind, operandsToFind, instr); + CodeInstruction[] replacemnt = { - Pawn creator = __state.Creator; - if (creator == null || creator.Downed || creator.Destroyed || !creator.Spawned) - { - return __result; - } - Thing thing = __instance.billStack.billGiver as Thing; - if (thing != null) - { - WorkTypeDef workTypeDef = null; - List allDefsListForReading = DefDatabase.AllDefsListForReading; - for (int i = 0; i < allDefsListForReading.Count; i++) - { - if (allDefsListForReading[i].fixedBillGiverDefs != null && allDefsListForReading[i].fixedBillGiverDefs.Contains(thing.def)) - { - workTypeDef = allDefsListForReading[i].workType; - break; - } - } - if (workTypeDef != null && !creator.workSettings.WorkIsActive(workTypeDef)) - { - return __result; - } - } - Traverse.Create(__instance).Field("boundUftInt").SetValue(__state); - DebugLogger.debug($"Returning creator {creator.LabelShort}, value override"); - return creator; - } - - return __result; + new CodeInstruction(OpCodes.Nop), + new CodeInstruction(OpCodes.Nop), + new CodeInstruction(OpCodes.Nop, label), + }; + return HPatcher.ReplaceFragment(opCodesToFind, operandsToFind, instr, replacemnt, "Patch_Bill_ProductionWithUft"); } } } diff --git a/Source/HarmonyPatches/Patches_Escaping/Patch_EscapeTracker.cs b/Source/HarmonyPatches/Patches_Escaping/Patch_EscapeTracker.cs deleted file mode 100644 index 6e19c42c..00000000 --- a/Source/HarmonyPatches/Patches_Escaping/Patch_EscapeTracker.cs +++ /dev/null @@ -1,38 +0,0 @@ -using HarmonyLib; -using PrisonLabor.Core.Trackers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Verse; - -namespace PrisonLabor.HarmonyPatches.Patches_Escaping -{ - static class Patch_EscapeTracker - { - [HarmonyPatch(typeof(Pawn))] - [HarmonyPatch(nameof(Pawn.ExposeData))] - static class Patch_ExposeData - { - static void Postfix(Pawn __instance) - { - var escapeTracker = EscapeTracker.Of(__instance); - Scribe_Deep.Look(ref escapeTracker, "EscapeTracker", new object[] { __instance}); - EscapeTracker.Save(__instance, escapeTracker); - } - } - - [HarmonyPatch(typeof(Pawn))] - [HarmonyPatch(nameof(Pawn.Tick))] - static class Patch_Tick - { - static void Postfix(Pawn __instance) - { - if (!__instance.Dead) - { - EscapeTracker.Of(__instance)?.Tick(); - } - } - } - } -} diff --git a/Source/HarmonyPatches/Patches_Escaping/Patch_EscapingPrisoner.cs b/Source/HarmonyPatches/Patches_Escaping/Patch_EscapingPrisoner.cs index be6ff011..525598b6 100644 --- a/Source/HarmonyPatches/Patches_Escaping/Patch_EscapingPrisoner.cs +++ b/Source/HarmonyPatches/Patches_Escaping/Patch_EscapingPrisoner.cs @@ -7,6 +7,7 @@ using System; using System.IO; using PrisonLabor.Core.Trackers; +using PrisonLabor.Core.Components; namespace PrisonLabor.HarmonyPatches.Patches_Escaping { @@ -39,8 +40,9 @@ private static IEnumerable Transpiler(ILGenerator gen, MethodBa public static bool IsReadyToEscape(Pawn pawn) { - var escapeTracker = EscapeTracker.Of(pawn, true); - if (escapeTracker.ReadyToEscape) + + var prisonerComp = pawn.TryGetComp(); + if (prisonerComp != null && prisonerComp.escapeTracker.ReadyToEscape) return true; else return false; diff --git a/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_AddScrollToPrisonerTab.cs b/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_AddScrollToPrisonerTab.cs index cc303421..19084942 100644 --- a/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_AddScrollToPrisonerTab.cs +++ b/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_AddScrollToPrisonerTab.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using PrisonLabor.Constants; using RimWorld; using System; using System.Collections.Generic; @@ -20,7 +21,7 @@ internal class Patch_AddScrollToPrisonerTab { private static IEnumerable Transpiler(ILGenerator gen, IEnumerable instr) { - #region fragment>>GUI.BeginGroup(position); + #region fragment>>GUI.BeginGroup(position); OpCode[] opCodes1 = { OpCodes.Call, @@ -76,6 +77,7 @@ private static IEnumerable Transpiler(ILGenerator gen, IEnumera #endregion foreach (var ci in instr) { + // end scroll if (HPatcher.IsFragment(opCodes2, operands2, ci, ref step2, "AddScrollToPrisonerTab2")) { diff --git a/Source/HarmonyPatches/Patches_InteractionMode/Patch_VisitorTab_TabDraw.cs b/Source/HarmonyPatches/Patches_InteractionMode/Patch_VisitorTab_TabDraw.cs new file mode 100644 index 00000000..81d8c32f --- /dev/null +++ b/Source/HarmonyPatches/Patches_InteractionMode/Patch_VisitorTab_TabDraw.cs @@ -0,0 +1,70 @@ +using HarmonyLib; +using PrisonLabor.Constants; +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_InteractionMode +{ + [HarmonyPatch(typeof(ITab_Pawn_Visitor), "FillTab")] + class Patch_VisitorTab_TabDraw + { + static IEnumerable Transpiler(ILGenerator gen, MethodBase mBase, IEnumerable instructions) + { + OpCode[] opCodesToFind = + { + OpCodes.Call, + OpCodes.Ldfld, + OpCodes.Ldfld, + OpCodes.Ldsfld, + OpCodes.Bne_Un + }; + string[] operandsToFind = + { + "Verse.Pawn get_SelPawn()", + "RimWorld.Pawn_GuestTracker guest", + "RimWorld.PrisonerInteractionModeDef interactionMode", + "RimWorld.PrisonerInteractionModeDef Convert", + "System.Reflection.Emit.Label" + }; + + OpCode[] opCodesToReplace = + { + OpCodes.Call, + OpCodes.Ldfld, + OpCodes.Ldfld, + OpCodes.Ldsfld, + OpCodes.Bne_Un + }; + string[] operandsToReplace = + { + "Verse.Pawn get_SelPawn()", + "RimWorld.Pawn_GuestTracker guest", + "RimWorld.PrisonerInteractionModeDef interactionMode", + "RimWorld.PrisonerInteractionModeDef Convert", + "System.Reflection.Emit.Label" + }; + + var label = (Label)HPatcher.FindOperandAfter(opCodesToFind, operandsToFind, instructions); + CodeInstruction[] replacment = + { + new CodeInstruction(OpCodes.Call, typeof(Patch_VisitorTab_TabDraw).GetMethod(nameof(ShouldDisplayConvertIco))), + new CodeInstruction(OpCodes.Brfalse, label) + }; + + return HPatcher.ReplaceFragment(opCodesToReplace, operandsToReplace, instructions, replacment, nameof(ITab_Pawn_Visitor) + ": patch display ideo ico"); + } + + public static bool ShouldDisplayConvertIco(ITab_Pawn_Visitor tab) + { + Pawn p = Traverse.Create(tab).Property("SelPawn").GetValue(); + return p.guest.interactionMode == PrisonerInteractionModeDefOf.Convert || p.guest.interactionMode == PL_DefOf.PrisonLabor_workAndConvertOption; + } + } +} diff --git a/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_TakeToPen.cs b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_TakeToPen.cs new file mode 100644 index 00000000..974dc37b --- /dev/null +++ b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_TakeToPen.cs @@ -0,0 +1,26 @@ +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/PrisonLabor.csproj b/Source/PrisonLabor.csproj index da6d00f2..22bd05bc 100644 --- a/Source/PrisonLabor.csproj +++ b/Source/PrisonLabor.csproj @@ -133,7 +133,6 @@ - @@ -144,6 +143,7 @@ + @@ -183,6 +183,7 @@ + @@ -272,6 +273,9 @@ Organizer\changelog.txt + + Ideology\Defs\PrisonersInteractionMode.xml + Language\Keys.xml Designer @@ -293,6 +297,9 @@ Organizer\credits.md + + MakeRelease.bat + Organizer\README.md diff --git a/Textures/PL_TabIcon.png b/Textures/PL_TabIcon.png new file mode 100644 index 00000000..649cc155 Binary files /dev/null and b/Textures/PL_TabIcon.png differ diff --git a/changelog.txt b/changelog.txt index 7d188c6e..9517e71f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,15 @@ Changelog: +1.3.1 +- Added NPR checks for new table workers +- Added Work and Convert option (https://github.com/samdeane) +- Added Work and enslave option +- Work and Convert/Enslave should load only for DLC owners +- Setting convert interaction option from Overview should select default ideology +- Dev tab should only show in dev mode +- Escape tracker is now checked after rare tick (~4s) refactored how alert is notified. +- Added icon for new main table. Create by me, so it's not fancy. +- Updated Chinese translation (https://github.com/Juijote) + 1.3.0 - Update to Rimworld 1.3 - Created menu for prisoners