public static Toil CheckNeedStorageCell(Toil jumpToil, TargetIndex CarrierInd, TargetIndex StoreCellInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn actor = toil.actor;

                Vehicle_Cart     cart     = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart;
                Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack;
                if (cart == null && backpack == null)
                {
                    Log.Error(actor.LabelCap + " Report: Don't have Carrier");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                }
                ThingContainer container = cart != null ? cart.storage : backpack.slotsComp.slots;
                if (container.Count == 0)
                {
                    return;
                }

                IntVec3 cell = ToolsForHaulUtility.FindStorageCell(actor, container.First());
                if (cell != IntVec3.Invalid)
                {
                    toil.actor.jobs.curJob.SetTarget(StoreCellInd, cell);
                    Find.Reservations.Reserve(actor, cell);
                    toil.actor.jobs.curDriver.JumpToToil(jumpToil);
                }
            };
            return(toil);
        }
        public static Toil CallAnimalCart(TargetIndex CartInd, TargetIndex Ind, Pawn pawn = null)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn         actor = toil.GetActor();
                Vehicle_Cart cart  = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart;
                if (cart == null)
                {
                    Log.Error(actor.LabelCap + " Report: Cart is invalid.");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                }
                Job job;
                if (pawn != null)
                {
                    job = new Job(HaulJobDefOf.StandBy, pawn.Position, defaultWaitWorker);
                }
                else
                {
                    job = new Job(HaulJobDefOf.StandBy, toil.actor.jobs.curJob.GetTarget(Ind), defaultWaitWorker);
                }

                cart.mountableComp.Driver.jobs.StartJob(job, JobCondition.InterruptForced);
            };
            return(toil);
        }
        public static Toil CheckDuplicates(Toil jumpToil, TargetIndex CarrierInd, TargetIndex HaulableInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                IntVec3 storeCell = IntVec3.Invalid;
                Pawn    actor     = toil.GetActor();

                TargetInfo target = toil.actor.jobs.curJob.GetTarget(HaulableInd);
                if (target.Thing.def.stackLimit <= 1)
                {
                    return;
                }
                List <TargetInfo> targetQueue = toil.actor.jobs.curJob.GetTargetQueue(HaulableInd);
                if (!targetQueue.NullOrEmpty() && target.Thing.def.defName == targetQueue.First().Thing.def.defName)
                {
                    toil.actor.jobs.curJob.SetTarget(HaulableInd, targetQueue.First());
                    Find.Reservations.Reserve(actor, targetQueue.First());
                    targetQueue.RemoveAt(0);
                    toil.actor.jobs.curDriver.JumpToToil(jumpToil);
                    return;
                }
                Vehicle_Cart     cart     = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart;
                Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack;

                if (cart == null && backpack == null)
                {
                    Log.Error(actor.LabelCap + " Report: Don't have Carrier");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                    return;
                }
                int curItemCount = (cart != null ? cart.storage.Count : backpack.slotsComp.slots.Count) + targetQueue.Count;
                int curItemStack = (cart != null ? cart.storage.TotalStackCount : backpack.slotsComp.slots.TotalStackCount)
                                   + targetQueue.Sum(item => item.Thing.stackCount);
                int maxItem  = cart != null ? cart.MaxItem : backpack.MaxItem;
                int maxStack = cart != null ? cart.MaxStack : backpack.MaxStack;
                if (curItemCount >= maxItem || curItemStack >= maxStack)
                {
                    return;
                }
                //Check target's nearby
                Thing thing = GenClosest.ClosestThing_Global_Reachable(actor.Position,
                                                                       ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                       PathEndMode.Touch,
                                                                       TraverseParms.For(actor, Danger.Some),
                                                                       NearbyCell,
                                                                       item => !targetQueue.Contains(item) &&
                                                                       item.def.defName == target.Thing.def.defName &&
                                                                       !item.IsBurning() &&
                                                                       Find.Reservations.CanReserve(actor, item));
                if (thing != null)
                {
                    toil.actor.jobs.curJob.SetTarget(HaulableInd, thing);
                    Find.Reservations.Reserve(actor, thing);
                    toil.actor.jobs.curDriver.JumpToToil(jumpToil);
                }
            };
            return(toil);
        }
