public Toil DepositFuelIntoBurner(TargetIndex burnerIndex) { var toil = new Toil(); toil.initAction = delegate { var actor = toil.actor; var curJob = actor.jobs.curJob; if (actor.carrier.CarriedThing == null) { Log.Error(actor + " tried to place hauled thing in container but is not hauling anything."); return; } var thingContainerOwner = curJob.GetTarget(burnerIndex).Thing.TryGetComp<CompFueled>() as IThingContainerOwner; if (thingContainerOwner != null) { var num = actor.carrier.CarriedThing.stackCount; actor.carrier.container.TransferToContainer(actor.carrier.CarriedThing, thingContainerOwner.GetContainer(), num); } else if (curJob.GetTarget(burnerIndex).Thing.def.Minifiable) { actor.carrier.container.Clear(); } else { Log.Error("Could not deposit hauled thing in container: " + curJob.GetTarget(burnerIndex).Thing); } }; return toil; }
public static Toil CheckNeedStorageCell(Toil jumpToil, TargetIndex CarrierInd, TargetIndex StoreCellInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.actor; Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack; if (cart == null && backpack == null) { Log.Error(actor.LabelCap + " Report: Don't have Carrier"); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } ThingContainer container = cart != null ? cart.storage : actor.inventory.container; if (container.Count == 0) return; IntVec3 cell = ToolsForHaulUtility.FindStorageCell(actor, container.First()); if (cell != IntVec3.Invalid) { toil.actor.jobs.curJob.SetTarget(StoreCellInd, cell); Find.Reservations.Reserve(actor, cell); toil.actor.jobs.curDriver.JumpToToil(jumpToil); } }; return toil; }
public static Toil CheckArrestable( TargetIndex PrisonerInd, TargetIndex BedInd ) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Instant; toil.initAction = () => { var prisoner = toil.actor.CurJob.GetTarget( PrisonerInd ).Thing as Pawn; var bed = toil.actor.CurJob.GetTarget( BedInd ).Thing as Building_Bed; if( !bed.ForPrisoners ) { return; } var lord = prisoner.GetLord(); if( lord != null ) { lord.Notify_PawnAttemptArrested( prisoner ); } GenClamor.DoClamor( prisoner, 10f, ClamorType.Harm ); if( prisoner.CheckAcceptArrest( toil.actor ) ) { return; } //Log.Message( "Toils_Prisoner.CheckArrestable returning JobCondition.Incompleteable!" ); toil.actor.jobs.EndCurrentJob( JobCondition.Incompletable ); }; return toil; }
private Toil Manage( TargetIndex targetIndex ) { Building_ManagerStation station = CurJob.GetTarget( targetIndex ).Thing as Building_ManagerStation; if ( station == null ) { Log.Error( "Target of manager job was not a manager station. This should never happen." ); return null; } Comp_ManagerStation comp = station.GetComp<Comp_ManagerStation>(); if ( comp == null ) { Log.Error( "Target of manager job does not have manager station comp. This should never happen." ); return null; } Toil toil = new Toil(); toil.defaultDuration = (int)( comp.props.Speed * ( 1 - pawn.GetStatValue( StatDef.Named( "ManagingSpeed" ) ) + .5 ) ); #if DEBUG_WORKGIVER Log.Message("Pawn stat: " + pawn.GetStatValue(StatDef.Named("ManagingSpeed")) + " (+0.5) Station speed: " + comp.props.Speed + "Total time: " + toil.defaultDuration); #endif toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.tickAction = delegate { toil.actor.skills.GetSkill( DefDatabase<SkillDef>.GetNamed( "Managing" ) ).Learn( 0.11f ); }; List<Action> finishers = new List<Action>(); finishers.Add( delegate { Manager.Get.DoWork(); } ); toil.finishActions = finishers; return toil; }
public static Toil CheckDuplicates(Toil jumpToil, TargetIndex CarrierInd, TargetIndex HaulableInd) { Toil toil = new Toil(); toil.initAction = () => { IntVec3 storeCell = IntVec3.Invalid; Pawn actor = toil.GetActor(); TargetInfo target = toil.actor.jobs.curJob.GetTarget(HaulableInd); if (target.Thing.def.stackLimit <= 1) return; List<TargetInfo> targetQueue = toil.actor.jobs.curJob.GetTargetQueue(HaulableInd); if (!targetQueue.NullOrEmpty() && target.Thing.def.defName == targetQueue.First().Thing.def.defName) { toil.actor.jobs.curJob.SetTarget(HaulableInd, targetQueue.First()); Find.Reservations.Reserve(actor, targetQueue.First()); targetQueue.RemoveAt(0); toil.actor.jobs.curDriver.JumpToToil(jumpToil); return; } Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack; if (cart == null && backpack == null) { Log.Error(actor.LabelCap + " Report: Don't have Carrier"); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); return; } int curItemCount = (cart != null ? cart.storage.Count : actor.inventory.container.Count) + targetQueue.Count; int curItemStack = (cart != null ? cart.storage.TotalStackCount : actor.inventory.container.TotalStackCount) + targetQueue.Sum(item => item.Thing.stackCount); int maxItem = cart != null ? cart.MaxItem : backpack.MaxItem; int maxStack = cart != null ? cart.MaxStack : backpack.MaxStack; if (curItemCount >= maxItem || curItemStack >= maxStack) return; //Check target's nearby Thing thing = GenClosest.ClosestThing_Global_Reachable(actor.Position, ListerHaulables.ThingsPotentiallyNeedingHauling(), PathEndMode.Touch, TraverseParms.For(actor, Danger.Some), NearbyCell, item => !targetQueue.Contains(item) && item.def.defName == target.Thing.def.defName && !FireUtility.IsBurning(item) && Find.Reservations.CanReserve(actor, item)); if (thing != null) { toil.actor.jobs.curJob.SetTarget(HaulableInd, thing); Find.Reservations.Reserve(actor, thing); toil.actor.jobs.curDriver.JumpToToil(jumpToil); return; } }; return toil; }
public static Toil FaceThing(TargetIndex thingInd) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Instant; toil.initAction = delegate { Pawn actor = toil.actor; actor.drawer.rotator.FaceCell(actor.jobs.curJob.GetTarget(thingInd).Cell); }; return toil; }
public static Toil PrepareDoorInteraction( TargetIndex DoorInd, Toil interactionToil ) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Instant; toil.initAction = () => { var door = toil.actor.CurJob.GetTarget( DoorInd ).Thing as Building_RestrictedDoor; var compLock = door.TryGetComp<CompLockable>(); interactionToil.defaultDuration = compLock.LockToggleTime( toil.actor ); }; return toil; }
public static Toil DoorUnLock( TargetIndex DoorInd ) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.WithProgressBarToilDelay( DoorInd ); toil.AddFinishAction( () => { var door = toil.actor.CurJob.GetTarget( DoorInd ).Thing as Building_RestrictedDoor; var compLock = door.TryGetComp<CompLockable>(); compLock.ChangeLockState( false ); } ); return toil; }
public Toil PractiseCombat(TargetIndex targetInd) { var toil = new Toil(); var lastMeleeExperienceValue = pawn.skills.GetSkill(SkillDefOf.Melee).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Melee).xpSinceLastLevel; var lastShootingExperienceValue = pawn.skills.GetSkill(SkillDefOf.Shooting).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Shooting).xpSinceLastLevel; toil.tickAction = () => { // try execute attack on dummy pawn.equipment.TryStartAttack(CurJob.GetTarget(targetInd)); // if zoom is close enough and dummy is selected if (Find.CameraDriver.CurrentZoom == CameraZoomRange.Closest && (Find.Selector.IsSelected(CurJob.GetTarget(targetInd).Thing) || Find.Selector.IsSelected(pawn))) { var currentMeleeExperienceValue = pawn.skills.GetSkill(SkillDefOf.Melee).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Melee).xpSinceLastLevel; var currentShootingExperienceValue = pawn.skills.GetSkill(SkillDefOf.Shooting).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Shooting).xpSinceLastLevel; // throws text mote of gained melee experience if (currentMeleeExperienceValue - lastMeleeExperienceValue >= 1f) { var expGained = currentMeleeExperienceValue - lastMeleeExperienceValue; MoteMaker.ThrowText(new Vector3(pawn.Position.x + 0.5f, pawn.Position.y, pawn.Position.z + 1f), expGained.ToString("F0") + " XP", Color.green, GenDate.SecondsToTicks(1)); lastMeleeExperienceValue = currentMeleeExperienceValue; } // throws text mote of gained shooting experience if (currentShootingExperienceValue - lastShootingExperienceValue >= 1f) { var expGained = currentShootingExperienceValue - lastShootingExperienceValue; MoteMaker.ThrowText(new Vector3(pawn.Position.x + 0.5f, pawn.Position.y, pawn.Position.z + 1f), expGained.ToString("F0") + " XP", Color.green, GenDate.SecondsToTicks(1)); lastShootingExperienceValue = currentShootingExperienceValue; } } }; toil.AddEndCondition(() => { // fail if pawn has life needs or can't hit target var dummy = CurJob.GetTarget(targetInd).Thing as Dummy; if (dummy != null && (dummy.PawnHasNeeds(pawn) || !pawn.equipment.PrimaryEq.PrimaryVerb.CanHitTarget(CurJob.GetTarget(targetInd)))) { return JobCondition.InterruptForced; } return JobCondition.Ongoing; }); toil.defaultCompleteMode = ToilCompleteMode.Never; return toil; }
public static Toil ArrestPawn( TargetIndex PrisonerInd, TargetIndex BedInd ) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Instant; toil.initAction = () => { var prisoner = toil.actor.CurJob.GetTarget( PrisonerInd ).Thing as Pawn; var bed = toil.actor.CurJob.GetTarget( BedInd ).Thing as Building_Bed; var compPrisoner = prisoner.TryGetComp<CompPrisoner>(); if( bed.ForPrisoners ) { if( prisoner.guest.released ) { prisoner.guest.released = false; prisoner.guest.interactionMode = PrisonerInteractionMode.NoInteraction; } if( !prisoner.IsPrisonerOfColony ) { if( prisoner.Faction != null ) { prisoner.Faction.Notify_MemberCaptured( prisoner, toil.actor.Faction ); } prisoner.guest.SetGuestStatus( Faction.OfPlayer, true ); if( prisoner.guest.IsPrisoner ) { TaleRecorder.RecordTale( TaleDefOf.Captured, toil.actor, prisoner ); toil.actor.records.Increment( RecordDefOf.PeopleCaptured ); } } } else if( ( prisoner.Faction != Faction.OfPlayer )&& ( prisoner.HostFaction != Faction.OfPlayer )&& ( prisoner.guest != null ) ) { prisoner.guest.SetGuestStatus( Faction.OfPlayer, false ); } if( prisoner.playerSettings == null ) { prisoner.playerSettings = new Pawn_PlayerSettings( prisoner ); } // Set that the pawn was arrested and how long it should be held for compPrisoner.wasArrested = true; compPrisoner.releaseAfterTick = Find.TickManager.TicksGame + (int)( compPrisoner.lawBroken.daysToImprisonFor * (float)GenDate.TicksPerDay ); }; return toil; }
public static Toil DismountAt(TargetIndex CartInd, TargetIndex StoreCellInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.GetActor(); Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart; if (cart == null) { Log.Error(actor.LabelCap + " Report: Cart is invalid."); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } cart.GetComp<CompMountable>().DismountAt(toil.actor.jobs.curJob.GetTarget(StoreCellInd).Cell); }; return toil; }
public static Toil CallAnimalCart(TargetIndex CartInd, TargetIndex Ind) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.GetActor(); Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart; if (cart == null) { Log.Error(actor.LabelCap + " Report: Cart is invalid."); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } Job job = new Job(jobDefStandby, toil.actor.jobs.curJob.GetTarget(Ind), defaultWaitWorker); cart.mountableComp.Driver.jobs.StartJob(job, JobCondition.InterruptForced); }; return toil; }
public static Toil PickUpTool(TargetIndex toolInd) { Toil toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Instant; toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing tool = curJob.GetTarget(toolInd).Thing; actor.carrier.TryStartCarry(tool); if (tool != actor.carrier.CarriedThing && Find.Reservations.FirstReserverOf(tool, actor.Faction) == actor) { Log.Error("Carried tool != target tool"); Find.Reservations.Release(tool, actor); } curJob.targetC = actor.carrier.CarriedThing; }; return toil; }
private static Toil TakeFromSynthesier( TargetIndex ind, Pawn eater, Func<ThingDef,bool> validator, Func<ThingDef,ThingDef,int> sorter ) { var synthesizer = (Building_AutomatedFactory) eater.jobs.curJob.GetTarget( ind ).Thing; var bestDef = synthesizer.BestProduct( validator, sorter ); var takeFromSynthesizer = new Toil(); //Log.Message( string.Format( "{0}.TakeMealFromSynthesizier( {1}, {2} )", eater == null ? "null" : eater.NameStringShort, synthesizer == null ? "null" : synthesizer.ThingID, bestDef == null ? "null" : bestDef.defName ) ); if( bestDef == null ) { takeFromSynthesizer.defaultCompleteMode = ToilCompleteMode.Delay; takeFromSynthesizer.AddEndCondition( () => { return JobCondition.Incompletable; } ); takeFromSynthesizer.defaultDuration = 999; } else { takeFromSynthesizer.defaultCompleteMode = ToilCompleteMode.Delay; takeFromSynthesizer.AddFinishAction( () => { Thing thing = synthesizer.TryProduceThingDef( bestDef ); if( thing == null ) { Log.Error( eater.Label + " unable to take " + bestDef.label + " from " + synthesizer.ThingID ); eater.jobs.curDriver.EndJobWith( JobCondition.Incompletable ); } else { eater.carrier.TryStartCarry( thing ); eater.jobs.curJob.targetA = (TargetInfo) eater.carrier.CarriedThing; } } ); takeFromSynthesizer.defaultDuration = synthesizer.ProductionTicks( bestDef ); } return takeFromSynthesizer; }
public static Toil MonitorStation( TargetIndex StationInd, TargetIndex WardenInd ) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.defaultDuration = Data.MonitorRemoteJobTicks; toil.WithProgressBarToilDelay( WardenInd ); toil.AddFinishAction( () => { var stationThing = toil.actor.CurJob.GetTarget( StationInd ).Thing; if( stationThing == null ) { throw new Exception( "Target thing is null for Toils_SecurityStation.MonitorStation!" ); } var stationComp = stationThing.TryGetComp<CompSecurityStation>(); if( stationComp == null ) { throw new Exception( "Target thing is missing CompSecurityStation for Toils_SecurityStation.MonitorStation!" ); } stationComp.FinishMonitoring(); Find.Reservations.Release( toil.actor.jobs.curJob.GetTarget( StationInd ), toil.actor ); } ); toil.tickAction = () => { var stationThing = toil.actor.CurJob.GetTarget( StationInd ).Thing; if( stationThing == null ) { throw new Exception( "Target thing is null for Toils_SecurityStation.MonitorStation!" ); } var stationComp = stationThing.TryGetComp<CompSecurityStation>(); if( stationComp == null ) { throw new Exception( "Target thing is missing CompSecurityStation for Toils_SecurityStation.MonitorStation!" ); } stationComp.UpdateMonitor(); }; return toil; }
private static Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; if (actor.carrier.CarriedThing.def.stackLimit != 1 && actor.carrier.container.AvailableStackSpace > 0) { int num2 = curJob.maxNumToCarry - actor.carrier.CarriedThing.stackCount; if (num2 > 0) { Predicate<Thing> validator = t => { if (((!t.SpawnedInWorld || (t.def != actor.carrier.CarriedThing.def)) || (!t.CanStackWith(actor.carrier.CarriedThing) || t.IsForbidden(actor.Faction))) || (t.IsInValidStorage() || ((storeCellInd != TargetIndex.None) && !curJob.GetTarget(storeCellInd).Cell.IsValidStorageFor(t)))) { return false; } return actor.CanReserve(t, 1); }; Thing pack = GenClosest.ClosestThingReachable(actor.Position, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, true), 8f, validator, null, -1); if (pack != null) { curJob.SetTarget(haulableInd, pack); actor.jobs.curDriver.SetNextToil(getHaulTargetToil); actor.jobs.curDriver.SetCompleteMode(ToilCompleteMode.Instant); } } } }; return toil; }
public static Toil TakeMealFromSynthesizer( TargetIndex ind, Pawn eater ) { return TakeFromSynthesier( ind, eater, FoodSynthesis.IsMeal, FoodSynthesis.SortMeal ); }
public static Toil WaitAnimalCart(TargetIndex CartInd, TargetIndex HaulableInd) { Toil toil = new Toil(); int tickTime = 0; toil.initAction = () => { Pawn actor = toil.GetActor(); Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart; if (cart == null) { Log.Error(actor.LabelCap + " Report: Cart is invalid."); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } tickTime = 0; if (cart.mountableComp.IsMounted) { //Worker is arrival and Animal cart is coming if (cart.mountableComp.Driver.CurJob.def == jobDefStandby && !actor.Position.AdjacentTo8WayOrInside(cart)) tickTime = 0; //Worker is arrival and Animal cart is arrival else if (cart.mountableComp.Driver.CurJob.def == jobDefStandby && actor.Position.AdjacentTo8WayOrInside(cart)) toil.actor.jobs.curDriver.ReadyForNextToil(); //Worker is arrival but Animal cart is missing else { Job job = new Job(jobDefStandby, actor.jobs.curJob.GetTarget(HaulableInd), defaultWaitWorker); cart.mountableComp.Driver.jobs.StartJob(job, JobCondition.InterruptForced); } } else toil.actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); }; toil.tickAction = () => { Pawn actor = toil.GetActor(); Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart; if (cart == null) { Log.Error(actor.LabelCap + " Report: Cart is invalid."); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } if (Find.TickManager.TicksGame % tickCheckInterval == 0) if (cart.mountableComp.IsMounted) { //Animal cart is arrival if (cart.mountableComp.Driver.CurJob.def == jobDefStandby && actor.Position.AdjacentTo8WayOrInside(cart)) toil.actor.jobs.curDriver.ReadyForNextToil(); //Animal cart would never come. Imcompletable. else if (cart.mountableComp.Driver.CurJob.def != jobDefStandby || tickTime >= defaultWaitWorker) toil.actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else toil.actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); }; toil.defaultCompleteMode = ToilCompleteMode.Never; return toil; }
public static Toil CarryIngestibleToChewSpot(Pawn pawn, TargetIndex ingestibleInd) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; IntVec3 intVec = IntVec3.Invalid; Thing thing = null; Thing thing2 = actor.CurJob.GetTarget(ingestibleInd).Thing; Predicate <Thing> baseChairValidator = delegate(Thing t) { if (t.def.building == null || !t.def.building.isSittable) { return(false); } if (t.IsForbidden(pawn)) { return(false); } if (!actor.CanReserve(t, 1, -1, null, false)) { return(false); } if (!t.IsSociallyProper(actor)) { return(false); } if (t.IsBurning()) { return(false); } if (t.HostileTo(pawn)) { return(false); } bool result = false; for (int i = 0; i < 4; i++) { IntVec3 c = t.Position + GenAdj.CardinalDirections[i]; Building edifice = c.GetEdifice(t.Map); if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat) { result = true; break; } } return(result); }; if (thing2.def.ingestible.chairSearchRadius > 0f) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None, null, 0, -1, false, RegionType.Set_Passable, false); } if (thing == null) { intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing); Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map); if (chewSpotDanger != Danger.None) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) <= chewSpotDanger, null, 0, -1, false, RegionType.Set_Passable, false); } } if (thing != null) { intVec = thing.Position; actor.Reserve(thing, actor.CurJob, 1, -1, null, true); } actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec); actor.pather.StartPath(intVec, PathEndMode.OnCell); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(toil); }
public static Toil TakeAlcoholFromSynthesizer(TargetIndex ind, Pawn eater) { return(TakeFromSynthesier(ind, eater, FoodSynthesis.IsAlcohol, FoodSynthesis.SortAlcohol)); }
public static Toil CastVerb(TargetIndex targetInd, bool canHitNonTargetPawns = true) { return(CastVerb(targetInd, TargetIndex.None, canHitNonTargetPawns)); }
public static Toil FinishPourRecipe(TargetIndex billGiverIndex, TargetIndex ingListIndex) { 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; // 経験値取得 if (curJob.RecipeDef.workSkill != null) { float xp = (float)jobDriver_DoBill.ticksSpentDoingRecipeWork * 0.11f * curJob.RecipeDef.workSkillLearnFactor; actor.skills.GetSkill(curJob.RecipeDef.workSkill).Learn(xp, false); } // 注ぎ込んだ水の総量と水質を求める float totalWaterVolume = 0f; var totalWaterType = WaterType.NoWater; foreach (var tspc in curJob.placedThings) { var thingDef = tspc.thing.def; var compprop = thingDef.GetCompProperties <CompProperties_WaterSource>(); if (compprop == null) { Log.Error("compprop is null"); actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } totalWaterVolume += compprop.waterVolume * tspc.Count; totalWaterType = totalWaterType.GetMinType(compprop.waterType); } var billGiver = curJob.GetTarget(billGiverIndex).Thing as Building_WaterNetWorkTable; if (billGiver == null) { Log.Error("billGiver is null"); actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 水の増加 billGiver.AddWaterVolume(totalWaterVolume); // 水質変更 billGiver.TankComp.StoredWaterType = billGiver.TankComp.StoredWaterType.GetMinType(totalWaterType); // 水アイテムの消費 foreach (var tspc in curJob.placedThings) { Thing thing; if (tspc.Count < tspc.thing.stackCount) { thing = tspc.thing.SplitOff(tspc.Count); } else { thing = tspc.thing; } curJob.RecipeDef.Worker.ConsumeIngredient(thing, curJob.RecipeDef, actor.Map); } curJob.bill.Notify_IterationCompleted(actor, null); //RecordsUtility.Notify_BillDone(actor, new List<Thing>()); actor.jobs.EndCurrentJob(JobCondition.Succeeded, true); }; toil.defaultCompleteMode = ToilCompleteMode.Instant; return(toil); }
// duplicated to make changes public Toil CarryHauledThingToCell(TargetIndex squareIndex) { Toil toil = new Toil(); toil.initAction = delegate { IntVec3 cell = toil.actor.jobs.curJob.GetTarget(squareIndex).Cell; toil.actor.pather.StartPath(cell, PathEndMode.ClosestTouch); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; toil.AddFailCondition(delegate { Pawn actor = toil.actor; IntVec3 cell = actor.jobs.curJob.GetTarget(squareIndex).Cell; // call duplicated to make changes return actor.jobs.curJob.haulMode == HaulMode.ToCellStorage && !IsValidStorageFor(cell, actor.carrier.CarriedThing); }); return toil; }
public static Toil WithEffect(this Toil toil, Func <EffecterDef> effecterDefGetter, TargetIndex ind) { return(toil.WithEffect(effecterDefGetter, () => toil.actor.CurJob.GetTarget(ind))); }
public static Toil LayDown(TargetIndex bedOrRestSpotIndex, bool hasBed, bool lookForOtherJobs, bool canSleep = true, bool gainRestAndHealth = true) { Toil layDown = new Toil(); layDown.initAction = delegate { Pawn actor3 = layDown.actor; actor3.pather.StopDead(); JobDriver curDriver3 = actor3.jobs.curDriver; if (hasBed) { Building_Bed t = (Building_Bed)actor3.CurJob.GetTarget(bedOrRestSpotIndex).Thing; if (!t.OccupiedRect().Contains(actor3.Position)) { Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + actor3); actor3.jobs.EndCurrentJob(JobCondition.Errored); return; } actor3.jobs.posture = PawnPosture.LayingInBed; } else { actor3.jobs.posture = PawnPosture.LayingOnGroundNormal; } curDriver3.asleep = false; if (actor3.mindState.applyBedThoughtsTick == 0) { actor3.mindState.applyBedThoughtsTick = Find.TickManager.TicksGame + Rand.Range(2500, 10000); actor3.mindState.applyBedThoughtsOnLeave = false; } if (actor3.ownership != null && actor3.CurrentBed() != actor3.ownership.OwnedBed) { ThoughtUtility.RemovePositiveBedroomThoughts(actor3); } }; layDown.tickAction = delegate { Pawn actor2 = layDown.actor; Job curJob = actor2.CurJob; JobDriver curDriver2 = actor2.jobs.curDriver; Building_Bed building_Bed = (Building_Bed)curJob.GetTarget(bedOrRestSpotIndex).Thing; actor2.GainComfortFromCellIfPossible(); if (!curDriver2.asleep) { if (canSleep && ((actor2.needs.rest != null && actor2.needs.rest.CurLevel < RestUtility.FallAsleepMaxLevel(actor2)) || curJob.forceSleep)) { curDriver2.asleep = true; } } else if (!canSleep) { curDriver2.asleep = false; } else if ((actor2.needs.rest == null || actor2.needs.rest.CurLevel >= RestUtility.WakeThreshold(actor2)) && !curJob.forceSleep) { curDriver2.asleep = false; } if (curDriver2.asleep && gainRestAndHealth && actor2.needs.rest != null) { float restEffectiveness = (building_Bed == null || !building_Bed.def.statBases.StatListContains(StatDefOf.BedRestEffectiveness)) ? 0.8f : building_Bed.GetStatValue(StatDefOf.BedRestEffectiveness); actor2.needs.rest.TickResting(restEffectiveness); } if (actor2.mindState.applyBedThoughtsTick != 0 && actor2.mindState.applyBedThoughtsTick <= Find.TickManager.TicksGame) { ApplyBedThoughts(actor2); actor2.mindState.applyBedThoughtsTick += 60000; actor2.mindState.applyBedThoughtsOnLeave = true; } if (actor2.IsHashIntervalTick(100) && !actor2.Position.Fogged(actor2.Map)) { if (curDriver2.asleep) { MoteMaker.ThrowMetaIcon(actor2.Position, actor2.Map, ThingDefOf.Mote_SleepZ); } if (gainRestAndHealth && actor2.health.hediffSet.GetNaturallyHealingInjuredParts().Any()) { MoteMaker.ThrowMetaIcon(actor2.Position, actor2.Map, ThingDefOf.Mote_HealingCross); } } if (actor2.ownership != null && building_Bed != null && !building_Bed.Medical && !building_Bed.owners.Contains(actor2)) { if (actor2.Downed) { actor2.Position = CellFinder.RandomClosewalkCellNear(actor2.Position, actor2.Map, 1); } actor2.jobs.EndCurrentJob(JobCondition.Incompletable); } else if (lookForOtherJobs && actor2.IsHashIntervalTick(211)) { actor2.jobs.CheckForJobOverride(); } }; layDown.defaultCompleteMode = ToilCompleteMode.Never; if (hasBed) { layDown.FailOnBedNoLongerUsable(bedOrRestSpotIndex); } layDown.AddFinishAction(delegate { Pawn actor = layDown.actor; JobDriver curDriver = actor.jobs.curDriver; if (actor.mindState.applyBedThoughtsOnLeave) { ApplyBedThoughts(actor); } curDriver.asleep = false; }); return(layDown); }
public static Toil WithEffect(this Toil toil, EffecterDef effectDef, TargetIndex ind) { return(toil.WithEffect(() => effectDef, ind)); }
public static Toil WithProgressBarToilDelay(this Toil toil, TargetIndex ind, int toilDuration, bool interpolateBetweenActorAndTarget = false, float offsetZ = -0.5f) { return(toil.WithProgressBar(ind, () => 1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / (float)toilDuration, interpolateBetweenActorAndTarget, offsetZ)); }
// Token: 0x06000011 RID: 17 RVA: 0x00002D14 File Offset: 0x00000F14 private static Toil MarvsGotoCastPosition(TargetIndex targetInd, bool closeIfDowned = false) { var toil = new Toil(); toil.initAction = delegate { var actor = toil.actor; var curJob = actor.jobs.curJob; var thing = curJob.GetTarget(targetInd).Thing; if (thing is not Pawn pawn) { return; } var curWeatherAccuracyMultiplier = pawn.Map.weatherManager.CurWeatherAccuracyMultiplier; var newReq = new CastPositionRequest { caster = toil.actor, target = thing, verb = curJob.verbToUse, wantCoverFromTarget = false }; if (!pawn.Downed && !pawn.Awake() && pawn.def.race.predator) { toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } if (closeIfDowned && (pawn.Downed || Hunting_Loader.settings.shouldApprochSleepers && !pawn.Awake())) { newReq.maxRangeFromTarget = Mathf.Min(curJob.verbToUse.verbProps.range, pawn.RaceProps.executionRange); } else { var def = actor.equipment.Primary.def; var num = GetGoodWeaponHuntingRange(def); if (IsPawnTriggerHappy(actor) && !def.IsMeleeWeapon) { num += TriggerHappyRangeReduction; } if (!def.IsMeleeWeapon) { num *= curWeatherAccuracyMultiplier; } var safeHuntingDistance = GetSafeHuntingDistance(pawn); newReq.maxRangeFromTarget = Mathf.Max(num, safeHuntingDistance); } if (!CastPositionFinder.TryFindCastPosition(newReq, out var intVec)) { toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); } else { if (intVec != toil.actor.Position) { toil.actor.pather.StartPath(intVec, PathEndMode.OnCell); actor.Map.pawnDestinationReservationManager.Reserve(actor, curJob, intVec); } else { toil.actor.pather.StopDead(); toil.actor.jobs.curDriver.ReadyForNextToil(); } } }; toil.FailOnDespawnedOrNull(targetInd); toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(toil); }
private bool IsQueueEmpty( TargetIndex ind ) { return( this.CurJob.GetTargetQueue( ind ).NullOrEmpty() ); }
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); }
public static Toil CheckNeedStorageCell(Toil jumpToil, TargetIndex CarrierInd, TargetIndex StoreCellInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.actor; Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; Apparel_Backpack backpack = toil.actor.jobs.curJob.GetTarget(CarrierInd).Thing as Apparel_Backpack; if (cart == null && backpack == null) { Log.Error(actor.LabelCap + " Report: Don't have Carrier"); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } ThingContainer container = cart != null ? cart.storage : actor.inventory.container; if (container.Count == 0) { return; } IntVec3 cell = ToolsForHaulUtility.FindStorageCell(actor, container.First()); if (cell != IntVec3.Invalid) { toil.actor.jobs.curJob.SetTarget(StoreCellInd, cell); Find.Reservations.Reserve(actor, cell); toil.actor.jobs.curDriver.JumpToToil(jumpToil); } }; 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); }
// duplicated to make changes public Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; IntVec3 cell = curJob.GetTarget(cellInd).Cell; SlotGroup slotGroup = Find.SlotGroupManager.SlotGroupAt(cell); if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carrier.CarriedThing)) { Find.DesignationManager.RemoveAllDesignationsOn(actor.carrier.CarriedThing, false); } Thing thing; // call duplicated to make changes if (TryDropCarriedThing(actor, cell, ThingPlaceMode.Direct, out thing)) { if (curJob.def == JobDefOf.DoBill && thing != null) { if (curJob.placedTargets == null) { curJob.placedTargets = new List<TargetInfo>(); } if (!curJob.placedTargets.Contains(thing)) { curJob.placedTargets.Add(thing); } } } else if (storageMode) { IntVec3 vec; // call duplicated to make changes if (nextToilOnPlaceFailOrIncomplete != null && WorkGiver_HaulGeneral.TryFindBestBetterStoreCellFor(actor.carrier.CarriedThing, actor, StoragePriority.Unstored, actor.Faction, out vec, true)) { actor.CurJob.SetTarget(cellInd, vec); actor.jobs.curDriver.SetNextToil(nextToilOnPlaceFailOrIncomplete); return; } Job job = HaulAIUtility.HaulAsideJobFor(actor, actor.carrier.CarriedThing); if (job != null) { curJob.targetA = job.targetA; curJob.targetB = job.targetB; curJob.targetC = job.targetC; curJob.maxNumToCarry = job.maxNumToCarry; curJob.haulOpportunisticDuplicates = job.haulOpportunisticDuplicates; curJob.haulMode = job.haulMode; actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Log.Error(string.Concat(new object[] { "Incomplete haul for ", actor, ": Could not find anywhere to put ", actor.carrier.CarriedThing, " near ", actor.Position, ". Destroying. actor.carrier should never happen!" })); actor.carrier.CarriedThing.Destroy(DestroyMode.Vanish); } } else if (nextToilOnPlaceFailOrIncomplete != null) { actor.jobs.curDriver.SetNextToil(nextToilOnPlaceFailOrIncomplete); return; } }; return toil; }
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)) { Messages.Message("MessageFoodPoisoning".Translate(new object[] { actor.LabelShort, "AreaLower".Translate() }).CapitalizeFirst(), 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 IntVec3 TargetCell( this JobDriver obj, TargetIndex Ind ) { return obj.Target( Ind ).Cell; }
public static Toil DropCarriedThing(TargetIndex prisonerIndex, TargetIndex dropSpotIndex) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; // そもそも何も運んでいない if (actor.carryTracker == null || actor.carryTracker.CarriedThing == null) { return; } // ターゲットが場所ではなく物 if (actor.CurJob.GetTarget(dropSpotIndex).HasThing) { return; } Thing dropThing = null; // その場に置いてみる bool isDropSuccess = actor.carryTracker.TryDropCarriedThing(actor.CurJob.GetTarget(dropSpotIndex).Cell, ThingPlaceMode.Direct, out dropThing); if (!isDropSuccess) { // その場に置けなかったら近くに置いてみる isDropSuccess = actor.carryTracker.TryDropCarriedThing(actor.CurJob.GetTarget(dropSpotIndex).Cell, ThingPlaceMode.Near, out dropThing); } // その場or近くに置けなかった if (!isDropSuccess) { return; } if (actor.Map.reservationManager.ReservedBy(dropThing, actor)) { // 持ってる人に予約されているなら、解放する actor.Map.reservationManager.Release(dropThing, actor, actor.CurJob); } // 相手が囚人でない可能性 if (!actor.CurJob.GetTarget(prisonerIndex).HasThing) { return; } Pawn prisoner = actor.CurJob.GetTarget(prisonerIndex).Thing as Pawn; // 囚人がポーンではない if (prisoner == null) { return; } //// 置いた水を囚人が飲むジョブを作成 //Job job = new Job(MizuDef.Job_DrinkWater, dropThing) //{ // count = MizuUtility.WillGetStackCountOf(prisoner, dropThing) //}; //// ジョブを囚人の待ち行列に加える //prisoner.jobs.jobQueue.EnqueueLast(job, JobTag.SatisfyingNeeds); //// 新ジョブに対して水を予約させる //prisoner.Map.reservationManager.Reserve(prisoner, job, dropThing); }; toil.defaultCompleteMode = ToilCompleteMode.Instant; toil.atomicWithPrevious = true; return(toil); }
/// <summary> /// Returns a <see cref="System.String" /> that represents this instance. /// </summary> /// <returns> /// A <see cref="System.String" /> that represents this instance. /// </returns> public override string ToString() { return(TargetIndex.ToString()); }
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); } }; 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); }
protected Toil AttemptCalm(TargetIndex ctrg) { Pawn subjectee = (Pawn)this.pawn.CurJob.targetA.Thing; var toil = new Toil { initAction = () => { if (subjectee == null) { return; } subjectee.jobs.EndCurrentJob(JobCondition.InterruptForced); this.TargetThingB = this.pawn; // Defining our initiator pawn float rand = Rand.RangeSeeded(0f, 0.70f, Find.TickManager.TicksAbs); pawn.interactions.TryInteractWith(subjectee, SnapDefOf.CalmDownInteraction); float num = SnapUtils.DoFormula(pawn, subjectee); if (SOMod.Settings.AlwaysSucceed) { rand = 0f; } SnapUtils.DebugLog(string.Format("Success chance of {0} opposed to failure chance of {1}", num.ToString(), rand.ToString())); if (rand > num) { if (SOMod.Settings.MessagesEnabled) { SnapUtils.CalmText(this.pawn, Color.red); } if (subjectee.InAggroMentalState) { subjectee.TryStartAttack(pawn); SnapUtils.DoStatusMessage(3, pawn, subjectee); subjectee.mindState.lastAssignedInteractTime = Find.TickManager.TicksGame; return; } SnapUtils.DoStatusMessage(2, pawn, subjectee); subjectee.mindState.lastAssignedInteractTime = Find.TickManager.TicksGame; SnapUtils.AttemptSendSafety(subjectee); return; } if (SOMod.Settings.MessagesEnabled) { SnapUtils.CalmText(this.pawn, Color.green); } if (subjectee.InAggroMentalState) { subjectee.MentalState.RecoverFromState(); if (SOMod.Settings.DisableCath) { subjectee.needs.mood.thoughts.memories.RemoveMemoriesOfDef(ThoughtDefOf.Catharsis); } subjectee.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Wander_Sad); } SnapUtils.DoStatusMessage(1, pawn, subjectee); pawn.needs.mood.thoughts.memories.TryGainMemory(SnapDefOf.HelpedThought, null); pawn.skills.Learn(SkillDefOf.Social, Rand.RangeSeeded(50, 125, Find.TickManager.TicksAbs)); subjectee.jobs.EndCurrentJob(JobCondition.Succeeded); recoverjob.playerForced = true; subjectee.jobs.StartJob(recoverjob, JobCondition.Succeeded); subjectee.mindState.lastAssignedInteractTime = Find.TickManager.TicksGame; }, socialMode = RandomSocialMode.Off, defaultCompleteMode = ToilCompleteMode.Instant, defaultDuration = SOMod.Settings.CalmDuration }; return(toil.WithProgressBarToilDelay(TargetIndex.B)); }
public static Toil FinishDrawWater(TargetIndex drawerIndex) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing thing = curJob.GetTarget(drawerIndex).Thing; if (thing == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } var building = thing as IBuilding_DrinkWater; if (building == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 生産物の生成 // 地下水脈の水の種類から水アイテムの種類を決定 var waterThingDef = MizuUtility.GetWaterThingDefFromWaterType(building.WaterType); if (waterThingDef == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 水アイテムの水源情報を得る var compprop = waterThingDef.GetCompProperties <CompProperties_WaterSource>(); if (compprop == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 地下水脈から水を減らす building.DrawWater(compprop.waterVolume); // 水を生成 var createThing = ThingMaker.MakeThing(waterThingDef); if (createThing == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 個数設定 createThing.stackCount = 1; // 水汲み記録追加 actor.records.AddTo(MizuDef.Record_WaterDrew, 1); // 床置き指定 if (!GenPlace.TryPlaceThing(createThing, actor.Position, actor.Map, ThingPlaceMode.Near, null)) { Log.Error(string.Concat(new object[] { actor, " could not drop recipe product ", thing, " near ", actor.Position })); } actor.jobs.EndCurrentJob(JobCondition.Succeeded, true); return; }; toil.defaultCompleteMode = ToilCompleteMode.Instant; return(toil); }
public static Toil FindStoreCellForCart(TargetIndex CartInd) { const int NearbyCell = 8; const int RegionCellOffset = 16; IntVec3 invalid = new IntVec3(0, 0, 0); #if DEBUG StringBuilder stringBuilder = new StringBuilder(); #endif Toil toil = new Toil(); toil.initAction = () => { IntVec3 storeCell = IntVec3.Invalid; Pawn actor = toil.GetActor(); Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart; if (cart == null) { Log.Error(actor.LabelCap + " Report: Cart is invalid."); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } //Find Valid Storage foreach (IntVec3 cell in GenRadial.RadialCellsAround(cart.Position, NearbyCell, false)) { if (cell.IsValidStorageFor(cart) && ReservationUtility.CanReserveAndReach(actor, cell, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(actor))) { storeCell = cell; #if DEBUG stringBuilder.AppendLine("Found cell: " + storeCell); #endif } } if (storeCell == IntVec3.Invalid) { //Regionwise Flood-fill cellFinder int regionInd = 0; List<Region> regions = new List<Region>(); regions.Add(cart.Position.GetRegion()); #if DEBUG stringBuilder.AppendLine(actor.LabelCap + " Report"); #endif bool flag1 = false; while (regionInd < regions.Count) { #if DEBUG stringBuilder.AppendLine("Region id: " + regions[regionInd].id); #endif if (regions[regionInd].extentsClose.Center.InHorDistOf(cart.Position, NearbyCell + RegionCellOffset)) { IntVec3 foundCell = IntVec3.Invalid; IntVec3 distCell = (regionInd > 0)? regions[regionInd - 1].extentsClose.Center : cart.Position; float distFoundCell = float.MaxValue; foreach (IntVec3 cell in regions[regionInd].Cells) { //Find best cell for placing cart if (cell.GetEdifice() == null && cell.GetZone() == null && cell.Standable() && !GenAdj.CellsAdjacentCardinal(cell, Rot4.North, IntVec2.One).Any(cardinal => cardinal.GetEdifice() is Building_Door) && ReservationUtility.CanReserveAndReach(actor, cell, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(actor))) { if (distCell.DistanceToSquared(cell) < distFoundCell) { foundCell = cell; distFoundCell = distCell.DistanceToSquared(cell); flag1 = true; } } } if (flag1 == true) { storeCell = foundCell; #if DEBUG stringBuilder.AppendLine("Found cell: " + storeCell); #endif break; } foreach (RegionLink link in regions[regionInd].links) { if (regions.Contains(link.RegionA) == false) regions.Add(link.RegionA); if (regions.Contains(link.RegionB) == false) regions.Add(link.RegionB); } } regionInd++; } } //Log.Message(stringBuilder.ToString()); /* //Home Area if (storeCell == IntVec3.Invalid) foreach (IntVec3 cell in Find.AreaHome.ActiveCells.Where(cell => (cell.GetZone() == null || cell.IsValidStorageFor(cart)) && cell.Standable() && cell.GetEdifice() == null)) if (cell.DistanceToSquared(cart.Position) < NearbyCell) storeCell = cell; */ ReservationUtility.Reserve(actor, storeCell); toil.actor.jobs.curJob.targetB = (storeCell != invalid && storeCell != IntVec3.Invalid) ? storeCell : cart.Position; }; return toil; }
private static Toil JumpToCollectNextIntoHandsForBill(Toil gotoGetTargetToil, TargetIndex ind) { Toil toil = new Toil(); toil.initAction = delegate() { Pawn actor = toil.actor; if (actor.carryTracker.CarriedThing == null) { Log.Error("JumpToAlsoCollectTargetInQueue run on " + actor + " who is not carrying something.", false); } else if (!actor.carryTracker.Full) { Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(ind); if (!targetQueue.NullOrEmpty <LocalTargetInfo>()) { for (int i = 0; i < targetQueue.Count; i++) { if (GenAI.CanUseItemForWork(actor, targetQueue[i].Thing)) { if (targetQueue[i].Thing.CanStackWith(actor.carryTracker.CarriedThing)) { if ((float)(actor.Position - targetQueue[i].Thing.Position).LengthHorizontalSquared <= 64f) { int num = (actor.carryTracker.CarriedThing != null) ? actor.carryTracker.CarriedThing.stackCount : 0; int num2 = curJob.countQueue[i]; num2 = Mathf.Min(num2, targetQueue[i].Thing.def.stackLimit - num); num2 = Mathf.Min(num2, actor.carryTracker.AvailableStackSpace(targetQueue[i].Thing.def)); if (num2 > 0) { curJob.count = num2; curJob.SetTarget(ind, targetQueue[i].Thing); List <int> countQueue; int index; (countQueue = curJob.countQueue)[index = i] = countQueue[index] - num2; if (curJob.countQueue[i] <= 0) { curJob.countQueue.RemoveAt(i); targetQueue.RemoveAt(i); } actor.jobs.curDriver.JumpToToil(gotoGetTargetToil); break; } } } } } } } }; return(toil); }
public static Toil TakeAlcoholFromSynthesizer( TargetIndex ind, Pawn eater ) { return TakeFromSynthesier( ind, eater, FoodSynthesis.IsAlcohol, FoodSynthesis.SortAlcohol ); }
public static Toil GoToDineSpot(Pawn pawn, TargetIndex dineSpotInd) { var toil = new Toil(); toil.initAction = () => { Pawn actor = toil.actor; IntVec3 targetPosition = IntVec3.Invalid; var diningSpot = (DiningSpot)actor.CurJob.GetTarget(dineSpotInd).Thing; bool BaseChairValidator(Thing t) { if (t.def.building == null || !t.def.building.isSittable) { return(false); } if (t.IsForbidden(pawn)) { return(false); } if (!actor.CanReserve(t)) { return(false); } if (!t.IsSociallyProper(actor)) { return(false); } if (t.IsBurning()) { return(false); } if (t.HostileTo(pawn)) { return(false); } return(true); } var chair = GenClosest.ClosestThingReachable(diningSpot.Position, diningSpot.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor), 2, t => BaseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None); if (chair == null) { Log.Message($"{pawn.NameShortColored} could not find a chair around {diningSpot.Position}."); if (diningSpot.MayDineStanding) { targetPosition = RCellFinder.SpotToChewStandingNear(actor, diningSpot); var chewSpotDanger = targetPosition.GetDangerFor(pawn, actor.Map); if (chewSpotDanger != Danger.None) { Log.Message($"{pawn.NameShortColored} could not find a save place around {diningSpot.Position} ({chewSpotDanger})."); actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); return; } } } if (chair != null) { targetPosition = chair.Position; actor.Reserve(chair, actor.CurJob); } actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, targetPosition); actor.pather.StartPath(targetPosition, PathEndMode.OnCell); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; return(toil); }
public static Toil DropTheCarriedInCell(TargetIndex StoreCellInd, ThingPlaceMode placeMode, TargetIndex CarrierInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Vehicle_Cart carrier = actor.jobs.curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; if (carrier.storage.Count <= 0) { return; } toil.actor.jobs.curJob.SetTarget(TargetIndex.A, carrier.storage.First()); Thing dropThing = toil.actor.jobs.curJob.targetA.Thing; IntVec3 destLoc = actor.jobs.curJob.GetTarget(StoreCellInd).Cell; Thing dummy; if (destLoc.GetStorable() == null) { Find.DesignationManager.RemoveAllDesignationsOn(dropThing); carrier.storage.TryDrop(dropThing, destLoc, placeMode, out dummy); } //Check cell queue is adjacent List <TargetInfo> cells = curJob.GetTargetQueue(StoreCellInd); for (int i = 0; i < cells.Count && i < carrier.storage.Count; i++) { if (destLoc.AdjacentTo8Way(cells[i].Cell) && cells[i].Cell.GetStorable() == null) { Find.DesignationManager.RemoveAllDesignationsOn(carrier.storage[i]); carrier.storage.TryDrop(carrier.storage[i], cells[i].Cell, ThingPlaceMode.Direct, out dummy); cells.RemoveAt(i); i--; } } //Check item queue is valid storage for adjacent cell foreach (IntVec3 adjCell in GenAdj.CellsAdjacent8Way(destLoc)) { if (carrier.storage.Count > 0 && adjCell.GetStorable() == null && StoreUtility.IsValidStorageFor(adjCell, carrier.storage.First())) { Find.DesignationManager.RemoveAllDesignationsOn(carrier.storage.First()); carrier.storage.TryDrop(carrier.storage.First(), adjCell, ThingPlaceMode.Direct, out dummy); } } }; toil.FailOnDespawned(CarrierInd); return(toil); }
public static new Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode, bool tryStoreInSameStorageIfSpotCantHoldWholeStack = false) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; IntVec3 cell = curJob.GetTarget(cellInd).Cell; if (actor.carryTracker.CarriedThing == null) { Log.Error(string.Concat(actor, " tried to place hauled thing in cell but is not hauling anything.")); } else { SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carryTracker.CarriedThing)) { actor.Map.designationManager.TryRemoveDesignationOn(actor.carryTracker.CarriedThing, DesignationDefOf.Haul); } Action <Thing, int> placedAction = null; if (curJob.def == CultsDefOf.Cults_DoBill /*JobDefOf.DoBill*/ || curJob.def == JobDefOf.RefuelAtomic || curJob.def == JobDefOf.RearmTurretAtomic) { placedAction = delegate(Thing th, int added) { if (curJob.placedThings == null) { curJob.placedThings = new List <ThingCountClass>(); } ThingCountClass thingCountClass = curJob.placedThings.Find((ThingCountClass x) => x.thing == th); if (thingCountClass != null) { thingCountClass.Count += added; } else { curJob.placedThings.Add(new ThingCountClass(th, added)); if (th is Pawn) // inserted code, sacrifice must not move { Pawn sacrifice = (Pawn)th; Job job = JobMaker.MakeJob(Cults.CultsDefOf.Cults_WaitDemise); sacrifice.jobs.TryTakeOrderedJob(job); Log.Message("sacrificing: " + sacrifice.LabelShort.ToString()); } } }; } if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out Thing _, placedAction)) { if (storageMode) { if (nextToilOnPlaceFailOrIncomplete != null && ((tryStoreInSameStorageIfSpotCantHoldWholeStack && StoreUtility.TryFindBestBetterStoreCellForIn(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, cell.GetSlotGroup(actor.Map), out IntVec3 foundCell)) || StoreUtility.TryFindBestBetterStoreCellFor(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell))) { if (actor.CanReserve(foundCell)) { actor.Reserve(foundCell, actor.CurJob); } actor.CurJob.SetTarget(cellInd, foundCell); actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Job job = HaulAIUtility.HaulAsideJobFor(actor, actor.carryTracker.CarriedThing); if (job != null) { curJob.targetA = job.targetA; curJob.targetB = job.targetB; curJob.targetC = job.targetC; curJob.count = job.count; curJob.haulOpportunisticDuplicates = job.haulOpportunisticDuplicates; curJob.haulMode = job.haulMode; actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Log.Error(string.Concat("Incomplete haul for ", actor, ": Could not find anywhere to put ", actor.carryTracker.CarriedThing, " near ", actor.Position, ". Destroying. This should never happen!")); actor.carryTracker.CarriedThing.Destroy(); } } }
// fixes bug for decreased carry capacity public static Toil JumpToCollectNextIntoHandsForBill(Toil gotoGetTargetToil, TargetIndex ind) { var toil = new Toil(); toil.initAction = () => { const float MaxDist = 8; var actor = toil.actor; var curJob = actor.jobs.curJob; var targetQueue = curJob.GetTargetQueue(ind); if (targetQueue.NullOrEmpty()) return; if (actor.carrier.CarriedThing == null) { Log.Error("JumpToAlsoCollectTargetInQueue run on " + actor + " who is not carrying something."); return; } //Find an item in the queue matching what you're carrying for (var i = 0; i < targetQueue.Count; i++) { //Can't use item - skip if (!GenAI.CanUseItemForWork(actor, targetQueue[i].Thing)) continue; //Cannot stack with thing in hands - skip if (!targetQueue[i].Thing.CanStackWith(actor.carrier.CarriedThing)) continue; //Too far away - skip if ((actor.Position - targetQueue[i].Thing.Position).LengthHorizontalSquared > MaxDist * MaxDist) continue; //Determine num in hands var numInHands = actor.carrier.CarriedThing?.stackCount ?? 0; //Determine num to take var numToTake = Mathf.Min(curJob.numToBringList[i], actor.carrier.AvailableStackSpace(targetQueue[i].Thing.def)); //Won't take any - skip if (numToTake == 0) continue; //Remove the amount to take from the num to bring list curJob.numToBringList[i] -= numToTake; //Set pawn to go get it curJob.maxNumToCarry = numInHands + numToTake; curJob.SetTarget(ind, targetQueue[i].Thing); //Remove from queue if I'm going to take all if (curJob.numToBringList[i] == 0) { curJob.numToBringList.RemoveAt(i); targetQueue.RemoveAt(i); } actor.jobs.curDriver.JumpToToil(gotoGetTargetToil); return; } }; return toil; }
public static Toil TakeToItemBelt(TargetIndex ind, int count) { return(Toils_ItemBelt.TakeToItemBelt(ind, () => count)); }
public static Toil CollectInCarrier(TargetIndex CarrierInd, TargetIndex HaulableInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing haulThing = curJob.GetTarget(HaulableInd).Thing; Vehicle_Cart carrier = curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; //Check haulThing is human_corpse. If other race has apparel, It need to change Find.DesignationManager.RemoveAllDesignationsOn(haulThing); if ((haulThing.ThingID.IndexOf("Human_Corpse") <= -1) ? false : true) { Corpse corpse = (Corpse)haulThing; var wornApparel = corpse.innerPawn.apparel.WornApparel; //Drop wornApparel. wornApparel cannot Add to container directly because it will be duplicated. corpse.innerPawn.apparel.DropAll(corpse.innerPawn.Position, false); //Transfer in container foreach (Thing apparel in wornApparel) { if (carrier.storage.TryAdd(apparel)) { apparel.holder = carrier.GetContainer(); apparel.holder.owner = carrier; } } } //Collecting TargetIndex ind if (carrier.storage.TryAdd(haulThing)) { haulThing.holder = carrier.GetContainer(); haulThing.holder.owner = carrier; } List <TargetInfo> thingList = curJob.GetTargetQueue(HaulableInd); for (int i = 0; i < thingList.Count; i++) { if (actor.Position.AdjacentTo8Way(thingList[i].Thing.Position)) { if (carrier.storage.TryAdd(thingList[i].Thing)) { thingList[i].Thing.holder = carrier.GetContainer(); thingList[i].Thing.holder.owner = carrier; } thingList.RemoveAt(i); i--; } } }; toil.FailOn(() => { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing haulThing = curJob.GetTarget(HaulableInd).Thing; Vehicle_Cart carrier = curJob.GetTarget(CarrierInd).Thing as Vehicle_Cart; if (!carrier.storage.CanAcceptAnyOf(haulThing) && actor.Position.IsAdjacentTo8WayOrInside(haulThing.Position, haulThing.Rotation, haulThing.RotatedSize)) { return(true); } return(false); }); toil.FailOnDespawned(CarrierInd); return(toil); }
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); }
// duplicated to make changes public Toil CheckForGetOpportunityDuplicate(Toil getHaulTargetToil, TargetIndex haulableInd, TargetIndex storeCellInd) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; if (actor.carrier.CarriedThing.def.stackLimit == 1) { return; } if (actor.carrier.Full) { return; } int num = curJob.maxNumToCarry - actor.carrier.CarriedThing.stackCount; if (num <= 0) { return; } // call duplicated to make changes (IsValidStorageFor) // NOTE !t.IsInValidStorage() might require optimization Predicate<Thing> validator = (Thing t) => t.SpawnedInWorld && t.def == actor.carrier.CarriedThing.def && !t.IsForbidden(actor) && !t.IsInValidStorage() && (storeCellInd == TargetIndex.None || IsValidStorageFor(curJob.GetTarget(storeCellInd).Cell , t)) && actor.CanReserve(t, 1); Thing thing = GenClosest.ClosestThingReachable(actor.Position, ThingRequest.ForGroup(ThingRequestGroup.HaulableAlways), PathEndMode.ClosestTouch, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), 8f, validator, null, -1, false); if (thing != null) { curJob.SetTarget(haulableInd, thing); actor.jobs.curDriver.SetNextToil(getHaulTargetToil); actor.jobs.curDriver.SetCompleteMode(ToilCompleteMode.Instant); } }; return toil; }
public static Toil ChewIngestible(Pawn chewer, float durationMultiplier, TargetIndex ingestibleInd, TargetIndex eatSurfaceInd = TargetIndex.None) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Thing thing = actor.CurJob.GetTarget(ingestibleInd).Thing; if (!thing.IngestibleNow) { chewer.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } actor.jobs.curDriver.ticksLeftThisToil = Mathf.RoundToInt((float)thing.def.ingestible.baseIngestTicks * durationMultiplier); if (thing.Spawned) { thing.Map.physicalInteractionReservationManager.Reserve(chewer, actor.CurJob, thing); } }; toil.tickAction = delegate { if (chewer != toil.actor) { toil.actor.rotationTracker.FaceCell(chewer.Position); } else { Thing thing = toil.actor.CurJob.GetTarget(ingestibleInd).Thing; if (thing != null && thing.Spawned) { toil.actor.rotationTracker.FaceCell(thing.Position); } else if (eatSurfaceInd != TargetIndex.None && toil.actor.CurJob.GetTarget(eatSurfaceInd).IsValid) { toil.actor.rotationTracker.FaceCell(toil.actor.CurJob.GetTarget(eatSurfaceInd).Cell); } } toil.actor.GainComfortFromCellIfPossible(); }; toil.WithProgressBar(ingestibleInd, delegate { Pawn actor = toil.actor; Thing thing = actor.CurJob.GetTarget(ingestibleInd).Thing; if (thing == null) { return(1f); } return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / Mathf.Round((float)thing.def.ingestible.baseIngestTicks * durationMultiplier)); }, false, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.FailOnDestroyedOrNull(ingestibleInd); toil.AddFinishAction(delegate { if (chewer == null) { return; } if (chewer.CurJob == null) { return; } Thing thing = chewer.CurJob.GetTarget(ingestibleInd).Thing; if (thing == null) { return; } if (chewer.Map.physicalInteractionReservationManager.IsReservedBy(chewer, thing)) { chewer.Map.physicalInteractionReservationManager.Release(chewer, toil.actor.CurJob, thing); } }); toil.handlingFacing = true; Toils_ItemBelt.AddIngestionEffects(toil, chewer, ingestibleInd, eatSurfaceInd); return(toil); }
public static Toil TakeMealFromSynthesizer(TargetIndex ind, Pawn eater) { return(TakeFromSynthesier(ind, eater, FoodSynthesis.IsMeal, FoodSynthesis.SortMeal)); }
private static Toil JumpToCollectNextIntoHandsForBill(Toil gotoGetTargetToil, TargetIndex ind) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; if (actor.carryTracker.CarriedThing == null) { Log.Error(string.Concat("JumpToAlsoCollectTargetInQueue run on ", actor, " who is not carrying something.")); } else if (!actor.carryTracker.Full) { Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(ind); if (!targetQueue.NullOrEmpty()) { int num = 0; int a; while (true) { if (num >= targetQueue.Count) { return; } if (GenAI.CanUseItemForWork(actor, targetQueue[num].Thing) && targetQueue[num].Thing.CanStackWith(actor.carryTracker.CarriedThing) && !((float)(actor.Position - targetQueue[num].Thing.Position).LengthHorizontalSquared > 64f)) { int num2 = (actor.carryTracker.CarriedThing != null) ? actor.carryTracker.CarriedThing.stackCount : 0; a = curJob.countQueue[num]; a = Mathf.Min(a, targetQueue[num].Thing.def.stackLimit - num2); a = Mathf.Min(a, actor.carryTracker.AvailableStackSpace(targetQueue[num].Thing.def)); if (a > 0) { break; } } num++; } curJob.count = a; curJob.SetTarget(ind, targetQueue[num].Thing); curJob.countQueue[num] -= a; if (curJob.countQueue[num] <= 0) { curJob.countQueue.RemoveAt(num); targetQueue.RemoveAt(num); } actor.jobs.curDriver.JumpToToil(gotoGetTargetToil); } } }; return(toil); }
public static TargetInfo Target( this JobDriver obj, TargetIndex Ind ) { return obj.pawn.CurJob.GetTarget( Ind ); }
public static Toil Enslave( TargetIndex PrisonerInd, TargetIndex CollarInd ) { var toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.defaultDuration = 250; toil.WithProgressBarToilDelay( PrisonerInd ); toil.AddFinishAction( () => { try { var prisoner = toil.actor.CurJob.GetTarget( PrisonerInd ).Thing as Pawn; var collar = toil.actor.CurJob.GetTarget( CollarInd ).Thing as Apparel; var compPrisoner = prisoner.TryGetComp<CompPrisoner>(); if( ( prisoner == null ) || ( collar == null ) || ( compPrisoner == null ) ) { throw new Exception( string.Format( "prisoner = {0}\n\tcollar = {1}\n\tcompPrisoner = {2}", prisoner == null ? "null" : prisoner.ThingID, collar == null ? "null" : collar.ThingID, compPrisoner == null ? "null" : "valid" ) ); } if( prisoner.apparel == null ) { throw new Exception( "Prisoner " + prisoner.Name + " is missing Pawn_ApparelTracker!" ); } // Make sure the prisoner has worksettings if( prisoner.workSettings == null ) { prisoner.workSettings = new Pawn_WorkSettings( prisoner ); prisoner.workSettings.Disable( WorkTypeDefOf.Warden ); } // Get the prisoners original faction and pawk kind compPrisoner.originalFaction = prisoner.Faction; compPrisoner.originalPawnKind = prisoner.kindDef; // Assign the prisoner faction and pawn kind then update guest status prisoner.SetFaction( Faction.OfPlayer ); prisoner.kindDef = Data.PawnKindDefOf.Slave; prisoner.guest.SetGuestStatus( Faction.OfPlayer, true ); // Now put the collar on the prisoner toil.actor.inventory.container.Remove( collar ); compPrisoner.ForceApparelOnPawn( prisoner, collar ); // Update the interaction mode prisoner.guest.interactionMode = PrisonerInteractionMode.NoInteraction; // Update doors Data.UpdateAllDoors(); } catch( Exception e ) { Log.Error( "Prisoners & Slaves :: Could not enslave prisoner!\n\t" + e.Message ); } } ); return toil; }
public static Thing TargetThing( this JobDriver obj, TargetIndex Ind ) { return obj.Target( Ind ).Thing; }
public static Toil ReleaseAnimalCart(TargetIndex CartInd) { Toil toil = new Toil(); toil.initAction = () => { Pawn actor = toil.GetActor(); Vehicle_Cart cart = toil.actor.jobs.curJob.GetTarget(CartInd).Thing as Vehicle_Cart; if (cart == null) { Log.Error(actor.LabelCap + " Report: Cart is invalid."); toil.actor.jobs.curDriver.EndJobWith(JobCondition.Errored); } if (cart.mountableComp.IsMounted && cart.mountableComp.Driver.CurJob.def == jobDefStandby) cart.mountableComp.Driver.jobs.curDriver.EndJobWith(JobCondition.Succeeded); }; return toil; }
public static Toil JumpIfAlsoCollectingNextTargetInQueue(Toil gotoGetTargetToil, TargetIndex ind) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(ind); if (!targetQueue.NullOrEmpty() && curJob.count > 0) { if (actor.carryTracker.CarriedThing == null) { Log.Error("JumpToAlsoCollectTargetInQueue run on " + actor + " who is not carrying something."); } else if (actor.carryTracker.AvailableStackSpace(actor.carryTracker.CarriedThing.def) > 0) { int num = 0; while (true) { if (num >= targetQueue.Count) { return; } if (!GenAI.CanUseItemForWork(actor, targetQueue[num].Thing)) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } if (targetQueue[num].Thing.def == actor.carryTracker.CarriedThing.def) { break; } num++; } curJob.SetTarget(ind, targetQueue[num].Thing); targetQueue.RemoveAt(num); actor.jobs.curDriver.JumpToToil(gotoGetTargetToil); } } }; return(toil); }
public void AddQueuedTarget(TargetIndex ind, LocalTargetInfo target) { this.GetTargetQueue(ind).Add(target); }