public Toil Cultivate() { var targetCell = CurJob.targetA.Cell; var toil = new Toil(); toil.initAction = () => { workTicks = Mathf.RoundToInt(terrainReplacements[targetCell.GetTerrain()].GetStatValueAbstract(StatDefOf.WorkToMake) * pawn.GetStatValue(StatDefOf.PlantWorkSpeed)); pawn.jobs.curDriver.ticksLeftThisToil = workTicks; }; toil.tickAction = () => { if (--pawn.jobs.curDriver.ticksLeftThisToil < 0) { // remove designation var designation = Find.DesignationManager.DesignationAt(targetCell, DefDatabase<DesignationDef>.GetNamed("CultivateLand")); if (designation != null) { Find.DesignationManager.RemoveDesignation(designation); } // replace terrain Find.TerrainGrid.SetTerrain(targetCell, terrainReplacements[targetCell.GetTerrain()]); ReadyForNextToil(); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.FailOnCellMissingDesignation(CellInd, DefDatabase<DesignationDef>.GetNamed("CultivateLand")); toil.WithEffect(() => EffecterDef.Named("CutStone"), CellInd); toil.PlaySustainerOrSound(() => DefDatabase<SoundDef>.GetNamedSilentFail("Recipe_Surgery")); toil.WithProgressBar(CellInd, () => 1f - (float) pawn.jobs.curDriver.ticksLeftThisToil/workTicks); return toil; }
protected override IEnumerable <Toil> MakeNewToils() { Toil initExtractTargetFromQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, null); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(TargetIndex.A)); yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A, true)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, initExtractTargetFromQueue).JumpIfOutsideHomeArea(TargetIndex.A, initExtractTargetFromQueue)); Toil clean = new Toil(); clean.initAction = delegate { this.$this.cleaningWorkDone = 0f; this.$this.totalCleaningWorkDone = 0f; this.$this.totalCleaningWorkRequired = this.$this.Filth.def.filth.cleaningWorkToReduceThickness * (float)this.$this.Filth.thickness; }; clean.tickAction = delegate { Filth filth = this.$this.Filth; this.$this.cleaningWorkDone += 1f; this.$this.totalCleaningWorkDone += 1f; if (this.$this.cleaningWorkDone > filth.def.filth.cleaningWorkToReduceThickness) { filth.ThinFilth(); this.$this.cleaningWorkDone = 0f; if (filth.Destroyed) { clean.actor.records.Increment(RecordDefOf.MessesCleaned); this.$this.ReadyForNextToil(); return; } } }; clean.defaultCompleteMode = ToilCompleteMode.Never; clean.WithEffect(EffecterDefOf.Clean, TargetIndex.A); clean.WithProgressBar(TargetIndex.A, () => this.$this.totalCleaningWorkDone / this.$this.totalCleaningWorkRequired, true, -0.5f); clean.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); clean.JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, initExtractTargetFromQueue); clean.JumpIfOutsideHomeArea(TargetIndex.A, initExtractTargetFromQueue); yield return(clean); yield return(Toils_Jump.Jump(initExtractTargetFromQueue)); }
public static Toil AddIngestionEffects(Toil toil, Pawn chewer, TargetIndex ingestibleInd, TargetIndex eatSurfaceInd) { toil.WithEffect(delegate { LocalTargetInfo target = toil.actor.CurJob.GetTarget(ingestibleInd); if (!target.HasThing) { return(null); } EffecterDef result = target.Thing.def.ingestible.ingestEffect; if (chewer.RaceProps.intelligence < Intelligence.ToolUser && target.Thing.def.ingestible.ingestEffectEat != null) { result = target.Thing.def.ingestible.ingestEffectEat; } return(result); }, delegate { if (!toil.actor.CurJob.GetTarget(ingestibleInd).HasThing) { return(null); } Thing thing = toil.actor.CurJob.GetTarget(ingestibleInd).Thing; if (chewer != toil.actor) { return(chewer); } if (eatSurfaceInd != TargetIndex.None && toil.actor.CurJob.GetTarget(eatSurfaceInd).IsValid) { return(toil.actor.CurJob.GetTarget(eatSurfaceInd)); } return(thing); }); toil.PlaySustainerOrSound(delegate { if (!chewer.RaceProps.Humanlike) { return(null); } LocalTargetInfo target = toil.actor.CurJob.GetTarget(ingestibleInd); if (!target.HasThing) { return(null); } return(target.Thing.def.ingestible.ingestSound); }); return(toil); }
// Token: 0x06000373 RID: 883 RVA: 0x0001EF58 File Offset: 0x0001D358 protected override IEnumerable <Toil> MakeNewToils() { this.FailOnIncapable(PawnCapacityDefOf.Manipulation); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell)); yield return(Toils_Haul.StartCarryThing(TargetIndex.A, false, true, false)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(new Toil { initAction = delegate() { if (this.pawn.Position.OnEdge(this.pawn.Map) || this.pawn.Map.exitMapGrid.IsExitCell(this.pawn.Position)) { this.pawn.ExitMap(true, CellRect.WholeMap(base.Map).GetClosestEdge(this.pawn.Position)); } }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, false)); Toil prepare = Toils_General.Wait(this.useDuration, TargetIndex.A); prepare.NPCWithProgressBarToilDelay(TargetIndex.A, false, -0.5f); prepare.FailOnDespawnedNullOrForbidden(TargetIndex.A); // prepare.FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell); prepare.WithEffect(EffecterDefOf.Vomit, TargetIndex.A); prepare.PlaySustainerOrSound(() => SoundDefOf.Vomit); yield return(prepare); Toil use = new Toil(); use.initAction = delegate() { Pawn actor = use.actor; Pawn Infectable = (Pawn)actor.CurJob.targetA.Thing; Infectable.health.AddHediff(heCocDeff); }; use.defaultCompleteMode = ToilCompleteMode.Instant; yield return(use); yield break; }
public static Toil makeCleanToil(TargetIndex progListIndex, TargetIndex filthListIndex, Toil nextTarget) { Toil toil = new Toil(); toil.initAction = delegate() { Filth filth = toil.actor.jobs.curJob.GetTarget(filthListIndex).Thing as Filth; var progQue = toil.actor.jobs.curJob.GetTargetQueue(progListIndex); progQue[0] = new IntVec3(0, 0, (int)filth.def.filth.cleaningWorkToReduceThickness * filth.thickness); }; toil.tickAction = delegate() { Filth filth = toil.actor.jobs.curJob.GetTarget(filthListIndex).Thing as Filth; var progQue = toil.actor.jobs.curJob.GetTargetQueue(progListIndex); IntVec3 iv = progQue[0].Cell; iv.x += 1; iv.y += 1; if (iv.x > filth.def.filth.cleaningWorkToReduceThickness) { filth.ThinFilth(); iv.x = 0; if (filth.Destroyed) { toil.actor.records.Increment(RecordDefOf.MessesCleaned); toil.actor.jobs.curDriver.ReadyForNextToil(); return; } } progQue[0] = iv; }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(EffecterDefOf.Clean, filthListIndex); toil.WithProgressBar(filthListIndex, delegate() { var q = toil.actor.CurJob.GetTargetQueue(progListIndex)[0]; float result = (float)q.Cell.y / q.Cell.z; return(result); } , true, -0.5f); toil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); toil.JumpIfDespawnedOrNullOrForbidden(filthListIndex, nextTarget); toil.JumpIfOutsideHomeArea(filthListIndex, nextTarget); toil.FailOnDestroyedOrNull(TargetIndex.A); return(toil); }
protected override IEnumerable <Toil> MakeNewToils() { this.EndOnDespawnedOrNull(TargetIndex.A); yield return(Toils_Reserve.Reserve(TargetIndex.A, job.def.joyMaxParticipants)); if (TargetB != null) { yield return(Toils_Reserve.Reserve(TargetIndex.B)); } yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.OnCell)); var toil = new Toil(); toil.PlaySustainerOrSound(DefDatabase <SoundDef> .GetNamed("Estate_SoundManualTypewriter")); toil.tickAction = delegate { pawn.rotationTracker.FaceCell(TargetA.Cell); pawn.GainComfortFromCellIfPossible(); var statValue = TargetThingA.GetStatValue(StatDefOf.JoyGainFactor); JoyUtility.JoyTickCheckEnd(pawn, JoyTickFullJoyAction.EndJob, statValue); }; toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.defaultDuration = job.def.joyDuration; // toil.AddFinishAction(delegate // { // if (Cthulhu.Utility.IsCosmicHorrorsLoaded()) // { // try // { // if (Cthulhu.Utility.HasSanityLoss(this.pawn)) // { // Cthulhu.Utility.ApplySanityLoss(this.pawn, -sanityRestoreRate, 1); // Messages.Message(this.pawn.ToString() + " has restored some sanity using the " + this.TargetA.Thing.def.label + ".", new TargetInfo(this.pawn.Position, this.pawn.Map), MessageTypeDefOf.NeutralEvent);// .Standard); // } // } // catch // { // Log.Message("Error loading Sanity Hediff."); // } // } // // JoyUtility.TryGainRecRoomThought(this.pawn); // }); yield return(toil); }
protected override IEnumerable <Toil> MakeNewToils() { Toil toil = new Toil(); toil.initAction = delegate { ticksLeft = Rand.Range(300, 900); int num = 0; IntVec3 c; do { c = pawn.Position + GenAdj.AdjacentCellsAndInside[Rand.Range(0, 9)]; num++; if (num > 12) { c = pawn.Position; break; } }while (!c.InBounds(pawn.Map) || !c.Standable(pawn.Map)); job.targetA = c; pawn.pather.StopDead(); }; toil.tickAction = delegate { if (ticksLeft % 150 == 149) { FilthMaker.TryMakeFilth(job.targetA.Cell, base.Map, CultsDefOf.Cults_Filth_BileVomit, pawn.LabelIndefinite()); if (pawn.needs.food.CurLevelPercentage > 0.1f) // TODO: do other harm? { pawn.needs.food.CurLevel -= pawn.needs.food.MaxLevel * 0.04f; } } ticksLeft--; if (ticksLeft <= 0) { ReadyForNextToil(); TaleRecorder.RecordTale(TaleDefOf.Vomited, pawn); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(CultsDefOf.Cults_Effecter_VomitBile, TargetIndex.A); toil.PlaySustainerOrSound(() => SoundDefOf.Vomit); yield return(toil); }
public static Toil AddChewEffects(Toil toil, Pawn chewer, TargetIndex ind) { toil.WithEffect(delegate { Pawn actor = toil.actor; Thing thing = actor.CurJob.GetTarget(ind).Thing; EffecterDef result; if (thing.def.ingestible != null) { result = thing.def.ingestible.ingestEffect; } else { result = DefDatabase <EffecterDef> .GetNamed("EatVegetarian", true); } return(result); }, delegate { if (!toil.actor.CurJob.GetTarget(ind).HasThing) { return(null); } Thing thing = toil.actor.CurJob.GetTarget(ind).Thing; if (chewer != toil.actor) { return(chewer); } return(thing); }); toil.PlaySustainerOrSound(delegate { LocalTargetInfo target = toil.actor.CurJob.GetTarget(ind); if (!target.HasThing) { return(null); } SoundDef result = DefDatabase <SoundDef> .GetNamed("RawMeat_Eat", true); return(result); }); return(toil); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDestroyedOrNull(TargetIndex.A); this.SetCompleteMode(ToilCompleteMode.Never); yield return(Toils_Reserve.Reserve(TargetIndex.A, 1)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell)); Toil toil = new Toil(); Texture2D deitySymbol = ((CosmicEntityDef)DropAltar.currentOfferingDeity.def).Symbol; toil.PlaySustainerOrSound(CultDefOfs.RitualChanting); toil.initAction = delegate { this.workLeft = 2300f; if (deitySymbol != null) { MoteMaker.MakeInteractionMote(this.pawn, null, ThingDefOf.Mote_Speech, deitySymbol); } }; toil.tickAction = delegate { this.workLeft -= 1; if (this.workLeft <= 0f) { //Thing thing = ThingMaker.MakeThing(ThingDefOf.Snowman, null); //thing.SetFaction(this.<> f__this.pawn.Faction, null); //GenSpawn.Spawn(thing, this.<> f__this.TargetLocA); this.ReadyForNextToil(); return; } JoyUtility.JoyTickCheckEnd(this.pawn, JoyTickFullJoyAction.EndJob, 1f); }; toil.WithProgressBar(TargetIndex.A, () => this.workLeft / this.BaseWorkAmount, true, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Never; //toil.FailOn(() => !JoyUtility.EnjoyableOutsideNow(this.<> f__this.pawn, null)); yield return(toil); yield break; }
public static Toil AddIngestionEffects(Toil toil, Pawn chewer, TargetIndex ingestibleInd, TargetIndex eatSurfaceInd) { toil.WithEffect(delegate { LocalTargetInfo target2 = toil.actor.CurJob.GetTarget(ingestibleInd); if (!target2.HasThing) { return(null); } EffecterDef result = target2.Thing.GetIngestibleProperties().ingestEffect; if ((int)chewer.RaceProps.intelligence < 1 && target2.Thing.GetIngestibleProperties().ingestEffectEat != null) { result = target2.Thing.GetIngestibleProperties().ingestEffectEat; } return(result); }, delegate { if (!toil.actor.CurJob.GetTarget(ingestibleInd).HasThing) { return(null); } Thing thing = toil.actor.CurJob.GetTarget(ingestibleInd).Thing; if (chewer != toil.actor) { return(chewer); } return((eatSurfaceInd != 0 && toil.actor.CurJob.GetTarget(eatSurfaceInd).IsValid) ? toil.actor.CurJob.GetTarget(eatSurfaceInd) : ((LocalTargetInfo)thing)); }); toil.PlaySustainerOrSound(delegate { if (!chewer.RaceProps.Humanlike) { return(null); } LocalTargetInfo target = toil.actor.CurJob.GetTarget(ingestibleInd); return((!target.HasThing) ? null : target.Thing.GetIngestibleProperties().ingestSound); }); return(toil); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnForbidden(TargetIndex.A); yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch)); Toil doWork = new Toil(); doWork.defaultCompleteMode = ToilCompleteMode.Never; doWork.FailOn(() => !JoyUtility.EnjoyableOutsideNow(this.pawn, null)); doWork.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); doWork.PlaySustainerOrSound(SoundDefOf.Interact_CleanFilth); doWork.initAction = () => { this.workLeft = 600f; }; doWork.tickAction = () => { if (pawn.IsHashIntervalTick(50)) { pawn.skills.Learn(SkillDefOf.Artistic, 0.5f); } this.workLeft -= doWork.actor.GetStatValue(StatDefOf.WorkSpeedGlobal, true); if (this.workLeft <= 0f) { Thing thing = ThingMaker.MakeThing(DSFIThingDefOf.DSFI_Scribbling, null); Thing spawnedThing = GenSpawn.Spawn(thing, this.TargetLocA, this.Map, WipeMode.Vanish); spawnedThing.Rotation = Rot4.Random; this.ReadyForNextToil(); return; } }; yield return(doWork); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch)); Toil clearToil = new Toil(); clearToil.tickAction = delegate { float statValue = clearToil.actor.GetStatValue(StatDefOf.GeneralLaborSpeed); workDone += statValue; if (workDone >= TotalNeededWork) { base.Map.snowGrid.SetDepth(base.TargetLocA, 0f); ReadyForNextToil(); } }; clearToil.defaultCompleteMode = ToilCompleteMode.Never; clearToil.WithEffect(EffecterDefOf.ClearSnow, TargetIndex.A); clearToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); clearToil.WithProgressBar(TargetIndex.A, () => workDone / TotalNeededWork, interpolateBetweenActorAndTarget: true); clearToil.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); yield return(clearToil); }
public static Toil DrinkTerrain(TargetIndex cellIndex, int baseDrinkTicksFromTerrain) { // 地形から水を飲む int initialTicks = 1; Toil toil = new Toil(); toil.initAction = delegate { var actor = toil.actor; var cell = actor.CurJob.GetTarget(cellIndex).Cell; var need_water = actor.needs.water(); if (need_water == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } var waterType = cell.GetTerrain(actor.Map).ToWaterType(); if (waterType == WaterType.NoWater || waterType == WaterType.Undefined) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } var waterTypeDef = MizuDef.Dic_WaterTypeDef[waterType]; // 向き変更 actor.rotationTracker.FaceCell(actor.Position); // 作業量 actor.jobs.curDriver.ticksLeftThisToil = (int)(baseDrinkTicksFromTerrain * need_water.WaterWanted); initialTicks = actor.jobs.curDriver.ticksLeftThisToil; if (actor.needs.mood != null) { // 水分摂取による心情変化 List <ThoughtDef> thoughtList = new List <ThoughtDef>(); MizuUtility.ThoughtsFromWaterTypeDef(actor, waterTypeDef, true, thoughtList); foreach (var thoughtDef in thoughtList) { actor.needs.mood.thoughts.memories.TryGainMemory(thoughtDef); } } // 指定された健康状態になる if (waterTypeDef.hediffs != null) { foreach (var hediff in waterTypeDef.hediffs) { actor.health.AddHediff(HediffMaker.MakeHediff(hediff, actor)); } } // 確率で食中毒 if (Rand.Value < waterTypeDef.foodPoisonChance) { actor.health.AddHediff(HediffMaker.MakeHediff(HediffDefOf.FoodPoisoning, actor)); if (PawnUtility.ShouldSendNotificationAbout(actor)) { var water = ThingMaker.MakeThing(MizuUtility.GetWaterThingDefFromWaterType(waterType)); string cause = "MizuPoisonedByDirtyWater".Translate().CapitalizeFirst(); string text = "MessageFoodPoisoning".Translate(actor.LabelShort, water.ToString(), cause, actor.Named("PAWN"), water.Named("FOOD")).CapitalizeFirst(); Messages.Message(text, actor, MessageTypeDefOf.NegativeEvent); } } }; toil.tickAction = delegate { toil.actor.GainComfortFromCellIfPossible(); var need_water = toil.actor.needs.water(); var cell = toil.actor.CurJob.GetTarget(cellIndex).Cell; if (need_water == null) { toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 徐々に飲む float riseNeedWater = 1 / (float)baseDrinkTicksFromTerrain; need_water.CurLevel = Mathf.Min(need_water.CurLevel + riseNeedWater, need_water.MaxLevel); }; toil.WithProgressBar(cellIndex, delegate { return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / initialTicks); }, false, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.FailOn((t) => { Pawn actor = toil.actor; return(actor.CurJob.targetA.Cell.IsForbidden(actor) || !actor.CanReach(actor.CurJob.targetA.Cell, PathEndMode.OnCell, Danger.Deadly)); }); // エフェクト追加 toil.PlaySustainerOrSound(delegate { return(DefDatabase <SoundDef> .GetNamed("Ingest_Beer")); }); return(toil); }
public static Toil DrinkFromBuilding(TargetIndex buildingIndex) { int initialTicks = 1; Toil toil = new Toil(); toil.initAction = delegate { var actor = toil.actor; var thing = actor.CurJob.GetTarget(buildingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); var building = thing as IBuilding_DrinkWater; if (actor.needs == null || actor.needs.water() == null || building == null || comp == null || !comp.IsWaterSource) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } var need_water = actor.needs.water(); var waterTypeDef = MizuDef.Dic_WaterTypeDef[comp.WaterType]; // 向きを変更 actor.rotationTracker.FaceCell(actor.Position); // 作業量 actor.jobs.curDriver.ticksLeftThisToil = (int)(comp.BaseDrinkTicks * need_water.WaterWanted); initialTicks = actor.jobs.curDriver.ticksLeftThisToil; if (actor.needs.mood != null) { // 水分摂取による心情変化 foreach (var thoughtDef in MizuUtility.ThoughtsFromGettingWater(actor, thing)) { actor.needs.mood.thoughts.memories.TryGainMemory(thoughtDef); } } // 指定された健康状態になる if (waterTypeDef.hediffs != null) { foreach (var hediff in waterTypeDef.hediffs) { actor.health.AddHediff(HediffMaker.MakeHediff(hediff, actor)); } } // 確率で食中毒 if (Rand.Value < waterTypeDef.foodPoisonChance) { FoodUtility.AddFoodPoisoningHediff(actor, thing, FoodPoisonCause.Unknown); } }; toil.tickAction = delegate { toil.actor.GainComfortFromCellIfPossible(); var need_water = toil.actor.needs.water(); var thing = toil.actor.CurJob.GetTarget(buildingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); var building = thing as IBuilding_DrinkWater; if (thing == null || comp == null || !comp.IsWaterSource || building == null || building.IsEmpty) { toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 徐々に飲む float riseNeedWater = 1 / (float)comp.BaseDrinkTicks; need_water.CurLevel = Mathf.Min(need_water.CurLevel + riseNeedWater, need_water.MaxLevel); building.DrawWater(riseNeedWater * Need_Water.NeedWaterVolumePerDay); }; toil.WithProgressBar(buildingIndex, delegate { return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / initialTicks); }, false, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.FailOn((t) => { Pawn actor = toil.actor; var target = actor.CurJob.GetTarget(buildingIndex); if (target.Thing.def.hasInteractionCell) { // 使用場所があるなら使用場所基準 return(target.Thing.InteractionCell.IsForbidden(actor) || !actor.CanReach(target.Thing.InteractionCell, PathEndMode.OnCell, Danger.Deadly)); } else { // 使用場所がないなら設備の場所基準 return(target.Thing.Position.IsForbidden(actor) || !actor.CanReach(target.Thing.Position, PathEndMode.ClosestTouch, Danger.Deadly)); } }); // エフェクト追加 toil.PlaySustainerOrSound(delegate { return(DefDatabase <SoundDef> .GetNamed("Ingest_Beer")); }); return(toil); }
public static Toil DoRecipeWorkDrawing(TargetIndex billGiverIndex) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; jobDriver_DoBill.workLeft = curJob.bill.recipe.WorkAmountTotal(null); jobDriver_DoBill.billStartTick = Find.TickManager.TicksGame; jobDriver_DoBill.ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); }; toil.tickAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; jobDriver_DoBill.ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction = actor.CurJob.GetTarget(billGiverIndex).Thing as IBillGiverWithTickAction; if (billGiverWithTickAction != null) { // 設備の時間経過処理 billGiverWithTickAction.UsedThisTick(); } // 工数を進める処理 float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; Building_WorkTable building_WorkTable = jobDriver_DoBill.BillGiver as Building_WorkTable; if (building_WorkTable != null) { num *= building_WorkTable.GetStatValue(StatDefOf.WorkTableWorkSpeedFactor, true); } if (DebugSettings.fastCrafting) { num *= 30f; } jobDriver_DoBill.workLeft -= num; // 椅子から快適さを得る actor.GainComfortFromCellIfPossible(); // 完了チェック if (jobDriver_DoBill.workLeft <= 0f) { jobDriver_DoBill.ReadyForNextToil(); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => toil.actor.CurJob.bill.recipe.effectWorking, billGiverIndex); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(billGiverIndex, delegate { Pawn actor = toil.actor; Job curJob = actor.CurJob; return(1f - ((JobDriver_DoBill)actor.jobs.curDriver).workLeft / curJob.bill.recipe.WorkAmountTotal(null)); }, false, -0.5f); toil.FailOn(() => toil.actor.CurJob.bill.suspended); return(toil); }
private static Toil DrinkSomeone(TargetIndex thingIndex, Func <Toil, Func <LocalTargetInfo> > funcGetter) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Thing thing = actor.CurJob.GetTarget(thingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); if (comp == null || comp.SourceType != CompProperties_WaterSource.SourceType.Item) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } actor.rotationTracker.FaceCell(actor.Position); if (!thing.CanDrinkWaterNow()) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } actor.jobs.curDriver.ticksLeftThisToil = comp.BaseDrinkTicks; if (thing.Spawned) { thing.Map.physicalInteractionReservationManager.Reserve(actor, actor.CurJob, thing); } }; toil.tickAction = delegate { toil.actor.GainComfortFromCellIfPossible(); }; toil.WithProgressBar(thingIndex, delegate { Pawn actor = toil.actor; Thing thing = actor.CurJob.GetTarget(thingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); if (thing == null || comp == null || comp.SourceType != CompProperties_WaterSource.SourceType.Item) { return(1f); } return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / (float)comp.BaseDrinkTicks); }, false, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.FailOnDestroyedOrNull(thingIndex); toil.AddFinishAction(delegate { Pawn actor = toil.actor; if (actor == null) { return; } if (actor.CurJob == null) { return; } Thing thing = actor.CurJob.GetTarget(thingIndex).Thing; if (thing == null) { return; } if (actor.Map.physicalInteractionReservationManager.IsReservedBy(actor, thing)) { actor.Map.physicalInteractionReservationManager.Release(actor, actor.CurJob, thing); } }); // エフェクト追加 toil.WithEffect(delegate { Pawn actor = toil.actor; LocalTargetInfo target = toil.actor.CurJob.GetTarget(thingIndex); if (!target.HasThing) { return(null); } EffecterDef effecter = null; var comp = target.Thing.TryGetComp <CompWaterSource>(); if (comp != null) { effecter = comp.GetEffect; } return(effecter); }, funcGetter(toil)); toil.PlaySustainerOrSound(delegate { Pawn actor = toil.actor; if (!actor.RaceProps.Humanlike) { return(null); } LocalTargetInfo target = toil.actor.CurJob.GetTarget(thingIndex); if (!target.HasThing) { return(null); } var comp = target.Thing.TryGetComp <CompWaterSource>(); if (comp == null) { return(null); } return(comp.Props.getSound); }); return(toil); }
protected override Toil DoBill() { var objectThing = job.GetTarget(objectTI).Thing; var qualityComponent = objectThing.TryGetComp <CompQuality> (); var tableThing = job.GetTarget(tableTI).Thing as Building_WorkTable; var tablePowerTraderComp = tableThing.GetComp <CompPowerTrader> (); var toil = new Toil(); toil.initAction = delegate { job.bill.Notify_DoBillStarted(pawn); processedHitPoints = 0; failChance = ChanceDef.GetFor(objectThing); workCycleProgress = workCycle = Math.Max(job.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { if (objectThing == null || objectThing.Destroyed) { pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress -= StatExtension.GetStatValue(pawn, StatDefOf.WorkToMake, true); tableThing.UsedThisTick(); if (!tableThing.UsableNow) { pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } if (workCycleProgress <= 0) { objectThing.HitPoints -= fixedHitPointsPerCycle; if (tablePowerTraderComp != null && tablePowerTraderComp.PowerOn) { processedHitPoints += fixedHitPointsPerCycle; } else { processedHitPoints += fixedHitPointsPerCycle / 2; } float skillPerc = 0.5f; var skillDef = job.RecipeDef.workSkill; if (skillDef != null) { var skill = pawn.skills.GetSkill(skillDef); if (skill != null) { skillPerc = (float)skill.Level / 20f; skill.Learn(0.11f * job.RecipeDef.workSkillLearnFactor); } } if (qualityComponent != null && qualityComponent.Quality > QualityCategory.Awful) { var qc = qualityComponent.Quality; float skillFactor = Mathf.Lerp(0.5f, 1.5f, skillPerc); if (failChance != null && Rand.Value < failChance.Chance(qc) * skillFactor) { objectThing.HitPoints -= fixedFailedDamage; MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "Failed"); } } pawn.GainComfortFromCellIfPossible(); if (objectThing.HitPoints <= 0) { pawn.Map.reservationManager.Release(job.targetB, pawn, job); objectThing.Destroy(DestroyMode.Vanish); float skillFactor = Mathf.Lerp(0.5f, 1.5f, skillPerc); float healthPerc = (float)processedHitPoints / (float)objectThing.MaxHitPoints; float healthFactor = Mathf.Lerp(0f, 0.4f, healthPerc); var list = JobDriverUtils.Reclaim(objectThing, skillFactor * healthFactor); if (list.Count > 1) { for (int j = 1; j < list.Count; j++) { if (!GenPlace.TryPlaceThing(list [j], pawn.Position, pawn.Map, ThingPlaceMode.Near, null)) { Log.Error("Mending :: " + pawn + " could not drop recipe product " + list [j] + " near " + pawn.Position); } } } else if (list.Count == 1) { list [0].SetPositionDirect(pawn.Position); job.bill.Notify_IterationCompleted(pawn, list); job.targetB = list [0]; pawn.Map.reservationManager.Reserve(pawn, job, job.targetB, 1); } else { Log.Message("Mending :: " + pawn + " could not reclaim anything from " + objectThing); } ReadyForNextToil(); } workCycleProgress = workCycle; } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => job.bill.recipe.effectWorking, tableTI); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(tableTI, delegate { return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { return(toil.actor.CurJob.bill.suspended || !tableThing.UsableNow); }); return(toil); }
static IEnumerable <Toil> prepToils(JobDriver_Ingest driver, Toil chewToil) { if ((bool)LeatingFromInventory.GetValue(driver)) { yield return(Toils_Misc.TakeItemFromInventoryToCarrier(driver.pawn, TargetIndex.A)); } else { yield return((Toil)LReserveFood.Invoke(driver, new object[] { })); Toil gotoToPickup = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A); yield return(Toils_Jump.JumpIf(gotoToPickup, () => driver.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(TargetIndex.A)); yield return(Toils_Jump.Jump(chewToil)); yield return(gotoToPickup); yield return(Toils_Ingest.PickupIngestible(TargetIndex.A, driver.pawn)); gotoToPickup = null; } if (driver.job.takeExtraIngestibles > 0) { foreach (Toil toil in (IEnumerable <Toil>)LTakeExtraIngestibles.Invoke(driver, new object[] { })) { yield return(toil); } } if (!driver.pawn.Drafted) { yield return(reserveChewSpot(driver.pawn, TargetIndex.A, TargetIndex.B)); Toil gotospot = gotoSpot(TargetIndex.B).FailOnDestroyedOrNull(TargetIndex.A); if (!Utility.IncapableOfCleaning(driver.pawn)) { TargetIndex filthListIndex = TargetIndex.B; TargetIndex progIndex = TargetIndex.A; Toil FilthList = new Toil(); FilthList.initAction = delegate() { Job curJob = FilthList.actor.jobs.curJob; // if (curJob.GetTargetQueue(filthListIndex).NullOrEmpty()) { LocalTargetInfo A = curJob.GetTarget(filthListIndex); if (!A.HasThing) { return; } IEnumerable <Filth> l = Utility.SelectAllFilth(FilthList.actor, A, Settings.adv_clean_num); Utility.AddFilthToQueue(curJob, filthListIndex, l, FilthList.actor); FilthList.actor.ReserveAsManyAsPossible(curJob.GetTargetQueue(filthListIndex), curJob); curJob.GetTargetQueue(filthListIndex).Add(A); } }; yield return(FilthList); yield return(Toils_Jump.JumpIf(gotospot, () => driver.job.GetTargetQueue(filthListIndex).NullOrEmpty())); Toil nextTarget = Toils_JobTransforms.ExtractNextTargetFromQueue(filthListIndex, true); yield return(nextTarget); yield return(Toils_Jump.JumpIf(gotospot, () => driver.job.GetTargetQueue(filthListIndex).NullOrEmpty())); yield return(Toils_Goto.GotoThing(filthListIndex, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(filthListIndex, nextTarget).JumpIfOutsideHomeArea(filthListIndex, nextTarget)); // if (driver.job.GetTargetQueue(progIndex).Count == 0) { driver.job.GetTargetQueue(progIndex).Add(new IntVec3(0, 0, 0)); } // Toil clean = new Toil(); clean.initAction = delegate() { Filth filth = clean.actor.jobs.curJob.GetTarget(filthListIndex).Thing as Filth; var progQue = clean.actor.jobs.curJob.GetTargetQueue(progIndex); progQue[0] = new IntVec3(0, 0, (int)filth.def.filth.cleaningWorkToReduceThickness * filth.thickness); }; clean.tickAction = delegate() { Filth filth = clean.actor.jobs.curJob.GetTarget(filthListIndex).Thing as Filth; var progQue = clean.actor.jobs.curJob.GetTargetQueue(progIndex); IntVec3 iv = progQue[0].Cell; iv.x += 1; iv.y += 1; if (iv.x > filth.def.filth.cleaningWorkToReduceThickness) { filth.ThinFilth(); iv.x = 0; if (filth.Destroyed) { clean.actor.records.Increment(RecordDefOf.MessesCleaned); driver.ReadyForNextToil(); return; } } progQue[0] = iv; }; clean.defaultCompleteMode = ToilCompleteMode.Never; clean.WithEffect(EffecterDefOf.Clean, filthListIndex); clean.WithProgressBar(filthListIndex, delegate() { var q = driver.job.GetTargetQueue(progIndex)[0]; float result = (float)q.Cell.y / q.Cell.z; return(result); } , true, -0.5f); clean.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); clean.JumpIfDespawnedOrNullOrForbidden(filthListIndex, nextTarget); clean.JumpIfOutsideHomeArea(filthListIndex, nextTarget); clean.FailOnDestroyedOrNull(TargetIndex.A); yield return(clean); yield return(Toils_Jump.Jump(nextTarget)); } yield return(gotospot); } yield return(Toils_Ingest.FindAdjacentEatSurface(TargetIndex.B, TargetIndex.A)); yield break; }
protected override Toil DoBill() { var objectThing = job.GetTarget(objectTI).Thing; var tableThing = job.GetTarget(tableTI).Thing as Building_WorkTable; var toil = new Toil(); toil.initAction = delegate { job.bill.Notify_DoBillStarted(pawn); workCycleProgress = workCycle = Math.Max(job.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { if (objectThing == null || objectThing.Destroyed) { pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress -= StatExtension.GetStatValue(pawn, StatDefOf.WorkToMake, true); tableThing.UsedThisTick(); if (!tableThing.CurrentlyUsableForBills()) { pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } if (workCycleProgress <= 0) { int remainingHitPoints = objectThing.MaxHitPoints - objectThing.HitPoints; if (remainingHitPoints > 0) { objectThing.HitPoints += (int)Math.Min(remainingHitPoints, fixedHitPointsPerCycle); } float skillPerc = 0.5f; var skillDef = job.RecipeDef.workSkill; if (skillDef != null) { var skill = pawn.skills.GetSkill(skillDef); if (skill != null) { skillPerc = (float)skill.Level / 20f; skill.Learn(0.11f * job.RecipeDef.workSkillLearnFactor); } } var qualityComponent = objectThing.TryGetComp <CompQuality>(); if (qualityComponent != null && qualityComponent.Quality > QualityCategory.Awful) { var qc = qualityComponent.Quality; float skillFactor = Mathf.Lerp(1.5f, 0f, skillPerc); if (!SuccessChanceUtil.SuccessOnAction(pawn, skillFactor, objectThing)) { objectThing.HitPoints -= fixedFailedDamage; MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "Failed"); } } pawn.GainComfortFromCellIfPossible(); if (objectThing.HitPoints <= 0) { // recycling whats left... float skillFactor = Mathf.Lerp(0.5f, 1.5f, skillPerc); var list = JobDriverUtils.Reclaim(objectThing, skillFactor * 0.1f); pawn.Map.reservationManager.Release(job.targetB, pawn, job); objectThing.Destroy(DestroyMode.Vanish); if (list.Count > 1) { for (int j = 1; j < list.Count; j++) { if (!GenPlace.TryPlaceThing(list [j], pawn.Position, pawn.Map, ThingPlaceMode.Near, null)) { Log.Error("Mending :: " + pawn + " could not drop recipe product " + list [j] + " near " + pawn.Position); } } } list[0].SetPositionDirect(pawn.Position); job.targetB = list[0]; job.bill.Notify_IterationCompleted(pawn, list); pawn.Map.reservationManager.Reserve(pawn, job, job.targetB, 1); ReadyForNextToil(); } else if (objectThing.HitPoints == objectThing.MaxHitPoints) { // fixed! var mendApparel = objectThing as Apparel; if (mendApparel != null) { ApparelWornByCorpseInt.SetValue(mendApparel, false); } var list = new List <Thing> (); list.Add(objectThing); job.bill.Notify_IterationCompleted(pawn, list); ReadyForNextToil(); } else if (objectThing.HitPoints > objectThing.MaxHitPoints) { Log.Error("Mending :: This should never happen! HitPoints > MaxHitPoints"); pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress = workCycle; } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => job.bill.recipe.effectWorking, tableTI); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(tableTI, delegate { return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { var billGiver = job.GetTarget(tableTI).Thing as IBillGiver; return(job.bill.suspended || job.bill.DeletedOrDereferenced || (billGiver != null && !billGiver.CurrentlyUsableForBills())); }); return(toil); }
public override IEnumerable <Toil> MakeNewToils() { this.FailOnIncapable(PawnCapacityDefOf.Manipulation); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell)); if (_Necron == null) { Log.Warning("ERROR!!!! _Necron null"); yield break; } if (!DamagedNecron.Spawned && !DamagedNecron.Corpse.Spawned) { Log.Warning("ERROR!!!! DamagedNecron despawned"); yield break; } if (DamagedNecron == null) { Log.Warning("ERROR!!!! DamagedNecron null"); yield break; } if (!_Necron.PawnHediffs.NullOrEmpty()) { // Log.Message("CHECKING!!!! _Necron Damage"); foreach (Hediff hd in _Necron.PawnHediffs) { if (hd.def.hediffClass == typeof(Hediff_Injury)) { // Log.Message("INJURY!!!!"); this.useDuration += (int)(((hd.Severity * DamagedNecron.BodySize)) * (_Necron.UnhealableHediffs.Contains(hd) ? 3 : 1)); } else if (hd.def.hediffClass == typeof(Hediff_MissingPart) && !DamagedNecron.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(hd.Part)) { // Log.Message("MISSING PART!!!!"); this.useDuration += (int)(((300 * DamagedNecron.BodySize) * hd.Severity) * (_Necron.UnhealableHediffs.Contains(hd) ? 3 : 1)); } else { // Log.Message("STILL CHECKING!!!!"); if (hd.def.hediffClass != typeof(Hediff_Implant) && hd.def.hediffClass != typeof(Hediff_MissingPart)) { // Log.Message("NOT IMPLANT OR MISSINGPART!!!!"); } // Log.Message(string.Format("Missed {0} {1} on {2}", hd.LabelCap, hd.def.hediffClass, hd.Part.LabelCap)); } } } else { // Log.Warning("ERROR!!!! DamagedNecron null"); } if (DamagedNecron.Dead) { this.useDuration = (int)(500 * DamagedNecron.BodySize); } Toil prepare = Toils_General.Wait(this.useDuration, TargetIndex.A); prepare.NPCWithProgressBarToilDelay(TargetIndex.A, false, -0.5f); prepare.FailOnDespawnedNullOrForbidden(TargetIndex.A); prepare.WithEffect(EffecterDefOf.ConstructMetal, TargetIndex.A); prepare.PlaySustainerOrSound(() => SoundDefOf.Crunch); if (DamagedNecron.Dead) { yield return(prepare); Toil use = new Toil(); use.initAction = delegate() { Pawn Spyder = use.actor; _Necron.TryRevive(true); }; use.defaultCompleteMode = ToilCompleteMode.Instant; yield return(use); } else { if (DamagedNecron.Downed) { yield return(prepare); Toil use = new Toil(); use.initAction = delegate() { Pawn Spyder = use.actor; foreach (Hediff hd in _Necron.PawnHediffs) { DamagedNecron.health.RemoveHediff(hd); } }; use.defaultCompleteMode = ToilCompleteMode.Instant; yield return(use); if (_Necron.originalWeapon != null) { ThingWithComps thing = _Necron.originalWeapon; if (thing.Spawned) { thing.DeSpawn(); } if (DamagedNecron.inventory.innerContainer.Contains(thing)) { DamagedNecron.inventory.innerContainer.Remove(thing); } DamagedNecron.equipment.AddEquipment(thing); } if (_Necron.secondryWeapon != null) { ThingWithComps thing = _Necron.secondryWeapon; if (thing.Spawned) { thing.DeSpawn(); } if (DamagedNecron.inventory.innerContainer.Contains(thing)) { DamagedNecron.inventory.innerContainer.Remove(thing); } // DamagedNecron.equipment.AdMechAddOffHandEquipment(thing); } } } yield break; }
// added support for fuel burners public static Toil DoRecipeWork() { // research injection. initialized here to check if research project wan't change during work var startedResearch = Find.ResearchManager.currentProj; var toil = new Toil(); toil.initAction = () => { var actor = toil.actor; var curJob = actor.jobs.curJob; var curDriver = actor.jobs.curDriver as JobDriver_DoBill; var unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null && unfinishedThing.Initialized) { curDriver.workLeft = unfinishedThing.workLeft; } else { // research injection var researchComp = toil.actor.jobs.curJob.GetTarget(TargetIndex.A).Thing.TryGetComp<CompResearcher>(); if (researchComp != null) { curDriver.workLeft = startedResearch.CostApparent - startedResearch.ProgressApparent; } else { curDriver.workLeft = curJob.bill.recipe.WorkAmountTotal(unfinishedThing?.Stuff); } if (unfinishedThing != null) { unfinishedThing.workLeft = curDriver.workLeft; } } curDriver.billStartTick = Find.TickManager.TicksGame; curJob.bill.Notify_DoBillStarted(); }; toil.tickAction = () => { var actor = toil.actor; var curJob = actor.jobs.curJob; actor.GainComfortFromCellIfPossible(); // burner support injection var burner = curJob.GetTarget(TargetIndex.A).Thing.TryGetComp<CompFueled>(); if (burner != null && burner.internalTemp < burner.compFueled.Properties.operatingTemp) { return; } var unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null && unfinishedThing.Destroyed) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } curJob.bill.Notify_PawnDidWork(actor); var billGiverWithTickAction = curJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; billGiverWithTickAction?.BillTick(); if (curJob.RecipeDef.workSkill != null) { actor.skills.GetSkill(curJob.RecipeDef.workSkill) .Learn(LearnRates.XpPerTickRecipeBase*curJob.RecipeDef.workSkillLearnFactor); } var workProgress = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat) : 1f; var curDriver = actor.jobs.curDriver as JobDriver_DoBill; var building_WorkTable = curDriver.BillGiver as Building_WorkTable; var researchComp = curJob.GetTarget(TargetIndex.A).Thing.TryGetComp<CompResearcher>(); if (building_WorkTable != null) { // research injection workProgress *= researchComp == null ? building_WorkTable.GetStatValue(StatDefOf.WorkTableWorkSpeedFactor) : building_WorkTable.GetStatValue(StatDefOf.ResearchSpeedFactor); } if (DebugSettings.fastCrafting) { workProgress *= 30f; } curDriver.workLeft -= workProgress; if (unfinishedThing != null) { unfinishedThing.workLeft = curDriver.workLeft; } // research injection if (researchComp != null) { if (Find.ResearchManager.currentProj != null && Find.ResearchManager.currentProj == startedResearch) { Find.ResearchManager.ResearchPerformed(workProgress, actor); } if (Find.ResearchManager.currentProj != startedResearch) { actor.jobs.EndCurrentJob(JobCondition.Succeeded); // scatter around all ingridients foreach (var cell in building_WorkTable.IngredientStackCells) { var ingridientsOnCell = Find.ThingGrid.ThingsListAtFast(cell)? .Where(thing => thing.def.category == ThingCategory.Item) .ToList(); if (!ingridientsOnCell.NullOrEmpty()) { Thing dummy; // despawn thing to spawn again with TryPlaceThing ingridientsOnCell.FirstOrDefault().DeSpawn(); if ( !GenPlace.TryPlaceThing(ingridientsOnCell.FirstOrDefault(), building_WorkTable.InteractionCell, ThingPlaceMode.Near, out dummy)) { Log.Error("No free spot for " + ingridientsOnCell); } } } } } else if (curDriver.workLeft <= 0f) { curDriver.ReadyForNextToil(); } if (curJob.bill.recipe.UsesUnfinishedThing) { var num2 = Find.TickManager.TicksGame - curDriver.billStartTick; if (num2 >= 3000 && num2%1000 == 0) { actor.jobs.CheckForJobOverride(); } } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => toil.actor.CurJob.bill.recipe.effectWorking, TargetIndex.A); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(TargetIndex.A, () => { var actor = toil.actor; var curJob = actor.CurJob; var unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; var researchComp = curJob.GetTarget(TargetIndex.A).Thing.TryGetComp<CompResearcher>(); // research injection return researchComp == null ? 1f - ((JobDriver_DoBill) actor.jobs.curDriver).workLeft/ curJob.bill.recipe.WorkAmountTotal(unfinishedThing?.Stuff) : startedResearch.ProgressPercent; }); return toil; }
protected override Toil DoBill() { Pawn actor = GetActor(); Job curJob = actor.jobs.curJob; Thing objectThing = curJob.GetTarget(objectTI).Thing; Building_WorkTable tableThing = curJob.GetTarget(tableTI).Thing as Building_WorkTable; Toil toil = new Toil(); toil.initAction = delegate { curJob.bill.Notify_DoBillStarted(actor); this.workCycleProgress = this.workCycle = Math.Max(curJob.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { if (objectThing == null || objectThing.Destroyed) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress -= StatExtension.GetStatValue(actor, StatDefOf.WorkToMake, true); tableThing.UsedThisTick(); //if (!tableThing.UsableNow) //{ // actor.jobs.EndCurrentJob(JobCondition.Incompletable); //} if (workCycleProgress <= 0) { float skillPerc = 0.5f; SkillDef skillDef = curJob.RecipeDef.workSkill; if (skillDef != null) { SkillRecord skill = actor.skills.GetSkill(skillDef); if (skill != null) { skillPerc = (float)skill.Level / 20f; skill.Learn(0.11f * curJob.RecipeDef.workSkillLearnFactor); } } actor.GainComfortFromCellIfPossible(); Apparel mendApparel = objectThing as Apparel; if (mendApparel != null) { ApparelWornByCorpseInt.SetValue(mendApparel, false); } List <Thing> list = new List <Thing>(); list.Add(objectThing); curJob.bill.Notify_IterationCompleted(actor, list); workCycleProgress = workCycle; ReadyForNextToil(); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => curJob.bill.recipe.effectWorking, tableTI); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(tableTI, delegate { return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { IBillGiver billGiver = curJob.GetTarget(tableTI).Thing as IBillGiver; return(curJob.bill.suspended || curJob.bill.DeletedOrDereferenced || (billGiver != null && !billGiver.CurrentlyUsableForBills())); }); return(toil); }
public Toil CollectClay(int ticksToCollect) { var targetCell = CurJob.targetA.Cell; var toil = new Toil(); toil.initAction = () => { pawn.jobs.curDriver.ticksLeftThisToil = Mathf.RoundToInt(ticksToCollect*pawn.GetStatValue(StatDef.Named("CollectingSpeed"))); totalWork = pawn.jobs.curDriver.ticksLeftThisToil; }; toil.tickAction = () => { if (--pawn.jobs.curDriver.ticksLeftThisToil < 0) { // remove designation var designation = Find.DesignationManager.DesignationAt(targetCell, DefDatabase<DesignationDef>.GetNamed("CollectClay")); if (designation != null) { Find.DesignationManager.RemoveDesignation(designation); } // replace terrain if (Find.TerrainGrid.TerrainAt(targetCell) == TerrainDef.Named("Mud")) Find.TerrainGrid.SetTerrain(targetCell, DefDatabase<TerrainDef>.GetNamed("Soil")); if (Find.TerrainGrid.TerrainAt(targetCell) == TerrainDef.Named("SoilRich")) Find.TerrainGrid.SetTerrain(targetCell, DefDatabase<TerrainDef>.GetNamed("Soil")); if (Find.TerrainGrid.TerrainAt(targetCell) == TerrainDef.Named("WaterShallow")) { Find.TerrainGrid.SetTerrain(targetCell, DefDatabase<TerrainDef>.GetNamed("WaterDeep")); var list = new List<Thing>(Find.ThingGrid.ThingsListAtFast(targetCell) .Where(thing => thing.def.category == ThingCategory.Item || thing.def.category == ThingCategory.Pawn)); foreach (var thing in list) { Thing dummy; // despawn thing to spawn again with TryPlaceThing thing.DeSpawn(); if (!GenPlace.TryPlaceThing(thing, thing.Position, ThingPlaceMode.Near, out dummy)) { Log.Error("No free spot for " + thing); } } } // spawn resources var clayRed = ThingMaker.MakeThing(ThingDef.Named("ClumpClayGray")); clayRed.stackCount = Rand.RangeInclusive(25, 75); GenPlace.TryPlaceThing(clayRed, targetCell, ThingPlaceMode.Near); // Rand.Value = Rand.Range(0, 1) if (Rand.Value < RareResourceSpawnChance) { var clayWhite = ThingMaker.MakeThing(ThingDef.Named("ClumpClayWhite")); clayWhite.stackCount = Rand.RangeInclusive(5, 10); GenPlace.TryPlaceThing(clayWhite, targetCell, ThingPlaceMode.Near); } ReadyForNextToil(); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.FailOnCellMissingDesignation(CellInd, DefDatabase<DesignationDef>.GetNamed("CollectClay")); toil.WithEffect(() => EffecterDef.Named("CutStone"), CellInd); toil.PlaySustainerOrSound(() => DefDatabase<SoundDef>.GetNamedSilentFail("Recipe_Surgery")); toil.WithProgressBar(CellInd, () => 1f - (float) pawn.jobs.curDriver.ticksLeftThisToil/totalWork); return toil; }
static IEnumerable <Toil> DoMakeToils(JobDriver_DoBill_Access __instance) { //normal scenario __instance.AddEndCondition(delegate { Thing thing = __instance.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; if (thing is Building && !thing.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); __instance.FailOnBurningImmobile(TargetIndex.A); __instance.FailOn(delegate() { if (__instance.job.GetTarget(TargetIndex.A).Thing is Filth) { return(false); } IBillGiver billGiver = __instance.job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (__instance.job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); yield return(new Toil { initAction = delegate() { if (__instance.job.targetQueueB != null && __instance.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = __instance.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)__instance.job.bill; } } } }); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.B).NullOrEmpty())); //hauling patch if (Settings.adv_haul_all_ings && __instance.pawn.Faction == Faction.OfPlayer) { Toil checklist = new Toil(); checklist.initAction = delegate() { Pawn actor = checklist.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); if (targetQueue.NullOrEmpty()) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { foreach (var target in (targetQueue)) { if (target == null || target.Thing.DestroyedOrNull()) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); break; } } } }; yield return(checklist); Toil extract = new Toil(); extract.initAction = delegate() { Pawn actor = extract.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); if (!curJob.countQueue.NullOrEmpty()) { if (curJob.countQueue[0] > targetQueue[0].Thing.stackCount) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { curJob.SetTarget(TargetIndex.B, targetQueue[0]); targetQueue.RemoveAt(0); curJob.count = curJob.countQueue[0]; curJob.countQueue.RemoveAt(0); } } }; Toil PickUpThing; List <LocalTargetInfo> L = __instance.job.GetTargetQueue(TargetIndex.B); if (L.Count < 2 && (L.Count == 0 || L[0].Thing.def.stackLimit < 2)) { PickUpThing = Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true); } else { PickUpThing = new Toil(); PickUpThing.initAction = delegate() { Pawn actor = PickUpThing.actor; Job curJob = actor.jobs.curJob; Thing thing = curJob.GetTarget(TargetIndex.B).Thing; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); bool InventorySpawned = thing.ParentHolder == actor.inventory; if (InventorySpawned || !Toils_Haul.ErrorCheckForCarry(actor, thing)) { if (thing.stackCount < curJob.count) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { Thing splitThing = thing.SplitOff(curJob.count); if (splitThing.ParentHolder != actor.inventory && !actor.inventory.GetDirectlyHeldThings().TryAdd(splitThing, false)) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } if (!splitThing.Destroyed && splitThing.stackCount != 0) { targetQueue.Add(splitThing); if (!InventorySpawned) { CompUnloadChecker CUC = splitThing.TryGetComp <CompUnloadChecker>(); if (CUC != null) { CUC.ShouldUnload = true; } } } if (splitThing != thing && actor.Map.reservationManager.ReservedBy(thing, actor, curJob)) { actor.Map.reservationManager.Release(thing, actor, curJob); } } } }; } Toil TakeToHands = new Toil(); TakeToHands.initAction = delegate() { Pawn actor = TakeToHands.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); if (!targetQueue.NullOrEmpty() && targetQueue[0].Thing.ParentHolder != actor.carryTracker) { actor.inventory.innerContainer.TryTransferToContainer(targetQueue[0].Thing, actor.carryTracker.innerContainer); actor.Reserve(targetQueue[0], curJob); curJob.SetTarget(TargetIndex.B, targetQueue[0]); targetQueue.RemoveAt(0); } }; yield return(extract); Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(Toils_Jump.JumpIf(PickUpThing, () => __instance.job.GetTarget(TargetIndex.B).Thing.ParentHolder == __instance.pawn.inventory)); yield return(getToHaulTarget); yield return(PickUpThing); yield return(Toils_Jump.JumpIf(extract, () => !__instance.job.countQueue.NullOrEmpty())); yield return(TakeToHands); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B)); Toil findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); yield return(findPlaceTarget); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget, false)); yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, TakeToHands)); } else { Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true); yield return(extract); Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(getToHaulTarget); yield return(Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true)); yield return(JobDriver_DoBill_Access.JumpToCollectNextIntoHandsForBillCrutch(getToHaulTarget, TargetIndex.B)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B)); Toil findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); yield return(findPlaceTarget); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget, false)); yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, extract)); } yield return(gotoBillGiver); //one line from normal scenario //cleaning patch if (Settings.adv_cleaning && !Utility.IncapableOfCleaning(__instance.pawn)) { Toil returnToBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); Toil FilthList = new Toil(); FilthList.initAction = delegate() { Job curJob = FilthList.actor.jobs.curJob; if (curJob.GetTargetQueue(TargetIndex.A).NullOrEmpty()) { LocalTargetInfo A = curJob.GetTarget(TargetIndex.A); DoCleanComp comp; if (!Settings.clean_gizmo || (comp = A.Thing?.TryGetComp <DoCleanComp>()) == null || comp.Active) { IEnumerable <Filth> l = Utility.SelectAllFilth(FilthList.actor, A, Settings.adv_clean_num); Utility.AddFilthToQueue(curJob, TargetIndex.A, l, FilthList.actor); FilthList.actor.ReserveAsManyAsPossible(curJob.GetTargetQueue(TargetIndex.A), curJob); } curJob.targetQueueA.Add(A); } }; yield return(FilthList); yield return(Toils_Jump.JumpIf(returnToBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.A).NullOrEmpty())); Toil CleanFilthList = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, null); yield return(CleanFilthList); yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A, true)); yield return(Toils_Jump.JumpIf(returnToBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.A).NullOrEmpty())); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, CleanFilthList).JumpIfOutsideHomeArea(TargetIndex.A, CleanFilthList)); Toil clean = new Toil(); clean.initAction = delegate() { Filth filth = clean.actor.jobs.curJob.GetTarget(TargetIndex.A).Thing as Filth; __instance.billStartTick = 0; __instance.ticksSpentDoingRecipeWork = 0; __instance.workLeft = filth.def.filth.cleaningWorkToReduceThickness * filth.thickness; }; clean.tickAction = delegate() { Filth filth = clean.actor.jobs.curJob.GetTarget(TargetIndex.A).Thing as Filth; __instance.billStartTick += 1; __instance.ticksSpentDoingRecipeWork += 1; if (__instance.billStartTick > filth.def.filth.cleaningWorkToReduceThickness) { filth.ThinFilth(); __instance.billStartTick = 0; if (filth.Destroyed) { clean.actor.records.Increment(RecordDefOf.MessesCleaned); __instance.ReadyForNextToil(); return; } } }; clean.defaultCompleteMode = ToilCompleteMode.Never; clean.WithEffect(EffecterDefOf.Clean, TargetIndex.A); clean.WithProgressBar(TargetIndex.A, () => __instance.ticksSpentDoingRecipeWork / __instance.workLeft, true, -0.5f); clean.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); clean.JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, CleanFilthList); clean.JumpIfOutsideHomeArea(TargetIndex.A, CleanFilthList); yield return(clean); yield return(Toils_Jump.Jump(CleanFilthList)); yield return(returnToBillGiver); } //continuation of normal scenario yield return(Toils_Recipe.MakeUnfinishedThingIfNeeded()); yield return(Toils_Recipe.DoRecipeWork().FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell)); yield return(Toils_Recipe.FinishRecipeAndStartStoringProduct()); if (!__instance.job.RecipeDef.products.NullOrEmpty() || !__instance.job.RecipeDef.specialProducts.NullOrEmpty()) { yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); Toil recount = new Toil(); recount.initAction = delegate() { Bill_Production bill_Production = recount.actor.jobs.curJob.bill as Bill_Production; if (bill_Production != null && bill_Production.repeatMode == BillRepeatModeDefOf.TargetCount) { __instance.MapCrutch().resourceCounter.UpdateResourceCounts(); } }; yield return(recount); } yield break; }
Toil HarvestSeedsToil() { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Never; toil.tickAction = delegate { var actor = toil.actor; var plant = Plant; if (actor.skills != null) { actor.skills.Learn(SkillDefOf.Growing, xpPerTick, true); } workDone += actor.GetStatValue(StatDefOf.PlantWorkSpeed, true); if (workDone >= plant.def.plant.harvestWork) { if (plant.def.plant.harvestedThingDef != null) { if (actor.RaceProps.Humanlike && plant.def.plant.harvestFailable && Rand.Value > actor.GetStatValue(StatDefOf.PlantHarvestYield, true)) { MoteMaker.ThrowText((actor.DrawPos + plant.DrawPos) / 2f, actor.Map, "TextMote_HarvestFailed".Translate(), 3.65f); } else { int plantYield = plant.YieldNow(); ThingDef harvestedThingDef; var seedDef = plant.def.blueprintDef as SeedDef; if (seedDef != null) { float parameter = Mathf.Min(Mathf.InverseLerp(plant.def.plant.harvestMinGrowth, 0.9f, plant.Growth), 1f); if (seedDef.seed.seedFactor > 0 && Rand.Value < seedDef.seed.baseChance * parameter) { int count; if (Rand.Value < seedDef.seed.extraChance) { count = 2; } else { count = 1; } Thing seeds = ThingMaker.MakeThing(seedDef, null); seeds.stackCount = Mathf.RoundToInt(seedDef.seed.seedFactor * count); GenPlace.TryPlaceThing(seeds, actor.Position, actor.Map, ThingPlaceMode.Near); } plantYield = Mathf.RoundToInt(plantYield * seedDef.seed.harvestFactor); harvestedThingDef = seedDef.harvest; } else { harvestedThingDef = plant.def.plant.harvestedThingDef; } if (plantYield > 0) { var thing = ThingMaker.MakeThing(harvestedThingDef, null); thing.stackCount = plantYield; if (actor.Faction != Faction.OfPlayer) { thing.SetForbidden(true, true); } GenPlace.TryPlaceThing(thing, actor.Position, actor.Map, ThingPlaceMode.Near, null); actor.records.Increment(RecordDefOf.PlantsHarvested); } } } plant.def.plant.soundHarvestFinish.PlayOneShot(actor); plant.PlantCollected(); workDone = 0; ReadyForNextToil(); return; } }; toil.FailOnDespawnedNullOrForbidden(TargetIndex.A); toil.WithEffect(EffecterDefOf.Harvest, TargetIndex.A); toil.WithProgressBar(TargetIndex.A, () => workDone / Plant.def.plant.harvestWork, true, -0.5f); toil.PlaySustainerOrSound(() => Plant.def.plant.soundHarvesting); return(toil); }
Toil SowSeedToil() { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Never; toil.initAction = delegate { var actor = toil.actor; if (IsActorCarryingAppropriateSeed(actor, job.plantDefToSow)) { var plant = (Plant)GenSpawn.Spawn(job.plantDefToSow, TargetLocA, actor.Map); plant.Growth = 0; plant.sown = true; job.targetC = plant; actor.Reserve(job.targetC, job, 1); sowWorkDone = 0; } else { EndJobWith(JobCondition.Incompletable); } }; toil.tickAction = delegate { var actor = toil.actor; var plant = (Plant)job.targetC.Thing; if (actor.skills != null) { actor.skills.Learn(SkillDefOf.Plants, 0.22f); } if (plant.LifeStage != PlantLifeStage.Sowing) { Log.Error(this + " getting sowing work while not in Sowing life stage.", false); } sowWorkDone += StatExtension.GetStatValue(actor, StatDefOf.PlantWorkSpeed, true); if (sowWorkDone >= plant.def.plant.sowWork) { if (!IsActorCarryingAppropriateSeed(actor, job.plantDefToSow)) { EndJobWith(JobCondition.Incompletable); return; } if (actor.carryTracker.CarriedThing.stackCount <= 1) { actor.carryTracker.CarriedThing.Destroy(DestroyMode.Cancel); } else { actor.carryTracker.CarriedThing.stackCount--; } plant.Growth = 0.05f; plant.Map.mapDrawer.MapMeshDirty(plant.Position, MapMeshFlag.Things); actor.records.Increment(RecordDefOf.PlantsSown); ReadyForNextToil(); } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.FailOnDespawnedNullOrForbidden(TargetIndex.A); toil.WithEffect(EffecterDefOf.Sow, TargetIndex.A); toil.WithProgressBar(TargetIndex.A, () => sowWorkDone / job.plantDefToSow.plant.sowWork, true, -0.5f); toil.PlaySustainerOrSound(() => SoundDefOf.Interact_Sow); toil.AddFinishAction(delegate { var actor = toil.actor; var thing = job.targetC.Thing; if (thing != null) { var plant = (Plant)thing; if (sowWorkDone < plant.def.plant.sowWork && !thing.Destroyed) { thing.Destroy(DestroyMode.Vanish); } actor.Map.reservationManager.Release(job.targetC, actor, job); job.targetC = null; } }); return(toil); }
protected Toil Train(Thing currentWeapon) { Toil train = new Toil(); train.initAction = delegate() { Pawn actor = train.actor; Job curJob = actor.jobs.curJob; ThingDef weapon = practice ? currentWeapon.def : job.targetB.Thing.def; workLeft = curJob.bill.recipe.WorkAmountTotal(null); billStartTick = Find.TickManager.TicksGame; ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); Verb verbToUse = actor.TryGetAttackVerb(currentWeapon, true); LocalTargetInfo target = actor.jobs.curJob.GetTarget(TargetIndex.A); pawn.stances.SetStance(new Stance_Cooldown(2, target, verbToUse)); }; train.tickAction = delegate() { Pawn actor = train.actor; Job curJob = actor.jobs.curJob; ThingDef weapon = practice ? currentWeapon.def : job.targetB.Thing.def; ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction = train.actor.CurJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; if (billGiverWithTickAction != null) { billGiverWithTickAction.UsedThisTick(); } float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; if (curJob.RecipeDef.workTableSpeedStat != null) { Building_WorkTable building_WorkTable = BillGiver as Building_WorkTable; if (building_WorkTable != null) { num *= building_WorkTable.GetStatValue(curJob.RecipeDef.workTableSpeedStat, true); } } if (DebugSettings.fastCrafting) { num *= 30f; } workLeft -= num; actor.GainComfortFromCellIfPossible(); if (workLeft <= 0f) { ReadyForNextToil(); } LearningUtility.WeaponTrainingAnimation(pawn, pawn.jobs.curJob.GetTarget(TargetIndex.A), actor.TryGetAttackVerb(currentWeapon, true), ticksSpentDoingRecipeWork); if (job.RecipeDef.workSkill != null) { float xpDelta = practice ? 0.5f : 0.1f; float xp = xpDelta * job.RecipeDef.workSkillLearnFactor; actor.skills.GetSkill(job.RecipeDef.workSkill).Learn(xp, false); } }; train.defaultCompleteMode = ToilCompleteMode.Never; train.WithEffect(() => train.actor.CurJob.bill.recipe.effectWorking, TargetIndex.A); train.PlaySustainerOrSound(() => train.actor.CurJob.bill.recipe.soundWorking); train.WithProgressBar(TargetIndex.A, delegate { Pawn actor = train.actor; Job curJob = actor.CurJob; return(1f - (workLeft / curJob.bill.recipe.WorkAmountTotal(null))); }, false, -0.5f); train.FailOn(() => train.actor.CurJob.bill.suspended); train.activeSkill = () => train.actor.CurJob.bill.recipe.workSkill; return(train); }
protected override Toil DoBill() { Pawn actor = GetActor(); Job curJob = actor.jobs.curJob; Thing objectThing = curJob.GetTarget(objectTI).Thing; Building_WorkTable tableThing = curJob.GetTarget(tableTI).Thing as Building_WorkTable; Toil toil = new Toil(); toil.initAction = delegate { curJob.bill.Notify_DoBillStarted(); this.failChance = ChanceDef.GetFor(objectThing); this.workCycleProgress = this.workCycle = Math.Max(curJob.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { if (objectThing == null || objectThing.Destroyed) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress -= StatExtension.GetStatValue(actor, StatDefOf.WorkToMake, true); if (!tableThing.UsableNow) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } if (workCycleProgress <= 0) { int remainingHitPoints = objectThing.MaxHitPoints - objectThing.HitPoints; if (remainingHitPoints > 0) { objectThing.HitPoints += (int)Math.Min(remainingHitPoints, fixedHitPointsPerCycle); } SkillRecord skill = actor.skills.GetSkill(SkillDefOf.Crafting); if (skill == null) { Log.Error("Mending :: This should never happen! skill == null"); actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } float skillPerc = (float)skill.Level / 20f; skill.Learn(0.33f); CompQuality qualityComponent = objectThing.TryGetComp <CompQuality>(); if (qualityComponent != null && qualityComponent.Quality > QualityCategory.Awful) { QualityCategory qc = qualityComponent.Quality; float skillFactor = Mathf.Lerp(1.5f, 0f, skillPerc); if (failChance != null && Rand.Value < failChance.Chance(qc) * skillFactor) { objectThing.HitPoints -= fixedFailedDamage; MoteMaker.ThrowText(actor.DrawPos, actor.Map, "Failed"); } } actor.GainComfortFromCellIfPossible(); if (objectThing.HitPoints <= 0) { // recycling whats left... float skillFactor = Mathf.Lerp(0.5f, 1.5f, skillPerc); var list = JobDriverUtils.Reclaim(objectThing, skillFactor * 0.1f); pawn.Map.reservationManager.Release(curJob.targetB, pawn); objectThing.Destroy(DestroyMode.Vanish); if (list.Count > 1) { for (int j = 1; j < list.Count; j++) { if (!GenPlace.TryPlaceThing(list [j], actor.Position, actor.Map, ThingPlaceMode.Near, null)) { Log.Error("Mending :: " + actor + " could not drop recipe product " + list [j] + " near " + actor.Position); } } } list[0].SetPositionDirect(actor.Position); curJob.targetB = list[0]; curJob.bill.Notify_IterationCompleted(actor, list); pawn.Map.reservationManager.Reserve(pawn, curJob.targetB, 1); ReadyForNextToil(); } else if (objectThing.HitPoints == objectThing.MaxHitPoints) { // fixed! Apparel mendApparel = objectThing as Apparel; if (mendApparel != null) { ApparelWornByCorpseInt.SetValue(mendApparel, false); } List <Thing> list = new List <Thing> (); list.Add(objectThing); curJob.bill.Notify_IterationCompleted(actor, list); ReadyForNextToil(); } else if (objectThing.HitPoints > objectThing.MaxHitPoints) { Log.Error("Mending :: This should never happen! HitPoints > MaxHitPoints"); actor.jobs.EndCurrentJob(JobCondition.Incompletable); } workCycleProgress = workCycle; } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => curJob.bill.recipe.effectWorking, tableTI); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(tableTI, delegate { return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { IBillGiver billGiver = curJob.GetTarget(tableTI).Thing as IBillGiver; return(curJob.bill.suspended || curJob.bill.DeletedOrDereferenced || (billGiver != null && !billGiver.CurrentlyUsable())); }); return(toil); }
// Token: 0x060000EE RID: 238 RVA: 0x00008574 File Offset: 0x00006774 public static void DoRecipeWork_Prefix(ref Toil __result) { Toil toil = new Toil(); toil.initAction = delegate() { Log.Message("init delegated.", false); Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; bool animal = actor.RaceProps.Animal; if (animal) { Log.Message("I am in.", false); JobDriver curDriver = actor.jobs.curDriver; JobDriver_WPDoBill jobDriver_WPDoBill = curDriver as JobDriver_WPDoBill; UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; jobDriver_WPDoBill.workLeft = curJob.bill.recipe.WorkAmountTotal(unfinishedThing.def); bool flag = unfinishedThing != null; if (flag) { unfinishedThing.workLeft = jobDriver_WPDoBill.workLeft; } jobDriver_WPDoBill.billStartTick = Find.TickManager.TicksGame; jobDriver_WPDoBill.ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); } else { Log.Message("I am here instead.", false); JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; UnfinishedThing unfinishedThing2 = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; bool flag2 = unfinishedThing2 != null && unfinishedThing2.Initialized; if (flag2) { jobDriver_DoBill.workLeft = unfinishedThing2.workLeft; } else { jobDriver_DoBill.workLeft = curJob.bill.recipe.WorkAmountTotal((unfinishedThing2 == null) ? null : unfinishedThing2.Stuff); bool flag3 = unfinishedThing2 != null; if (flag3) { unfinishedThing2.workLeft = jobDriver_DoBill.workLeft; } } jobDriver_DoBill.billStartTick = Find.TickManager.TicksGame; jobDriver_DoBill.ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); } }; toil.tickAction = delegate() { Log.Message("tick delegated.", false); Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver curDriver = actor.jobs.curDriver; bool animal = actor.RaceProps.Animal; if (animal) { JobDriver_WPDoBill jobDriver_WPDoBill = curDriver as JobDriver_WPDoBill; UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; bool flag = unfinishedThing != null && unfinishedThing.Destroyed; if (flag) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true, true); return; } jobDriver_WPDoBill.ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction = toil.actor.CurJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; bool flag2 = billGiverWithTickAction != null; if (flag2) { billGiverWithTickAction.UsedThisTick(); } float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; Building_WorkTable building_WorkTable = jobDriver_WPDoBill.BillGiver as Building_WorkTable; bool flag3 = building_WorkTable != null; if (flag3) { num *= building_WorkTable.GetStatValue(StatDefOf.WorkTableWorkSpeedFactor, true); } bool fastCrafting = DebugSettings.fastCrafting; if (fastCrafting) { num *= 30f; } jobDriver_WPDoBill.workLeft -= num; bool flag4 = unfinishedThing != null; if (flag4) { unfinishedThing.workLeft = jobDriver_WPDoBill.workLeft; } actor.GainComfortFromCellIfPossible(false); bool flag5 = jobDriver_WPDoBill.workLeft <= 0f; if (flag5) { jobDriver_WPDoBill.ReadyForNextToil(); } bool usesUnfinishedThing = curJob.bill.recipe.UsesUnfinishedThing; if (usesUnfinishedThing) { int num2 = Find.TickManager.TicksGame - jobDriver_WPDoBill.billStartTick; bool flag6 = num2 >= 3000 && num2 % 1000 == 0; if (flag6) { actor.jobs.CheckForJobOverride(); } } } bool flag7 = !actor.RaceProps.Animal; if (flag7) { JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; UnfinishedThing unfinishedThing2 = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; bool flag8 = unfinishedThing2 != null && unfinishedThing2.Destroyed; if (flag8) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true, true); } else { jobDriver_DoBill.ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction2 = toil.actor.CurJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; bool flag9 = billGiverWithTickAction2 != null; if (flag9) { billGiverWithTickAction2.UsedThisTick(); } bool flag10 = curJob.RecipeDef.workSkill != null && curJob.RecipeDef.UsesUnfinishedThing; if (flag10) { actor.skills.GetSkill(curJob.RecipeDef.workSkill).Learn(0.11f * curJob.RecipeDef.workSkillLearnFactor, false); } float num3 = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; Building_WorkTable building_WorkTable2 = jobDriver_DoBill.BillGiver as Building_WorkTable; bool flag11 = building_WorkTable2 != null; if (flag11) { num3 *= building_WorkTable2.GetStatValue(StatDefOf.WorkTableWorkSpeedFactor, true); } bool fastCrafting2 = DebugSettings.fastCrafting; if (fastCrafting2) { num3 *= 30f; } jobDriver_DoBill.workLeft -= num3; bool flag12 = unfinishedThing2 != null; if (flag12) { unfinishedThing2.workLeft = jobDriver_DoBill.workLeft; } actor.GainComfortFromCellIfPossible(false); bool flag13 = jobDriver_DoBill.workLeft <= 0f; if (flag13) { jobDriver_DoBill.ReadyForNextToil(); } bool usesUnfinishedThing2 = curJob.bill.recipe.UsesUnfinishedThing; if (usesUnfinishedThing2) { int num4 = Find.TickManager.TicksGame - jobDriver_DoBill.billStartTick; bool flag14 = num4 >= 3000 && num4 % 1000 == 0; if (flag14) { actor.jobs.CheckForJobOverride(); } } } } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => toil.actor.CurJob.bill.recipe.effectWorking, TargetIndex.A); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(TargetIndex.A, delegate { Pawn actor = toil.actor; Job curJob = actor.CurJob; UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; bool animal = actor.RaceProps.Animal; float result; if (animal) { result = 1f - ((JobDriver_WPDoBill)actor.jobs.curDriver).workLeft / curJob.bill.recipe.WorkAmountTotal((unfinishedThing == null) ? null : unfinishedThing.Stuff); } else { result = 1f - ((JobDriver_DoBill)actor.jobs.curDriver).workLeft / curJob.bill.recipe.WorkAmountTotal((unfinishedThing == null) ? null : unfinishedThing.Stuff); } return(result); }, false, -0.5f); toil.FailOn(() => toil.actor.CurJob.bill.suspended); __result = toil; }
protected override IEnumerable <Toil> MakeNewToils() { // ツールまで移動 yield return(Toils_Goto.GotoThing(ToolInd, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(ToolInd)); // ツールを手に取る yield return(Toils_Haul.StartCarryThing(ToolInd)); // ターゲットが水やり対象として不適になっていたらリストから外す Toil initExtractTargetFromQueue = Toils_Mizu.ClearConditionSatisfiedTargets(WateringInd, (lti) => { var mapComp = this.Map.GetComponent <MapComponent_Watering>(); return(mapComp.Get(this.Map.cellIndices.CellToIndex(lti.Cell)) > 0); }); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(WateringInd)); // ターゲットキューから次のターゲットを取り出す yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(WateringInd, true)); // ターゲットの元へ移動 yield return(Toils_Goto.GotoCell(WateringInd, PathEndMode.Touch)); // 作業中 Toil workToil = new Toil(); workToil.initAction = delegate { // 必要工数の計算 this.ticksLeftThisToil = WorkingTicks; }; // 細々とした設定 workToil.defaultCompleteMode = ToilCompleteMode.Delay; workToil.WithProgressBar(WateringInd, () => 1f - (float)this.ticksLeftThisToil / WorkingTicks, true, -0.5f); workToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); yield return(workToil); // 作業終了 var finishToil = new Toil(); finishToil.initAction = () => { // 水やり更新 var mapComp = this.Map.GetComponent <MapComponent_Watering>(); mapComp.Set(this.Map.cellIndices.CellToIndex(WateringPos), MapComponent_Watering.MaxWateringValue); this.Map.mapDrawer.SectionAt(WateringPos).dirtyFlags = MapMeshFlag.Terrain; // ツールから水を減らす var compTool = Tool.GetComp <CompWaterTool>(); compTool.StoredWaterVolume -= ConsumeWaterVolume; }; finishToil.defaultCompleteMode = ToilCompleteMode.Instant; yield return(finishToil); // 最初に戻る yield return(Toils_Jump.JumpIf(initExtractTargetFromQueue, () => { return this.pawn.jobs.curJob.GetTargetQueue(WateringInd).Count > 0; })); // ツールを片付ける場所を決める yield return(Toils_Mizu.TryFindStoreCell(ToolInd, ToolPlaceInd)); // 倉庫まで移動 yield return(Toils_Goto.GotoCell(ToolPlaceInd, PathEndMode.Touch)); // 倉庫に置く yield return(Toils_Haul.PlaceHauledThingInCell(ToolPlaceInd, null, true)); }
protected override IEnumerable <Toil> MakeNewToils() { //Commence fail checks! this.FailOnDestroyedOrNull(TargetIndex.A); yield return(Toils_Reserve.Reserve(AltarIndex, 1)); yield return(new Toil { initAction = delegate { this.DropAltar.IsFilling = true; this.customString = "FillChthonianPitGoing".Translate(); } }); yield return(Toils_Goto.GotoThing(AltarIndex, PathEndMode.Touch)); Toil chantingTime = new Toil() { defaultCompleteMode = ToilCompleteMode.Delay, defaultDuration = 5000 }; chantingTime.WithProgressBarToilDelay(AltarIndex, false, -0.5f); chantingTime.PlaySustainerOrSound(() => SoundDefOf.Interact_ClearSnow); chantingTime.initAction = delegate { this.customString = "FillChthonianPitFilling".Translate(); }; chantingTime.AddPreTickAction(() => { if (this.DropAltar.IsActive) { if (Rand.Range(1, 100) > 95) { this.DropAltar.TrySpawnChthonian(); } } if (this.DropAltar.GaveSacrifice) { if (this.pawn.IsHashIntervalTick(300)) { if (Rand.Range(1, 100) > 60) { Messages.Message("CriesFromBelow".Translate(new object[] { this.pawn.LabelShort, this.pawn.gender.GetPronoun() }), MessageTypeDefOf.NegativeEvent); } } } }); yield return(chantingTime); yield return(new Toil { initAction = delegate { this.customString = "FillChthonianPitFinished".Translate(); IntVec3 position = this.DropAltar.Position; FillingCompleted(); }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(Toils_Reserve.Release(TargetIndex.A)); //Toil 9: Think about that. yield return(new Toil { initAction = delegate { ////It's a day to remember //TaleDef taleToAdd = TaleDef.Named("HeldSermon"); //if ((this.pawn.IsColonist || this.pawn.HostFaction == Faction.OfPlayer) && taleToAdd != null) //{ // TaleRecorder.RecordTale(taleToAdd, new object[] // { // this.pawn, // }); //} }, defaultCompleteMode = ToilCompleteMode.Instant }); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { // モップまで移動 yield return(Toils_Goto.GotoThing(MopInd, PathEndMode.Touch).FailOnDespawnedNullOrForbidden(MopInd)); // モップを手に取る yield return(Toils_Haul.StartCarryThing(MopInd)); // ターゲットが掃除対象として不適になっていたらリストから外す // Thing系にしか使えない var initExtractTargetFromQueue = Toils_Mizu.ClearConditionSatisfiedTargets( MoppingInd, lti => lti.Cell.GetFirstThing(pawn.Map, MizuDef.Thing_MoppedThing) != null); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(MoppingInd)); // ターゲットキューから次のターゲットを取り出す yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(MoppingInd)); // ターゲットの元へ移動 yield return(Toils_Goto.GotoCell(MoppingInd, PathEndMode.Touch).JumpIf( () => { var target = pawn.jobs.curJob.GetTarget(MoppingInd); if (target.HasThing) { return true; } return target.Cell.GetFirstThing(pawn.Map, MizuDef.Thing_MoppedThing) != null; }, initExtractTargetFromQueue).JumpIfOutsideMopArea(MoppingInd, initExtractTargetFromQueue)); // モップ掛け作業中 var mopToil = new Toil { initAction = delegate { // 必要工数の計算 ticksLeftThisToil = MoppingTicks; }, // 細々とした設定 defaultCompleteMode = ToilCompleteMode.Delay }; mopToil.WithProgressBar(MoppingInd, () => 1f - ((float)ticksLeftThisToil / MoppingTicks), true); mopToil.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); // 掃除中に条件が変更されたら最初に戻る mopToil.JumpIf( () => { var target = pawn.jobs.curJob.GetTarget(MoppingInd); if (target.HasThing) { return(true); } return(target.Cell.GetFirstThing(pawn.Map, MizuDef.Thing_MoppedThing) != null); }, initExtractTargetFromQueue); mopToil.JumpIfOutsideMopArea(MoppingInd, initExtractTargetFromQueue); yield return(mopToil); // モップ掛け終了 var finishToil = new Toil { initAction = () => { // モップオブジェクト生成 var moppedThing = ThingMaker.MakeThing(MizuDef.Thing_MoppedThing); GenSpawn.Spawn(moppedThing, MoppingPos, mopToil.actor.Map); // モップから水を減らす var compTool = Mop.GetComp <CompWaterTool>(); compTool.StoredWaterVolume -= ConsumeWaterVolume; }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(finishToil); // 最初に戻る yield return(Toils_Jump.JumpIf( initExtractTargetFromQueue, () => pawn.jobs.curJob.GetTargetQueue(MoppingInd).Count > 0)); // モップを片付ける場所を決める yield return(Toils_Mizu.TryFindStoreCell(MopInd, MopPlaceInd)); // Toil startCarryToil = new Toil(); // startCarryToil.initAction = () => // { // var actor = startCarryToil.actor; // var curJob = actor.jobs.curJob; // IntVec3 c; // if (StoreUtility.TryFindBestBetterStoreCellFor(Mop, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out c)) // { // curJob.targetC = c; // curJob.count = 99999; // return; // } // }; // startCarryToil.defaultCompleteMode = ToilCompleteMode.Instant; // yield return startCarryToil; // 倉庫まで移動 yield return(Toils_Goto.GotoCell(MopPlaceInd, PathEndMode.Touch)); // 倉庫に置く yield return(Toils_Haul.PlaceHauledThingInCell(MopPlaceInd, null, true)); }
protected override IEnumerable <Toil> MakeNewToils() { Bill bill = job.bill; AddEndCondition(delegate { Thing thing = GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; if (thing is Building && !thing.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); this.FailOnBurningImmobile(TargetIndex.A); this.FailOn(delegate() { IBillGiver billGiver = job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); AddFinishAction(delegate() { //Log.Message("LearnWeapon: finishing"); ThingWithComps thingWithComps = (ThingWithComps)job.targetB.Thing; if (pawn.equipment.Primary != null) { pawn.equipment.TryDropEquipment(thingWithComps, out thingWithComps, pawn.Position, false); } }); Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => job.GetTargetQueue(TargetIndex.B).NullOrEmpty <LocalTargetInfo>())); Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true); yield return(extract); Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(getToHaulTarget); //temporary equip yield return(new Toil { initAction = delegate() { ThingWithComps thingWithComps = (ThingWithComps)job.targetB.Thing; ThingWithComps thingWithComps2; if (thingWithComps.def.stackLimit > 1 && thingWithComps.stackCount > 1) { thingWithComps2 = (ThingWithComps)thingWithComps.SplitOff(1); } else { thingWithComps2 = thingWithComps; thingWithComps2.DeSpawn(DestroyMode.Vanish); } pawn.equipment.MakeRoomFor(thingWithComps2); pawn.equipment.AddEquipment(thingWithComps2); if (thingWithComps.def.soundInteract != null) { thingWithComps.def.soundInteract.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false)); } }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, extract)); yield return(gotoBillGiver); yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A)); Toil train = new Toil(); train.initAction = delegate() { Pawn actor = train.actor; Job curJob = actor.jobs.curJob; ThingDef weapon = job.targetB.Thing.def; workLeft = curJob.bill.recipe.WorkAmountTotal(null); billStartTick = Find.TickManager.TicksGame; ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); //sound: if (weapon.soundInteract != null) { weapon.soundInteract.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false)); } }; train.tickAction = delegate() { Pawn actor = train.actor; Job curJob = actor.jobs.curJob; ThingDef weapon = job.targetB.Thing.def; ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction = train.actor.CurJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; if (billGiverWithTickAction != null) { billGiverWithTickAction.UsedThisTick(); } float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; if (curJob.RecipeDef.workTableSpeedStat != null) { Building_WorkTable building_WorkTable = BillGiver as Building_WorkTable; if (building_WorkTable != null) { num *= building_WorkTable.GetStatValue(curJob.RecipeDef.workTableSpeedStat, true); } } if (DebugSettings.fastCrafting) { num *= 30f; } workLeft -= num; actor.GainComfortFromCellIfPossible(); if (workLeft <= 0f) { ReadyForNextToil(); } //pawn posture Verb verbToUse = actor.jobs.curJob.verbToUse; LocalTargetInfo target = actor.jobs.curJob.GetTarget(TargetIndex.A); pawn.stances.SetStance(new Stance_Warmup(1, target, verbToUse)); //sound: if (verbToUse.verbProps != null && verbToUse.verbProps.warmupTime > 0) { if ((ticksSpentDoingRecipeWork % verbToUse.verbProps.AdjustedFullCycleTime(verbToUse, actor).SecondsToTicks()) == 0) { if (verbToUse.verbProps.soundCast != null) { verbToUse.verbProps.soundCast.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false)); } if (verbToUse.verbProps.soundCastTail != null) { verbToUse.verbProps.soundCastTail.PlayOneShotOnCamera(pawn.Map); } } } if (job.RecipeDef.workSkill != null) { //float xpDelta = techComp.proficientWeapons.Contains(job.targetB.Thing.def) ? 1f : 0.1f; float xp = 0.1f * job.RecipeDef.workSkillLearnFactor; actor.skills.GetSkill(job.RecipeDef.workSkill).Learn(xp, false); } }; train.defaultCompleteMode = ToilCompleteMode.Never; train.WithEffect(() => train.actor.CurJob.bill.recipe.effectWorking, TargetIndex.A); train.PlaySustainerOrSound(() => train.actor.CurJob.bill.recipe.soundWorking); train.WithProgressBar(TargetIndex.A, delegate { Pawn actor = train.actor; Job curJob = actor.CurJob; //return 1f - ((JobDriver_DoBill)actor.jobs.curDriver).workLeft / curJob.bill.recipe.WorkAmountTotal(null); return(1f - (workLeft / curJob.bill.recipe.WorkAmountTotal(null))); }, false, -0.5f); train.FailOn(() => train.actor.CurJob.bill.suspended); train.activeSkill = () => train.actor.CurJob.bill.recipe.workSkill; yield return(train.FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell)); Toil finalizeTraining = new Toil(); finalizeTraining.initAction = delegate { Pawn actor = finalizeTraining.actor; CompKnowledge techComp = actor.TryGetComp <CompKnowledge>(); if (!techComp.proficientWeapons.Contains(job.targetB.Thing.def)) { techComp.proficientWeapons.Add(TargetThingB.def); } job.bill.Notify_IterationCompleted(actor, new List <Thing> { }); actor.jobs.EndCurrentJob(JobCondition.Succeeded, false); }; finalizeTraining.defaultCompleteMode = ToilCompleteMode.Instant; finalizeTraining.FailOnDespawnedOrNull(TargetIndex.A); yield return(finalizeTraining); //testing yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); Toil findPlaceTarget = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(findPlaceTarget); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, findPlaceTarget, true, true)); yield break; }