Beispiel #4
0
        private float GetStatFactor(Pawn thisPawn)
        {
            float result = 1f;

            if (MapComponent_ToolsForHaul.currentVehicle.ContainsKey(thisPawn))
            {
                Vehicle_Cart vehicleCart = MapComponent_ToolsForHaul.currentVehicle[thisPawn] as Vehicle_Cart;
                if (vehicleCart != null)
                {
                    if (vehicleCart.mountableComp.IsMounted && !vehicleCart.mountableComp.Driver.RaceProps.Animal && vehicleCart.mountableComp.Driver == thisPawn)
                    {
                        if (vehicleCart.IsCurrentlyMotorized())
                        {
                            result = Mathf.Clamp(vehicleCart.VehicleSpeed, 2f, 100f);
                        }
                        else
                        {
                            result = Mathf.Clamp(vehicleCart.VehicleSpeed, 0.5f, 1f);
                        }
                        return(result);
                    }
                }

                Vehicle_Turret vehicleTank = MapComponent_ToolsForHaul.currentVehicle[thisPawn] as Vehicle_Turret;
                if (vehicleTank != null)
                {
                    if (vehicleTank.mountableComp.IsMounted && !vehicleTank.mountableComp.Driver.RaceProps.Animal && vehicleTank.mountableComp.Driver == thisPawn)
                    {
                        if (vehicleTank.IsCurrentlyMotorized())
                        {
                            result = Mathf.Clamp(vehicleTank.VehicleSpeed, 2f, 100f);
                        }
                        else
                        {
                            result = Mathf.Clamp(vehicleTank.VehicleSpeed, 0.5f, 1f);
                        }
                        return(result);
                    }
                }
            }

            Apparel_Backpack  apparelBackpack   = ToolsForHaulUtility.TryGetBackpack(thisPawn);
            CompSlotsBackpack compSlotsBackpack = apparelBackpack?.slotsComp;

            if (compSlotsBackpack != null)
            {
                result = Mathf.Clamp(compSlotsBackpack.moveSpeedFactor - compSlotsBackpack.encumberPenalty, 0.1f, 1f);
            }

            CompInventory compInventory = thisPawn.TryGetComp <CompInventory>();

            if (compInventory != null)
            {
                result = Mathf.Clamp(compInventory.moveSpeedFactor - compInventory.encumberPenalty, 0.1f, 1f);
                return(result);
            }

            return(result);
        }
        public static Toil DropTheCarriedInCell(TargetIndex StoreCellInd, ThingPlaceMode placeMode, TargetIndex CarrierInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn         actor   = toil.actor;
                Job          curJob  = actor.jobs.curJob;
                Vehicle_Cart carrier = actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart;
                if (carrier.storage.Count <= 0)
                {
                    return;
                }
                toil.actor.jobs.curJob.SetTarget(TargetIndex.A, carrier.storage.First());
                Thing   dropThing = toil.actor.jobs.curJob.targetA.Thing;
                IntVec3 destLoc   = actor.jobs.curJob.GetTarget(StoreCellInd).Cell;
                Thing   dummy;

                SlotGroup slotGroup = Find.SlotGroupManager.SlotGroupAt(destLoc);
                //    if (destLoc.GetStorable() == null)
                if (slotGroup != null && slotGroup.Settings.AllowedToAccept(dropThing))
                {
                    Find.DesignationManager.RemoveAllDesignationsOn(dropThing);
                    carrier.storage.TryDrop(dropThing, destLoc, placeMode, out dummy);
                }

                //Check cell queue is adjacent
                List <TargetInfo> cells = curJob.GetTargetQueue(StoreCellInd);
                for (int i = 0; i < cells.Count && i < carrier.storage.Count; i++)
                {
                    if (destLoc.AdjacentTo8Way(cells[i].Cell) && cells[i].Cell.GetStorable() == null)
                    {
                        Find.DesignationManager.RemoveAllDesignationsOn(carrier.storage[i]);
                        carrier.storage.TryDrop(carrier.storage[i], cells[i].Cell, ThingPlaceMode.Direct, out dummy);
                        cells.RemoveAt(i);
                        i--;
                    }
                }
                //Check item queue is valid storage for adjacent cell
                foreach (IntVec3 adjCell in GenAdj.CellsAdjacent8Way(destLoc))
                {
                    if (carrier.storage.Count > 0 && adjCell.GetStorable() == null && adjCell.IsValidStorageFor(carrier.storage.First()))
                    {
                        Find.DesignationManager.RemoveAllDesignationsOn(carrier.storage.First());
                        carrier.storage.TryDrop(carrier.storage.First(), adjCell, ThingPlaceMode.Direct, out dummy);
                    }
                }
            };
            toil.FailOnDestroyedOrNull(CarrierInd);
            return(toil);
        }
        public static Toil MountOtherOn(TargetIndex CartInd, Pawn patient)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn         actor = toil.GetActor();
                Vehicle_Cart cart  = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart;
                if (cart == null)
                {
                    Log.Error(actor.LabelCap + " Report: Wheel chair is invalid.");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                }

                cart.mountableComp.MountOn(patient);
            };
            return(toil);
        }
Beispiel #7
0
        protected override void FillTab()
        {
            ThingFilter allowances;

            PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.StorageTab, KnowledgeAmount.FrameDisplayed);
            LessonAutoActivator.TeachOpportunity(ConceptDefOf.StorageTab, OpportunityType.Critical);
            LessonAutoActivator.TeachOpportunity(ConceptDefOf.Stockpiles, OpportunityType.Critical);
            Vehicle_Cart cart = Find.Selector.SelectedObjects.First() as Vehicle_Cart;

            allowances = ((Vehicle_Cart)Find.Selector.SelectedObjects.First()).allowances;



            Rect position = new Rect(0.0f, 0.0f, WinSize.x, WinSize.y).ContractedBy(10f);

            GUI.BeginGroup(position);

            ThingFilterUI.DoThingFilterConfigWindow(new Rect(0.0f, 35f, position.width, position.height - 35f), ref scrollPosition, allowances);
            GUI.EndGroup();
        }
        public static Toil ReleaseAnimalCart(TargetIndex CartInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn         actor = toil.GetActor();
                Vehicle_Cart cart  = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart;
                if (cart == null)
                {
                    Log.Error(actor.LabelCap + " Report: Cart is invalid.");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                }
                if (cart.mountableComp.IsMounted && cart.mountableComp.Driver.CurJob.def == HaulJobDefOf.StandBy)
                {
                    cart.mountableComp.Driver.jobs.curDriver.EndJobWith(JobCondition.Succeeded);
                }
            };
            return(toil);
        }
        public static Toil CollectInCarrier(TargetIndex CarrierInd, TargetIndex HaulableInd)
        {
            Toil toil = new Toil();

            toil.initAction = () =>
            {
                Pawn         actor     = toil.actor;
                Job          curJob    = actor.jobs.curJob;
                Thing        haulThing = curJob.GetTarget(HaulableInd).Thing;
                Vehicle_Cart carrier   = curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart;
                //Check haulThing is human_corpse. If other race has apparel, It need to change

                Find.DesignationManager.RemoveAllDesignationsOn(haulThing);
                //if (haulThing.ThingID.IndexOf("Human_Corpse") <= -1 ? false : true)
                //{
                //    Corpse corpse = (Corpse)haulThing;
                //    List<Apparel> wornApparel = corpse.innerPawn.apparel.WornApparel;
                //
                //    //Drop wornApparel. wornApparel cannot Add to container directly because it will be duplicated.
                //    corpse.innerPawn.apparel.DropAll(corpse.innerPawn.Position, false);
                //
                //    //Transfer in container
                //    foreach (Thing apparel in wornApparel)
                //    {
                //        if (carrier.storage.TryAdd(apparel))
                //        {
                //            apparel.holder = carrier.GetContainer();
                //            apparel.holder.owner = carrier;
                //        }
                //    }
                //}
                //Collecting TargetIndex ind
                if (carrier.storage.TryAdd(haulThing))
                {
                    haulThing.holder       = carrier.GetContainer();
                    haulThing.holder.owner = carrier;
                }

                List <TargetInfo> thingList = curJob.GetTargetQueue(HaulableInd);
                for (int i = 0; i < thingList.Count; i++)
                {
                    if (actor.Position.AdjacentTo8Way(thingList[i].Thing.Position))
                    {
                        if (carrier.storage.TryAdd(thingList[i].Thing))
                        {
                            thingList[i].Thing.holder       = carrier.GetContainer();
                            thingList[i].Thing.holder.owner = carrier;
                        }
                        thingList.RemoveAt(i);
                        i--;
                    }
                }
            };
            toil.FailOn(() =>
            {
                Pawn actor           = toil.actor;
                Job curJob           = actor.jobs.curJob;
                Thing haulThing      = curJob.GetTarget(HaulableInd).Thing;
                Vehicle_Cart carrier = curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart;

                if (!carrier.storage.CanAcceptAnyOf(haulThing) &&
                    actor.Position.IsAdjacentTo8WayOrInside(haulThing.Position, haulThing.Rotation, haulThing.RotatedSize))
                {
                    return(true);
                }
                return(false);
            });
            toil.FailOnDestroyedOrNull(CarrierInd);
            return(toil);
        }
        public void MountOn(Pawn pawn)
        {
            if (Driver != null)
            {
                return;
            }

            Building_Reloadable turret = (parent as Building_Reloadable);

            if (turret != null)
            {
                turret.dontReload = true;
            }

            // Check to make pawns not mount two vehicles at once
            if (ToolsForHaulUtility.IsDriver(pawn))
            {
                if (ToolsForHaulUtility.GetCartByDriver(pawn) != null)
                {
                    ToolsForHaulUtility.GetCartByDriver(pawn).mountableComp.Dismount();
                }

                if (ToolsForHaulUtility.GetTurretByDriver(pawn) != null)
                {
                    ToolsForHaulUtility.GetTurretByDriver(pawn).mountableComp.Dismount();
                }
            }

            Driver = pawn;

            MapComponent_ToolsForHaul.currentVehicle.Add(pawn, parent);

            if (Driver.RaceProps.Humanlike)
            {
                Driver.RaceProps.makesFootprints = false;
            }

            if (pawn.RaceProps.Humanlike)
            {
                driverComp = new CompDriver {
                    vehicle = parent as Building
                };
                Driver?.AllComps?.Add(driverComp);
                driverComp.parent = Driver;
            }

            Vehicle_Cart vehicleCart = parent as Vehicle_Cart;

            if (vehicleCart != null)
            {
                // Set faction of vehicle to whoever mounts it
                if (vehicleCart.Faction != Driver.Faction && vehicleCart.ClaimableBy(Driver.Faction))
                {
                    parent.SetFaction(Driver.Faction);
                }


                if (vehicleCart.IsCurrentlyMotorized())
                {
                    SoundInfo info = SoundInfo.InWorld(parent);
                    sustainerAmbient = vehicleCart.vehicleComp.compProps.soundAmbient.TrySpawnSustainer(info);
                }


                return;
            }

            Vehicle_Turret vehicleTurret = parent as Vehicle_Turret;

            if (vehicleTurret != null)
            {
                // Set faction of vehicle to whoever mounts it
                if (vehicleTurret.Faction != Driver.Faction && vehicleTurret.ClaimableBy(Driver.Faction))
                {
                    parent.SetFaction(Driver.Faction);
                }

                if (vehicleTurret.IsCurrentlyMotorized())
                {
                    SoundInfo info = SoundInfo.InWorld(parent);
                    sustainerAmbient = vehicleTurret.vehicleComp.compProps.soundAmbient.TrySpawnSustainer(info);
                }

                return;
            }
        }
