public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { Job job = JobMaker.MakeJob(Globals.AutocleanerClean); job.AddQueuedTarget(TargetIndex.A, t); int num = 15; Map map = t.Map; Room room = t.GetRoom(RegionType.Set_Passable); for (int i = 0; i < 100; i++) { IntVec3 intVec = t.Position + GenRadial.RadialPattern[i]; if (intVec.InBounds(map) && intVec.GetRoom(map, RegionType.Set_Passable) == room) { List <Thing> thingList = intVec.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { Thing thing = thingList[j]; if (HasJobOnThing(pawn, thing, forced) && thing != t) { job.AddQueuedTarget(TargetIndex.A, thing); } } if (job.GetTargetQueue(TargetIndex.A).Count >= num) { break; } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { var job = new Job(JobDefOf.Clean); job.AddQueuedTarget(TargetIndex.A, t); var num = 15; var map = t.Map; var room = t.GetRoom(RegionType.Set_Passable); for (var i = 0; i < 100; i++) { var intVec = t.Position + GenRadial.RadialPattern[i]; if (intVec.InBounds(map) && intVec.GetRoom(map, RegionType.Set_Passable) == room) { var thingList = intVec.GetThingList(map); for (var j = 0; j < thingList.Count; j++) { var thing = thingList[j]; if (HasJobOnThing(pawn, thing, forced) && thing != t) { job.AddQueuedTarget(TargetIndex.A, thing); } } if (job.GetTargetQueue(TargetIndex.A).Count >= num) { break; } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { job.targetQueueA.SortBy(targ => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.Map == null) { return(null); } if (!pawn.story.WorkTagIsDisabled(WorkTags.Cleaning) && pawn.Map.listerFilthInHomeArea.FilthInHomeArea.Count > 0) { Thing closestFilth = pawn.Map.listerFilthInHomeArea.FilthInHomeArea.RandomElement(); if (closestFilth != null && pawn.CanReserveAndReach(closestFilth, PathEndMode.Touch, Danger.Some)) { Job job = new Job(JobDefOf.Clean); job.AddQueuedTarget(TargetIndex.A, closestFilth); int num = 15; Map map = closestFilth.Map; Room room = closestFilth.GetRoom(RegionType.Set_Passable); for (int i = 0; i < 100; i++) { IntVec3 intVec = closestFilth.Position + GenRadial.RadialPattern[i]; if (intVec.InBounds(map) && intVec.GetRoom(map, RegionType.Set_Passable) == room) { List <Thing> thingList = intVec.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { Thing thing = thingList[j]; if (thing != closestFilth && IsValidFilth(pawn, thing)) { job.AddQueuedTarget(TargetIndex.A, thing); } } if (job.GetTargetQueue(TargetIndex.A).Count >= num) { break; } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); } } if (!pawn.story.WorkTagIsDisabled(WorkTags.Hauling) && pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling().Count > 0) { Thing thing = pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling().RandomElement(); if (thing != null && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, true) && pawn.CanReserveAndReach(thing, PathEndMode.Touch, Danger.Some)) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } } return(null); }
private bool TryGiveWeaponRepairJob2ToPawn(Pawn pawn) { if (!CanBeRepaired) { return(false); } Building workTable = GetClosestValidWorktable(pawn); Thing thingMain = parent; List <Thing> thingIngredients = GetAvailableRepairThings(pawn, GetNeededRepairMaterialsRaw()); if (workTable == null || thingMain == null || thingIngredients == null || thingIngredients.Count == 0) { return(false); } if (JobDriver_WeaponRepairTwo2One.maxAllowedRepair != Props.maxRepair) { JobDriver_WeaponRepairTwo2One.maxAllowedRepair = Props.maxRepair; } Job job = new Job(Props.jobDef, workTable, thingMain, thingIngredients[0]); foreach (Thing thingIngredient in thingIngredients) { if (thingIngredient == thingIngredients[0]) { continue; } job.AddQueuedTarget(TargetIndex.C, thingIngredient); } job.count = 1; return(pawn.jobs.TryTakeOrderedJob(job)); }
public override Job JobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { Job job = new Job(JobDefOf.Harvest); Map map = pawn.Map; Room room = c.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 intVec = c + GenRadial.RadialPattern[i]; if (intVec.GetRoom(map, RegionType.Set_Passable) == room) { if (this.HasJobOnCell(pawn, intVec, false)) { Plant plant = intVec.GetPlant(map); if (!(intVec != c) || plant.def == WorkGiver_Grower.CalculateWantedPlantDef(intVec, map)) { num += plant.def.plant.harvestWork; if (intVec != c && num > 2400f) { break; } job.AddQueuedTarget(TargetIndex.A, plant); } } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public override Job JobOnCell(Pawn pawn, IntVec3 c) { Job job = new Job(ZenDefOf.ZEN_PlantsHarvestSecondary); Map map = pawn.Map; Room room = c.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 c2 = c + GenRadial.RadialPattern[i]; if (c.GetRoom(map, RegionType.Set_Passable) == room) { if (HasJobOnCell(pawn, c2)) { Plant plant = c2.GetPlant(map); num += 250; if (num > 2400f) { break; } job.AddQueuedTarget(TargetIndex.A, plant); } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public override Job JobOnCell(Pawn pawn, IntVec3 c) { Job job = new Job(JobDefOf.Harvest); Map map = pawn.Map; Room room = c.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 c2 = c + GenRadial.RadialPattern[i]; if (c.GetRoom(map, RegionType.Set_Passable) == room && this.HasJobOnCell(pawn, c2)) { Plant plant = c2.GetPlant(map); num += plant.def.plant.harvestWork; if (!(num > 2400.0)) { job.AddQueuedTarget(TargetIndex.A, plant); continue; } break; } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
protected override IEnumerable <Toil> MakeNewToils() { //this.FailOn(() => PawnUtility.PlayerForcedJobNowOrSoon(pawn)); this.FailOn(() => pawn.health.Downed); this.FailOn(() => pawn.IsBurning()); this.FailOn(() => pawn.IsFighting()); this.FailOn(() => pawn.Drafted); //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); // Faster fapping when frustrated. ticks_left = (int)(xxx.need_some_sex(pawn) > 2f ? 2500.0f * Rand.Range(0.2f, 0.7f) : 2500.0f * Rand.Range(0.2f, 0.4f)); Toil findfapspot = new Toil { initAction = delegate { pawn.pather.StartPath(cell, PathEndMode.OnCell); }, defaultCompleteMode = ToilCompleteMode.PatherArrival }; yield return(findfapspot); //Log.Message("[RJW] Making new toil for QuickFap."); Toil fap = Toils_General.Wait(ticks_left); fap.tickAction = delegate { --ticks_left; xxx.reduce_rest(pawn, 1); if (ticks_left <= 0) { ReadyForNextToil(); } else if (pawn.IsHashIntervalTick(ticks_between_hearts)) { MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart); } }; fap.AddFinishAction(delegate { SexUtility.Aftersex(pawn, xxx.rjwSextype.Masturbation); if (!SexUtility.ConsiderCleaning(pawn)) { return; } LocalTargetInfo own_cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = new Job(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, own_cum); pawn.jobs.jobQueue.EnqueueFirst(clean); }); yield return(fap); }
public static void AddFilthToQueue(Job j, TargetIndex ind, IEnumerable <Filth> l, Pawn pawn) { foreach (Filth f in (l)) { j.AddQueuedTarget(ind, f); } OptimizePath(j.GetTargetQueue(ind), pawn); }
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { var job = new Job(DefDatabase <JobDef> .GetNamed("Clean_Prioritized")); job.AddQueuedTarget(TargetIndex.A, t); var map = t.Map; var maxQueued = 15; var room = t.GetRoom(); for (var i = 0; i < 100; i++) { var intVec = t.Position + GenRadial.RadialPattern[i]; if (!intVec.InBounds(map) || intVec.GetRoom(map) != room) { continue; } var thingList = intVec.GetThingList(map); foreach (var thing in thingList) { if (HasJobOnThing(pawn, thing, forced) && thing != t) { job.AddQueuedTarget(TargetIndex.A, thing); } } if (job.GetTargetQueue(TargetIndex.A).Count >= maxQueued) { break; } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { job.targetQueueA.SortBy(targ => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { if (t.def.category != ThingCategory.Plant) { return(null); } if (!(t is PlantWithSecondary)) { return(null); } PlantWithSecondary plant = (PlantWithSecondary)t; if (!plant.Sec_HarvestableNow) { return(null); } Job job = new Job(ZenDefOf.ZEN_PlantsHarvestSecondary); Map map = pawn.Map; Room room = t.Position.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 c2 = t.Position + GenRadial.RadialPattern[i]; if (c2.GetRoom(map, RegionType.Set_Passable) == room) { if (HasHarvestJobOnCell(pawn, c2)) { num += 250f; if (num > 2400f) { break; } job.AddQueuedTarget(TargetIndex.A, plant); } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
protected override IEnumerable <Toil> MakeNewToils() { // Faster fapping when frustrated. //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); ticks_left = (int)(xxx.need_some_sex(pawn) > 2f ? 2500.0f * Rand.Range(0.2f, 0.7f) : 2500.0f * Rand.Range(0.2f, 0.4f)); this.FailOnDespawnedOrNull(ibed); this.FailOn(() => pawn.Drafted); this.KeepLyingDown(ibed); yield return(Toils_Bed.ClaimBedIfNonMedical(ibed)); yield return(Toils_Bed.GotoBed(ibed)); Toil do_fappin = Toils_LayDown.LayDown(ibed, true, false, false, false); do_fappin.AddPreTickAction(delegate { --ticks_left; xxx.reduce_rest(pawn, 1); if (ticks_left <= 0) { ReadyForNextToil(); } else if (pawn.IsHashIntervalTick(ticks_between_hearts)) { MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart); } }); do_fappin.AddFinishAction(delegate { //Moved satisfy and tick increase to aftersex, since it works with solo acts now. SexUtility.Aftersex(pawn, xxx.rjwSextype.Masturbation); if (SexUtility.ConsiderCleaning(pawn)) { LocalTargetInfo own_cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = new Job(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, own_cum); pawn.jobs.jobQueue.EnqueueFirst(clean); } }); do_fappin.socialMode = RandomSocialMode.Off; yield return(do_fappin); }
protected override Job TryGiveJob(Pawn pawn) { Predicate <Thing> filth = f => f.def.category == ThingCategory.Filth; Thing closestThing = null; //Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Filth), PathEndMode.ClosestTouch, //TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 300f, filth, null, 0, -1, false, RegionType.Set_Passable, false); if (pawn != null && pawn.Map != null) { List <Thing> filthList = pawn.Map.listerFilthInHomeArea.FilthInHomeArea; if (filthList != null && filthList.Count > 0) { for (int i = 0; i < filthList.Count; i++) { if (!filthList[i].Position.IsForbidden(pawn) && pawn.CanReserve(filthList[i], 1, -1, ReservationLayerDefOf.Floor, false) && pawn.CanReach(filthList[i], PathEndMode.Touch, Danger.Deadly, false, false, TraverseMode.ByPawn)) { Thing thing = filthList[i]; if (closestThing != null && thing != null && (thing.Position - pawn.Position).LengthHorizontal < (closestThing.Position - pawn.Position).LengthHorizontal) { closestThing = thing; } else if (closestThing == null)// && (pawn.CanReserve(closestThing))) { closestThing = thing; } else { //do nothing } } } } if (closestThing != null && pawn.CanReserve(closestThing)) { Job job = new Job(JobDefOf.Clean); job.AddQueuedTarget(TargetIndex.A, closestThing); return(job); } } return(null); }
protected override Job TryGiveJob(Pawn pawn) { Predicate <Thing> filth = f => f.def.category == ThingCategory.Filth; //Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Filth), PathEndMode.ClosestTouch, // TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 300f, filth, null, 0, -1, false, RegionType.Set_Passable, false); List <Thing> filthList = pawn.Map.listerFilthInHomeArea.FilthInHomeArea; for (int i = 0; i < filthList.Count; i++) { if (pawn.CanReserve(filthList[i], 1, -1, ReservationLayerDefOf.Floor, false)) { Thing thing = filthList[i]; if (thing != null && pawn.CanReserve(thing)) { Job job = new Job(JobDefOf.Clean); job.AddQueuedTarget(TargetIndex.A, thing); return(job); } } } return(null); }
protected override IEnumerable <Toil> MakeNewToils() { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - making toils"); setup_ticks(); this.FailOnDespawnedOrNull(iTarget); this.FailOnDespawnedNullOrForbidden(iBed); //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() fail conditions check " + !xxx.CanUse(pawn, Bed) + " " + !pawn.CanReserve(Partner)); this.FailOn(() => !xxx.CanUse(pawn, Bed) || !pawn.CanReserve(Partner)); this.FailOn(() => pawn.Drafted); this.FailOn(() => Partner.IsFighting()); this.FailOn(() => !Partner.CanReach(pawn, PathEndMode.Touch, Danger.Deadly)); yield return(Toils_Reserve.Reserve(iTarget, 1, 0)); //yield return Toils_Reserve.Reserve(BedInd, Bed.SleepingSlotsCount, 0); //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - generate toils"); Toil gotoBed = new Toil(); gotoBed.defaultCompleteMode = ToilCompleteMode.PatherArrival; gotoBed.FailOnWhorebedNoLongerUsable(iBed, Bed); gotoBed.AddFailCondition(() => Partner.Downed); gotoBed.FailOn(() => !Partner.CanReach(Bed, PathEndMode.Touch, Danger.Deadly)); gotoBed.initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - gotoWhoreBed initAction is called"); pawn.pather.StartPath(SleepSpot, PathEndMode.OnCell); Partner.jobs.StopAll(); Job job = JobMaker.MakeJob(JobDefOf.GotoMindControlled, SleepSpot); Partner.jobs.StartJob(job, JobCondition.InterruptForced); }; yield return(gotoBed); ticks_left = (int)(2000.0f * Rand.Range(0.30f, 1.30f)); Toil waitInBed = new Toil(); waitInBed.initAction = delegate { ticksLeftThisToil = 5000; }; waitInBed.tickAction = delegate { pawn.GainComfortFromCellIfPossible(); if (IsInOrByBed(Bed, Partner) && pawn.PositionHeld == Partner.PositionHeld) { ReadyForNextToil(); } }; waitInBed.defaultCompleteMode = ToilCompleteMode.Delay; yield return(waitInBed); Toil StartPartnerJob = new Toil(); StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant; StartPartnerJob.socialMode = RandomSocialMode.Off; StartPartnerJob.initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - StartPartnerJob"); var gettin_loved = JobMaker.MakeJob(xxx.gettin_loved, pawn, Bed); Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced); }; yield return(StartPartnerJob); Toil loveToil = new Toil(); loveToil.AddFailCondition(() => Partner.Dead || Partner.CurJobDef != xxx.gettin_loved); loveToil.defaultCompleteMode = ToilCompleteMode.Never; loveToil.socialMode = RandomSocialMode.Off; loveToil.handlingFacing = true; loveToil.initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - loveToil"); // TODO: replace this quick n dirty way CondomUtility.GetCondomFromRoom(pawn); // Try to use w***e's condom first, then client's usedCondom = CondomUtility.TryUseCondom(pawn) || CondomUtility.TryUseCondom(Partner); Start(); if (xxx.HasNonPolyPartnerOnCurrentMap(Partner)) { Pawn lover = LovePartnerRelationUtility.ExistingLovePartner(Partner); // We have to do a few other checks because the pawn might have multiple lovers and ExistingLovePartner() might return the wrong one if (lover != null && pawn != lover && !lover.Dead && (lover.Map == Partner.Map || Rand.Value < 0.25)) { lover.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, Partner); } } }; loveToil.AddPreTickAction(delegate { --ticks_left; if (pawn.IsHashIntervalTick(ticks_between_hearts)) { if (xxx.is_nympho(pawn)) { ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart); } else { ThrowMetaIcon(pawn.Position, pawn.Map, xxx.mote_noheart); } } SexUtility.reduce_rest(Partner, 1); SexUtility.reduce_rest(pawn, 2); if (ticks_left <= 0) { ReadyForNextToil(); } }); loveToil.AddFinishAction(delegate { End(); }); yield return(loveToil); Toil afterSex = new Toil { initAction = delegate { // Adding interactions, social logs, etc SexUtility.ProcessSex(pawn, Partner, usedCondom: usedCondom, whoring: isWhoring, sextype: sexType); if (!(Partner.IsColonist && (pawn.IsPrisonerOfColony || pawn.IsColonist))) { int price = WhoringHelper.PriceOfWhore(pawn); //--Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Partner should pay the price now in afterSex.initAction"); int remainPrice = WhoringHelper.PayPriceToWhore(Partner, price, pawn); /*if (remainPrice <= 0) * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price is success"); * } * else * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price failed"); * }*/ xxx.UpdateRecords(pawn, price - remainPrice); } var thought = (pawn.IsPrisoner || xxx.is_slave(pawn)) ? thought_captive : thought_free; pawn.needs.mood.thoughts.memories.TryGainMemory(thought); if (SexUtility.ConsiderCleaning(pawn)) { LocalTargetInfo cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = JobMaker.MakeJob(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, cum); pawn.jobs.jobQueue.EnqueueFirst(clean); } }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(afterSex); }
protected override Job TryGiveJob(Pawn pawn) { if (ShouldSkip(pawn)) { return(null); } Predicate <Thing> predicate = (Thing x) => x.def.category == ThingCategory.Filth && HasJobOnThing(pawn, x); Thing t = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Filth), PathEndMode, TraverseParms.For(pawn, Danger.Some, TraverseMode.ByPawn), 100f, predicate, PotentialWorkThingsGlobal(pawn)); if (t is null) { return(null); } Job job = JobMaker.MakeJob(JobDefOf.Clean); job.AddQueuedTarget(TargetIndex.A, t); int num = 15; Map map = t.Map; Room room = t.GetRoom(); for (int i = 0; i < 100; i++) { IntVec3 c2 = t.Position + GenRadial.RadialPattern[i]; if (!ShouldClean(c2)) { continue; } List <Thing> thingList = c2.GetThingList(map); for (int j = 0; j < thingList.Count; j++) { Thing thing = thingList[j]; if (HasJobOnThing(pawn, thing) && thing != t) { job.AddQueuedTarget(TargetIndex.A, thing); } } if (job.GetTargetQueue(TargetIndex.A).Count >= num) { break; } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); bool ShouldClean(IntVec3 c) { if (!c.InBounds(map)) { return(false); } Room room2 = c.GetRoom(map); if (room == room2) { return(true); } Region region = c.GetDoor(map)?.GetRegion(RegionType.Portal); if (region != null && !region.links.NullOrEmpty()) { for (int k = 0; k < region.links.Count; k++) { RegionLink regionLink = region.links[k]; for (int l = 0; l < 2; l++) { if (regionLink.regions[l] != null && regionLink.regions[l] != region && regionLink.regions[l].valid && regionLink.regions[l].Room == room) { return(true); } } } } return(false); } }
protected override IEnumerable <Toil> MakeNewToils() { setup_ticks(); //this.FailOn(() => PawnUtility.PlayerForcedJobNowOrSoon(pawn)); this.FailOn(() => pawn.health.Downed); this.FailOn(() => pawn.IsBurning()); this.FailOn(() => pawn.IsFighting()); this.FailOn(() => pawn.Drafted); Toil findfapspot = new Toil { initAction = delegate { pawn.pather.StartPath(cell, PathEndMode.OnCell); }, defaultCompleteMode = ToilCompleteMode.PatherArrival }; yield return(findfapspot); //Log.Message("[RJW] Making new toil for QuickFap."); Toil fap = Toils_General.Wait(duration); fap.handlingFacing = true; fap.initAction = delegate { Start(); }; fap.tickAction = delegate { --duration; if (pawn.IsHashIntervalTick(ticks_between_hearts)) { ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart); } SexTick(pawn, null); SexUtility.reduce_rest(pawn, 1); if (duration <= 0) { ReadyForNextToil(); } }; fap.AddFinishAction(delegate { End(); }); yield return(fap); yield return(new Toil { initAction = delegate { SexUtility.Aftersex(pawn, xxx.rjwSextype.Masturbation); if (!SexUtility.ConsiderCleaning(pawn)) { return; } LocalTargetInfo own_cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = JobMaker.MakeJob(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, own_cum); pawn.jobs.jobQueue.EnqueueFirst(clean); }, defaultCompleteMode = ToilCompleteMode.Instant }); }
protected override IEnumerable <Toil> MakeNewToils() { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - making toils"); this.FailOnDespawnedOrNull(PartnerInd); this.FailOnDespawnedNullOrForbidden(BedInd); //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() fail conditions check " + (Actor is null) + " " + !xxx.CanUse(Actor, Bed) + " " + !Actor.CanReserve(Partner)); this.FailOn(() => Actor is null || !xxx.CanUse(Actor, Bed) || !Actor.CanReserve(Partner)); this.FailOn(() => pawn.Drafted); int price = WhoringHelper.PriceOfWhore(Actor); yield return(Toils_Reserve.Reserve(PartnerInd, 1, 0)); //yield return Toils_Reserve.Reserve(BedInd, Bed.SleepingSlotsCount, 0); bool partnerHasPenis = Genital_Helper.has_penis(Partner) || Genital_Helper.has_penis_infertile(Partner); Toil gotoWhoreBed = new Toil { initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - gotoWhoreBed initAction is called"); Actor.pather.StartPath(WhoreSleepSpot, PathEndMode.OnCell); Partner.jobs.StopAll(); Partner.pather.StartPath(WhoreSleepSpot, PathEndMode.Touch); }, tickAction = delegate { if (Partner.IsHashIntervalTick(150)) { Partner.pather.StartPath(Actor, PathEndMode.Touch); //Log.Message(xxx.get_pawnname(Partner) + ": I'm following the w***e"); } }, defaultCompleteMode = ToilCompleteMode.PatherArrival }; gotoWhoreBed.FailOnWhorebedNoLongerUsable(BedInd, Bed); yield return(gotoWhoreBed); Toil waitInBed = new Toil { initAction = delegate { //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); //Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - waitInBed, initAction is called"); ticksLeftThisToil = 5000; ticks_left = (int)(2000.0f * Rand.Range(0.30f, 1.30f)); //Actor.pather.StopDead(); //Let's just make w****s standing at the bed //JobDriver curDriver = Actor.jobs.curDriver; //curDriver.layingDown = LayingDownState.LayingInBed; //curDriver.asleep = false; var gettin_loved = new Job(xxx.gettin_loved, Actor, Bed); Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced); }, tickAction = delegate { Actor.GainComfortFromCellIfPossible(); if (IsInOrByBed(Bed, Partner)) { //Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - waitInBed, tickAction pass"); ticksLeftThisToil = 0; } }, defaultCompleteMode = ToilCompleteMode.Delay, }; waitInBed.FailOn(() => pawn.GetRoom() == null); yield return(waitInBed); bool canAfford = WhoringHelper.CanAfford(Partner, Actor, price); if (canAfford) { Toil loveToil = new Toil { initAction = delegate { //Actor.jobs.curDriver.ticksLeftThisToil = 1200; //Using ticks_left to control the time of sex //--Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - loveToil, setting initAction"); /* * //Hoge: W***e is just work. no feel cheatedOnMe. * if (xxx.HasNonPolyPartner(Actor)) * { * Pawn pawn = LovePartnerRelationUtility.ExistingLovePartner(Actor); * if (((Partner != pawn) && !pawn.Dead) && ((pawn.Map == Actor.Map) || (Rand.Value < 0.15))) * { * pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, Actor); * } * } */ if (xxx.HasNonPolyPartnerOnCurrentMap(Partner)) { Pawn lover = LovePartnerRelationUtility.ExistingLovePartner(Partner); //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); // We have to do a few other checks because the pawn might have multiple lovers and ExistingLovePartner() might return the wrong one if (lover != null && Actor != lover && !lover.Dead && (lover.Map == Partner.Map || Rand.Value < 0.25)) { lover.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, Partner); } } if (!partnerHasPenis) { Actor.rotationTracker.Face(Partner.DrawPos); } }, defaultCompleteMode = ToilCompleteMode.Never, //Changed from Delay }; loveToil.AddPreTickAction(delegate { //Actor.Reserve(Partner, 1, 0); --ticks_left; xxx.reduce_rest(Partner); xxx.reduce_rest(Actor, 2); if (ticks_left <= 0) { ReadyForNextToil(); } else if (pawn.IsHashIntervalTick(ticks_between_hearts)) { MoteMaker.ThrowMetaIcon(Actor.Position, Actor.Map, ThingDefOf.Mote_Heart); } Actor.GainComfortFromCellIfPossible(); Partner.GainComfortFromCellIfPossible(); }); loveToil.AddFinishAction(delegate { //Log.Message("[RJW] JobDriver_WhoreIsServingVisitors::MakeNewToils() - finished loveToil"); //// Trying to add some interactions and social logs //xxx.processAnalSex(Partner, Actor, ref isAnalSex, partnerHasPenis); }); loveToil.AddFailCondition(() => Partner.Dead || !IsInOrByBed(Bed, Partner)); loveToil.socialMode = RandomSocialMode.Off; yield return(loveToil); Toil afterSex = new Toil { initAction = delegate { // Adding interactions, social logs, etc SexUtility.ProcessSex(Actor, Partner, false, false, true); //--Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Partner should pay the price now in afterSex.initAction"); int remainPrice = WhoringHelper.PayPriceToWhore(Partner, price, Actor); /*if (remainPrice <= 0) * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price is success"); * } * else * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price failed"); * }*/ xxx.UpdateRecords(Actor, price - remainPrice); var thought = (Actor.IsPrisoner) ? thought_captive : thought_free; pawn.needs.mood.thoughts.memories.TryGainMemory(thought); if (SexUtility.ConsiderCleaning(pawn)) { LocalTargetInfo cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = new Job(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, cum); pawn.jobs.jobQueue.EnqueueFirst(clean); } }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(afterSex); } }
public override Job JobOnCell(Pawn pawn, IntVec3 cell) { // モップジョブ作成 Job job = new Job(MizuDef.Job_Mop); job.AddQueuedTarget(TargetIndex.A, cell); // 一番近いモップを探す Thing candidateMop = null; int minDist = int.MaxValue; var mopList = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways).Where((t) => t.def == MizuDef.Thing_Mop); foreach (var mop in mopList) { // 予約できないモップはパス if (!pawn.CanReserve(mop)) { continue; } int mopDist = (mop.Position - pawn.Position).LengthHorizontalSquared; if (minDist > mopDist) { minDist = mopDist; candidateMop = mop; } } if (candidateMop == null) { Log.Error("candidateMop is null"); return(null); } // モップをTargetBにセット job.targetB = candidateMop; job.count = 1; var compTool = candidateMop.TryGetComp <CompWaterTool>(); int maxQueueLength = Mathf.RoundToInt(compTool.StoredWaterVolume / JobDriver_Mop.ConsumeWaterVolume); Map map = pawn.Map; Room room = cell.GetRoom(map); for (int i = 0; i < 100; i++) { // 対象の汚れの周囲100マスをサーチ IntVec3 intVec = cell + GenRadial.RadialPattern[i]; if (intVec.InBounds(map) && intVec.GetRoom(map, RegionType.Set_Passable) == room) { // そこが同じ部屋の中 if (this.HasJobOnCell(pawn, intVec) && intVec != cell) { // 同じジョブが作成可能(汚れがある等)あるならこのジョブの処理対象に追加 job.AddQueuedTarget(TargetIndex.A, intVec); } // 掃除最大個数チェック if (job.GetTargetQueue(TargetIndex.A).Count >= maxQueueLength) { break; } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { // 掃除対象が5個以上あるならポーンからの距離が近い順に掃除させる job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public override Job JobOnCell(Pawn pawn, IntVec3 cell) { // ジョブ作成 Job job = new Job(MizuDef.Job_WaterFarm); job.AddQueuedTarget(TargetIndex.A, cell); // 一番近いツールを探す Thing candidateTool = null; int minDist = int.MaxValue; var toolList = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways).Where((t) => { // 使用禁止チェック if (t.IsForbidden(pawn)) { return(false); } var comp = t.TryGetComp <CompWaterTool>(); if (comp == null) { return(false); } if (!comp.UseWorkType.Contains(CompProperties_WaterTool.UseWorkType.WaterFarm)) { return(false); } int maxQueueLengthForCheck = (int)Mathf.Floor(comp.StoredWaterVolume / JobDriver_WaterFarm.ConsumeWaterVolume); if (maxQueueLengthForCheck <= 0) { return(false); } return(true); }); foreach (var tool in toolList) { // 予約できないツールはパス if (!pawn.CanReserve(tool)) { continue; } int toolDist = (tool.Position - pawn.Position).LengthHorizontalSquared; if (minDist > toolDist) { minDist = toolDist; candidateTool = tool; } } if (candidateTool == null) { Log.Error("candidateTool is null"); return(null); } // ツールをTargetBにセット job.targetB = candidateTool; job.count = 1; var compTool = candidateTool.TryGetComp <CompWaterTool>(); int maxQueueLength = Mathf.RoundToInt(compTool.StoredWaterVolume / JobDriver_WaterFarm.ConsumeWaterVolume); Map map = pawn.Map; Room room = cell.GetRoom(map); for (int i = 0; i < 100; i++) { // 対象のセルの周囲100マスをサーチ IntVec3 intVec = cell + GenRadial.RadialPattern[i]; if (intVec.InBounds(map) && intVec.GetRoom(map, RegionType.Set_Passable) == room) { // そこが同じ部屋の中 if (this.HasJobOnCell(pawn, intVec) && intVec != cell) { // 同じジョブが作成可能であるならこのジョブの処理対象に追加 job.AddQueuedTarget(TargetIndex.A, intVec); } // 最大個数チェック if (job.GetTargetQueue(TargetIndex.A).Count >= maxQueueLength) { break; } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { // 対象が5個以上あるならポーンからの距離が近い順に仕事をさせる job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public override Job JobOnCell(Pawn pawn, IntVec3 cell, bool forced = false) { // モップジョブ作成 var job = new Job(MizuDef.Job_Mop); job.AddQueuedTarget(TargetIndex.A, cell); // 一番近いモップを探す Thing candidateMop = null; var minDist = int.MaxValue; var mopList = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways).Where( t => { // 使用禁止チェック if (t.IsForbidden(pawn)) { return(false); } var comp = t.TryGetComp <CompWaterTool>(); if (comp == null) { return(false); } if (!comp.UseWorkType.Contains(CompProperties_WaterTool.UseWorkType.Mop)) { return(false); } var maxQueueLengthForCheck = (int)Mathf.Floor(comp.StoredWaterVolume / JobDriver_Mop.ConsumeWaterVolume); if (maxQueueLengthForCheck <= 0) { return(false); } return(true); }); foreach (var mop in mopList) { // 予約できないモップはパス if (!pawn.CanReserve(mop)) { continue; } var mopDist = (mop.Position - pawn.Position).LengthHorizontalSquared; if (minDist <= mopDist) { continue; } minDist = mopDist; candidateMop = mop; } if (candidateMop == null) { Log.Error("candidateMop is null"); return(null); } // モップをTargetBにセット job.targetB = candidateMop; job.count = 1; var compTool = candidateMop.TryGetComp <CompWaterTool>(); var maxQueueLength = Mathf.RoundToInt(compTool.StoredWaterVolume / JobDriver_Mop.ConsumeWaterVolume); var map = pawn.Map; var room = cell.GetRoom(map); for (var i = 0; i < 100; i++) { // 対象の汚れの周囲100マスをサーチ var intVec = cell + GenRadial.RadialPattern[i]; if (!intVec.InBounds(map) || intVec.GetRoom(map) != room) { continue; } // そこが同じ部屋の中 if (HasJobOnCell(pawn, intVec) && intVec != cell) { // 同じジョブが作成可能(汚れがある等)あるならこのジョブの処理対象に追加 job.AddQueuedTarget(TargetIndex.A, intVec); } // 掃除最大個数チェック if (job.GetTargetQueue(TargetIndex.A).Count >= maxQueueLength) { break; } } if (job.targetQueueA != null && job.targetQueueA.Count >= 5) { // 掃除対象が5個以上あるならポーンからの距離が近い順に掃除させる job.targetQueueA.SortBy(targ => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }