Skip to content

Commit

Permalink
v0.18.1.8
Browse files Browse the repository at this point in the history
While You're Up, dynamic opportunistic hauling, improved loading and unloading.
Mehni committed Mar 19, 2018
1 parent d14edce commit bf7fe32
Showing 10 changed files with 118 additions and 51 deletions.
2 changes: 1 addition & 1 deletion About/About.xml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
<url>https://ludeon.com/forums/index.php?topic=35832</url>
<description>"Greatest hauling mod ever" - Chicken Plucker

v0.18.1.7
v0.18.1.8

Colonists will gather stuff in their inventory, then haul it all to a stockpile.

Binary file modified Assemblies/PickUpAndHaul.dll
Binary file not shown.
48 changes: 38 additions & 10 deletions Source/PickUpAndHaul/PickUpAndHaul/HarmonyPatches.cs
Original file line number Diff line number Diff line change
@@ -50,8 +50,23 @@ static HarmonyPatches()
}
}))();
}
catch (TypeLoadException) { }
Log.Message("PickUpAndHaul v0.18.1.7 welcomes you to RimWorld with pointless logspam.");
catch (TypeLoadException) { }

//Thanks to AlexTD for the While You're Up functionality improvement
try
{
((Action)(() =>
{
if (ModCompatibilityCheck.WhileYoureUpIsActive)
{
harmony.Patch(AccessTools.Method(typeof(WhileYoureUp.Utils), "MaybeHaulOtherStuffFirst"),
null, new HarmonyMethod(typeof(HarmonyPatches), nameof(WhileYoureUpMaybeHaulOtherStuffFirst_PostFix)), null);
}
}))();
}
catch (TypeLoadException) { }

Log.Message("PickUpAndHaul v0.18.1.8 welcomes you to RimWorld with pointless logspam.");
}


@@ -89,10 +104,8 @@ private static bool AllowToolHaulUrgentlyJobOnThing_PreFix(ref Job __result, Paw
private static bool Drop_Prefix(ref Pawn pawn, ref Thing thing)
{
CompHauledToInventory takenToInventory = pawn.TryGetComp<CompHauledToInventory>();
if (takenToInventory == null)
{
return true;
}
if (takenToInventory == null) return true;

HashSet<Thing> carriedThing = takenToInventory.GetHashSet();

if (carriedThing.Contains(thing))
@@ -134,10 +147,10 @@ private static void JobDriver_HaulToCell_PostFix(JobDriver_HaulToCell __instance
{
PawnUnloadChecker.CheckIfPawnShouldUnloadInventory(__instance.pawn, true);
}
else //we could politely ask
{
PawnUnloadChecker.CheckIfPawnShouldUnloadInventory(__instance.pawn);
}
//else //we could politely ask
//{
// PawnUnloadChecker.CheckIfPawnShouldUnloadInventory(__instance.pawn);
//}
}

public static void IdleJoy_Postfix(ref Pawn pawn)
@@ -181,5 +194,20 @@ public static IEnumerable<CodeInstruction> FloatMenuMakerMad_AddHumanlikeOrders_
yield return instruction;
}
}