Beispiel #11
0
        public static Job HaulWithTools(Pawn pawn, Vehicle_Cart cart = null, Thing haulThing = null)
        {
            Trace.stopWatchStart();

            //Job Setting
            bool                UseBackpack = false;
            JobDef              jobDef      = null;
            TargetInfo          targetC;
            int                 maxItem;
            int                 thresholdItem;
            int                 reservedMaxItem;
            IEnumerable <Thing> remainingItems;
            bool                ShouldDrop;
            Thing               lastItem = TryGetBackpackLastItem(pawn);
            Apparel_Backpack    backpack = TryGetBackpack(pawn);

            if (cart == null)
            {
                jobDef  = HaulJobDefOf.HaulWithBackpack;
                targetC = backpack;
                maxItem = backpack.MaxItem;
                // thresholdItem = (int)Math.Ceiling(maxItem * 0.5);
                thresholdItem   = 2;
                reservedMaxItem = backpack.slotsComp.slots.Count;
                remainingItems  = backpack.slotsComp.slots;
                ShouldDrop      = false;
                UseBackpack     = true;
                if (lastItem != null)
                {
                    for (int i = 0; i < backpack.slotsComp.slots.Count; i++)
                    {
                        if (backpack.slotsComp.slots[i] == lastItem && reservedMaxItem - (i + 1) <= 0)
                        {
                            ShouldDrop = false;
                            break;
                        }
                    }
                }
            }
            else
            {
                if (cart.mountableComp.IsMounted)
                {
                    jobDef = cart.mountableComp.Driver.RaceProps.Animal
                        ? HaulJobDefOf.HaulWithAnimalCart
                        : HaulJobDefOf.HaulWithCart;
                }
                else
                {
                    jobDef = HaulJobDefOf.HaulWithCart;
                }

                targetC = cart;

                maxItem         = cart.MaxItem;
                thresholdItem   = (int)Math.Ceiling(maxItem * 0.25);
                reservedMaxItem = cart.storage.Count;
                remainingItems  = cart.storage;


                ShouldDrop = reservedMaxItem > 0 ? true : false;
            }
            Job job = new Job(jobDef)
            {
                targetQueueA = new List <TargetInfo>(),
                targetQueueB = new List <TargetInfo>(),
                targetC      = targetC
            };

            if (UseBackpack)
            {
                job.numToBringList = new List <int>();
            }

            Trace.AppendLine(pawn.LabelCap + " In HaulWithTools: " + jobDef.defName + "\n"
                             + "MaxItem: " + maxItem + " reservedMaxItem: " + reservedMaxItem);

            //Drop remaining item
            if (ShouldDrop)
            {
                Trace.AppendLine("Start Drop remaining item");
                bool startDrop = false;
                for (int i = 0; i < remainingItems.Count(); i++)
                {
                    if (UseBackpack && startDrop == false)
                    {
                        if (remainingItems.ElementAt(i) == lastItem)
                        {
                            startDrop = true;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    IntVec3 storageCell = FindStorageCell(pawn, remainingItems.ElementAt(i), job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }
                    job.targetQueueB.Add(storageCell);
                }
                if (!job.targetQueueB.NullOrEmpty())
                {
                    Trace.AppendLine("Dropping Job is issued");
                    Trace.LogMessage();
                    return(job);
                }
                if (!UseBackpack && job.def == HaulJobDefOf.HaulWithCart && !cart.IsInValidStorage())
                {
                    Trace.AppendLine("In DismountInBase");
                    return(DismountInBase(pawn, cart));
                }
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
                Trace.AppendLine("End Drop remaining item");
                Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
                Trace.LogMessage();
                return(null);
            }

            //Collect item
            Trace.AppendLine("Start Collect item");
            IntVec3 searchPos;

            if (haulThing != null)
            {
                searchPos = haulThing.Position;
            }
            else if (!UseBackpack)
            {
                searchPos = cart.Position;
            }
            else
            {
                searchPos = pawn.Position;
            }
            foreach (SlotGroup slotGroup in Find.SlotGroupManager.AllGroupsListInPriorityOrder)
            {
                Trace.AppendLine("Start searching slotGroup");
                if (slotGroup.CellsList.Count - slotGroup.HeldThings.Count() < maxItem)
                {
                    continue;
                }

                //Counting valid items
                Trace.AppendLine("Start Counting valid items");
                int thingsCount =
                    ListerHaulables.ThingsPotentiallyNeedingHauling()
                    .Count(item => slotGroup.Settings.AllowedToAccept(item));

                //Finding valid items
                Trace.AppendLine("Start Finding valid items");
                if (thingsCount > thresholdItem)
                {
                    Thing thing;
                    if (haulThing == null)
                    {
                        //ClosestThing_Global_Reachable Configuration
                        Predicate <Thing> predicate = item
                                                      => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                      !item.IsInAnyStorage() &&
                                                      (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                           category =>
                                                           backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                               subCategory =>
                                                               subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                           &&
                                                           !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                               subCategory =>
                                                               subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                      !item.IsForbidden(pawn.Faction) &&
                                                      slotGroup.Settings.AllowedToAccept(item) &&
                                                      pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger());
                        //&& !(item is UnfinishedThing && ((UnfinishedThing)item).BoundBill != null)
                        //&& (item.def.IsNutritionSource && !SocialProperness.IsSociallyProper(item, pawn, false, false));
                        thing = GenClosest.ClosestThing_Global_Reachable(searchPos,
                                                                         ListerHaulables.ThingsPotentiallyNeedingHauling(),
                                                                         PathEndMode.ClosestTouch,
                                                                         TraverseParms.For(pawn, pawn.NormalMaxDanger()),
                                                                         9999,
                                                                         predicate);
                        if (thing == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        thing = haulThing;
                    }

                    //Find StorageCell
                    IntVec3 storageCell = FindStorageCell(pawn, thing, job.targetQueueB);
                    if (storageCell == IntVec3.Invalid)
                    {
                        break;
                    }

                    //Add Queue & Reserve
                    job.targetQueueA.Add(thing);
                    //for backpacks
                    if (UseBackpack)
                    {
                        job.numToBringList.Add(thing.def.stackLimit);
                    }

                    job.targetQueueB.Add(storageCell);


                    IntVec3 center = thing.Position;

                    //Enqueue SAME items in valid distance
                    Trace.AppendLine("Start Enqueuing SAME items in valid distance");
                    foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                   => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                   !item.IsInAnyStorage() &&
                                                                                                   (UseBackpack
                               ? item.def.thingCategories.Exists(
                                                                                                        category =>
                                                                                                        backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                            subCategory =>
                                                                                                            subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                        &&
                                                                                                        !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                            subCategory =>
                                                                                                            subCategory.ThisAndChildCategoryDefs.Contains(category)))
                               : cart.allowances.Allows(item)) &&
                                                                                                   !item.IsForbidden(pawn.Faction) &&
                                                                                                   slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                   pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                   center.DistanceToSquared(item.Position) <= ValidDistance))
                    {
                        job.targetQueueA.Add(item);
                        if (UseBackpack)
                        {
                            job.numToBringList.Add(item.def.stackLimit);
                        }


                        reservedMaxItem++;

                        if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                        {
                            break;
                        }
                    }

                    //Enqueue other items in valid distance
                    if (reservedMaxItem + job.targetQueueA.Count < maxItem)
                    {
                        Trace.AppendLine("Start Enqueuing items in valid distance");

                        foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                       => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                       !item.IsInAnyStorage() &&
                                                                                                       (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                                                                            category =>
                                                                                                            backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                            &&
                                                                                                            !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                                                                       !item.IsForbidden(pawn.Faction) &&
                                                                                                       slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                       pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                       center.DistanceToSquared(item.Position) <= ValidDistance))
                        {
                            job.targetQueueA.Add(item);
                            if (UseBackpack)
                            {
                                job.numToBringList.Add(item.def.stackLimit);
                            }
                            reservedMaxItem++;

                            if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                            {
                                break;
                            }
                        }
                    }

                    //Also enqueue items in whiche are not in their best storage cell
                    if (reservedMaxItem + job.targetQueueA.Count < maxItem)
                    {
                        Trace.AppendLine("Start Enqueuing items in valid distance & not in best storage cell");
                        foreach (Thing item in ListerHaulables.ThingsPotentiallyNeedingHauling().Where(item
                                                                                                       => !job.targetQueueA.Contains(item) && !item.IsBurning() &&
                                                                                                       !item.IsInValidBestStorage() &&
                                                                                                       (UseBackpack
                                   ? item.def.thingCategories.Exists(
                                                                                                            category =>
                                                                                                            backpack.slotsComp.Properties.allowedThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category))
                                                                                                            &&
                                                                                                            !backpack.slotsComp.Properties.forbiddenSubThingCategoryDefs.Exists(
                                                                                                                subCategory =>
                                                                                                                subCategory.ThisAndChildCategoryDefs.Contains(category)))
                                   : cart.allowances.Allows(item)) &&
                                                                                                       !item.IsForbidden(pawn.Faction) &&
                                                                                                       slotGroup.Settings.AllowedToAccept(item) &&
                                                                                                       pawn.CanReserveAndReach(item, PathEndMode.Touch, pawn.NormalMaxDanger()) &&
                                                                                                       center.DistanceToSquared(item.Position) <= ValidDistance))
                        {
                            job.targetQueueA.Add(item);
                            if (UseBackpack)
                            {
                                job.numToBringList.Add(item.def.stackLimit);
                            }
                            reservedMaxItem++;

                            if (reservedMaxItem + job.targetQueueA.Count >= maxItem)
                            {
                                break;
                            }
                        }
                    }

                    //Find storage cell
                    Trace.AppendLine("Start Finding storage cell");
                    if (reservedMaxItem + job.targetQueueA.Count > thresholdItem)
                    {
                        foreach (
                            IntVec3 cell in
                            slotGroup.CellsList.Where(
                                cell =>
                                pawn.CanReserveAndReach(cell, PathEndMode.ClosestTouch, Danger.Some) &&
                                cell.Standable() && cell.GetStorable() == null))
                        {
                            StoragePriority currentPriority = HaulAIUtility.StoragePriorityAtFor(thing.Position, thing);
                            IntVec3         storeCell       = cell;
                            if (
                                !StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, currentPriority, pawn.Faction,
                                                                            out storeCell))
                            {
                                if (cell.InAllowedArea(pawn))
                                {
                                    job.targetQueueB.Add(cell);
                                }
                                if (job.targetQueueB.Count >= job.targetQueueA.Count)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                if (storeCell.InAllowedArea(pawn))
                                {
                                    job.targetQueueB.Add(storeCell);
                                }
                                if (job.targetQueueB.Count >= job.targetQueueA.Count)
                                {
                                    break;
                                }
                            }
                        }
                        break;
                    }
                    job.targetQueueA.Clear();
                }
            }
            Trace.AppendLine("Elapsed Time");
            Trace.stopWatchStop();

            //Check job is valid
            if (!job.targetQueueA.NullOrEmpty() && reservedMaxItem + job.targetQueueA.Count > thresholdItem &&
                !job.targetQueueB.NullOrEmpty())
            {
                Trace.AppendLine("Hauling Job is issued");
                Trace.LogMessage();
                return(job);
            }
            if (cart != null && job.def == HaulJobDefOf.HaulWithCart && !cart.IsInValidStorage())
            {
                Trace.AppendLine("In DismountInBase: ");
                return(DismountInBase(pawn, cart));
            }

            if (job.targetQueueA.NullOrEmpty())
            {
                JobFailReason.Is("NoHaulable".Translate());
            }
            else if (reservedMaxItem + job.targetQueueA.Count <= thresholdItem)
            {
                JobFailReason.Is(TooLittleHaulable);
            }
            else if (job.targetQueueB.NullOrEmpty())
            {
                JobFailReason.Is(NoEmptyPlaceLowerTrans);
            }
            Trace.AppendLine("No Job. Reason: " + JobFailReason.Reason);
            Trace.LogMessage();
            return(null);
        }
