diff --git a/1.2/Assemblies/PrisonLabor.dll b/1.2/Assemblies/PrisonLabor.dll
index 5e82cbdb..e66eb78b 100644
Binary files a/1.2/Assemblies/PrisonLabor.dll and b/1.2/Assemblies/PrisonLabor.dll differ
diff --git a/About/About.xml b/About/About.xml
index c16c9449..caed7958 100644
--- a/About/About.xml
+++ b/About/About.xml
@@ -23,7 +23,7 @@
- Version 1.2.2
+ Version 1.2.3
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/Defs/ThinkTreeDef.xml b/Defs/ThinkTreeDef.xml
index 18571ade..91d01f4d 100644
--- a/Defs/ThinkTreeDef.xml
+++ b/Defs/ThinkTreeDef.xml
@@ -12,7 +12,13 @@
-
+
+ ChangingApparel
+
+
+
+
+
diff --git a/Languages/English/Keyed/Keys.xml b/Languages/English/Keyed/Keys.xml
index f7f8c219..73c65cdb 100644
--- a/Languages/English/Keyed/Keys.xml
+++ b/Languages/English/Keyed/Keys.xml
@@ -91,4 +91,7 @@
Remove/put handcuffs
Remove/put legscuffs
+
+ Enable Debug Logs
+ Turning on this option may spam log
diff --git a/README.md b/README.md
index 28fa8244..8d7500b0 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-
+
diff --git a/Source/CompatibilityPatches/Initialization.cs b/Source/CompatibilityPatches/Initialization.cs
index 03a22e49..83fdd8a4 100644
--- a/Source/CompatibilityPatches/Initialization.cs
+++ b/Source/CompatibilityPatches/Initialization.cs
@@ -12,6 +12,7 @@ internal static void Run()
//NoWaterNoLife.Init();
WorkTab.Init();
Quarry.Init();
+ Kajin2.Init();
}
}
}
diff --git a/Source/CompatibilityPatches/Kajin2.cs b/Source/CompatibilityPatches/Kajin2.cs
new file mode 100644
index 00000000..b88fc6ea
--- /dev/null
+++ b/Source/CompatibilityPatches/Kajin2.cs
@@ -0,0 +1,64 @@
+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 Kajin2
+ {
+ private static ModSearcher modSeeker;
+ internal static void Init()
+ {
+ ModSearcher modSeeker = new ModSearcher("Kijin Race 2.0");
+ if (modSeeker.LookForMod())
+ {
+ Patch();
+ }
+ }
+
+ private static void Patch()
+ {
+ try
+ {
+ MethodBase methodBase = getTargetMethod();
+ if (methodBase != null)
+ {
+ var harmony = new Harmony("Harmony_PrisonLabor_Kajin2");
+ harmony.Patch(methodBase, postfix: new HarmonyMethod(typeof(Kajin2).GetMethod("postfix_Job")));
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error($"PrisonLaborException: failed to proceed Kijin Race 2.0 mod patches: {e.ToString()}");
+ }
+
+ }
+
+ public static Pawn postfix_Job( Pawn __result, IntVec3 c, Map map)
+ {
+ if (__result == null)
+ {
+ foreach(Thing thing in GridsUtility.GetThingList(c, map) )
+ {
+ Pawn val = thing as Pawn;
+ if (val != null && !val.Dead && !val.Downed && val.IsPrisonerOfColony)
+ {
+ return val;
+ }
+ }
+ }
+ return __result;
+ }
+ private static MethodBase getTargetMethod()
+ {
+ return AccessTools.Method("Kijin2.Kijin2PlantCollectedPatch:GetFirstPawnNotDeadOrDowned");
+ }
+ }
+}
diff --git a/Source/Core/AI/JobGivers/JobGiver_BedTime.cs b/Source/Core/AI/JobGivers/JobGiver_BedTime.cs
index 30977965..de152d51 100644
--- a/Source/Core/AI/JobGivers/JobGiver_BedTime.cs
+++ b/Source/Core/AI/JobGivers/JobGiver_BedTime.cs
@@ -19,6 +19,10 @@ public override ThinkNode DeepCopy(bool resolve = true)
public override float GetPriority(Pawn pawn)
{
+ if (pawn.needs.rest == null)
+ {
+ return 0f;
+ }
if (HealthAIUtility.ShouldHaveSurgeryDoneNow(pawn))
return 15f;
if (pawn.timetable != null && pawn.timetable.CurrentAssignment == TimeAssignmentDefOf.Sleep)
@@ -28,6 +32,10 @@ public override float GetPriority(Pawn pawn)
protected override Job TryGiveJob(Pawn pawn)
{
+ if(pawn.needs.rest == null)
+ {
+ return null;
+ }
if (pawn.timetable == null || pawn.timetable.CurrentAssignment != TimeAssignmentDefOf.Sleep)
return null;
if (RestUtility.DisturbancePreventsLyingDown(pawn))
diff --git a/Source/Core/Incidents/IncidentWorker_ResocializationOffer.cs b/Source/Core/Incidents/IncidentWorker_ResocializationOffer.cs
index 1a059a0e..a969f1b0 100644
--- a/Source/Core/Incidents/IncidentWorker_ResocializationOffer.cs
+++ b/Source/Core/Incidents/IncidentWorker_ResocializationOffer.cs
@@ -18,7 +18,7 @@ protected override bool CanFireNowSub(IncidentParms parms)
foreach (var pawn in map.mapPawns.PrisonersOfColony)
{
- if (pawn.IsColonist)
+ if (pawn.IsColonist || !pawn.Spawned)
continue;
var treatment = pawn.needs.TryGetNeed();
@@ -39,7 +39,7 @@ protected override bool TryExecuteWorker(IncidentParms parms)
var affectedPawns = new List(map.mapPawns.PrisonersOfColony);
foreach (var pawn in map.mapPawns.PrisonersOfColony)
{
- if (pawn.IsColonist)
+ if (pawn.IsColonist || !pawn.Spawned)
continue;
var treatment = pawn.needs.TryGetNeed();
@@ -58,8 +58,14 @@ protected override bool TryExecuteWorker(IncidentParms parms)
return false;
Tutorials.Treatment();
-
- SendStandardLetter(parms, prisoner, prisoner.Name.ToStringShort, prisoner.Faction.Name);
+ if (prisoner.Faction == null)
+ {
+ SendStandardLetter(parms, prisoner, prisoner.Name.ToStringShort);
+ }
+ else
+ {
+ SendStandardLetter(parms, prisoner, prisoner.Name.ToStringShort, prisoner.Faction.Name);
+ }
return true;
}
}
diff --git a/Source/Core/Incidents/IncidentWorker_Suicide.cs b/Source/Core/Incidents/IncidentWorker_Suicide.cs
index a78551b6..daa2d4cf 100644
--- a/Source/Core/Incidents/IncidentWorker_Suicide.cs
+++ b/Source/Core/Incidents/IncidentWorker_Suicide.cs
@@ -21,7 +21,7 @@ protected override bool CanFireNowSub(IncidentParms parms)
foreach (var pawn in map.mapPawns.PrisonersOfColony)
{
- if (pawn.IsColonist || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Manipulation) == 0f || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness) == 0f)
+ if (pawn.IsColonist || !pawn.Spawned || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Manipulation) == 0f || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness) == 0f)
{
continue;
}
@@ -42,7 +42,7 @@ protected override bool TryExecuteWorker(IncidentParms parms)
var affectedPawns = new List(map.mapPawns.PrisonersOfColony);
foreach (var pawn in map.mapPawns.PrisonersOfColony)
{
- if (pawn.IsColonist)
+ if (pawn.IsColonist || !pawn.Spawned || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Manipulation) == 0f || pawn.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness) == 0f)
continue;
var need = pawn.needs.TryGetNeed();
diff --git a/Source/Core/Meta/Prefs.cs b/Source/Core/Meta/Prefs.cs
index 78fb1e20..9d55d141 100644
--- a/Source/Core/Meta/Prefs.cs
+++ b/Source/Core/Meta/Prefs.cs
@@ -15,6 +15,18 @@ public static class PrisonLaborPrefs
private static readonly string prefsFilePath =
Path.Combine(GenFilePaths.ConfigFolderPath, "PrisonLabor_Prefs.xml");
+ public static bool DebugLogs
+ {
+ get
+ {
+ return data.enable_debug_logging;
+ }
+ set
+ {
+ data.enable_debug_logging = value;
+ Apply();
+ }
+ }
public static Version Version
{
get { return data.version; }
@@ -209,6 +221,7 @@ public static void RestoreToDefault()
data.version = version;
data.last_version = last_version;
data.tutorials_flags = tutorials;
+ data.enable_debug_logging = false;
Apply();
}
diff --git a/Source/Core/Meta/PrefsData.cs b/Source/Core/Meta/PrefsData.cs
index cbdcfb35..0ec8eb8b 100644
--- a/Source/Core/Meta/PrefsData.cs
+++ b/Source/Core/Meta/PrefsData.cs
@@ -15,6 +15,7 @@ public class PrisonLaborPrefsData
public bool show_treatment_happiness = false;
public bool enable_suicide = true;
public bool enable_full_heal_rest = true;
+ public bool enable_debug_logging = false;
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 84bbf79d..47a8c096 100644
--- a/Source/Core/Meta/Version.cs
+++ b/Source/Core/Meta/Version.cs
@@ -64,6 +64,7 @@ public enum Version
v1_1_11,
v1_2_0,
v1_2_1,
- v1_2_2
+ v1_2_2,
+ v1_2_3
}
}
diff --git a/Source/Core/Meta/VersionUtility.cs b/Source/Core/Meta/VersionUtility.cs
index 4d8242ae..8d7da64a 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_2_2;
- public const string versionString = "1.2.2";
+ public const Version versionNumber = Version.v1_2_3;
+ public const string versionString = "1.2.3";
public static Version VersionOfSaveFile { get; set; }
diff --git a/Source/Core/Needs/Need_Motivation.cs b/Source/Core/Needs/Need_Motivation.cs
index a2ae7275..e9ae8d63 100644
--- a/Source/Core/Needs/Need_Motivation.cs
+++ b/Source/Core/Needs/Need_Motivation.cs
@@ -85,7 +85,11 @@ private float GetChangePoints()
value -= BGP.Laziness_LazyRate;
if (HealthAIUtility.ShouldSeekMedicalRest(pawn))
value -= BGP.Laziness_HealthRate;
- value -= (int)pawn.needs.food.CurCategory * BGP.Laziness_HungryRate;
+ if (pawn.needs.food != null)
+ {
+ //warforged
+ value -= (int)pawn.needs.food.CurCategory * BGP.Laziness_HungryRate;
+ }
// Some pawns have no rest need (e.g. Pawns with Circadian Half Cycler or androids from other mods)
if (pawn.needs.rest != null)
{
diff --git a/Source/Core/Needs/Need_Treatment.cs b/Source/Core/Needs/Need_Treatment.cs
index b036eb8d..f1a77b5e 100644
--- a/Source/Core/Needs/Need_Treatment.cs
+++ b/Source/Core/Needs/Need_Treatment.cs
@@ -85,18 +85,21 @@ public override void NeedInterval()
CurLevel += BGP.JoyRate;
// Status
- var hunger = pawn.needs.TryGetNeed();
-
- int statusScore = 0;
- if (hunger.CurCategory < HungerCategory.UrgentlyHungry)
- statusScore += 5;
- if (hunger.CurCategory < HungerCategory.Hungry)
- statusScore += 5;
- statusScore -= (int)pawn.health.hediffSet.PainTotal / 10;
- if (pawn.health.HasHediffsNeedingTend())
- statusScore -= 7;
-
- CurLevel += statusScore * BGP.StatusMultiplier;
+ if (pawn.needs.food != null)
+ {
+ var hunger = pawn.needs.TryGetNeed();
+
+ int statusScore = 0;
+ if (hunger.CurCategory < HungerCategory.UrgentlyHungry)
+ statusScore += 5;
+ if (hunger.CurCategory < HungerCategory.Hungry)
+ statusScore += 5;
+ statusScore -= (int)pawn.health.hediffSet.PainTotal / 10;
+ if (pawn.health.HasHediffsNeedingTend())
+ statusScore -= 7;
+
+ CurLevel += statusScore * BGP.StatusMultiplier;
+ }
// Labor
diff --git a/Source/Core/Other/CleanPrisonersStatus.cs b/Source/Core/Other/CleanPrisonersStatus.cs
new file mode 100644
index 00000000..1be2e40c
--- /dev/null
+++ b/Source/Core/Other/CleanPrisonersStatus.cs
@@ -0,0 +1,31 @@
+using PrisonLabor.Constants;
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace PrisonLabor.Core.Other
+{
+ public static class CleanPrisonersStatus
+ {
+
+ static public void Clean(Pawn prisoner)
+ {
+ prisoner.workSettings = new Pawn_WorkSettings(prisoner);
+ Hediff legs = prisoner.health.hediffSet.GetFirstHediffOfDef(PL_DefOf.PrisonLabor_RemovedLegscuffs, false);
+ if (legs != null)
+ {
+ prisoner.health.hediffSet.hediffs.Remove(legs);
+ }
+ Hediff hands = prisoner.health.hediffSet.GetFirstHediffOfDef(PL_DefOf.PrisonLabor_RemovedHandscuffs, false);
+ if (hands != null)
+ {
+ prisoner.health.hediffSet.hediffs.Remove(hands);
+ }
+ prisoner.playerSettings.AreaRestriction = null;
+ }
+ }
+}
diff --git a/Source/Core/Other/CustomForbidenUtil.cs b/Source/Core/Other/CustomForbidenUtil.cs
index ffb69956..dc170536 100644
--- a/Source/Core/Other/CustomForbidenUtil.cs
+++ b/Source/Core/Other/CustomForbidenUtil.cs
@@ -10,70 +10,74 @@
namespace PrisonLabor.Core.Other
{
- public static class CustomForbidenUtil
+ public static class CustomForbidenUtil
{
- public static bool PrisonerCaresAboutForbidden(Pawn pawn, bool cellTarget)
- {
- if (!pawn.Spawned || !pawn.IsPrisonerOfColony && pawn.timetable.CurrentAssignment != TimeAssignmentDefOf.Work)
- {
- return false;
- }
- if (pawn.InMentalState)
- {
- return false;
- }
- if (cellTarget && ThinkNode_ConditionalShouldFollowMaster.ShouldFollowMaster(pawn))
- {
- return false;
- }
- return true;
- }
+ public static bool PrisonerCaresAboutForbidden(Pawn pawn, bool cellTarget)
+ {
+ if (!pawn.Spawned || !pawn.IsPrisonerOfColony && pawn.timetable.CurrentAssignment != TimeAssignmentDefOf.Work)
+ {
+ return false;
+ }
+ if (pawn.InMentalState)
+ {
+ return false;
+ }
+ if (cellTarget && ThinkNode_ConditionalShouldFollowMaster.ShouldFollowMaster(pawn))
+ {
+ return false;
+ }
+ return true;
+ }
- public static bool IsFoodForbiden(this Thing t, Pawn pawn)
+ public static bool IsFoodForbiden(this Thing t, Pawn pawn)
{
- return PrisonerFoodReservation.IsReserved(t) && !pawn.IsPrisoner;
- }
+ if (pawn.IsPrisonerOfColony)
+ {
+ DebugLogger.debug($"[PL] Pawn {pawn.LabelShort} checking null object");
+ }
+ return t != null && PrisonerFoodReservation.IsReserved(t) && !pawn.IsPrisoner;
+ }
- public static bool IsForbiddenForPrisoner(this Thing t, Pawn pawn)
- {
+ public static bool IsForbiddenForPrisoner(this Thing t, Pawn pawn)
+ {
- if (pawn.IsWatched() && ForbidUtility.IsForbidden(t, Faction.OfPlayer))
- {
- return true;
- }
- if (!PrisonerCaresAboutForbidden(pawn, cellTarget: false))
- {
- return false;
- }
- if (t.Spawned && t.Position.IsForbiddenForPrisoner(pawn))
- {
- return true;
- }
- Lord lord = pawn.GetLord();
- if (lord != null && lord.extraForbiddenThings.Contains(t))
- {
- return true;
- }
- return false;
- }
+ if (pawn.IsWatched() && ForbidUtility.IsForbidden(t, Faction.OfPlayer))
+ {
+ return true;
+ }
+ if (!PrisonerCaresAboutForbidden(pawn, cellTarget: false))
+ {
+ return false;
+ }
+ if (t != null && t.Spawned && t.Position.IsForbiddenForPrisoner(pawn))
+ {
+ return true;
+ }
+ Lord lord = pawn.GetLord();
+ if (lord != null && lord.extraForbiddenThings.Contains(t))
+ {
+ return true;
+ }
+ return false;
+ }
- public static bool IsForbiddenForPrisoner(this IntVec3 c, Pawn pawn)
- {
- if (!PrisonerCaresAboutForbidden(pawn, cellTarget: true))
- {
- return false;
- }
- if (!c.InAllowedArea(pawn))
- {
- return true;
- }
- if (pawn.mindState.maxDistToSquadFlag > 0f && !c.InHorDistOf(pawn.DutyLocation(), pawn.mindState.maxDistToSquadFlag))
- {
- return true;
- }
- return false;
- }
- }
+ public static bool IsForbiddenForPrisoner(this IntVec3 c, Pawn pawn)
+ {
+ if (!PrisonerCaresAboutForbidden(pawn, cellTarget: true))
+ {
+ return false;
+ }
+ if (!c.InAllowedArea(pawn))
+ {
+ return true;
+ }
+ if (pawn.mindState.maxDistToSquadFlag > 0f && !c.InHorDistOf(pawn.DutyLocation(), pawn.mindState.maxDistToSquadFlag))
+ {
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/Source/Core/Other/DebugLogger.cs b/Source/Core/Other/DebugLogger.cs
new file mode 100644
index 00000000..c454f972
--- /dev/null
+++ b/Source/Core/Other/DebugLogger.cs
@@ -0,0 +1,26 @@
+using PrisonLabor.Core.Meta;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace PrisonLabor.Core.Other
+{
+ public static class DebugLogger
+ {
+ public static void debug(string msg)
+ {
+ if (PrisonLaborPrefs.DebugLogs)
+ {
+ Log.Message(msg);
+ }
+ }
+
+ public static void info(string msg)
+ {
+ Log.Message(msg);
+ }
+ }
+}
diff --git a/Source/Core/PrisonLaborUtility.cs b/Source/Core/PrisonLaborUtility.cs
index aacf2db2..dc544f0a 100644
--- a/Source/Core/PrisonLaborUtility.cs
+++ b/Source/Core/PrisonLaborUtility.cs
@@ -30,8 +30,8 @@ public static bool RecruitInLaborEnabled(Pawn pawn)
public static bool WorkTime(Pawn pawn)
{
- if (pawn.needs == null || pawn.needs.food == null || pawn.needs.rest == null)
- return false;
+/* 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/Settings/SettingsMenu.cs b/Source/Core/Settings/SettingsMenu.cs
index b50e5991..4839ef73 100644
--- a/Source/Core/Settings/SettingsMenu.cs
+++ b/Source/Core/Settings/SettingsMenu.cs
@@ -22,6 +22,7 @@ internal class SettingsMenu : Mod
private static bool enableFullHealRest;
private static bool advancedGrowing;
private static int defaultInteractionMode;
+ private static bool enableDebbuging;
private static List interactionModeList;
@@ -40,6 +41,7 @@ public static void Init()
enableSuicide = PrisonLaborPrefs.EnableSuicide;
showTreatmentHappiness = PrisonLaborPrefs.ShowTreatmentHappiness;
enableFullHealRest = PrisonLaborPrefs.EnableFullHealRest;
+ enableDebbuging = PrisonLaborPrefs.DebugLogs;
interactionModeList = new List(DefDatabase.AllDefs);
defaultInteractionMode = interactionModeList.IndexOf(DefDatabase.GetNamed(PrisonLaborPrefs.DefaultInteractionMode));
@@ -107,6 +109,9 @@ public override void DoSettingsWindowContents(Rect inRect)
listing_options.CheckboxLabeled("PrisonLabor_EnableFullHealRest".Translate(), ref enableFullHealRest,
"PrisonLabor_EnableFullHealRestDesc".Translate());
+ listing_options.CheckboxLabeled("PrisonLabor_EnableDebugLogs".Translate(), ref enableDebbuging,
+ "PrisonLabor_EnableDebugLogsDesc".Translate());
+
listing_options.GapLine();
@@ -177,6 +182,7 @@ public override void WriteSettings()
PrisonLaborPrefs.EnableSuicide = enableSuicide;
PrisonLaborPrefs.EnableFullHealRest = enableFullHealRest;
PrisonLaborPrefs.DefaultInteractionMode = interactionModeList[defaultInteractionMode].defName;
+ PrisonLaborPrefs.DebugLogs = enableDebbuging;
PrisonLaborPrefs.Save();
Log.Message("Prison Labor settings saved");
}
diff --git a/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs b/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs
new file mode 100644
index 00000000..8f1440db
--- /dev/null
+++ b/Source/HarmonyPatches/Patches_BillAssignation/Patch_Bill_ProductionWithUft.cs
@@ -0,0 +1,69 @@
+using HarmonyLib;
+using PrisonLabor.Core.Other;
+using RimWorld;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace PrisonLabor.HarmonyPatches.Patches_BillAssignation
+{
+ [HarmonyPatch(typeof(Bill_ProductionWithUft), "get_BoundWorker")]
+ class Patch_Bill_ProductionWithUft
+ {
+
+ static void Prefix(Bill_ProductionWithUft __instance, out UnfinishedThing __state)
+ {
+ UnfinishedThing unfinishedThing = Traverse.Create(__instance).Field("boundUftInt").GetValue();
+
+ if(unfinishedThing != null && unfinishedThing.Creator != null && unfinishedThing.Creator.IsPrisonerOfColony)
+ {
+ DebugLogger.debug($"[PL] Saving unfinished thing to state pawn: {unfinishedThing.Creator.LabelShort}, bill: {unfinishedThing.LabelShort}");
+ __state = unfinishedThing;
+ }
+ else
+ {
+ __state = null;
+ }
+
+ }
+
+ static Pawn Postfix(Pawn __result, Bill_ProductionWithUft __instance, UnfinishedThing __state)
+ {
+
+ if (__result == null && __state != null)
+ {
+ 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;
+ }
+ }
+}
diff --git a/Source/HarmonyPatches/Patches_Food/ReservedByPrisonerPatch.cs b/Source/HarmonyPatches/Patches_Food/ReservedByPrisonerPatch.cs
index 19ea7c32..6da5d673 100644
--- a/Source/HarmonyPatches/Patches_Food/ReservedByPrisonerPatch.cs
+++ b/Source/HarmonyPatches/Patches_Food/ReservedByPrisonerPatch.cs
@@ -33,6 +33,10 @@ static IEnumerable Transpiler(ILGenerator gen, MethodBase mBase
public static bool CanHaulAndInPrisonCell(Pawn p, Thing t, bool forced)
{
+ if (p.IsPrisonerOfColony)
+ {
+ DebugLogger.debug($"Prisoner {p.LabelShort} call: {t}");
+ }
var unfinishedThing = t as UnfinishedThing;
if (unfinishedThing != null && unfinishedThing.BoundBill != null)
return false;
diff --git a/Source/HarmonyPatches/Patches_ForbidUtil/Patch_ForbidUtility.cs b/Source/HarmonyPatches/Patches_ForbidUtil/Patch_ForbidUtility.cs
index 2c7d229a..f7bd4297 100644
--- a/Source/HarmonyPatches/Patches_ForbidUtil/Patch_ForbidUtility.cs
+++ b/Source/HarmonyPatches/Patches_ForbidUtil/Patch_ForbidUtility.cs
@@ -18,13 +18,19 @@ class Patch_ForbidUtility
[HarmonyPatch(new[] { typeof(Thing), typeof(Pawn) })]
static bool isForbidPostfix(bool __result, Thing t, Pawn pawn)
{
+ if (pawn.IsPrisonerOfColony)
+ {
+ DebugLogger.debug($"Prisoner {pawn.LabelShort}, forbid result: {__result} for {t}");
+ }
if (t.IsFoodForbiden(pawn))
{
+ DebugLogger.debug($"Forbid postfix food return true for {t}");
return true;
}
if (pawn.IsPrisonerOfColony)
{
+ DebugLogger.debug($"Forbid postfix return { t.IsForbiddenForPrisoner(pawn)} for {t}");
return t.IsForbiddenForPrisoner(pawn);
}
diff --git a/Source/HarmonyPatches/Patches_GUI/GUI_Bill/Patch_RestrictBillToPrisoner.cs b/Source/HarmonyPatches/Patches_GUI/GUI_Bill/Patch_RestrictBillToPrisoner.cs
index e1adfe2d..49c9249f 100644
--- a/Source/HarmonyPatches/Patches_GUI/GUI_Bill/Patch_RestrictBillToPrisoner.cs
+++ b/Source/HarmonyPatches/Patches_GUI/GUI_Bill/Patch_RestrictBillToPrisoner.cs
@@ -14,80 +14,80 @@ namespace PrisonLabor.HarmonyPatches.Patches_GUI.GUI_Bill
[HarmonyPatch("GeneratePawnRestrictionOptions")]
class Patch_RestrictBillToPrisoner
{
- static IEnumerable> Postfix(IEnumerable> values, Dialog_BillConfig __instance)
- {
- foreach (Widgets.DropdownMenuElement value in values)
+ static IEnumerable> Postfix(IEnumerable> values, Dialog_BillConfig __instance)
+ {
+ foreach (Widgets.DropdownMenuElement value in values)
{
- yield return value;
+ yield return value;
}
Bill_Production bill = Traverse.Create(__instance).Field("bill").GetValue();
- WorkGiverDef workGiver = bill.billStack.billGiver.GetWorkgiver();
+ WorkGiverDef workGiver = bill.billStack.billGiver.GetWorkgiver();
List allPrisonersOfColony = PawnsFinder.AllMaps_PrisonersOfColony;
- Widgets.DropdownMenuElement dropdownMenuElement;
- foreach (Pawn pawn in allPrisonersOfColony)
- {
- if (PrisonLaborUtility.LaborEnabled(pawn))
- {
- if (pawn.WorkTypeIsDisabled(workGiver.workType))
- {
- dropdownMenuElement = new Widgets.DropdownMenuElement
- {
- option = new FloatMenuOption(string.Format("{0} ({1})", pawn.LabelShortCap, "WillNever".Translate(workGiver.verb)), null),
- payload = pawn
- };
- yield return dropdownMenuElement;
- }
- else if (bill.recipe.workSkill != null && !pawn.workSettings.WorkIsActive(workGiver.workType))
- {
- dropdownMenuElement = new Widgets.DropdownMenuElement
- {
- option = new FloatMenuOption(string.Format("{0} ({1} {2}, {3})", pawn.LabelShortCap, pawn.skills.GetSkill(bill.recipe.workSkill).Level, bill.recipe.workSkill.label, "NotAssigned".Translate()), delegate
- {
- bill.pawnRestriction = pawn;
- }),
- payload = pawn
- };
- yield return dropdownMenuElement;
- }
- else if (!pawn.workSettings.WorkIsActive(workGiver.workType))
- {
- dropdownMenuElement = new Widgets.DropdownMenuElement
- {
- option = new FloatMenuOption(string.Format("{0} ({1})", pawn.LabelShortCap, "NotAssigned".Translate()), delegate
- {
- bill.pawnRestriction = pawn;
- }),
- payload = pawn
- };
- yield return dropdownMenuElement;
- }
- else if (bill.recipe.workSkill != null)
- {
- dropdownMenuElement = new Widgets.DropdownMenuElement
- {
- option = new FloatMenuOption($"{pawn.LabelShortCap} ({pawn.skills.GetSkill(bill.recipe.workSkill).Level} {bill.recipe.workSkill.label})", delegate
- {
- bill.pawnRestriction = pawn;
- }),
- payload = pawn
- };
- yield return dropdownMenuElement;
- }
- else
- {
- dropdownMenuElement = new Widgets.DropdownMenuElement
- {
- option = new FloatMenuOption($"{pawn.LabelShortCap}", delegate
- {
- bill.pawnRestriction = pawn;
- }),
- payload = pawn
- };
- yield return dropdownMenuElement;
- }
- }
- }
- }
- }
+ Widgets.DropdownMenuElement dropdownMenuElement;
+ foreach (Pawn pawn in allPrisonersOfColony)
+ {
+ if (PrisonLaborUtility.LaborEnabled(pawn))
+ {
+ if (pawn.WorkTypeIsDisabled(workGiver.workType))
+ {
+ dropdownMenuElement = new Widgets.DropdownMenuElement
+ {
+ option = new FloatMenuOption(string.Format("{0} ({1})", pawn.LabelShortCap, "WillNever".Translate(workGiver.verb)), null),
+ payload = pawn
+ };
+ yield return dropdownMenuElement;
+ }
+ else if (bill.recipe.workSkill != null && !pawn.workSettings.WorkIsActive(workGiver.workType))
+ {
+ dropdownMenuElement = new Widgets.DropdownMenuElement
+ {
+ option = new FloatMenuOption(string.Format("{0} ({1} {2}, {3})", pawn.LabelShortCap, pawn.skills.GetSkill(bill.recipe.workSkill).Level, bill.recipe.workSkill.label, "NotAssigned".Translate()), delegate
+ {
+ bill.pawnRestriction = pawn;
+ }),
+ payload = pawn
+ };
+ yield return dropdownMenuElement;
+ }
+ else if (!pawn.workSettings.WorkIsActive(workGiver.workType))
+ {
+ dropdownMenuElement = new Widgets.DropdownMenuElement
+ {
+ option = new FloatMenuOption(string.Format("{0} ({1})", pawn.LabelShortCap, "NotAssigned".Translate()), delegate
+ {
+ bill.pawnRestriction = pawn;
+ }),
+ payload = pawn
+ };
+ yield return dropdownMenuElement;
+ }
+ else if (bill.recipe.workSkill != null)
+ {
+ dropdownMenuElement = new Widgets.DropdownMenuElement
+ {
+ option = new FloatMenuOption($"{pawn.LabelShortCap} ({pawn.skills.GetSkill(bill.recipe.workSkill).Level} {bill.recipe.workSkill.label})", delegate
+ {
+ bill.pawnRestriction = pawn;
+ }),
+ payload = pawn
+ };
+ yield return dropdownMenuElement;
+ }
+ else
+ {
+ dropdownMenuElement = new Widgets.DropdownMenuElement
+ {
+ option = new FloatMenuOption($"{pawn.LabelShortCap}", delegate
+ {
+ bill.pawnRestriction = pawn;
+ }),
+ payload = pawn
+ };
+ yield return dropdownMenuElement;
+ }
+ }
+ }
+ }
+ }
}
diff --git a/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_PrisonerTab.cs b/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_PrisonerTab.cs
index 38ab4eb6..21de5b95 100644
--- a/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_PrisonerTab.cs
+++ b/Source/HarmonyPatches/Patches_GUI/GUI_PrisonerTab/Patch_PrisonerTab.cs
@@ -1,5 +1,7 @@
using HarmonyLib;
+using PrisonLabor.Constants;
using PrisonLabor.Core.Needs;
+using PrisonLabor.Core.Other;
using PrisonLabor.Core.Trackers;
using RimWorld;
using System;
@@ -74,8 +76,10 @@ public static void AddRecruitButton(Listing_Standard listingStandard)
{
if (listingStandard.ButtonTextLabeled("PrisonLabor_RecruitButtonDesc".Translate(), "PrisonLabor_RecruitButtonLabel".Translate()))
{
+ CleanPrisonersStatus.Clean(pawn);
pawn.guest.SetGuestStatus(null);
pawn.SetFaction(Faction.OfPlayer);
+
}
}
}
diff --git a/Source/HarmonyPatches/Patches_Work/Patch_JobGiver_Repair.cs b/Source/HarmonyPatches/Patches_Work/Patch_JobGiver_Repair.cs
new file mode 100644
index 00000000..1774d0a7
--- /dev/null
+++ b/Source/HarmonyPatches/Patches_Work/Patch_JobGiver_Repair.cs
@@ -0,0 +1,65 @@
+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_RescueDowned.cs b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_RescueDowned.cs
new file mode 100644
index 00000000..46b1fb5f
--- /dev/null
+++ b/Source/HarmonyPatches/Patches_Work/Patch_WorkGiver_RescueDowned.cs
@@ -0,0 +1,36 @@
+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_RescueDowned), "ShouldSkip")]
+
+ class Patch_WorkGiver_RescueDowned
+ {
+ static bool Prefix(ref bool __result, Pawn pawn, bool forced)
+ {
+ if(pawn != null && pawn.IsPrisonerOfColony)
+ {
+ List list = pawn.Map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer);
+ for (int i = 0; i < list.Count; i++)
+ {
+ if (list[i].Downed && !list[i].InBed())
+ {
+ __result = false;
+ return false;
+ }
+ }
+ __result = true;
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs b/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs
index c5c391f4..cb9b3bf1 100644
--- a/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs
+++ b/Source/HarmonyPatches/Patches_WorkSettings/Patch_ResetWorktableWhenRecruited.cs
@@ -1,5 +1,6 @@
using HarmonyLib;
using PrisonLabor.Constants;
+using PrisonLabor.Core.Other;
using RimWorld;
using System;
using System.Collections.Generic;
@@ -11,28 +12,20 @@
namespace PrisonLabor.HarmonyPatches.Patches_WorkSettings
{
- [HarmonyPatch(typeof(Pawn))]
- [HarmonyPatch("SetFaction")]
- [HarmonyPatch(new[] { typeof(Faction), typeof(Pawn) })]
+ [HarmonyPatch(typeof(InteractionWorker_RecruitAttempt))]
+ [HarmonyPatch("DoRecruit")]
+ [HarmonyPatch(new Type[] { typeof(Pawn), typeof(Pawn), typeof(float), typeof(string), typeof(string), typeof(bool), typeof(bool) },
+ new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out, ArgumentType.Out, ArgumentType.Normal, ArgumentType.Normal })]
class Patch_ResetWorktableWhenRecruited
{
- private static void Prefix(Pawn __instance, Faction newFaction, Pawn recruiter)
- {
- if (__instance.RaceProps.Humanlike && newFaction == Faction.OfPlayer)
+ static void Prefix(Pawn recruiter, Pawn recruitee)
+ {
+ if(recruitee != null && recruitee.IsPrisonerOfColony && recruiter != null && recruiter.Faction == Faction.OfPlayer)
{
- __instance.workSettings = new Pawn_WorkSettings(__instance);
- Hediff legs = __instance.health.hediffSet.GetFirstHediffOfDef(PL_DefOf.PrisonLabor_RemovedLegscuffs, false);
- if (legs != null)
- {
- __instance.health.hediffSet.hediffs.Remove(legs);
- }
- Hediff hands = __instance.health.hediffSet.GetFirstHediffOfDef(PL_DefOf.PrisonLabor_RemovedHandscuffs, false);
- if (hands != null)
- {
- __instance.health.hediffSet.hediffs.Remove(hands);
- }
- __instance.playerSettings.AreaRestriction = null;
+ CleanPrisonersStatus.Clean(recruitee);
+ Log.Message($"[PrisonLabor] Removed prisoners effects from {recruitee.LabelShort}");
}
}
+
}
}
diff --git a/Source/HarmonyPatches/Patches_WorkSettings/Patch_RespectAllowedArea.cs b/Source/HarmonyPatches/Patches_WorkSettings/Patch_RespectAllowedArea.cs
index 2ff4db45..36b7dc7d 100644
--- a/Source/HarmonyPatches/Patches_WorkSettings/Patch_RespectAllowedArea.cs
+++ b/Source/HarmonyPatches/Patches_WorkSettings/Patch_RespectAllowedArea.cs
@@ -16,7 +16,7 @@ class Patch_RespectAllowedArea
static bool Postfix(bool __result, Pawn_PlayerSettings __instance)
{
Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue();
- if (!__result && pawn.IsPrisonerOfColony )
+ if (!__result && pawn != null && pawn.IsPrisonerOfColony )
{
return true;
}
diff --git a/Source/PrisonLabor.csproj b/Source/PrisonLabor.csproj
index 42935158..54ceea07 100644
--- a/Source/PrisonLabor.csproj
+++ b/Source/PrisonLabor.csproj
@@ -70,6 +70,7 @@
+
@@ -91,7 +92,9 @@
+
+
@@ -102,6 +105,7 @@
+
@@ -154,9 +158,11 @@
+
+
diff --git a/Source/WorkUtils/ConstructionUtils.cs b/Source/WorkUtils/ConstructionUtils.cs
index 98d8ccbd..74229fd4 100644
--- a/Source/WorkUtils/ConstructionUtils.cs
+++ b/Source/WorkUtils/ConstructionUtils.cs
@@ -20,7 +20,7 @@ public static bool HasJobOnThingFixed(Pawn pawn, Thing t, bool forced)
{
return false;
}
- if (!pawn.Map.listerBuildingsRepairable.Contains(pawn.Faction, building))
+ if (!pawn.Map.listerBuildingsRepairable.Contains(Faction.OfPlayer, building))
{
return false;
}
@@ -36,7 +36,7 @@ public static bool HasJobOnThingFixed(Pawn pawn, Thing t, bool forced)
{
return false;
}
- if (pawn.Faction == Faction.OfPlayer && !pawn.Map.areaManager.Home[t.Position])
+ if (pawn.IsPrisonerOfColony && !pawn.Map.areaManager.Home[t.Position])
{
JobFailReason.Is(WorkGiver_FixBrokenDownBuilding.NotInHomeAreaTrans);
return false;
diff --git a/changelog.txt b/changelog.txt
index a135c878..f4808427 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,14 @@
Changelog:
+1.2.3
+- Fixing issue with faction set (animal and recruiting) from 1.2.1 and 1.2.2
+- Prisoners without food and/or sleep needs should work normally
+- Lots of null objects checks - it should reduce amount of errors
+- Suicide and resocialization event condition update. Those events should not trigger when a pawn is not spawned
+- Added logic for prisoners to search for appeal before work start. Put appeal in their cell and naked prisoners should wear it
+- Compatibility with "Kijin Race 2.0". Prisoners should drop hay when research is done, and they cut plants
+- More fixes for construction jobs. Pawn without faction should not spam errors
+- Improved continuation of unfinished bills. With that improvement mod human resources should be compatible
+- Update Chinese translation
1.2.2
- NPE fix for drawning icon
- Fix issue with animal taming