//Thanks to AlexTD
//Job WhileYoureUp.Utils.MaybeHaulOtherStuffFirst(Pawn pawn, LocalTargetInfo end)
public static void WhileYoureUpMaybeHaulOtherStuffFirst_PostFix(Pawn pawn, LocalTargetInfo end, ref Job __result)
{
if (__result == null || __result.def != JobDefOf.HaulToCell) return;

WorkGiver_HaulToInventory worker = pawn.workSettings.WorkGiversInOrderNormal.FirstOrDefault(wg => wg is WorkGiver_HaulToInventory) as WorkGiver_HaulToInventory;
if (worker == null) return;

Job myJob = worker.JobOnThing(pawn, __result.targetA.Thing, false);
if (myJob == null) return;

__result = myJob;
}
}
}
32 changes: 25 additions & 7 deletions Source/PickUpAndHaul/PickUpAndHaul/JobDriver_HaulToInventory.cs
Original file line number Diff line number Diff line change
@@ -9,23 +9,39 @@ namespace PickUpAndHaul
{
public class JobDriver_HaulToInventory : JobDriver
{


public override bool TryMakePreToilReservations()
{
return this.pawn.Reserve(this.job.targetA, this.job, 1, -1, null);
}


//reserve, goto, take, check for more. Branches off to "all over the place"
protected override IEnumerable<Toil> MakeNewToils()
{
CompHauledToInventory takenToInventory = pawn.TryGetComp<CompHauledToInventory>();
HashSet<Thing> carriedThings = takenToInventory.GetHashSet();
DesignationDef HaulUrgentlyDesignation = DefDatabase<DesignationDef>.GetNamed("HaulUrgentlyDesignation", false);

//Thanks to AlexTD for the more dynamic search range
float searchForOthersRangeFraction = 0.5f;
float distanceToOthers = 0f;

Toil wait = Toils_General.Wait(2);
Toil reserveTargetA = Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null);
Toil checkForOtherItemsToHaulToInventory = CheckForOtherItemsToHaulToInventory(reserveTargetA, TargetIndex.A, null);
Toil checkForOtherItemsToUrgentlyHaulToInventory = CheckForOtherItemsToHaulToInventory(reserveTargetA, TargetIndex.A, (Thing x) => pawn.Map.designationManager.DesignationOn(x)?.def == HaulUrgentlyDesignation);

Toil calculateExtraDistanceToGo = new Toil
{
initAction = () =>
{
if (StoreUtility.TryFindStoreCellNearColonyDesperate(this.job.targetA.Thing, this.pawn, out IntVec3 storeLoc))
distanceToOthers = (storeLoc - job.targetA.Thing.Position).LengthHorizontal * searchForOthersRangeFraction;
}
};
yield return calculateExtraDistanceToGo;

Toil checkForOtherItemsToHaulToInventory = CheckForOtherItemsToHaulToInventory(reserveTargetA, TargetIndex.A, distanceToOthers, null);
Toil checkForOtherItemsToUrgentlyHaulToInventory = CheckForOtherItemsToHaulToInventory(reserveTargetA, TargetIndex.A, distanceToOthers, (Thing x) => pawn.Map.designationManager.DesignationOn(x)?.def == HaulUrgentlyDesignation);

yield return reserveTargetA;

@@ -35,7 +51,7 @@ protected override IEnumerable<Toil> MakeNewToils()
{
this.pawn.pather.StartPath(this.TargetThingA, PathEndMode.ClosestTouch);
},
defaultCompleteMode = ToilCompleteMode.PatherArrival
defaultCompleteMode = ToilCompleteMode.PatherArrival,
};
gotoThing.FailOnDespawnedNullOrForbidden(TargetIndex.A);
yield return gotoThing;
@@ -121,25 +137,26 @@ protected override IEnumerable<Toil> MakeNewToils()

//regular Toils_Haul.CheckForGetOpportunityDuplicate isn't going to work for our purposes, since we're not carrying anything.
//Carrying something yields weird results with unspawning errors when transfering to inventory, so we copy-past-- I mean, implement our own.
public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIndex haulableInd, Predicate<Thing> extraValidator = null)
public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIndex haulableInd, float distanceToOthers, Predicate<Thing> extraValidator = null)
{
Toil toil = new Toil();
toil.initAction = delegate
{
Pawn actor = toil.actor;
Job curJob = actor.jobs.curJob;
IntVec3 storeCell = IntVec3.Invalid;

Predicate<Thing> validator = (Thing t) => t.Spawned
&& HaulAIUtility.PawnCanAutomaticallyHaulFast(actor, t, false)
&& (!t.IsInValidBestStorage())
&& !t.IsForbidden(actor)
&& !(t is Corpse)
&& (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, (HaulAIUtility.StoragePriorityAtFor(t.Position, t)), actor.Faction, out IntVec3 storeCell, true))
&& (StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, (HaulAIUtility.StoragePriorityAtFor(t.Position, t)), actor.Faction, out storeCell, true))
&& (extraValidator == null || extraValidator (t))
&& actor.CanReserve(t, 1, -1, null, false);

Thing thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch,
TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), 12f, validator, null, 0, -1, false, RegionType.Set_Passable, false);
TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), Math.Max(distanceToOthers, 12f), validator, null, 0, -1, false, RegionType.Set_Passable, false);

float usedBulkByPct = 1f;
float usedWeightByPct = 1f;
@@ -162,6 +179,7 @@ public Toil CheckForOtherItemsToHaulToInventory(Toil getHaulTargetToil, TargetIn
if (thing != null && (MassUtility.EncumbrancePercent(actor) <= 0.9f || usedBulkByPct >= 0.7f || usedWeightByPct >= 0.8f))
{
curJob.SetTarget(haulableInd, thing);
actor.Reserve(storeCell, this.job, 1, -1, null);
actor.jobs.curDriver.JumpToToil(getHaulTargetToil);
return;
}
Original file line number Diff line number Diff line change
@@ -23,8 +23,7 @@ public override bool TryMakePreToilReservations()
{
return true;
}



/// <summary>
/// Find spot, reserve spot, pull thing out of inventory, go to spot, drop stuff, repeat.
/// </summary>
@@ -85,7 +84,7 @@ protected override IEnumerable<Toil> MakeNewToils()
if (thing == null || !this.pawn.inventory.innerContainer.Contains(thing))
{
carriedThing.Remove(thing);
this.EndJobWith(JobCondition.Incompletable);
pawn.jobs.curDriver.JumpToToil(wait);
return;
}
if (!this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStoreable)
@@ -95,7 +94,7 @@ protected override IEnumerable<Toil> MakeNewToils()
carriedThing.Remove(thing);
}
else
{
{
this.pawn.inventory.innerContainer.TryTransferToContainer(thing, this.pawn.carryTracker.innerContainer, this.countToDrop, out thing, true);
this.job.count = this.countToDrop;
this.job.SetTarget(TargetIndex.A, thing);
@@ -121,6 +120,20 @@ protected override IEnumerable<Toil> MakeNewToils()
yield return Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch);
yield return carryToCell;
yield return Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true);

//If the original cell is full, PlaceHauledThingInCell will set a different TargetIndex resulting in errors on yield return Toils_Reserve.Release.
//We still gotta release though, mostly because of Extended Storage.
Toil releaseReservation = new Toil
{
initAction = () =>
{
if (pawn.Map.reservationManager.ReservedBy(this.job.targetB, pawn, pawn.CurJob))
{
pawn.Map.reservationManager.Release(this.job.targetB, pawn, pawn.CurJob);
}
}
};
yield return releaseReservation;
yield return Toils_Jump.Jump(wait);
yield return celebrate;
}
@@ -129,28 +142,32 @@ ThingStackPart FirstUnloadableThing(Pawn pawn)
{
CompHauledToInventory itemsTakenToInventory = pawn.TryGetComp<CompHauledToInventory>();
HashSet<Thing> carriedThings = itemsTakenToInventory.GetHashSet();

//find the overlap.
IEnumerable<Thing> potentialThingsToUnload =
from t in pawn.inventory.innerContainer
//orderby t.def.category
where carriedThings.Contains(t)
select t;

foreach (Thing thing in carriedThings)
//pawns seem to ignore OrderBy, probably because it's a hashset or something.

foreach (Thing thing in carriedThings/*.OrderBy(t => t.def.category)*/)
{
try
{
if (thing == null)
{
carriedThings.Remove(thing);
}
}
catch (Exception arg)
{
Log.Warning("There was an exception thrown by Pick Up And Haul. Pawn will clear inventory. \nException: " + arg);
carriedThings.Clear();
pawn.inventory.UnloadEverything = true;
}
//commented out because if it were actually functional, I'm removing items from a hashset I'm iterating over. Herp a derp.
//try
//{
// if (thing == null)
// {
// carriedThings.Remove(thing);
// }
//}
//catch (Exception arg)
//{
// Log.Warning("There was an exception thrown by Pick Up And Haul. Pawn will clear inventory. \nException: " + arg);
// carriedThings.Clear();
// pawn.inventory.UnloadEverything = true;
//}

//merged partially picked up stacks get a different thingID in inventory
if (!potentialThingsToUnload.Contains(thing))
@@ -161,6 +178,7 @@ where carriedThings.Contains(t)
IEnumerable<Thing> dirtyStragglers =
from straggler in pawn.inventory.innerContainer
where straggler.def == stragglerDef
//orderby straggler.def.category
select straggler;

carriedThings.Remove(thing);
8 changes: 8 additions & 0 deletions Source/PickUpAndHaul/PickUpAndHaul/ModCompatibilityCheck.cs
Original file line number Diff line number Diff line change
@@ -41,5 +41,13 @@ public static bool ExtendedStorageIsActive
return ModsConfig.ActiveModsInLoadOrder.Any(m => m.Name == "ExtendedStorageFluffyHarmonised");
}
}

