protected override IEnumerable<Toil> MakeNewToils() { //Set what will cause the job to fail: this.FailOnDestroyedOrForbidden(CorpseIndex); this.FailOnBurningImmobile(CorpseIndex); this.FailOn(() => !(pawn is Droid)); //Reserve the corpse yield return Toils_Reserve.Reserve(CorpseIndex); //Go to the corpse yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch); Toil toil = new Toil(); toil.initAction = () => { //Check if the pawn is set to strip bodies, if yes then strip it, otherwise skip this step Droid droid = (Droid)pawn; CremationWorker worker = droid.work.specialist.GetWorker<CremationWorker>(); if (worker.StripBodies) { Corpse corpse = (Corpse)TargetThingA; if (corpse.AnythingToStrip()) corpse.Strip(); } }; toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.defaultDuration = 300; toil.WithEffect(() => DefDatabase<EffecterDef>.GetNamed("Cremate"), CorpseIndex); toil.WithSustainer(() => DefDatabase<SoundDef>.GetNamed("Recipe_Cremate")); toil.AddFinishAction(() => TargetA.Thing.Destroy()); toil.FailOnBurningImmobile(CorpseIndex); toil.FailOnDestroyedOrForbidden(CorpseIndex); toil.AddEndCondition(() => this.ticksLeftThisToil <= 0 ? JobCondition.Succeeded : JobCondition.Ongoing); yield return toil; }
protected override IEnumerable <Toil> MakeNewToils() { //Set what will cause the job to fail: this.FailOnDestroyedOrForbidden(CorpseIndex); this.FailOnBurningImmobile(CorpseIndex); this.FailOn(() => !(pawn is Droid)); //Reserve the corpse yield return(Toils_Reserve.Reserve(CorpseIndex)); //Go to the corpse yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch)); Toil toil = new Toil(); toil.initAction = () => { //Check if the pawn is set to strip bodies, if yes then strip it, otherwise skip this step Droid droid = (Droid)pawn; CremationWorker worker = droid.work.specialist.GetWorker <CremationWorker>(); if (worker.StripBodies) { Corpse corpse = (Corpse)TargetThingA; if (corpse.AnythingToStrip()) { corpse.Strip(); } } }; toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.defaultDuration = 300; toil.WithEffect(() => DefDatabase <EffecterDef> .GetNamed("Cremate"), CorpseIndex); toil.WithSustainer(() => DefDatabase <SoundDef> .GetNamed("Recipe_Cremate")); toil.AddFinishAction(() => TargetA.Thing.Destroy()); toil.FailOnBurningImmobile(CorpseIndex); toil.FailOnDestroyedOrForbidden(CorpseIndex); toil.AddEndCondition(() => this.ticksLeftThisToil <= 0 ? JobCondition.Succeeded : JobCondition.Ongoing); yield return(toil); }
public static void Postfix(Toil __result, TargetIndex cellInd) { Utils.Warn(PlaceHauledThingInCell, "Starting new haul job, toils created"); //TODO? Make a wrapper around old initAction that doesn't put // stuff down if failure happens? var placeStuff = __result.initAction; // NOTE: none of this initAtion happens if the game is being loaded while storing is going on: // This means, among other things, that pawns don't get progress bars on reload // I could make it happen if it ever gets to be important... __result.initAction = delegate { // __result.defaultCompleteMode = ToilCompleteMode.Instant; var actor = __result.actor; var curJob = actor.jobs.curJob; var cell = curJob.GetTarget(cellInd).Cell; Utils.Warn(PlaceHauledThingInCell, "initAction called for " + actor + "'s haul job " + curJob.def.driverClass + " to " + cell + " (toil " + actor.jobs.curDriver.CurToilIndex + ")"); // Log.Error("Place Hauled Thing in Cell: Toil preInit! Putting in "+cell.ToString()); // actor.jobs.debugLog = true; if (actor.carryTracker.CarriedThing == null) { // error as per original toil code Log.Error(actor + " tried to place hauled thing in cell but is not hauling anything?"); return; } var slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); CompDeepStorage cds; if (!(slotGroup?.parent is ThingWithComps) || (cds = ((ThingWithComps)slotGroup?.parent)?.GetComp <CompDeepStorage>()) == null) { Utils.Warn(PlaceHauledThingInCell, "not going into Deep Storage"); // Pick Up & Haul reuses Toils; I realized this meant I need to keep original placeStuff() around: // Also, is it possible another mod does something weird with placeStuff? // this is a cheap "just to be on the safe side" check: if (placeStuff != null) { placeStuff(); } return; } var timeStoringTakes = cds.TimeStoringTakes(actor.Map, cell, actor); timeStoringTakes = (int)(timeStoringTakes * Settings.storingGlobalScale); if (timeStoringTakes <= 1 || !Settings.storingTakesTime) //boo, hiss, but some ppl use it { // just like vanilla Utils.Warn(PlaceHauledThingInCell, "Instantaneous storing time"); if (placeStuff != null) { placeStuff(); } return; } // __result.defaultCompleteMode = ToilCompleteMode.Delay; if (actor.jobs.curDriver.ticksLeftThisToil < 1) // test is probably superfluous { actor.jobs.curDriver.ticksLeftThisToil = timeStoringTakes; } Utils.Mess(PlaceHauledThingInCell, " Storing time set to: " + actor.jobs.curDriver.ticksLeftThisToil); // It'd be nice to have a progress bar for deep storage __result.WithProgressBar(TargetIndex.B, () => 1f - (float)__result.actor.jobs.curDriver.ticksLeftThisToil / timeStoringTakes, true); /***** Add some end conditions: *****/ //TODO: .....is this even a good idea? if the pawn is moving a lot of things at once // (I'm looking at you Mehni's Pick Up and Haul), this could break the entire chain. // TODO: Replace this with a check MUCH earlier. And one right before actual placement // takes place. /* Thing t = actor.CurJob.GetTarget(TargetIndex.A).Thing; * if (t != null) * __result.FailOn(() => !slotGroup.parent.Accepts(t)); */ //TODO: Find a way to track the end condition? Remove it? // Or just make it complicated :p // __result.FailOn(delegate() {}); // TODO: any other end conditions? Fail conditions? // TODO: Any reservations? }; // changed initAction! __result.defaultCompleteMode = ToilCompleteMode.Delay; // The tickAction is only called if we are going into Deep Storage, // otherwise the toil is over after initAction and no ticks happen. // This will still get called even on load/save, because ticks count down. __result.tickAction = delegate { var pawn = __result.actor; //Utils.Mess(PlaceHauledThingInCell, // " "+pawn+"'s ticks left: " + __result.actor.jobs.curDriver.ticksLeftThisToil); if (pawn.jobs.curDriver.ticksLeftThisToil <= 1) // last tick is 1, not 0 { Utils.Warn(PlaceHauledThingInCell, " " + pawn + " hit " + pawn.jobs.curDriver.ticksLeftThisToil + " ticks; about to put down " + (pawn.carryTracker.CarriedThing != null ? "" + pawn.carryTracker.CarriedThing.stackCount + pawn.carryTracker.CarriedThing : "NULL ITEM")); if (placeStuff != null) { placeStuff(); } } /* * if (pawn.jobs.curDriver.ticksLeftThisToil%50==0) { * // TODO: fail conditions * ...etc... * pawn.jobs.curDriver.EndJobWith(JobCondition.Incompletable); * } */ }; // ToilCompleteMode.Delay is acceptable in vanilla case, as duration is 0: // __result.defaultDuration = 0; // changed by PreInitAction, if needed // This is okay: it checks the current TargetIndex.B __result.FailOnBurningImmobile(TargetIndex.B); // todo reservations (possibly?) // also todo, undo reservations (possibly?) (as another final action?) // TODO: FailOn&c, EndOn&c // Other fails..... // No longer allowed in that area? <--- Very definitely TODO // Um? } // end Postfix
public static void Postfix(Toil __result, TargetIndex cellInd) { // make the "initAction" a final action: //TODO:::: Make a wrapper around old initAction that doesn't put // stuff down if failure happens? // __result.preInitActions.Add(delegate () { __result.actor.jobs.debugLog = true; }); // __result.AddFinishAction(__result.initAction); // replace it with a test for Deep Storage // and if it IS deep storage, set up wait: Action placeStuff = __result.initAction; __result.AddPreInitAction(delegate() { __result.tickAction = null; Pawn actor = __result.actor; Job curJob = actor.jobs.curJob; IntVec3 cell = curJob.GetTarget(cellInd).Cell; if (actor.carryTracker.CarriedThing == null) { Log.Error(actor + " tried to place hauled thing in cell but is not hauling anything?", false); return; } SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); ThingComp comp; if (slotGroup == null || !(slotGroup?.parent is ThingWithComps) || (comp = ((ThingWithComps)slotGroup.parent).TryGetComp <CompDeepStorage>()) == null) { __result.initAction = placeStuff; return; } int timeStoringTakes = ((LWM.DeepStorage.Properties)comp.props).timeStoringTakes; if (timeStoringTakes <= 0) // just like vanilla { __result.initAction = placeStuff; return; } __result.initAction = null; __result.tickAction = delegate() { if (actor.jobs.curDriver.ticksLeftThisToil == 1) // last tick is 1, not 0 { placeStuff(); } }; actor.jobs.curDriver.ticksLeftThisToil = timeStoringTakes; __result.WithProgressBar(TargetIndex.B, () => 1f - (float)__result.actor.jobs.curDriver.ticksLeftThisToil / timeStoringTakes, true); Thing t = actor.CurJob.GetTarget(TargetIndex.A).Thing; // Add some end conditions: if (t != null) { __result.FailOn(() => !slotGroup.parent.Accepts(t)); } }); // added pre-init action! // HMM...let's get rid of stuff: __result.initAction = null; __result.atomicWithPrevious = false; __result.defaultCompleteMode = ToilCompleteMode.Delay; __result.defaultDuration = 0; // changed by initAction, if needed __result.FailOnBurningImmobile(TargetIndex.B); // TODO: FailOn&c, EndOn&c // Other fails..... // No longer allowed in that area? // No longer accepts what we're puttin there? // Um? } // end Postfix
public static void Postfix(Toil __result, TargetIndex cellInd) { Utils.Err(PlaceHauledThingInCell, "Starting new haul job, toils created"); //TODO? Make a wrapper around old initAction that doesn't put // stuff down if failure happens? SlotGroup groupAt = __result?.actor?.Map?.haulDestinationManager?.SlotGroupAt(__result.actor?.CurJob?.GetTarget(cellInd).Cell ?? IntVec3.Invalid); if ((groupAt?.parent as ThingWithComps)?.GetComp <CompDeepStorage>() == null) { Utils.Err(PlaceHauledThingInCell, "Not going into Deep Storage, exiting ASAP without modifying anything."); return; } Action placeStuff = __result.initAction; // NOTE: none of this PreInitAtion happens if the game is being loaded while storing is going on: // This means, among other things, that pawns don't get progress bars on reload // I could make it happen if it ever gets to be important... __result.AddPreInitAction(delegate() { Pawn actor = __result.actor; Job curJob = actor.jobs.curJob; IntVec3 cell = curJob.GetTarget(cellInd).Cell; Utils.Err(PlaceHauledThingInCell, "PreInitAction called for " + actor + "'s haul job " + curJob.def.driverClass + " to " + cell); // Log.Error("Place Hauled Thing in Cell: Toil preInit! Putting in "+cell.ToString()); // actor.jobs.debugLog = true; if (actor.carryTracker.CarriedThing == null) { // error as per original toil code Log.Error(actor + " tried to place hauled thing in cell but is not hauling anything?", false); return; } SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); CompDeepStorage cds; if (!(slotGroup?.parent is ThingWithComps) || (cds = (((ThingWithComps)slotGroup?.parent)?.GetComp <CompDeepStorage>())) == null) { Utils.Warn(PlaceHauledThingInCell, "not going into Deep Storage"); return; // initAction still around, will handle } int timeStoringTakes = cds.timeStoringTakes(cell); if (timeStoringTakes <= 0) { // just like vanilla Utils.Warn(PlaceHauledThingInCell, "Instantaneous storing time"); return; } // Remove the initAction so it doesn't happen before waiting starts: __result.initAction = null; if (actor.jobs.curDriver.ticksLeftThisToil < 1) // test is probably superfluous { actor.jobs.curDriver.ticksLeftThisToil = timeStoringTakes; } // It'd be nice to have a progress bar for deep storage __result.WithProgressBar(TargetIndex.B, () => 1f - (float)__result.actor.jobs.curDriver.ticksLeftThisToil / timeStoringTakes, true); /***** Add some end conditions: *****/ Thing t = actor.CurJob.GetTarget(TargetIndex.A).Thing; if (t != null) { __result.FailOn(() => !slotGroup.parent.Accepts(t)); } // TODO: any other end conditions? Fail conditions? // TODO: Any reservations? }); // added pre-init action! // The tickAction is only called if we are going into Deep Storage, // otherwise the toil is over after initAction and no ticks happen. // This will still get called even on load/save, because ticks count down. __result.tickAction = delegate() { Pawn pawn = __result.actor; Utils.Warn(PlaceHauledThingInCell, " " + pawn + "'s ticks left: " + __result.actor.jobs.curDriver.ticksLeftThisToil); if (pawn.jobs.curDriver.ticksLeftThisToil <= 1) // last tick is 1, not 0 { Utils.Err(PlaceHauledThingInCell, "Hit 0 ticks"); placeStuff(); } }; // ToilCompleteMode.Delay is acceptable in vanilla case, as duration is 0: __result.defaultCompleteMode = ToilCompleteMode.Delay; __result.defaultDuration = 0; // changed by PreInitAction, if needed __result.FailOnBurningImmobile(TargetIndex.B); // todo reservations (possibly?) // also todo, undo reservations (possibly?) (as another final action?) // TODO: FailOn&c, EndOn&c // Other fails..... // No longer allowed in that area? <--- Very definitely TODO // Um? } // end Postfix