Beispiel #12
0
        public override string GetExplanation(StatRequest req, ToStringNumberSense numberSense)
        {
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.Append(base.GetExplanation(req, numberSense));
            if (req.HasThing)
            {
                Pawn thisPawn = req.Thing as Pawn;

                if (thisPawn != null)
                {
                    if (thisPawn.RaceProps.intelligence >= Intelligence.ToolUser)
                    {
                        if (MapComponent_ToolsForHaul.currentVehicle.ContainsKey(thisPawn))
                        {
                            Vehicle_Cart vehicle_Cart = MapComponent_ToolsForHaul.currentVehicle[thisPawn] as Vehicle_Cart;
                            if (vehicle_Cart != null)
                            {
                                if (vehicle_Cart.mountableComp.IsMounted && vehicle_Cart.mountableComp.Driver == thisPawn)
                                {
                                    stringBuilder.AppendLine();
                                    stringBuilder.AppendLine("VehicleSpeed".Translate() + ": x" + vehicle_Cart.VehicleSpeed);
                                    return(stringBuilder.ToString());
                                }
                            }

                            Vehicle_Turret vehicle_Turret = MapComponent_ToolsForHaul.currentVehicle[req.Thing as Pawn] as Vehicle_Turret;
                            if (vehicle_Turret != null)
                            {
                                if (vehicle_Turret.mountableComp.IsMounted && vehicle_Turret.mountableComp.Driver == thisPawn)
                                {
                                    stringBuilder.AppendLine();
                                    stringBuilder.AppendLine("VehicleSpeed".Translate() + ": x" + vehicle_Turret.VehicleSpeed);
                                    return(stringBuilder.ToString());
                                }
                            }
                        }

                        CompInventory compInventory = ThingCompUtility.TryGetComp <CompInventory>(req.Thing);
                        if (compInventory != null)
                        {
                            stringBuilder.AppendLine();
                            stringBuilder.AppendLine(Translator.Translate("CR_CarriedWeight") + ": x" + GenText.ToStringPercent(compInventory.moveSpeedFactor));
                            if (compInventory.encumberPenalty > 0f)
                            {
                                stringBuilder.AppendLine(Translator.Translate("CR_Encumbered") + ": -" + GenText.ToStringPercent(compInventory.encumberPenalty));
                                stringBuilder.AppendLine(Translator.Translate("CR_FinalModifier") + ": x" + GenText.ToStringPercent(this.GetStatFactor(thisPawn)));
                            }
                        }

                        CompSlotsBackpack compSlotsBackpack = ToolsForHaulUtility.TryGetBackpack(thisPawn).TryGetComp <CompSlotsBackpack>();
                        if (compSlotsBackpack != null)
                        {
                            stringBuilder.AppendLine();
                            stringBuilder.AppendLine("CR_CarriedWeightBackpack".Translate() + ": x" + compSlotsBackpack.moveSpeedFactor.ToStringPercent());
                            if (compSlotsBackpack.encumberPenalty > 0f)
                            {
                                stringBuilder.AppendLine("CR_EncumberedBackpack".Translate() + ": -" + compSlotsBackpack.encumberPenalty.ToStringPercent());
                                stringBuilder.AppendLine("CR_FinalModifierBackpack".Translate() + ": x" + GetStatFactor(thisPawn).ToStringPercent());
                            }
                        }
                    }
                }
            }

            return(stringBuilder.ToString());
        }
