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);
        }
Esempio n. 2
0
        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);
        }