Пример #1
0
        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);
        }
Пример #2
0
        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));
        }
Пример #5
0
        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);
        }
Пример #7
0
        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);
        }
Пример #9
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }
Пример #16
0
        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);
            }
        }
Пример #19
0
        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);
        }
Пример #20
0
        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);
        }
Пример #21
0
        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);
        }