/// <summary> /// Calculates whether the dialog or any of its transferable items have changed since last remembered, /// and records the new state if there were changes /// </summary> public static bool HasChanged(RimWorld.Dialog_FormCaravan dialogInstance) { if (dialogInstance == null) { Mod.LogError("Dialog instance was null"); return(true); } var hasChanged = false; if (lastDialogInstance != dialogInstance) { Mod.LogTrace("Dialog instance changed"); hasChanged = true; } var transferablesHash = CalculateTransferablesHash(dialogInstance.transferables); if (transferablesHash != lastTransferablesHash) { Mod.LogTrace("Transferables list changed"); hasChanged = true; } if (hasChanged) { Remember(dialogInstance, transferablesHash); } return(hasChanged); }
static void CheckForErrors_Postfix(RimWorld.Dialog_FormCaravan __instance, ref bool __result, ref bool ___massUsageDirty, List <Pawn> pawns) { // Don't intevene if only closing dialog to choose route if (__instance.choosingRoute) { return; } // Don't intervene if other errors are already preventing the dialog from closing if (!__result) { return; } // Errors are evaluated a second time before rendering confirmation, for some reason... ignore that call var stackFrame = new StackFrame(1); var callingMethod = stackFrame.GetMethod(); if (callingMethod.Name == "DoBottomButtons") { return; } // Inject bedroll check after other error validation Mod.LogTrace("Postfixing Dialog_FormCaravan.CheckForErrors"); __result = CaravanBedrollHelper.CheckBeforeClosing(__instance, pawns); ___massUsageDirty = true; }
public static void Remember(RimWorld.Dialog_FormCaravan dialogInstance) { if (dialogInstance == null) { Forget(); return; } var transferablesHash = CalculateTransferablesHash(dialogInstance.transferables); Remember(dialogInstance, transferablesHash); }
/// <summary> /// Checks if more bedrolls are needed for the caravan, and adds them if appropriate /// </summary> /// <returns> /// Whether to proceed with sending the caravan /// </returns> public static bool CheckBeforeClosing(RimWorld.Dialog_FormCaravan dialogInstance, List <Pawn> pawns) { var neededBedrolls = GetNeededBedrolls(dialogInstance.transferables, pawns); if (neededBedrolls.Count <= 0) { return(true); } var neededMass = GetNeededMass(neededBedrolls); Mod.LogTrace($"Need {neededMass} mass capacity for bedrolls"); var availableMass = GetAvailableMass(dialogInstance); Mod.LogTrace($"Have {availableMass} mass capacity available"); // Don't push the caravan over its mass limit if (neededMass > availableMass) { if (State.HasChanged(dialogInstance)) { // If the first time or if loadout changed, warn user and abort departure Messages.Message( $"Adding {neededBedrolls.Count} bedrolls would put caravan over weight by {neededMass - availableMass}. Accept or Confirm to leave as-is, or make changes to the caravan packing list to trigger re-processing.", MessageTypeDefOf.RejectInput, false); return(false); } else { // If trying the same thing twice in a row, allow caravan to leave without bedrolls State.Forget(); return(true); } } // Add needed bedrolls and leave if (neededBedrolls.Any()) { foreach (var neededBedroll in neededBedrolls) { neededBedroll.Key.AdjustBy(neededBedroll.Value); } Mod.LogMessage("Successfully added additional bedrolls"); Messages.Message($"Successfully added {neededBedrolls.Count} bedrolls to caravan.", MessageTypeDefOf.RejectInput, false); } State.Forget(); return(true); }
public static void Forget() { lastDialogInstance = null; lastTransferablesHash = 0; }
private static void Remember(RimWorld.Dialog_FormCaravan dialogInstance, int transferablesHash) { lastDialogInstance = dialogInstance; lastTransferablesHash = transferablesHash; }
public static float GetAvailableMass(RimWorld.Dialog_FormCaravan dialogInstance) => dialogInstance.MassCapacity - dialogInstance.MassUsage;