public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { if (t is ThingWithComps thing) { if (!pawn.Dead && !pawn.Downed && !pawn.IsBurning() && !thing.Destroyed && !thing.IsBurning() && pawn.CanReserveAndReach(thing, PathEndMode.InteractionCell, Danger.Deadly)) { CompUpgrade comp = null; foreach (var c in thing.AllComps.OfType <CompUpgrade>()) { if (c.beginUpgrade) { comp = c; break; } } if (comp == null) { return(null); } ThingDefCount needThingCount = comp.TryGetOneMissingMaterial(); if (!comp.PawnMeetsSkillRequirement(pawn)) { JobFailReason.Is("ConstructionSkillTooLow"); return(null); } if (needThingCount.Count > 0) { Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(needThingCount.ThingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly), 9999f, (Thing r) => { return(r.def == needThingCount.ThingDef && !r.IsForbidden(pawn) && pawn.CanReserve(r)); }); if (foundRes == null) { JobFailReason.Is("Upgrade_missingMaterial"); return(null); } } return(new Job(PESDefOf.PES_Job_InstallUpgrade, t)); } } return(null); }
protected override IEnumerable <Toil> MakeNewToils() { CompUpgrade comp = FindOneComp(); if (comp == null) { EndJobWith(JobCondition.Incompletable); yield break; } AddFailCondition(() => comp == null || !comp.parent.Spawned || !comp.beginUpgrade); this.FailOnDestroyedNullOrForbidden(TargetIndex.A); Toil gotoBuilding = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); Toil findMaterial = new Toil { initAction = delegate() { ThingDefCount thingDefCount = comp.TryGetOneMissingMaterial(); job.count = thingDefCount.Count; if (thingDefCount.Count > 0) { Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(thingDefCount.ThingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly), 9999f, (Thing r) => { return(r.def == thingDefCount.ThingDef && !r.IsForbidden(pawn) && pawn.CanReserve(r)); }); if (foundRes == null) { EndJobWith(JobCondition.Incompletable); } else { job.SetTarget(TargetIndex.B, foundRes); } } else { JumpToToil(gotoBuilding); } } }; //Haul things to building yield return(findMaterial); yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, job.count)); yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch).FailOnDestroyedNullOrForbidden(TargetIndex.B)); yield return(Toils_Haul.StartCarryThing(TargetIndex.B)); yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.InteractionCell)); yield return(new Toil { initAction = delegate() { var tracker = pawn.carryTracker; if (tracker.CarriedThing != null) { tracker.innerContainer.TryTransferToContainer(tracker.CarriedThing, comp.GetDirectlyHeldThings(), tracker.CarriedThing.stackCount, true); pawn.Map.reservationManager.ReleaseAllForTarget(TargetThingB); job.SetTarget(TargetIndex.B, null); JumpToToil(findMaterial); } } }); //Do upgrade yield return(gotoBuilding); yield return(new Toil { tickAction = delegate() { Pawn actor = GetActor(); comp.Work(actor, actor.GetStatValue(StatDefOf.ConstructionSpeed)); if (comp.complete) { EndJobWith(JobCondition.Succeeded); } }, defaultCompleteMode = ToilCompleteMode.Never }.WithEffect(EffecterDefOf.ConstructMetal, TargetIndex.A).WithProgressBar(TargetIndex.A, () => comp.FinishPercentage)); yield break; }