protected override IEnumerable<Toil> MakeNewToils()
        {
            var fillInto = TargetThingB as Apparel;
            var toWC = fillInto.TryGetComp<CompWaterContainer>();
            float packLitres = toWC.FreeSpaceLitres;
            CompWaterContainer fromWC;

            if (TargetA.HasThing)
            {
                // Packing from a Thing.
                var fillFrom = TargetThingA;
                fromWC = fillFrom.TryGetComp<CompWaterContainer>();

                // Reserve and go to the source.
                yield return Toils_Water.ReserveWaterIfNeeded(fillFrom, fromWC, packLitres);
                yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).
                    FailOnDespawnedOrForbidden(TargetIndex.A).FailOn(() => fromWC.IsEmpty);
            }
            else
            {
                // Packing from a bit of terrain.
                // This assumes that all terrain water acts as an infinite source.
                fromWC = new CompWaterSource();
                fromWC.Initialize(new CompPropertiesWaterSource() { unlimitedSource = true });

                yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch);
            }

            // Get water from the source.
            yield return Toils_Water.TransferWater(fromWC, toWC, packLitres);
        }
        protected override IEnumerable<Toil> MakeNewToils()
        {
            var need = pawn.needs.TryGetNeed<Need_Water>();
            CompWaterContainer wc;
            bool worn = false;

            if (TargetA.HasThing)
            {
                wc = TargetThingA.TryGetComp<CompWaterContainer>();
                var wearable = TargetThingA as Apparel;
                worn = (wearable != null) && (pawn.apparel.WornApparel.Contains(wearable));
                if (!worn)
                {
                    // Actor not wearing a drinkable Thing.
                    // Reserve it if necessary and move to the Thing.
                    yield return Toils_Water.ReserveWaterIfNeeded(TargetThingA, wc, need.HydrationWantedLitres);
                    yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).
                        FailOnDespawnedOrForbidden(TargetIndex.A).FailOn(() => wc.IsEmpty);
                }
            }
            else
            {
                // We're targeting a piece of terrain that has some water.
                // This assumes that all terrain water acts as an infinite source.
                wc = new CompWaterSource();
                wc.Initialize(new CompPropertiesWaterSource() {unlimitedSource=true});

                yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch);
            }

            // Now drink in little sips :P
            int sips = Toils_Water.SipsToDrink(need.HydrationWantedLitres);
            for (int i = 0; i < sips; i++)
            {
                yield return Toils_Water.SipWater(pawn, need, wc, worn);
            }
        }
        // TODO: very similar to JobDriver_HaulWater, could split out a common subset.
        protected override IEnumerable<Toil> MakeNewToils()
        {
            // TargetA = from
            // TargetB = to
            // TargetC = tool

            Pawn patient = TargetThingB as Pawn;
            var patientNeed = patient.needs.TryGetNeed<Need_Water>();

            var tool = TargetC.Thing;
            var toolWc = tool.TryGetComp<CompWaterContainer>();

            // Grab the water carrying tool if it's not in our inventory.
            if (!this.pawn.inventory.container.Contains(tool))
            {
                yield return Toils_Reserve.Reserve(TargetIndex.C);
                yield return Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch).FailOnDespawnedOrForbidden(TargetIndex.C);
                yield return Toils_General.PickUpTool(TargetIndex.C);
            }
            // If the tool is in our inventory, carry it.
            else
            {
                yield return Toils_General.CarryThingFromInventory(tool);
            }

            // Fill it if necessary.
            if (TargetA.IsValid)
            {
                float collectLitres = patientNeed.HydrationWantedLitres - toolWc.StoredLitres;
                if (collectLitres > toolWc.FreeSpaceLitres)
                {
                    collectLitres = toolWc.FreeSpaceLitres;
                }

                if (collectLitres > 0)
                {
                    CompWaterContainer fromWc;

                    // Go to Thing water source.
                    if (TargetA.HasThing)
                    {
                        fromWc = TargetThingA.TryGetComp<CompWaterContainer>();
                        yield return Toils_Water.ReserveWaterIfNeeded(TargetThingA, fromWc, collectLitres);
                        yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).
                            FailOnDespawnedOrForbidden(TargetIndex.A).FailOn(() => fromWc.IsEmpty);
                    }
                    // Go to Terrain water source.
                    else
                    {
                        // This assumes that all terrain water acts as an infinite source.
                        fromWc = new CompWaterSource();
                        fromWc.Initialize(new CompPropertiesWaterSource() { unlimitedSource = true });

                        yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch);
                    }

                    // (Partially) fill water carrying tool.
                    yield return Toils_Water.TransferWater(fromWc, toolWc, collectLitres);
                }
            }

            // Carry to patient and give.
            yield return Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).FailOnDespawnedOrForbidden(TargetIndex.B);
            yield return Toils_General.FaceThing(TargetIndex.B);
            int sips = Toils_Water.SipsToDrink(patientNeed.HydrationWantedLitres);
            for (int i = 0; i < sips; i++)
            {
                yield return Toils_Water.SipWater(patient, patientNeed, toolWc, false);
            }

            // Put tool back in inventory.  Speeds up multiple hauling trips and stops other colonists
            // trying to grab the tool all the time.
            yield return Verse.AI.Toils_General.PutCarriedThingInInventory();
        }