public static bool WhileYoureUpIsActive
{
get
{
return ModsConfig.ActiveModsInLoadOrder.Any(m => m.Name == "While You're Up");
}
}
}
}
11 changes: 3 additions & 8 deletions Source/PickUpAndHaul/PickUpAndHaul/PawnUnloadChecker.cs
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@
using Verse;
using Verse.AI;


namespace PickUpAndHaul
{
public class PawnUnloadChecker
@@ -26,13 +25,9 @@ public static void CheckIfPawnShouldUnloadInventory(Pawn pawn, bool forced = fal

if (carriedThing.Count != 0)
{
Thing thing = null;
try
{
if (carriedThing.Contains(thing))
{
carriedThing.Remove(thing);
}
carriedThing.RemoveWhere((Thing t) => t == null || t.ThingID == null || t.def == null);
}
catch (Exception arg)
{
@@ -75,12 +70,12 @@ public static void CheckIfPawnShouldUnloadInventory(Pawn pawn, bool forced = fal
}
}
}

if (Find.TickManager.TicksGame % 50 == 0 && pawn.inventory.innerContainer.Count < carriedThing.Count)
{
Log.Warning("[PickUpAndHaul] " + pawn + " inventory was found out of sync with haul index. Pawn will drop their inventory.");
carriedThing.Clear();
pawn.inventory.UnloadEverything = true;
pawn.inventory.UnloadEverything = true;
}
}
}
4 changes: 4 additions & 0 deletions Source/PickUpAndHaul/PickUpAndHaul/PickUpAndHaul.csproj
Original file line number Diff line number Diff line change
@@ -56,6 +56,10 @@
<HintPath>..\..\..\..\..\RimWorldWin_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="WhileYoureUp">
<HintPath>..\..\..\..\..\..\..\workshop\content\294100\1161112205\Assemblies\WhileYoureUp.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CompHauledToInventory.cs" />
4 changes: 2 additions & 2 deletions Source/PickUpAndHaul/PickUpAndHaul/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.18.1.7")]
[assembly: AssemblyFileVersion("1.0.0.561")]
[assembly: AssemblyVersion("0.18.1.8")]
[assembly: AssemblyFileVersion("1.0.0.565")]
Original file line number Diff line number Diff line change
@@ -33,10 +33,6 @@ public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)

if (t.IsForbidden(pawn) || StoreUtility.IsInValidBestStorage(t)) return null;

////because who doesn't love hardcoded checks?
//turns out I *can* fix issues in other people's mods. All it takes is a pull request :)
//if (ModCompatibilityCheck.SimplesidearmsIsActive && t.def.defName.Contains("Chunk")) return HaulAIUtility.HaulToStorageJob(pawn, t);

//bulky gear (power armor + minigun) so don't bother.
if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) return null;

0 comments on commit bf7fe32

Please sign in to comment.