Beispiel #13
0
        public override Job JobOnThing(Pawn pawn, Thing t)
        {
            Vehicle_Cart cart = null;

            if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t))
            {
                return(null);
            }

            // Vehicle selection

            if (ToolsForHaulUtility.IsDriver(pawn))
            {
                cart = ToolsForHaulUtility.GetCartByDriver(pawn);

                if (cart == null)
                {
                    //  JobFailReason.Is("Can't haul with military vehicle");
                    return(ToolsForHaulUtility.DismountInBase(pawn, MapComponent_ToolsForHaul.currentVehicle[pawn]));
                }
            }


            if (cart == null)
            {
                cart = RightTools.GetRightVehicle(pawn, WorkTypeDefOf.Hauling, t) as Vehicle_Cart;

                if (cart == null)
                {
                    return(null);
                }
            }



            if (cart.IsBurning())
            {
                JobFailReason.Is(ToolsForHaulUtility.BurningLowerTrans);
                return(null);
            }

            if (!cart.allowances.Allows(t))
            {
                JobFailReason.Is("Cart does not allow that thing");
                return(null);
            }

            if (ListerHaulables.ThingsPotentiallyNeedingHauling().Count == 0 && cart.storage.Count == 0)
            {
                JobFailReason.Is("NoHaulable".Translate());
                return(null);
            }

            if (Find.SlotGroupManager.AllGroupsListInPriorityOrder.Count == 0)
            {
                JobFailReason.Is(ToolsForHaulUtility.NoEmptyPlaceLowerTrans);
                return(null);
            }

            if (ToolsForHaulUtility.AvailableAnimalCart(cart) || ToolsForHaulUtility.AvailableVehicle(pawn, cart))
            {
                return(ToolsForHaulUtility.HaulWithTools(pawn, cart, t));
            }
            JobFailReason.Is(ToolsForHaulUtility.NoAvailableCart);
            return(null);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Vehicle_Cart cart = CurJob.GetTarget(CartInd).Thing as Vehicle_Cart;

            ///
            //Set fail conditions
            ///

            this.FailOnDestroyedOrNull(CartInd);
            //Note we only fail on forbidden if the target doesn't start that way
            //This helps haul-aside jobs on forbidden items
            if (!TargetThingA.IsForbidden(pawn.Faction))
            {
                this.FailOnForbidden(CartInd);
            }

            this.FailOn(() => !pawn.RaceProps.IsFlesh || !pawn.RaceProps.Humanlike);

            ///
            //Define Toil
            ///

            Toil findStoreCellForCart = Toils_Cart.FindStoreCellForCart(CartInd);
            Toil checkCartEmpty       = Toils_Jump.JumpIf(findStoreCellForCart, () => cart.storage.Count <= 0);


            Toil checkStoreCellEmpty = Toils_Jump.JumpIf(findStoreCellForCart, () => CurJob.GetTargetQueue(StoreCellInd).NullOrEmpty());
            Toil checkHaulableEmpty  = Toils_Jump.JumpIf(checkStoreCellEmpty, () => CurJob.GetTargetQueue(HaulableInd).NullOrEmpty());

            ///
            //Toils Start
            ///

            //Reserve thing to be stored and storage cell
            yield return(Toils_Reserve.Reserve(CartInd));

            yield return(Toils_Reserve.ReserveQueue(HaulableInd));

            yield return(Toils_Reserve.ReserveQueue(StoreCellInd));

            //JumpIf already mounted
            yield return(Toils_Jump.JumpIf(checkHaulableEmpty, () =>
            {
                if (cart.mountableComp.Driver == pawn)
                {
                    return true;
                }
                return false;
            }));

            //Mount on Target
            yield return(Toils_Goto.GotoThing(CartInd, PathEndMode.ClosestTouch)
                         .FailOnDestroyedOrNull(CartInd));

            yield return(Toils_Cart.MountOn(CartInd));

            //JumpIf checkStoreCellEmpty
            yield return(checkHaulableEmpty);

            //Collect TargetQueue
            {
                Toil extractA = Toils_Collect.Extract(HaulableInd);
                yield return(extractA);

                Toil gotoThing = Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch)
                                 .FailOnDestroyedOrNull(HaulableInd);
                yield return(gotoThing);

                yield return(Toils_Collect.CollectInCarrier(CartInd, HaulableInd));

                yield return(Toils_Collect.CheckDuplicates(gotoThing, CartInd, HaulableInd));

                yield return(Toils_Jump.JumpIfHaveTargetInQueue(HaulableInd, extractA));
            }

            //JumpIf findStoreCellForCart
            yield return(checkStoreCellEmpty);

            //Drop TargetQueue
            {
                yield return(checkCartEmpty);

                Toil extractB = Toils_Collect.Extract(StoreCellInd);
                yield return(extractB);

                Toil gotoCell = Toils_Goto.GotoCell(StoreCellInd, PathEndMode.ClosestTouch);
                yield return(gotoCell);

                yield return(Toils_Collect.DropTheCarriedInCell(StoreCellInd, ThingPlaceMode.Direct, CartInd));

                yield return(Toils_Jump.JumpIfHaveTargetInQueue(StoreCellInd, checkCartEmpty));

                yield return(Toils_Collect.CheckNeedStorageCell(gotoCell, CartInd, StoreCellInd));
            }

            yield return(findStoreCellForCart);

            yield return(Toils_Goto.GotoCell(StoreCellInd, PathEndMode.OnCell));

            yield return(Toils_Cart.DismountAt(CartInd, StoreCellInd));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Vehicle_Cart cart   = CurJob.GetTarget(CartInd).Thing as Vehicle_Cart;
            Job          jobNew = new Job();

            ///
            //Set fail conditions
            ///

            this.FailOnDestroyedOrNull(CartInd);
            this.FailOn(() => !cart.mountableComp.IsMounted);
            //Note we only fail on forbidden if the target doesn't start that way
            //This helps haul-aside jobs on forbidden items
            if (!TargetThingA.IsForbidden(pawn.Faction))
            {
                this.FailOnForbidden(CartInd);
            }

            ///
            //Define Toil
            ///

            Toil releaseAnimalCart   = Toils_Cart.ReleaseAnimalCart(CartInd);
            Toil checkStoreCellEmpty = Toils_Jump.JumpIf(releaseAnimalCart, () => CurJob.GetTargetQueue(StoreCellInd).NullOrEmpty());
            Toil checkHaulableEmpty  = Toils_Jump.JumpIf(checkStoreCellEmpty, () => CurJob.GetTargetQueue(HaulableInd).NullOrEmpty());

            ///
            //Toils Start
            ///

            //Reserve thing to be stored and storage cell
            yield return(Toils_Reserve.Reserve(CartInd));

            yield return(Toils_Reserve.ReserveQueue(HaulableInd));

            yield return(Toils_Reserve.ReserveQueue(StoreCellInd));

            yield return(Toils_Goto.GotoThing(CartInd, PathEndMode.Touch)
                         .FailOn(() => cart.Destroyed || !cart.mountableComp.IsMounted));

            //JumpIf toilCheckStoreCellEmpty
            yield return(checkHaulableEmpty);

            //Collect TargetQueue
            {
                Toil extractA = Toils_Collect.Extract(HaulableInd);
                yield return(extractA);

                yield return(Toils_Cart.CallAnimalCart(CartInd, HaulableInd)
                             .FailOnDestroyedOrNull(HaulableInd));

                yield return(Toils_Goto.GotoThing(HaulableInd, PathEndMode.ClosestTouch)
                             .FailOnDestroyedOrNull(HaulableInd));

                yield return(Toils_Cart.CallAnimalCart(CartInd, HaulableInd, pawn)
                             .FailOnDestroyedOrNull(HaulableInd));

                yield return(Toils_Cart.WaitForAnimalCart(CartInd, HaulableInd));

                yield return(Toils_Collect.CollectInCarrier(CartInd, HaulableInd));

                yield return(Toils_Collect.CheckDuplicates(extractA, CartInd, HaulableInd));

                yield return(Toils_Jump.JumpIfHaveTargetInQueue(HaulableInd, extractA));
            }

            //JumpIf releaseAnimalCart
            yield return(checkStoreCellEmpty);

            //Drop TargetQueue
            {
                Toil extractB = Toils_Collect.Extract(StoreCellInd);
                yield return(extractB);

                yield return(Toils_Cart.CallAnimalCart(CartInd, StoreCellInd));

                yield return(Toils_Goto.GotoCell(StoreCellInd, PathEndMode.ClosestTouch)
                             .FailOnBurningImmobile(StoreCellInd));

                yield return(Toils_Cart.CallAnimalCart(CartInd, HaulableInd, pawn));

                yield return(Toils_Cart.WaitForAnimalCart(CartInd, HaulableInd));

                yield return(Toils_Collect.DropTheCarriedInCell(StoreCellInd, ThingPlaceMode.Direct, CartInd));

                yield return(Toils_Jump.JumpIfHaveTargetInQueue(StoreCellInd, extractB));
            }

            yield return(releaseAnimalCart);
        }
        public static Toil WaitForAnimalCart(TargetIndex CartInd, TargetIndex HaulableInd)
        {
            //       Log.Message("WaitForAnimalCart");
            Toil toil     = new Toil();
            int  tickTime = 0;

            toil.initAction = () =>
            {
                Pawn         actor = toil.GetActor();
                Vehicle_Cart cart  = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart;
                if (cart == null)
                {
                    Log.Error(actor.LabelCap + " Report: Cart is invalid.");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                }
                tickTime = 0;
                if (cart.mountableComp.IsMounted)
                {
                    //Worker has arrived and Animal cart is coming
                    if (cart.mountableComp.Driver.CurJob.def == HaulJobDefOf.StandBy &&
                        (!actor.Position.InHorDistOf(cart.Position, 1f) ||
                         !actor.Position.InHorDistOf(cart.mountableComp.Driver.Position, 1f)))
                    {
                        tickTime = 0;
                    }
                    //Worker has arrived and Animal cart has arrived
                    else if (cart.mountableComp.Driver.CurJob.def == HaulJobDefOf.StandBy && (actor.Position.InHorDistOf(cart.mountableComp.Driver.Position, 1f)))
                    {
                        toil.actor.jobs.curDriver.ReadyForNextToil();
                    }
                    //Worker has arrived but Animal cart is missing
                    else
                    {
                        Job job = new Job(HaulJobDefOf.StandBy, actor, defaultWaitWorker);
                        cart.mountableComp.Driver.jobs.StartJob(job, JobCondition.InterruptForced);
                    }
                }
                else
                {
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                }
            };
            toil.tickAction = () =>
            {
                Pawn         actor = toil.GetActor();
                Vehicle_Cart cart  = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart;
                if (cart == null)
                {
                    Log.Error(actor.LabelCap + " Report: Cart is invalid.");
                    toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored);
                }
                if (Find.TickManager.TicksGame % tickCheckInterval == 0)
                {
                    if (cart.mountableComp.IsMounted)
                    {
                        //Animal cart has arrived
                        if (cart.mountableComp.Driver.CurJob.def == HaulJobDefOf.StandBy &&
                            (actor.Position.AdjacentTo8WayOrInside(cart.mountableComp.Driver) || actor.Position.AdjacentTo8WayOrInside(cart)))
                        {
                            toil.actor.jobs.curDriver.ReadyForNextToil();
                        }
                        //Animal cart would never come. Imcompletable.
                        else if (cart.mountableComp.Driver.CurJob.def != HaulJobDefOf.StandBy ||
                                 tickTime >= defaultWaitWorker)
                        {
                            toil.actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                        }
                    }
                    else
                    {
                        toil.actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                    }
                }
            };
            toil.defaultCompleteMode = ToilCompleteMode.Never;
            return(toil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            ///
            //Set fail conditions
            ///

            this.FailOnDestroyedOrNull(MountableInd);
            this.FailOnDowned(DriverInd);
            //Note we only fail on forbidden if the target doesn't start that way
            //This helps haul-aside jobs on forbidden items
            if (!TargetThingA.IsForbidden(pawn.Faction))
            {
                this.FailOnForbidden(MountableInd);
            }



            ///
            //Define Toil
            ///

            Toil toilMakeStandby = new Toil();

            toilMakeStandby.initAction = () =>
            {
                Pawn driver = CurJob.GetTarget(DriverInd).Thing as Pawn;
                driver.jobs.StartJob(new Job(HaulJobDefOf.StandBy, driver.Position, 2400 + (int)((pawn.Position - driver.Position).LengthHorizontal * 120)), JobCondition.InterruptForced);
            };

            Toil toilGoto = null;

            toilGoto = Toils_Goto.GotoThing(MountableInd, PathEndMode.ClosestTouch)
                       .FailOn(() =>
            {
                //Note we don't fail on losing hauling designation
                //Because that's a special case anyway

                //While hauling to cell storage, ensure storage dest is still valid
                Pawn actor = toilGoto.actor;
                Job curJob = actor.jobs.curJob;
                if (curJob.haulMode == HaulMode.ToCellStorage)
                {
                    Thing haulThing = curJob.GetTarget(MountableInd).Thing;

                    IntVec3 destLoc = actor.jobs.curJob.GetTarget(TargetIndex.B).Cell;
                    if (!destLoc.IsValidStorageFor(haulThing))
                    {
                        return(true);
                    }
                }

                return(false);
            });

            Toil toilMountOn = new Toil();

            toilMountOn.initAction = () =>
            {
                Pawn driver = TargetB.Thing as Pawn;
                if (driver != null && TargetThingA.TryGetComp <CompMountable>() != null)
                {
                    TargetThingA.TryGetComp <CompMountable>().MountOn(driver);
                }
                else
                {
                    Log.Error(GetActor().LabelCap + ": Try make mount without target B Driver");
                    EndJobWith(JobCondition.Errored);
                }
            };

            Toil toilEnd = new Toil();

            toilEnd.initAction = () =>
            {
                Vehicle_Cart cart = CurJob.GetTarget(MountableInd).Thing as Vehicle_Cart;

                //Vehicle_Saddle saddle = CurJob.GetTarget(MountableInd).Thing as Vehicle_Saddle;
                if (cart == null)// && saddle == null)
                {
                    Log.Error(GetActor().LabelCap + ": MakeMount get TargetA not cart or saddle.");
                    EndJobWith(JobCondition.Errored);
                    return;
                }
                if (cart != null && cart.mountableComp.IsMounted && cart.mountableComp.Driver.CurJob.def == HaulJobDefOf.StandBy)
                {
                    cart.mountableComp.Driver.jobs.curDriver.EndJobWith(JobCondition.Succeeded);
                }
                EndJobWith(JobCondition.Succeeded);
            };

            ///
            //Toils Start
            ///

            //Reserve thing to be stored and storage cell
            yield return(Toils_Reserve.Reserve(MountableInd));

            yield return(Toils_Reserve.Reserve(DriverInd));

            yield return(toilMakeStandby);

            yield return(toilGoto);

            yield return(Toils_Haul.StartCarryThing(MountableInd));

            yield return(Toils_Haul.CarryHauledThingToCell(DriverInd));

            yield return(toilMountOn);

            yield return(toilEnd);
        }
        protected override void FillTab()
        {
            float fieldHeight = 30.0f;


            PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.PrisonerTab, KnowledgeAmount.FrameDisplayed);
            Text.Font = GameFont.Small;
            Rect innerRect1 = new Rect(0.0f, 0.0f, size.x, size.y).ContractedBy(10f);

            GUI.BeginGroup(innerRect1);
            Rect  mountedRect  = new Rect(0.0f, 30.0f, innerRect1.width, fieldHeight);
            float mountedRectY = mountedRect.y;

            Widgets.ListSeparator(ref mountedRectY, innerRect1.width, txtDriver.Translate());
            mountedRect.y += fieldHeight;
            Rect thingIconRect   = new Rect(mountedRect.x, mountedRect.y, 30f, fieldHeight);
            Rect thingLabelRect  = new Rect(mountedRect.x + 35f, mountedRect.y + 5.0f, innerRect1.width - 35f, fieldHeight);
            Rect thingButtonRect = new Rect(mountedRect.x, mountedRect.y, innerRect1.width, fieldHeight);

            CompMountable compMountable = SelThing.TryGetComp <CompMountable>();

            if (compMountable.IsMounted)
            {
                Pawn driver = compMountable.Driver;
                Widgets.ThingIcon(thingIconRect, driver);
                Widgets.Label(thingLabelRect, driver.Label);
                if (Mouse.IsOver(thingLabelRect))
                {
                    GUI.DrawTexture(thingLabelRect, TexUI.HighlightTex);
                }
                if (Event.current.button == 1 && Widgets.ButtonInvisible(thingButtonRect))
                {
                    List <FloatMenuOption> options  = new List <FloatMenuOption>();
                    FloatMenuOption        dismount = new FloatMenuOption("Dismount".Translate(driver.LabelShort), () =>
                    {
                        compMountable.Dismount();
                    });
                    options.Add(dismount);

                    Find.WindowStack.Add(new FloatMenu(options));
                }
                thingIconRect.y  += fieldHeight;
                thingLabelRect.y += fieldHeight;
            }
            Rect  storageRect  = new Rect(0.0f, thingIconRect.y, innerRect1.width, fieldHeight);
            float storageRectY = storageRect.y;

            Widgets.ListSeparator(ref storageRectY, innerRect1.width, txtStorage.Translate());
            storageRect.y    += fieldHeight;
            thingIconRect.y   = storageRect.y;
            thingLabelRect.y  = storageRect.y;
            thingButtonRect.y = storageRect.y;

            #region Cart
            Vehicle_Cart cart = SelThing as Vehicle_Cart;
            if (cart != null)
            {
                foreach (Thing thing in cart.storage)
                {
                    if (thing.ThingID.IndexOf("Human_Corpse") > -1)
                    {
                        Widgets.DrawTextureFitted(thingIconRect, ContentFinder <Texture2D> .Get("Things/Pawn/IconHuman_Corpse"), 1.0f);
                    }
                    else if (thing.ThingID.IndexOf("Corpse") > -1)
                    {
                        Widgets.DrawTextureFitted(thingIconRect, ContentFinder <Texture2D> .Get("Things/Pawn/IconAnimal_Corpse"), 1.0f);
                    }
                    else
                    {
                        Widgets.ThingIcon(thingIconRect, thing);
                    }
                    Widgets.Label(thingLabelRect, thing.LabelCap);
                    if (Event.current.button == 1 && Widgets.ButtonInvisible(thingButtonRect))
                    {
                        List <FloatMenuOption> options = new List <FloatMenuOption>();
                        options.Add(new FloatMenuOption("ThingInfo".Translate(), () =>
                        {
                            Find.WindowStack.Add(new Dialog_InfoCard(thing));
                        }));
                        options.Add(new FloatMenuOption("DropThing".Translate(), () =>
                        {
                            Thing dummy;
                            cart.storage.TryDrop(thing, SelThing.Position, ThingPlaceMode.Near, out dummy);
                        }));

                        Find.WindowStack.Add(new FloatMenu(options, thing.LabelCap));
                    }
                    if (Mouse.IsOver(thingLabelRect))
                    {
                        GUI.DrawTexture(thingLabelRect, TexUI.HighlightTex);
                    }

                    TooltipHandler.TipRegion(thingLabelRect, thing.def.LabelStyled());
                    thingIconRect.y  += fieldHeight;
                    thingLabelRect.y += fieldHeight;
                }
                if (Widgets.ButtonText(new Rect(180f, 400f, 100f, 30f), "Drop All"))
                {
                    cart.storage.TryDropAll(SelThing.Position, ThingPlaceMode.Near);
                }
            }
            #endregion



            GUI.EndGroup();
        }