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