protected override bool TryCastShot() { CellRect cellRect = CellRect.CenteredOn(this.currentTarget.Cell, 1); Map map = base.CasterPawn.Map; cellRect.ClipInsideMap(map); IntVec3 centerCell = cellRect.CenterCell; Thing summonableThing = new Thing(); //FlyingObject flyingPawn = new FlyingObject(); Pawn summonablePawn = new Pawn(); bool pflag = true; summonableThing = centerCell.GetFirstPawn(map); if (summonableThing == null) { pflag = false; summonableThing = centerCell.GetFirstItem(map); } else { pVect = summonableThing.TrueCenter(); pVect.x = base.caster.TrueCenter().x; pVect.z = base.caster.TrueCenter().z; pVect.y = 0f; summonablePawn = summonableThing as Pawn; if (summonablePawn != base.CasterPawn) { //flyingPawn = (FlyingObject)GenSpawn.Spawn(ThingDef.Named("TM_SummonedPawn"), summonableThing.Position, summonableThing.Map); } else { //flyingPawn = null; summonableThing = null; Messages.Message("TM_CantSummonSelf".Translate(), MessageTypeDefOf.NegativeEvent); } } bool result = false; bool arg_40_0; if (this.currentTarget != null && base.CasterPawn != null) { IntVec3 arg_29_0 = this.currentTarget.Cell; arg_40_0 = this.currentTarget.Cell.IsValid; } else { arg_40_0 = false; } bool flag = arg_40_0; if (flag) { if (summonableThing != null) { if (pflag)// && flyingPawn != null) { //Thing p = summonablePawn; if (!summonablePawn.RaceProps.Humanlike || summonablePawn.Faction == this.CasterPawn.Faction) { summonablePawn.DeSpawn(); GenSpawn.Spawn(summonablePawn, base.CasterPawn.Position, map); } else if (summonablePawn.RaceProps.Humanlike && summonablePawn.Faction != this.CasterPawn.Faction && Rand.Chance(TM_Calc.GetSpellSuccessChance(this.CasterPawn, summonablePawn, true))) { //summonablePawn.DeSpawn(); //GenSpawn.Spawn(p, base.caster.Position, base.CasterPawn.Map, Rot4.North, false); //Pawn p = summonablePawn; summonablePawn.DeSpawn(); //p.SetPositionDirect(this.currentTarget.Cell); GenSpawn.Spawn(summonablePawn, base.CasterPawn.Position, map); //flyingPawn = null; //summonablePawn.Position = base.CasterPawn.Position; //p.jobs.StopAll(false); } else { MoteMaker.ThrowText(summonablePawn.DrawPos, summonablePawn.Map, "TM_ResistedSpell".Translate(), -1); } } else { summonableThing.DeSpawn(DestroyMode.Vanish); GenPlace.TryPlaceThing(summonableThing, this.CasterPawn.Position, this.CasterPawn.Map, ThingPlaceMode.Near); //summonableThing.Position = base.CasterPawn.Position; //summonableThing.Rotation = Rot4.North; //summonableThing.SetPositionDirect(base.CasterPawn.InteractionCell); } result = true; } } else { Log.Warning("failed to TryCastShot"); } this.burstShotsLeft = 0; //this.ability.TicksUntilCasting = (int)base.UseAbilityProps.SecondsToRecharge * 60; return(result); }
public static bool TryPlaceThing(ref bool __result, Thing thing, IntVec3 center, Map map, ThingPlaceMode mode, out Thing lastResultingThing, Action <Thing, int> placedAction = null, Predicate <IntVec3> nearPlaceValidator = null, Rot4 rot = default(Rot4)) { if (map == null) { Log.Error("Tried to place thing " + (object)thing + " in a null map."); lastResultingThing = (Thing)null; __result = false; return(false); } if (thing == null) { lastResultingThing = null; __result = false; return(false); } ThingDef def = thing.def; if (def == null) { lastResultingThing = null; __result = false; return(false); } if (def.category == ThingCategory.Filth) { mode = ThingPlaceMode.Direct; } if (mode == ThingPlaceMode.Direct) { return(GenPlace.TryPlaceDirect(thing, center, rot, map, out lastResultingThing, placedAction)); } if (mode != ThingPlaceMode.Near) { throw new InvalidOperationException(); } lastResultingThing = (Thing)null; int stackCount; do { stackCount = thing.stackCount; IntVec3 bestSpot; if (!GenPlace.TryFindPlaceSpotNear(center, rot, map, thing, true, out bestSpot, nearPlaceValidator)) { return(false); } if (GenPlace.TryPlaceDirect(thing, bestSpot, rot, map, out lastResultingThing, placedAction)) { return(true); } }while (thing.stackCount != stackCount); Log.Error("Failed to place " + (object)thing + " at " + (object)center + " in mode " + (object)mode + "."); lastResultingThing = (Thing)null; __result = false; return(false); }
// Always use this if you are placing an item. /// <summary> /// Place a Thing (onto the ground or into a proper receptacle) /// Any time ANY PRF building tries to place an item, this is THE way to do it: /// It checks if the space is clear, it checks for conveyor belts, in checks /// for other storage mods (well, Deep Storage, anyway). It does all the /// things! /// </summary> /// <returns><c>true</c>, if item was placed, <c>false</c> if it could not.</returns> /// <param name="placer">The PRF_Building doing the placing</param> /// <param name="t">Thing to place.</param> /// <param name="cell">Where to place.</param> /// <param name="map">Map.</param> /// <param name="forcePlace">If set to <c>true</c>, forces placing. For when /// you absolutely positively have to put it down.</param> public static bool PRFTryPlaceThing(this IPRF_Building placer, Thing t, IntVec3 cell, Map map, bool forcePlace = false) { // Storage: SlotGroup slotGroup = cell.GetSlotGroup(map); if (slotGroup != null) { Debug.Warning(Debug.Flag.PlaceThing, "Placing " + t + " in slotGroup: " + slotGroup.parent + " at " + cell); if (slotGroup.parent is IPRF_Building) { if (placer.PlaceThingNextBuilding((slotGroup.parent as IPRF_Building), t, cell, map)) { Debug.Message(Debug.Flag.PlaceThing, " which is owned by PRF " + slotGroup.parent); return(true); } if (forcePlace) { goto ForcePlace; } return(false); } if (placer.PlaceThingInSlotGroup(t, slotGroup, cell, map)) { return(true); } if (forcePlace) { goto ForcePlace; } return(false); } Debug.Warning(Debug.Flag.PlaceThing, "Place request: " + placer == null ? "NoPlacer" : placer.ToString() + " is trying to place " + t + " at " + cell); // Search through all items in cell: see if any will absorb // our thing. If we find a PRF_Building, stop looking and // try to pass it on. bool cellIsImpassible = false; foreach (Thing otherThing in map.thingGrid.ThingsListAt(cell)) { if (otherThing.TryAbsorbStack(t, true)) { Debug.Message(Debug.Flag.PlaceThing, " absorbed by " + otherThing); placer.EffectOnPlaceThing(otherThing); // I think? return(true); } if (otherThing.def.passability == Traversability.Impassable) { cellIsImpassible = true; } if (otherThing is IPRF_Building) { if (placer.PlaceThingNextBuilding((otherThing as IPRF_Building), t, cell, map)) { Debug.Message(Debug.Flag.PlaceThing, placer + " gave " + t + " to " + otherThing); placer.EffectOnPlaceThing(t); return(true); } // Continue loop - may be more than 1 PRF_Building here } } // There is no IPRF Building to take this from us if (cellIsImpassible) { Debug.Message(Debug.Flag.PlaceThing, " cell is impassable."); if (forcePlace) { goto ForcePlace; } return(false); } // The cell is not impassible! Try to place: if (CallNoStorageBlockersIn(cell, map, t)) { Debug.Message(Debug.Flag.PlaceThing, " placing directly."); bool wasSpawned = t.Spawned; if (wasSpawned) { t.DeSpawn(); } if (!GenPlace.TryPlaceThing(t, cell, map, ThingPlaceMode.Direct)) { // some of the stack Debug.Message(Debug.Flag.PlaceThing, " some absorbed, still have " + t.stackCount + " left"); // I think this is safe, as it shoudl still have its position? if (wasSpawned) { GenPlace.TryPlaceThing(t, t.Position, map, ThingPlaceMode.Near); } placer.EffectOnPlaceThing(t); if (forcePlace) { goto ForcePlace; } return(false); } placer.EffectOnPlaceThing(t); if (placer.ForbidOnPlacing(t)) { t.SetForbidden(true, false); } return(true); } if (!forcePlace) { return(false); } ForcePlace: Debug.Warning(Debug.Flag.PlaceThing, " Placement is forced!"); if (t.Spawned) { t.DeSpawn(); } GenPlace.TryPlaceThing(t, cell, map, ThingPlaceMode.Near); placer.EffectOnPlaceThing(t); if (placer.ForbidOnPlacing(t)) { t.SetForbidden(true, false); } return(true); }
protected override IEnumerable <Toil> MakeNewToils() { Init(); yield return(Toils_JobTransforms.MoveCurrentTargetIntoQueue(TargetIndex.A)); Toil initExtractTargetFromQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A); 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)); Toil cut = new Toil(); Plant plant = (Plant)Thing; CompHarvestableReagent reagent = Thing.TryGetComp <CompHarvestableReagent>(); cut.tickAction = delegate { Pawn actor = cut.actor; if (actor.skills != null) { actor.skills.Learn(DefDatabase <SkillDef> .GetNamed("Alchemy", true), xpPerTick, false); } float statValue = actor.GetStatValue(DefDatabase <StatDef> .GetNamed("ReagentHarvestingSpeed"), true); float num = statValue; workDone += num; if (!reagent.IsSecondaryHarvest) { if (plant != null) { if (workDone >= plant.def.plant.harvestWork) { if (plant.def.plant.harvestedThingDef != null) { if (actor.RaceProps.Humanlike && plant.def.plant.harvestFailable && Rand.Value > actor.GetStatValue(DefDatabase <StatDef> .GetNamed("ReagentHarvestingYield"), true)) { Vector3 loc = (pawn.DrawPos + plant.DrawPos) / 2f; MoteMaker.ThrowText(loc, Map, "TextMote_ReagentHarvestFailed".Translate(), 3.65f); } else { int num2 = plant.YieldNow(); if (num2 > 0) { Thing harvestedThing = ThingMaker.MakeThing(plant.def.plant.harvestedThingDef, null); harvestedThing.stackCount = num2; if (actor.Faction != Faction.OfPlayer) { harvestedThing.SetForbidden(true, true); } GenPlace.TryPlaceThing(harvestedThing, actor.Position, Map, ThingPlaceMode.Near, null); actor.records.Increment(DefDatabase <RecordDef> .GetNamed("ReagentsHarvested")); } } } plant.def.plant.soundHarvestFinish.PlayOneShot(actor); plant.PlantCollected(); workDone = 0f; ReadyForNextToil(); return; } } // Animal // Inanimate } else { if (workDone >= reagent.HarvestWork) { if (reagent.HarvestedThingDef != null) { if (actor.RaceProps.Humanlike && reagent.HarvestFailable && Rand.Value > actor.GetStatValue(DefDatabase <StatDef> .GetNamed("ReagentHarvestingYield"), true)) { Vector3 loc = (pawn.DrawPos + reagent.parent.DrawPos) / 2f; MoteMaker.ThrowText(loc, Map, "TextMote_ReagentHarvestFailed".Translate(), 3.65f); } else { int num2 = reagent.YieldNow(); if (num2 > 0) { Thing harvestedThing = ThingMaker.MakeThing(reagent.HarvestedThingDef, null); harvestedThing.stackCount = num2; if (actor.Faction != Faction.OfPlayer) { harvestedThing.SetForbidden(true, true); } GenPlace.TryPlaceThing(harvestedThing, actor.Position, Map, ThingPlaceMode.Near, null); actor.records.Increment(DefDatabase <RecordDef> .GetNamed("ReagentsHarvested")); } } } if (plant != null) { plant.def.plant.soundHarvestFinish.PlayOneShot(actor); } reagent.ReagentCollected(actor); workDone = 0f; ReadyForNextToil(); return; } } }; cut.FailOnDespawnedNullOrForbidden(TargetIndex.A); cut.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); cut.defaultCompleteMode = ToilCompleteMode.Never; cut.WithEffect(EffecterDefOf.Harvest, TargetIndex.A); if (!reagent.IsSecondaryHarvest) { if (plant != null) { cut.WithProgressBar(TargetIndex.A, () => workDone / plant.def.plant.harvestWork, true, -0.5f); cut.PlaySustainerOrSound(() => plant.def.plant.soundHarvesting); } // Animals } else { cut.WithProgressBar(TargetIndex.A, () => workDone / reagent.HarvestWork, true, -0.5f); if (plant != null) { cut.PlaySustainerOrSound(() => plant.def.plant.soundHarvesting); } } yield return(cut); Toil workDoneToil = WorkDoneToil(); if (workDoneToil != null) { yield return(workDoneToil); } yield return(Toils_Jump.Jump(initExtractTargetFromQueue)); }
protected virtual void Impact(Thing hitThing) { bool flag = hitThing == null; if (flag) { Pawn pawn; bool flag2 = (pawn = (base.Position.GetThingList(base.Map).FirstOrDefault((Thing x) => x == this.assignedTarget) as Pawn)) != null; if (flag2) { hitThing = pawn; } } bool hasValue = this.impactDamage.HasValue; if (hasValue) { hitThing.TakeDamage(this.impactDamage.Value); } try { SoundDefOf.Ambient_AltitudeWind.sustainFadeoutTime.Equals(30.0f); GenSpawn.Spawn(this.flyingThing, base.Position, base.Map); if (this.flyingThing is Pawn) { Pawn p = this.flyingThing as Pawn; if (p.IsColonist && this.drafted) { p.drafter.Drafted = true; } if (this.earlyImpact) { damageEntities(p, this.impactForce, DamageDefOf.Blunt); damageEntities(p, 2 * this.impactForce, DamageDefOf.Stun); } } else if (flyingThing.def.thingCategories != null && (flyingThing.def.thingCategories.Contains(ThingCategoryDefOf.Chunks) || flyingThing.def.thingCategories.Contains(ThingCategoryDef.Named("StoneChunks")))) { float radius = 4f; Vector3 center = this.ExactPosition; if (this.earlyImpact) { bool wallFlag90neg = false; IntVec3 wallCheck = (center + (Quaternion.AngleAxis(-90, Vector3.up) * this.direction)).ToIntVec3(); MoteMaker.ThrowMicroSparks(wallCheck.ToVector3Shifted(), base.Map); wallFlag90neg = wallCheck.Walkable(base.Map); wallCheck = (center + (Quaternion.AngleAxis(90, Vector3.up) * this.direction)).ToIntVec3(); MoteMaker.ThrowMicroSparks(wallCheck.ToVector3Shifted(), base.Map); bool wallFlag90 = wallCheck.Walkable(base.Map); if ((!wallFlag90 && !wallFlag90neg) || (wallFlag90 && wallFlag90neg)) { //fragment energy bounces in reverse direction of travel center = center + ((Quaternion.AngleAxis(180, Vector3.up) * this.direction) * 3); } else if (wallFlag90) { center = center + ((Quaternion.AngleAxis(90, Vector3.up) * this.direction) * 3); } else if (wallFlag90neg) { center = center + ((Quaternion.AngleAxis(-90, Vector3.up) * this.direction) * 3); } } List <IntVec3> damageRing = GenRadial.RadialCellsAround(base.Position, radius, true).ToList(); List <IntVec3> outsideRing = GenRadial.RadialCellsAround(base.Position, radius, false).Except(GenRadial.RadialCellsAround(base.Position, radius - 1, true)).ToList(); for (int i = 0; i < damageRing.Count; i++) { List <Thing> allThings = damageRing[i].GetThingList(base.Map); for (int j = 0; j < allThings.Count; j++) { if (allThings[j] is Pawn) { damageEntities(allThings[j], Rand.Range(14, 22), DamageDefOf.Blunt); } else if (allThings[j] is Building) { damageEntities(allThings[j], Rand.Range(56, 88), DamageDefOf.Blunt); } else { if (Rand.Chance(.1f)) { GenPlace.TryPlaceThing(ThingMaker.MakeThing(ThingDefOf.Filth_RubbleRock), damageRing[i], base.Map, ThingPlaceMode.Near); } } } } for (int i = 0; i < outsideRing.Count; i++) { IntVec3 intVec = outsideRing[i]; if (intVec.IsValid && intVec.InBounds(base.Map)) { Vector3 moteDirection = TM_Calc.GetVector(this.ExactPosition.ToIntVec3(), intVec); TM_MoteMaker.ThrowGenericMote(ThingDef.Named("Mote_Rubble"), this.ExactPosition, base.Map, Rand.Range(.3f, .6f), .2f, .02f, .05f, Rand.Range(-100, 100), Rand.Range(8f, 13f), (Quaternion.AngleAxis(90, Vector3.up) * moteDirection).ToAngleFlat(), 0); TM_MoteMaker.ThrowGenericMote(ThingDefOf.Mote_Smoke, this.ExactPosition, base.Map, Rand.Range(.9f, 1.2f), .3f, .02f, Rand.Range(.25f, .4f), Rand.Range(-100, 100), Rand.Range(5f, 8f), (Quaternion.AngleAxis(90, Vector3.up) * moteDirection).ToAngleFlat(), 0); GenExplosion.DoExplosion(intVec, base.Map, .4f, DamageDefOf.Blunt, pawn, 0, 0, SoundDefOf.Pawn_Melee_Punch_HitBuilding, null, null, null, ThingDefOf.Filth_RubbleRock, .4f, 1, false, null, 0f, 1, 0, false); //MoteMaker.ThrowSmoke(intVec.ToVector3Shifted(), base.Map, Rand.Range(.6f, 1f)); } } //damageEntities(this.flyingThing, 305, DamageDefOf.Blunt); this.flyingThing.Destroy(DestroyMode.Vanish); } this.Destroy(DestroyMode.Vanish); } catch { if (!this.flyingThing.Spawned) { GenSpawn.Spawn(this.flyingThing, base.Position, base.Map); } if (this.flyingThing is Pawn) { Pawn p = this.flyingThing as Pawn; } this.Destroy(DestroyMode.Vanish); } }
protected override IEnumerable <Toil> MakeNewToils() { this.Init(); yield return(Toils_JobTransforms.MoveCurrentTargetIntoQueue(TargetIndex.A)); Toil initExtractTargetFromQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, (this.RequiredDesignation == null) ? null : new Func <Thing, bool>((Thing t) => this.Map.designationManager.DesignationOn(t, this.RequiredDesignation) != null)); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(TargetIndex.A)); yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A, true)); Toil gotoThing = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, initExtractTargetFromQueue); if (this.RequiredDesignation != null) { gotoThing.FailOnThingMissingDesignation(TargetIndex.A, this.RequiredDesignation); } yield return(gotoThing); Toil cut = new Toil(); cut.tickAction = delegate() { Pawn actor = cut.actor; SurvivalToolUtility.TryDegradeTool(actor, ST_StatDefOf.TreeFellingSpeed); if (actor.skills != null) { actor.skills.Learn(SkillDefOf.Plants, this.xpPerTick, false); } float statValue = actor.GetStatValue(ST_StatDefOf.TreeFellingSpeed, true); float num = statValue; Plant plant = this.Plant; num *= Mathf.Lerp(3.3f, 1f, plant.Growth); this.workDone += num; if (this.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)) { Vector3 loc = (this.pawn.DrawPos + plant.DrawPos) / 2f; MoteMaker.ThrowText(loc, this.Map, "TextMote_HarvestFailed".Translate(), 3.65f); } else { int num2 = plant.YieldNow(); if (num2 > 0) { Thing thing = ThingMaker.MakeThing(plant.def.plant.harvestedThingDef, null); thing.stackCount = num2; if (actor.Faction != Faction.OfPlayer) { thing.SetForbidden(true, true); } GenPlace.TryPlaceThing(thing, actor.Position, this.Map, ThingPlaceMode.Near, null, null); actor.records.Increment(RecordDefOf.PlantsHarvested); } } } plant.def.plant.soundHarvestFinish.PlayOneShot(actor); plant.PlantCollected(); this.workDone = 0f; this.ReadyForNextToil(); return; } }; cut.FailOnDespawnedNullOrForbidden(TargetIndex.A); if (this.RequiredDesignation != null) { cut.FailOnThingMissingDesignation(TargetIndex.A, this.RequiredDesignation); } cut.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); cut.defaultCompleteMode = ToilCompleteMode.Never; cut.WithEffect(EffecterDefOf.Harvest, TargetIndex.A); cut.WithProgressBar(TargetIndex.A, () => this.workDone / this.Plant.def.plant.harvestWork, true, -0.5f); cut.PlaySustainerOrSound(() => this.Plant.def.plant.soundHarvesting); cut.activeSkill = (() => SkillDefOf.Plants); yield return(cut); Toil plantWorkDoneToil = this.PlantWorkDoneToil(); if (plantWorkDoneToil != null) { yield return(plantWorkDoneToil); } yield return(Toils_Jump.Jump(initExtractTargetFromQueue)); yield break; }
protected override Toil DoBill() { var tableThing = job.GetTarget(BillGiverInd).Thing as Building_WorkTable; var tablePowerTraderComp = tableThing.GetComp <CompPowerTrader> (); var toil = new Toil(); toil.initAction = delegate { var objectThing = job.GetTarget(IngredientInd).Thing; job.bill.Notify_DoBillStarted(pawn); costHitPointsPerCycle = (int)(objectThing.MaxHitPoints * Settings.costFromMaxHitPoints); processedHitPoints = 0; workCycleProgress = workCycle = Math.Max(job.bill.recipe.workAmount, 10f); }; toil.tickAction = delegate { var objectThing = job.GetTarget(IngredientInd).Thing; 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) { objectThing.HitPoints -= costHitPointsPerCycle; if (tablePowerTraderComp != null && tablePowerTraderComp.PowerOn) { processedHitPoints += costHitPointsPerCycle; } else { processedHitPoints += costHitPointsPerCycle / 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 (Settings.chances[objectThing.def.techLevel] > 1 - Mathf.Pow(Rand.Value, 1 + skillPerc * 3f)) { objectThing.HitPoints -= Rand.RangeInclusive(costHitPointsPerCycle, costHitPointsPerCycle * 4); 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("MendAndRecycle :: " + pawn + " could not drop recipe product " + list [j] + " near " + pawn.Position); } } } if (list.Count >= 1) { list [0].SetPositionDirect(pawn.Position); job.bill.Notify_IterationCompleted(pawn, list); job.SetTarget(IngredientInd, list[0]); pawn.Map.reservationManager.Reserve(pawn, job, job.GetTarget(IngredientInd), 1); ReadyForNextToil(); } else { Log.Message("MendAndRecycle :: " + pawn + " could not reclaim anything from " + objectThing); pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } } workCycleProgress = workCycle; } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => job.bill.recipe.effectWorking, BillGiverInd); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(BillGiverInd, delegate { var objectThing = job.GetTarget(IngredientInd).Thing; return((float)objectThing.HitPoints / (float)objectThing.MaxHitPoints); }, false, 0.5f); toil.FailOn(() => { return(toil.actor.CurJob.bill.suspended || !tableThing.CurrentlyUsableForBills()); }); return(toil); }