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); }
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); }
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; } }
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); }
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()); }
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(); }