Пример #1
0
 public static void Postfix(Pawn_MindState __instance)
 {
     if (__instance.pawn.NoOverlapAdjustedIsHashIntervalTick(100))
     {
         if (__instance.pawn.Spawned)
         {
             int regionsToScan = __instance.anyCloseHostilesRecently ? 24 : 18;
             __instance.anyCloseHostilesRecently = PawnUtility.EnemiesAreNearby(__instance.pawn, regionsToScan, true);
         }
         else
         {
             __instance.anyCloseHostilesRecently = false;
         }
     }
     if (TickUtility.NoOverlapTickMod(123) && __instance.pawn.Spawned && __instance.pawn.RaceProps.IsFlesh && __instance.pawn.needs.mood != null)
     {
         TerrainDef terrain = __instance.pawn.Position.GetTerrain(__instance.pawn.Map);
         if (terrain.traversedThought != null)
         {
             __instance.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(terrain.traversedThought);
         }
         WeatherDef curWeatherLerped = __instance.pawn.Map.weatherManager.CurWeatherLerped;
         if (curWeatherLerped.exposedThought != null && !__instance.pawn.Position.Roofed(__instance.pawn.Map))
         {
             __instance.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(curWeatherLerped.exposedThought);
         }
     }
 }
Пример #2
0
        private bool DoesTargetPawnAcceptAdvance()
        {
            //if (xxx.config.always_accept_whores)
            //	return true;

            //Log.Message("[RJW]JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() is called");

            if (PawnUtility.EnemiesAreNearby(TargetPawn))
            {
                //Log.Message("[RJW]JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() fail - enemy near");
                return(false);
            }
            if (!allowedJobs.Contains(TargetPawn.jobs.curJob.def))
            {
                //Log.Message("[RJW]JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() fail - not allowed job");
                return(false);
            }

            //Log.Message("Will try " + WhoringHelper.WillPawnTryHookup(TargetPawn));
            //Log.Message("Appeal  " + WhoringHelper.IsHookupAppealing(TargetPawn, W***e));
            //Log.Message("Afford " + WhoringHelper.CanAfford(TargetPawn, W***e));
            //Log.Message("Need sex " + (xxx.need_some_sex(TargetPawn) >= 1));
            W***e.skills.Learn(SkillDefOf.Social, 1.2f);
            return(WhoringHelper.WillPawnTryHookup(TargetPawn) && WhoringHelper.IsHookupAppealing(TargetPawn, W***e) && WhoringHelper.CanAfford(TargetPawn, W***e) && xxx.need_some_sex(TargetPawn) >= 1f);
        }
Пример #3
0
 public virtual void JobTrackerTick()
 {
     jobsGivenThisTick        = 0;
     jobsGivenThisTickTextual = "";
     if (pawn.IsHashIntervalTick(30))
     {
         ThinkResult thinkResult = DetermineNextConstantThinkTreeJob();
         if (thinkResult.IsValid)
         {
             if (ShouldStartJobFromThinkTree(thinkResult))
             {
                 CheckLeaveJoinableLordBecauseJobIssued(thinkResult);
                 StartJob(thinkResult.Job, JobCondition.InterruptForced, thinkResult.SourceNode, resumeCurJobAfterwards: false, cancelBusyStances: false, pawn.thinker.ConstantThinkTree, thinkResult.Tag);
             }
             else if (thinkResult.Job != curJob && !jobQueue.Contains(thinkResult.Job))
             {
                 JobMaker.ReturnToPool(thinkResult.Job);
             }
         }
     }
     if (curDriver != null)
     {
         if (curJob.expiryInterval > 0 && (Find.TickManager.TicksGame - curJob.startTick) % curJob.expiryInterval == 0 && Find.TickManager.TicksGame != curJob.startTick)
         {
             if (!curJob.expireRequiresEnemiesNearby || PawnUtility.EnemiesAreNearby(pawn, 25))
             {
                 if (debugLog)
                 {
                     DebugLogEvent("Job expire");
                 }
                 if (!curJob.checkOverrideOnExpire)
                 {
                     EndCurrentJob(JobCondition.Succeeded);
                 }
                 else
                 {
                     CheckForJobOverride();
                 }
                 FinalizeTick();
                 return;
             }
             if (debugLog)
             {
                 DebugLogEvent("Job expire skipped because there are no enemies nearby");
             }
         }
         curDriver.DriverTick();
     }
     if (curJob == null && !pawn.Dead && pawn.mindState.Active && CanDoAnyJob())
     {
         if (debugLog)
         {
             DebugLogEvent("Starting job from Tick because curJob == null.");
         }
         TryFindAndStartJob();
     }
     FinalizeTick();
 }
Пример #4
0
 public void MindStateTick()
 {
     if (wantsToTradeWithColony)
     {
         TradeUtility.CheckInteractWithTradersTeachOpportunity(pawn);
     }
     if (meleeThreat != null && !MeleeThreatStillThreat)
     {
         meleeThreat = null;
     }
     mentalStateHandler.MentalStateHandlerTick();
     mentalBreaker.MentalBreakerTick();
     inspirationHandler.InspirationHandlerTick();
     if (!pawn.GetPosture().Laying())
     {
         applyBedThoughtsTick = 0;
     }
     if (pawn.IsHashIntervalTick(100))
     {
         if (pawn.Spawned)
         {
             int regionsToScan = (!anyCloseHostilesRecently) ? 18 : 24;
             anyCloseHostilesRecently = PawnUtility.EnemiesAreNearby(pawn, regionsToScan, passDoors: true);
         }
         else
         {
             anyCloseHostilesRecently = false;
         }
     }
     if (WillJoinColonyIfRescued && AnythingPreventsJoiningColonyIfRescued)
     {
         WillJoinColonyIfRescued = false;
     }
     if (pawn.Spawned && pawn.IsWildMan() && !WildManEverReachedOutside && pawn.GetRoom() != null && pawn.GetRoom().TouchesMapEdge)
     {
         WildManEverReachedOutside = true;
     }
     if (Find.TickManager.TicksGame % 123 == 0 && pawn.Spawned && pawn.RaceProps.IsFlesh && pawn.needs.mood != null)
     {
         TerrainDef terrain = pawn.Position.GetTerrain(pawn.Map);
         if (terrain.traversedThought != null)
         {
             pawn.needs.mood.thoughts.memories.TryGainMemoryFast(terrain.traversedThought);
         }
         WeatherDef curWeatherLerped = pawn.Map.weatherManager.CurWeatherLerped;
         if (curWeatherLerped.exposedThought != null && !pawn.Position.Roofed(pawn.Map))
         {
             pawn.needs.mood.thoughts.memories.TryGainMemoryFast(curWeatherLerped.exposedThought);
         }
     }
     if (GenLocalDate.DayTick(pawn) == 0)
     {
         interactionsToday = 0;
     }
 }
 public virtual void JobTrackerTick()
 {
     this.jobsGivenThisTick        = 0;
     this.jobsGivenThisTickTextual = "";
     if (this.pawn.IsHashIntervalTick(30))
     {
         ThinkResult thinkResult = this.DetermineNextConstantThinkTreeJob();
         if (thinkResult.IsValid && this.ShouldStartJobFromThinkTree(thinkResult))
         {
             this.CheckLeaveJoinableLordBecauseJobIssued(thinkResult);
             this.StartJob(thinkResult.Job, JobCondition.InterruptForced, thinkResult.SourceNode, false, false, this.pawn.thinker.ConstantThinkTree, thinkResult.Tag, false);
         }
     }
     if (this.curDriver != null)
     {
         if (this.curJob.expiryInterval > 0 && (Find.TickManager.TicksGame - this.curJob.startTick) % this.curJob.expiryInterval == 0 && Find.TickManager.TicksGame != this.curJob.startTick)
         {
             if (!this.curJob.expireRequiresEnemiesNearby || PawnUtility.EnemiesAreNearby(this.pawn, 25, false))
             {
                 if (this.debugLog)
                 {
                     this.DebugLogEvent("Job expire");
                 }
                 if (!this.curJob.checkOverrideOnExpire)
                 {
                     this.EndCurrentJob(JobCondition.Succeeded, true);
                 }
                 else
                 {
                     this.CheckForJobOverride();
                 }
                 this.FinalizeTick();
                 return;
             }
             if (this.debugLog)
             {
                 this.DebugLogEvent("Job expire skipped because there are no enemies nearby");
             }
         }
         this.curDriver.DriverTick();
     }
     if (this.curJob == null && !this.pawn.Dead && this.pawn.mindState.Active && this.CanDoAnyJob())
     {
         if (this.debugLog)
         {
             this.DebugLogEvent("Starting job from Tick because curJob == null.");
         }
         this.TryFindAndStartJob();
     }
     this.FinalizeTick();
 }
Пример #6
0
 public static bool MindStateTick(Pawn_MindState __instance)
 {
     if (__instance.wantsToTradeWithColony)
     {
         TradeUtility.CheckInteractWithTradersTeachOpportunity(__instance.pawn);
     }
     if (__instance.meleeThreat != null && !__instance.MeleeThreatStillThreat)
     {
         __instance.meleeThreat = null;
     }
     __instance.mentalStateHandler.MentalStateHandlerTick();
     __instance.mentalBreaker.MentalBreakerTick();
     __instance.inspirationHandler.InspirationHandlerTick();
     if (!__instance.pawn.GetPosture().Laying())
     {
         __instance.applyBedThoughtsTick = 0;
     }
     if (__instance.pawn.IsHashIntervalTick(100))
     {
         __instance.anyCloseHostilesRecently = __instance.pawn.Spawned && PawnUtility.EnemiesAreNearby(__instance.pawn, __instance.anyCloseHostilesRecently ? 24 : 18, true);
     }
     if (__instance.WillJoinColonyIfRescued && __instance.AnythingPreventsJoiningColonyIfRescued)
     {
         __instance.WillJoinColonyIfRescued = false;
     }
     if (__instance.pawn.Spawned && __instance.pawn.IsWildMan() && (!__instance.WildManEverReachedOutside && __instance.pawn.GetRoom(RegionType.Set_Passable) != null) && __instance.pawn.GetRoom(RegionType.Set_Passable).TouchesMapEdge)
     {
         __instance.WildManEverReachedOutside = true;
     }
     if (Find.TickManager.TicksGame % 123 == 0 && __instance.pawn.Spawned && (__instance.pawn.RaceProps.IsFlesh && __instance.pawn.needs.mood != null))
     {
         TerrainDef terrain = __instance.pawn.Position.GetTerrain(__instance.pawn.Map);
         if (terrain.traversedThought != null)
         {
             __instance.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(terrain.traversedThought);
         }
         WeatherDef curWeatherLerped = __instance.pawn.Map.weatherManager.CurWeatherLerped;
         if (curWeatherLerped.exposedThought != null && !__instance.pawn.Position.Roofed(__instance.pawn.Map))
         {
             __instance.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(curWeatherLerped.exposedThought);
         }
     }
     //dirty hack for easy speedup - i'm sure this breaks things like pawn conversation interval.
     //if (GenLocalDate.DayTick((Thing)__instance.pawn) != 0)
     //	return;
     __instance.interactionsToday = 0;
     return(false);
 }
Пример #7
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.mindState.meleeThreat is null && !PawnUtility.EnemiesAreNearby(pawn))
            {
                return(null);
            }
            if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
            {
                return(null);
            }
            if (pawn.GetRegion() == null)
            {
                return(null);
            }
            if (pawn.equipment != null && !AlreadySatisfiedWithCurrentWeapon(pawn))
            {
                Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Weapon),
                                                               PathEndMode.OnCell, TraverseParms.For(pawn), 8f, (Thing x) => pawn.CanReserve(x) && !x.IsBurning() && ShouldEquipWeapon(x, pawn), null, 0, 15);
                if (thing != null)
                {
                    return(JobMaker.MakeJob(JobDefOf.Equip, thing));
                }
            }
            Pawn_EquipmentTracker equipment = pawn.equipment;

            if (equipment != null && equipment.Primary?.def?.IsRangedWeapon == true)
            {
                foreach (Apparel item in pawn.apparel.WornApparel)
                {
                    if (item.def == ThingDefOf.Apparel_ShieldBelt)
                    {
                        return(JobMaker.MakeJob(JobDefOf.RemoveApparel, item));
                    }
                }
            }
            if (pickUpUtilityItems && pawn.apparel != null && WouldPickupUtilityItem(pawn))
            {
                Thing thing2 = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Apparel), PathEndMode.OnCell, TraverseParms.For(pawn), 8f, (Thing x) => pawn.CanReserve(x) && !x.IsBurning() && ShouldEquipUtilityItem(x, pawn), null, 0, 15);
                if (thing2 != null)
                {
                    return(JobMaker.MakeJob(JobDefOf.Wear, thing2));
                }
            }
            return(null);
        }
        private bool DoesTargetPawnAcceptAdvance()
        {
            if (RJWSettings.DebugWhoring)
            {
                Log.Message($"JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() - {xxx.get_pawnname(TargetPawn)}");
            }
            //if (RJWSettings.WildMode) return true;

            if (PawnUtility.EnemiesAreNearby(TargetPawn))
            {
                if (RJWSettings.DebugWhoring)
                {
                    Log.Message($" fail - enemy near");
                }
                return(false);
            }
            if (!allowedJobs.Contains(TargetPawn.jobs.curJob.def))
            {
                if (RJWSettings.DebugWhoring)
                {
                    Log.Message($" fail - not allowed job");
                }
                return(false);
            }

            if (RJWSettings.DebugWhoring)
            {
                Log.Message("Will try hookup " + WhoringHelper.WillPawnTryHookup(TargetPawn));
                Log.Message("Is w***e appealing  " + WhoringHelper.IsHookupAppealing(TargetPawn, W***e));
                Log.Message("Can afford w***e " + WhoringHelper.CanAfford(TargetPawn, W***e));
                Log.Message("Need sex " + (xxx.need_some_sex(TargetPawn) >= 1));
            }
            if (WhoringHelper.WillPawnTryHookup(TargetPawn) && WhoringHelper.IsHookupAppealing(TargetPawn, W***e) && WhoringHelper.CanAfford(TargetPawn, W***e) && xxx.need_some_sex(TargetPawn) >= 1f)
            {
                W***e.skills.Learn(SkillDefOf.Social, 1.2f);
                return(true);
            }
            return(false);
        }
        private WorkPriority GetPriorityWork(Pawn pawn)
        {
            CompAmmoUser  primaryammouser = pawn.equipment.Primary.TryGetComp <CompAmmoUser>();
            CompInventory compammo        = pawn.TryGetComp <CompInventory>();

            if (pawn.Faction.IsPlayer && pawn.equipment.Primary != null && pawn.equipment.Primary.TryGetComp <CompAmmoUser>() != null)
            {
                Loadout loadout = pawn.GetLoadout();
                // if (loadout != null && !loadout.Slots.NullOrEmpty())
                if (loadout != null && loadout.SlotCount > 0)
                {
                    return(WorkPriority.None);
                }
            }

            if (pawn.kindDef.trader)
            {
                return(WorkPriority.None);
            }
            if (pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Tame)
            {
                return(WorkPriority.None);
            }

            if (pawn.equipment.Primary == null)
            {
                if (Unload(pawn))
                {
                    return(WorkPriority.Unloading);
                }
                else
                {
                    return(WorkPriority.Weapon);
                }
            }

            if (pawn.equipment.Primary != null && primaryammouser != null)
            {
                int ammocount = 0;
                foreach (AmmoLink link in primaryammouser.Props.ammoSet.ammoTypes)
                {
                    Thing ammoThing;
                    ammoThing = compammo.ammoList.Find(thing => thing.def == link.ammo);
                    if (ammoThing != null)
                    {
                        ammocount += ammoThing.stackCount;
                    }
                }

                // current ammo bulk
                float currentAmmoBulk = primaryammouser.CurrentAmmo.GetStatValueAbstract(CE_StatDefOf.Bulk);

                // weapon magazine size
                float stackSize = primaryammouser.Props.magazineSize;

                // weight projectile ratio to free bulk with x1.5 reserve
                float weightProjectileRatio = Mathf.RoundToInt(((compammo.capacityBulk - compammo.currentBulk) / 1.5f) / currentAmmoBulk);

                if (ammocount < stackSize * 1 && (ammocount < weightProjectileRatio))
                {
                    if (Unload(pawn))
                    {
                        return(WorkPriority.Unloading);
                    }
                    else
                    {
                        return(WorkPriority.LowAmmo);
                    }
                }

                if (!PawnUtility.EnemiesAreNearby(pawn, 30, true))
                {
                    if (ammocount < stackSize * 2 && (ammocount < weightProjectileRatio))
                    {
                        if (Unload(pawn))
                        {
                            return(WorkPriority.Unloading);
                        }
                        else
                        {
                            return(WorkPriority.Ammo);
                        }
                    }
                }
            }

            /*
             * if (!pawn.Faction.IsPlayer && pawn.equipment.Primary != null
             *  && !PawnUtility.EnemiesAreNearby(pawn, 30, true)
             || (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso)
             || !pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Legs)))
             ||{
             || return WorkPriority.Apparel;
             ||}
             */

            return(WorkPriority.None);
        }
Пример #10
0
        private static void Detour(Pawn_JobTracker __instance)
        {
            Profiler pro = null;

            __instance.jobsGivenThisTick        = 0;
            __instance.jobsGivenThisTickTextual = "";
            if (__instance.pawn.IsHashIntervalTick(30))
            {
                pro = ProfileController.Start("DetermineNextConstantThinkTreeJob");
                var thinkResult = __instance.DetermineNextConstantThinkTreeJob();
                pro.Stop();
                if (thinkResult.IsValid)
                {
                    pro = ProfileController.Start("ShouldStartJobFromThinkTree");
                    if (__instance.ShouldStartJobFromThinkTree(thinkResult))
                    {
                        __instance.CheckLeaveJoinableLordBecauseJobIssued(thinkResult);
                        __instance.StartJob(thinkResult.Job, JobCondition.InterruptForced, thinkResult.SourceNode,
                                            false, false, __instance.pawn.thinker.ConstantThinkTree, thinkResult.Tag);
                    }
                    else if (thinkResult.Job != __instance.curJob && !__instance.jobQueue.Contains(thinkResult.Job))
                    {
                        JobMaker.ReturnToPool(thinkResult.Job);
                    }

                    pro.Stop();
                }
            }

            if (__instance.curDriver != null)
            {
                if (__instance.curJob.expiryInterval > 0 &&
                    (Find.TickManager.TicksGame - __instance.curJob.startTick) % __instance.curJob.expiryInterval ==
                    0 && Find.TickManager.TicksGame != __instance.curJob.startTick)
                {
                    pro = ProfileController.Start("EnemiesAreNearby");
                    var enemies = !__instance.curJob.expireRequiresEnemiesNearby ||
                                  PawnUtility.EnemiesAreNearby(__instance.pawn, 25);
                    pro.Stop();
                    if (enemies)
                    {
                        if (__instance.debugLog)
                        {
                            __instance.DebugLogEvent("Job expire");
                        }

                        if (!__instance.curJob.checkOverrideOnExpire)
                        {
                            pro = ProfileController.Start("EndCurrentJob");
                            __instance.EndCurrentJob(JobCondition.Succeeded);
                            pro.Stop();
                        }
                        else
                        {
                            pro = ProfileController.Start("CheckForJobOverride");
                            __instance.CheckForJobOverride();
                            pro.Stop();
                        }

                        pro = ProfileController.Start("FinalizeTick");
                        __instance.FinalizeTick();
                        pro.Stop();
                        return;
                    }

                    if (__instance.debugLog)
                    {
                        __instance.DebugLogEvent("Job expire skipped because there are no enemies nearby");
                    }
                }

                var key = string.Empty;

                if (PerPawn)
                {
                    key = __instance.pawn.LabelShort + __instance.curDriver.job?.def.defName;
                }
                else
                {
                    key = __instance.curDriver.job?.def.defName;
                }

                string label()
                {
                    var daffy = string.Empty;

                    if (PerPawn)
                    {
                        daffy =
                            $"{__instance.pawn.LabelShort} {__instance.curDriver.job?.def?.defName} - {__instance.curDriver.job?.def?.driverClass} - {__instance.curDriver.job?.def?.modContentPack?.Name}";
                    }
                    else
                    {
                        daffy =
                            $"{__instance.curDriver.job?.def?.defName} - {__instance.curDriver.job?.def?.driverClass} - {__instance.curDriver.job?.def?.modContentPack?.Name}";
                    }

                    return(daffy);
                }

                var meth = AccessTools.Method(__instance.curDriver.job?.def?.driverClass, "DriverTick");

                pro = ProfileController.Start(key, label, __instance.curDriver.job?.def?.driverClass,
                                              __instance.curDriver.job?.def, __instance.pawn, meth);
                __instance.curDriver.DriverTick();
                pro.Stop();
            }

            if (__instance.curJob == null && !__instance.pawn.Dead && __instance.pawn.mindState.Active)
            {
                pro = ProfileController.Start("CanDoAnyJob");
                var doit = __instance.CanDoAnyJob();
                pro.Stop();
                if (doit)
                {
                    if (__instance.debugLog)
                    {
                        __instance.DebugLogEvent("Starting job from Tick because curJob == null.");
                    }

                    pro = ProfileController.Start("FinalizeTick");
                    __instance.TryFindAndStartJob();
                    pro.Stop();
                }
            }
            pro = ProfileController.Start("FinalizeTick");
            __instance.FinalizeTick();
            pro.Stop();
        }
Пример #11
0
 public void MindStateTick()
 {
     if (this.wantsToTradeWithColony)
     {
         TradeUtility.CheckInteractWithTradersTeachOpportunity(this.pawn);
     }
     if (this.meleeThreat != null && !this.MeleeThreatStillThreat)
     {
         this.meleeThreat = null;
     }
     this.mentalStateHandler.MentalStateHandlerTick();
     this.mentalBreaker.MentalBreakerTick();
     this.inspirationHandler.InspirationHandlerTick();
     if (this.pawn.CurJob == null || this.pawn.jobs.curDriver.layingDown == LayingDownState.NotLaying)
     {
         this.applyBedThoughtsTick = 0;
     }
     if (this.pawn.IsHashIntervalTick(100))
     {
         if (this.pawn.Spawned)
         {
             int regionsToScan = (!this.anyCloseHostilesRecently) ? 18 : 24;
             this.anyCloseHostilesRecently = PawnUtility.EnemiesAreNearby(this.pawn, regionsToScan, true);
         }
         else
         {
             this.anyCloseHostilesRecently = false;
         }
     }
     if (this.willJoinColonyIfRescued && this.pawn.Spawned && this.pawn.IsHashIntervalTick(30))
     {
         if (this.pawn.Faction == Faction.OfPlayer)
         {
             this.willJoinColonyIfRescued = false;
         }
         else if (this.pawn.CanReachMapEdge())
         {
             foreach (Pawn current in this.pawn.Map.mapPawns.FreeColonistsSpawned)
             {
                 if (current.IsColonistPlayerControlled)
                 {
                     this.PrisonerRescued(current);
                     break;
                 }
             }
         }
         else
         {
             Room room = this.pawn.GetRoom(RegionType.Set_Passable);
             if (room != null)
             {
                 List <Thing> containedAndAdjacentThings = room.ContainedAndAdjacentThings;
                 for (int i = 0; i < containedAndAdjacentThings.Count; i++)
                 {
                     Pawn pawn = containedAndAdjacentThings[i] as Pawn;
                     if (pawn != null && pawn.IsColonistPlayerControlled)
                     {
                         this.PrisonerRescued(pawn);
                         break;
                     }
                 }
             }
         }
     }
     if (this.pawn.Spawned && this.pawn.IsWildMan() && !this.wildManEverReachedOutside && this.pawn.GetRoom(RegionType.Set_Passable) != null && this.pawn.GetRoom(RegionType.Set_Passable).TouchesMapEdge)
     {
         this.wildManEverReachedOutside = true;
         this.pawn.Map.reachability.ClearCache();
     }
 }
        private WorkPriority GetPriorityWork(Pawn pawn)
        {
            #region Traders have no work priority
            if (pawn.kindDef.trader)
            {
                return(WorkPriority.None);
            }
            #endregion

            //#region Pawns with non-idle jobs have no work priority
            //bool hasCurJob = pawn.CurJob != null;
            //JobDef jobDef = hasCurJob ? pawn.CurJob.def : null;

            //if (hasCurJob && !jobDef.isIdle)
            //{
            //    return WorkPriority.None;
            //}
            //#endregion

            bool         hasPrimary      = (pawn.equipment != null && pawn.equipment.Primary != null);
            CompAmmoUser primaryAmmoUser = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : hasWeaponInInventory(pawn) ? weaponInInventory(pawn) : null;

            #region Colonists with primary ammo-user and a loadout have no work priority
            if (pawn.Faction.IsPlayer &&
                primaryAmmoUser != null)
            {
                Loadout loadout = pawn.GetLoadout();
                // if (loadout != null && !loadout.Slots.NullOrEmpty())
                if (loadout != null && loadout.SlotCount > 0)
                {
                    return(WorkPriority.None);
                }
            }
            #endregion

            // Pawns without weapon..
            if (!hasPrimary)
            {
                // With inventory && non-colonist && not stealing && little space left
                if (Unload(pawn))
                {
                    return(WorkPriority.Unloading);
                }
                // Without inventory || colonist || stealing || lots of space left
                if (!hasWeaponInInventory(pawn))
                {
                    return(WorkPriority.Weapon);
                }
            }

            CompInventory compInventory = pawn.TryGetComp <CompInventory>();
            // Pawn with ammo-using weapon..
            if (primaryAmmoUser != null && primaryAmmoUser.UseAmmo)
            {
                // Magazine size
                FloatRange magazineSize = new FloatRange(1f, 2f);
                LoadoutPropertiesExtension loadoutPropertiesExtension = (LoadoutPropertiesExtension)(pawn.kindDef.modExtensions?.FirstOrDefault(x => x is LoadoutPropertiesExtension));
                bool hasWeaponTags = pawn.kindDef.weaponTags?.Any() ?? false;

                if (hasWeaponTags &&
                    primaryAmmoUser.parent.def.weaponTags.Any(pawn.kindDef.weaponTags.Contains) &&
                    loadoutPropertiesExtension != null &&
                    loadoutPropertiesExtension.primaryMagazineCount != FloatRange.Zero)
                {
                    magazineSize.min = loadoutPropertiesExtension.primaryMagazineCount.min;
                    magazineSize.max = loadoutPropertiesExtension.primaryMagazineCount.max;
                }

                magazineSize.min *= primaryAmmoUser.Props.magazineSize;
                magazineSize.max *= primaryAmmoUser.Props.magazineSize;

                // Number of things in inventory that could be put in the weapon
                int   viableAmmoCarried = 0;
                float viableAmmoBulk    = 0;
                foreach (AmmoLink link in primaryAmmoUser.Props.ammoSet.ammoTypes)
                {
                    var count = compInventory.AmmoCountOfDef(link.ammo);
                    viableAmmoCarried += count;
                    viableAmmoBulk    += count * link.ammo.GetStatValueAbstract(CE_StatDefOf.Bulk);
                }

                // ~2/3rds of the inventory bulk minus non-usable and non-ammo bulk could be filled with ammo
                float potentialAmmoBulk = ammoFractionOfNonAmmoInventory * (compInventory.capacityBulk - compInventory.currentBulk + viableAmmoBulk);
                // There's less ammo [bulk] than fits the potential ammo bulk [bulk]
                if (viableAmmoBulk < potentialAmmoBulk)
                {
                    // There's less ammo [nr] than fits a clip [nr]
                    if (primaryAmmoUser.Props.magazineSize == 0 || viableAmmoCarried < magazineSize.min)
                    {
                        return(Unload(pawn) ? WorkPriority.Unloading : WorkPriority.LowAmmo);
                    }

                    // There's less ammo [nr] than fits two clips [nr] && no enemies are close
                    if (viableAmmoCarried < magazineSize.max &&
                        !PawnUtility.EnemiesAreNearby(pawn, 20, true))
                    {
                        return(Unload(pawn) ? WorkPriority.Unloading : WorkPriority.Ammo);
                    }
                }
            }
            return(WorkPriority.None);
        }
 public void MindStateTick()
 {
     if (this.wantsToTradeWithColony)
     {
         TradeUtility.CheckInteractWithTradersTeachOpportunity(this.pawn);
     }
     if (this.meleeThreat != null && !this.MeleeThreatStillThreat)
     {
         this.meleeThreat = null;
     }
     this.mentalStateHandler.MentalStateHandlerTick();
     this.mentalBreaker.MentalBreakerTick();
     this.inspirationHandler.InspirationHandlerTick();
     if (!this.pawn.GetPosture().Laying())
     {
         this.applyBedThoughtsTick = 0;
     }
     if (this.pawn.IsHashIntervalTick(100))
     {
         if (this.pawn.Spawned)
         {
             int regionsToScan = (!this.anyCloseHostilesRecently) ? 18 : 24;
             this.anyCloseHostilesRecently = PawnUtility.EnemiesAreNearby(this.pawn, regionsToScan, true);
         }
         else
         {
             this.anyCloseHostilesRecently = false;
         }
     }
     if (this.WillJoinColonyIfRescued && this.pawn.Spawned && this.pawn.IsHashIntervalTick(30))
     {
         if (this.pawn.Faction == Faction.OfPlayer)
         {
             this.WillJoinColonyIfRescued = false;
         }
         else if (this.pawn.IsPrisoner && !this.pawn.HostFaction.HostileTo(Faction.OfPlayer))
         {
             this.WillJoinColonyIfRescued = false;
         }
         else if (!this.pawn.IsPrisoner && this.pawn.Faction != null && this.pawn.Faction.HostileTo(Faction.OfPlayer) && !this.pawn.Downed)
         {
             this.WillJoinColonyIfRescued = false;
         }
         else
         {
             foreach (Pawn pawn in this.pawn.Map.mapPawns.FreeColonistsSpawned)
             {
                 if (pawn.IsColonistPlayerControlled && pawn.Position.InHorDistOf(this.pawn.Position, 4f) && GenSight.LineOfSight(this.pawn.Position, pawn.Position, this.pawn.Map, false, null, 0, 0))
                 {
                     this.JoinColonyBecauseRescuedBy(pawn);
                     break;
                 }
             }
         }
     }
     if (this.pawn.Spawned && this.pawn.IsWildMan() && !this.WildManEverReachedOutside && this.pawn.GetRoom(RegionType.Set_Passable) != null && this.pawn.GetRoom(RegionType.Set_Passable).TouchesMapEdge)
     {
         this.WildManEverReachedOutside = true;
     }
     if (Find.TickManager.TicksGame % 123 == 0 && this.pawn.Spawned && this.pawn.RaceProps.IsFlesh && this.pawn.needs.mood != null)
     {
         TerrainDef terrain = this.pawn.Position.GetTerrain(this.pawn.Map);
         if (terrain.traversedThought != null)
         {
             this.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(terrain.traversedThought);
         }
         WeatherDef curWeatherLerped = this.pawn.Map.weatherManager.CurWeatherLerped;
         if (curWeatherLerped.exposedThought != null && !this.pawn.Position.Roofed(this.pawn.Map))
         {
             this.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(curWeatherLerped.exposedThought);
         }
     }
     if (GenLocalDate.DayTick(this.pawn) == 0)
     {
         this.interactionsToday = 0;
     }
 }
Пример #14
0
        static bool Prefix(Pawn_MindState __instance)
        {
            if (!__instance.pawn.NonHumanlikeOrWildMan() && (UmbrellaDefMethods.HasUmbrella(__instance.pawn) || (RimbrellasMod.settings.cowboyHatsPreventSoakingWet && UmbrellaDefMethods.HasCowboyHat(__instance.pawn))))
            {
                if (__instance.wantsToTradeWithColony)
                {
                    TradeUtility.CheckInteractWithTradersTeachOpportunity(__instance.pawn);
                }
                if (__instance.meleeThreat != null && !__instance.MeleeThreatStillThreat)
                {
                    __instance.meleeThreat = null;
                }
                __instance.mentalStateHandler.MentalStateHandlerTick();
                __instance.mentalBreaker.MentalBreakerTick();
                __instance.inspirationHandler.InspirationHandlerTick();
                if (!__instance.pawn.GetPosture().Laying())
                {
                    __instance.applyBedThoughtsTick = 0;
                }
                if (__instance.pawn.IsHashIntervalTick(100))
                {
                    if (__instance.pawn.Spawned)
                    {
                        int regionsToScan = __instance.anyCloseHostilesRecently ? 24 : 18;
                        __instance.anyCloseHostilesRecently = PawnUtility.EnemiesAreNearby(__instance.pawn, regionsToScan, passDoors: true);
                    }
                    else
                    {
                        __instance.anyCloseHostilesRecently = false;
                    }
                }
                if (__instance.WillJoinColonyIfRescued && __instance.AnythingPreventsJoiningColonyIfRescued)
                {
                    __instance.WillJoinColonyIfRescued = false;
                }
                if (__instance.pawn.Spawned && __instance.pawn.IsWildMan() && !__instance.WildManEverReachedOutside && __instance.pawn.GetRoom() != null && __instance.pawn.GetRoom().TouchesMapEdge)
                {
                    __instance.WildManEverReachedOutside = true;
                }
                if (Find.TickManager.TicksGame % 123 == 0 && __instance.pawn.Spawned && __instance.pawn.RaceProps.IsFlesh && __instance.pawn.needs.mood != null)
                {
                    __instance.pawn.Drawer.renderer.graphics.ResolveAllGraphics();

                    TerrainDef terrain = __instance.pawn.Position.GetTerrain(__instance.pawn.Map);
                    if (terrain.traversedThought != null)
                    {
                        __instance.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(terrain.traversedThought);
                    }

                    /*WeatherDef curWeatherLerped = __instance.pawn.Map.weatherManager.CurWeatherLerped;
                     * if (curWeatherLerped.exposedThought != null && !__instance.pawn.Position.Roofed(__instance.pawn.Map)) {
                     *      __instance.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(curWeatherLerped.exposedThought);
                     * }*///this code would assign the Soaking Wet thought to a pawn outside in the rain, but we've already checked that the pawn has an umbrella
                }
                if (GenLocalDate.DayTick(__instance.pawn) == 0)
                {
                    __instance.interactionsToday = 0;
                }
                return(false);
            }
            return(true);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (!Controller.settings.EnableAmmoSystem || !Controller.settings.AutoTakeAmmo)
            {
                return(null);
            }

            if (!pawn.RaceProps.Humanlike || (pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent)))
            {
                return(null);
            }
            if (pawn.Faction.IsPlayer && pawn.Drafted)
            {
                return(null);
            }

            if (!Rand.MTBEventOccurs(60, 1, 30))
            {
                return(null);
            }

            // Log.Message(pawn.ToString() +  " - priority:" + (GetPriorityWork(pawn)).ToString() + " capacityWeight: " + pawn.TryGetComp<CompInventory>().capacityWeight.ToString() + " currentWeight: " + pawn.TryGetComp<CompInventory>().currentWeight.ToString() + " capacityBulk: " + pawn.TryGetComp<CompInventory>().capacityBulk.ToString() + " currentBulk: " + pawn.TryGetComp<CompInventory>().currentBulk.ToString());

            var           brawler         = (pawn.story != null && pawn.story.traits != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler));
            CompInventory inventory       = pawn.TryGetComp <CompInventory>();
            bool          hasPrimary      = (pawn.equipment != null && pawn.equipment.Primary != null);
            CompAmmoUser  primaryammouser = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : null;

            if (inventory != null)
            {
                // Prefer ranged weapon in inventory
                if (!pawn.Faction.IsPlayer && hasPrimary && pawn.equipment.Primary.def.IsMeleeWeapon && !brawler)
                {
                    if ((pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level ||
                         pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6))
                    {
                        ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine);
                        if (InvListGun3 != null)
                        {
                            inventory.TrySwitchToWeapon(InvListGun3);
                        }
                    }
                }

                // Drop excess ranged weapon
                if (!pawn.Faction.IsPlayer && primaryammouser != null && GetPriorityWork(pawn) == WorkPriority.Unloading && inventory.rangedWeaponList.Count >= 1)
                {
                    Thing ListGun = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null && thing.def != pawn.equipment.Primary.def);
                    if (ListGun != null)
                    {
                        Thing ammoListGun = null;
                        if (!ListGun.TryGetComp <CompAmmoUser>().HasAmmoOrMagazine)
                        {
                            foreach (AmmoLink link in ListGun.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes)
                            {
                                if (inventory.ammoList.Find(thing => thing.def == link.ammo) == null)
                                {
                                    ammoListGun = ListGun;
                                    break;
                                }
                            }
                        }
                        if (ammoListGun != null)
                        {
                            Thing droppedWeapon;
                            if (inventory.container.TryDrop(ListGun, pawn.Position, pawn.Map, ThingPlaceMode.Near, ListGun.stackCount, out droppedWeapon))
                            {
                                pawn.jobs.EndCurrentJob(JobCondition.None, true);
                                pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, droppedWeapon, 30, true));
                            }
                        }
                    }
                }

                // Find and drop not need ammo from inventory
                if (!pawn.Faction.IsPlayer && hasPrimary && inventory.ammoList.Count > 1 && GetPriorityWork(pawn) == WorkPriority.Unloading)
                {
                    Thing WrongammoThing = null;
                    WrongammoThing = primaryammouser != null
                        ? inventory.ammoList.Find(thing => !primaryammouser.Props.ammoSet.ammoTypes.Any(a => a.ammo == thing.def))
                        : inventory.ammoList.RandomElement <Thing>();

                    if (WrongammoThing != null)
                    {
                        Thing InvListGun = inventory.rangedWeaponList.Find(thing => hasPrimary && thing.TryGetComp <CompAmmoUser>() != null && thing.def != pawn.equipment.Primary.def);
                        if (InvListGun != null)
                        {
                            Thing ammoInvListGun = null;
                            foreach (AmmoLink link in InvListGun.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes)
                            {
                                ammoInvListGun = inventory.ammoList.Find(thing => thing.def == link.ammo);
                                break;
                            }
                            if (ammoInvListGun != null && ammoInvListGun != WrongammoThing)
                            {
                                Thing droppedThingAmmo;
                                if (inventory.container.TryDrop(ammoInvListGun, pawn.Position, pawn.Map, ThingPlaceMode.Near, ammoInvListGun.stackCount, out droppedThingAmmo))
                                {
                                    pawn.jobs.EndCurrentJob(JobCondition.None, true);
                                    pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, 30, true));
                                }
                            }
                        }
                        else
                        {
                            Thing droppedThing;
                            if (inventory.container.TryDrop(WrongammoThing, pawn.Position, pawn.Map, ThingPlaceMode.Near, WrongammoThing.stackCount, out droppedThing))
                            {
                                pawn.jobs.EndCurrentJob(JobCondition.None, true);
                                pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, 30, true));
                            }
                        }
                    }
                }

                Room room = RegionAndRoomQuery.RoomAtFast(pawn.Position, pawn.Map);

                // Find weapon in inventory and try to switch if any ammo in inventory.
                if (GetPriorityWork(pawn) == WorkPriority.Weapon && !hasPrimary)
                {
                    ThingWithComps InvListGun2 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp <CompAmmoUser>() != null);

                    if (InvListGun2 != null)
                    {
                        Thing ammoInvListGun2 = null;
                        foreach (AmmoLink link in InvListGun2.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes)
                        {
                            ammoInvListGun2 = inventory.ammoList.Find(thing => thing.def == link.ammo);
                            break;
                        }
                        if (ammoInvListGun2 != null)
                        {
                            inventory.TrySwitchToWeapon(InvListGun2);
                        }
                    }

                    // Find weapon with near ammo for ai.
                    if (!pawn.Faction.IsPlayer)
                    {
                        Predicate <Thing> validatorWS = (Thing w) => w.def.IsWeapon &&
                                                        w.MarketValue > 5 &&
                                                        pawn.CanReserve(w, 1) &&
                                                        pawn.Position.InHorDistOf(w.Position, fixedsearchrange(pawn, w, 30f)) &&
                                                        pawn.CanReach(w, PathEndMode.Touch, Danger.Deadly, true) &&
                                                        (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || (!pawn.Faction.HostileTo(Faction.OfPlayer) && !pawn.Map.areaManager.Home[w.Position]));

                        // generate a list of all weapons (this includes melee weapons)
                        List <Thing> allWeapons = (
                            from w in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                            where validatorWS(w)
                            orderby w.MarketValue - w.Position.DistanceToSquared(pawn.Position) * 2f descending
                            select w
                            ).ToList();

                        // now just get the ranged weapons out...
                        List <Thing> rangedWeapons = allWeapons.Where(w => w.def.IsRangedWeapon).ToList();
                        if (!rangedWeapons.NullOrEmpty())
                        {
                            foreach (Thing thing in rangedWeapons)
                            {
                                if (thing.TryGetComp <CompAmmoUser>() == null)
                                {
                                    // pickup a non-CE ranged weapon...
                                    int numToThing = 0;
                                    if (inventory.CanFitInInventory(thing, out numToThing))
                                    {
                                        return(new Job(JobDefOf.Equip, thing)
                                        {
                                            checkOverrideOnExpire = true,
                                            expiryInterval = 100
                                        });
                                    }
                                }
                                else
                                {
                                    // pickup a CE ranged weapon...
                                    List <ThingDef> thingDefAmmoList = thing.TryGetComp <CompAmmoUser>().Props.ammoSet.ammoTypes.Select(g => g.ammo as ThingDef).ToList();

                                    Predicate <Thing> validatorA = (Thing t) => t.def.category == ThingCategory.Item &&
                                                                   t is AmmoThing && pawn.CanReserve(t, 1) &&
                                                                   pawn.Position.InHorDistOf(t.Position, fixedsearchrange(pawn, t, 30f)) &&
                                                                   pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) &&
                                                                   (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || (!pawn.Faction.HostileTo(Faction.OfPlayer) && !pawn.Map.areaManager.Home[t.Position]));

                                    List <Thing> thingAmmoList = (
                                        from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                                        where validatorA(t)
                                        select t
                                        ).ToList();

                                    if (thingAmmoList.Count > 0 && thingDefAmmoList.Count > 0)
                                    {
                                        int   desiredStackSize = thing.TryGetComp <CompAmmoUser>().Props.magazineSize * 2;
                                        Thing th = thingAmmoList.FirstOrDefault(x => thingDefAmmoList.Contains(x.def) && x.stackCount > desiredStackSize);
                                        if (th != null)
                                        {
                                            int numToThing = 0;
                                            if (inventory.CanFitInInventory(thing, out numToThing))
                                            {
                                                return(new Job(JobDefOf.Equip, thing)
                                                {
                                                    checkOverrideOnExpire = true,
                                                    expiryInterval = 100
                                                });
                                            }
                                        }
                                    }
                                    else if (isGrenade(thing) && grenadeCountInInventory(pawn, inventory) < 5)
                                    {
                                        int numToThing = thing.stackCount > 7 ? 7 : thing.stackCount;
                                        if (inventory.CanFitInInventory(thing, out numToThing))
                                        {
                                            return(new Job(JobDefOf.TakeInventory, thing)
                                            {
                                                count = Mathf.RoundToInt(numToThing * 0.8f),
                                                checkOverrideOnExpire = true,
                                                expiryInterval = 150
                                            });
                                        }
                                    }
                                }
                            }
                        }
                        // else if no ranged weapons with nearby ammo was found, lets consider a melee weapon.
                        if (allWeapons != null && allWeapons.Count > 0)
                        {
                            // since we don't need to worry about ammo, just pick one.
                            Thing meleeWeapon = allWeapons.FirstOrDefault(w => !w.def.IsRangedWeapon && w.def.IsMeleeWeapon);

                            if (meleeWeapon != null)
                            {
                                return(new Job(JobDefOf.Equip, meleeWeapon)
                                {
                                    checkOverrideOnExpire = true,
                                    expiryInterval = 100
                                });
                            }
                        }
                    }
                }

                // Find ammo
                if ((GetPriorityWork(pawn) == WorkPriority.Ammo || GetPriorityWork(pawn) == WorkPriority.LowAmmo) &&
                    primaryammouser != null)
                {
                    List <ThingDef> curAmmoList = (from AmmoLink g in primaryammouser.Props.ammoSet.ammoTypes
                                                   select g.ammo as ThingDef).ToList();

                    if (curAmmoList.Count > 0)
                    {
                        Predicate <Thing> validator = (Thing t) => t is AmmoThing && pawn.CanReserve(t, 1) &&
                                                      pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) &&
                                                      ((pawn.Faction.IsPlayer && !ForbidUtility.IsForbidden(t, pawn)) || (!pawn.Faction.IsPlayer && pawn.Position.InHorDistOf(t.Position, fixedsearchrange(pawn, t, 30f)))) &&
                                                      (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || (!pawn.Faction.HostileTo(Faction.OfPlayer) && !pawn.Map.areaManager.Home[t.Position]));
                        List <Thing> curThingList = (
                            from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                            where validator(t)
                            select t
                            ).ToList();
                        foreach (Thing th in curThingList)
                        {
                            foreach (ThingDef thd in curAmmoList)
                            {
                                if (thd == th.def)
                                {
                                    //Defence from low count loot spam
                                    float thw = (th.GetStatValue(CE_StatDefOf.Bulk)) * th.stackCount;
                                    if (thw > 0.5f)
                                    {
                                        if (pawn.Faction.IsPlayer)
                                        {
                                            int SearchRadius = 0;
                                            if (GetPriorityWork(pawn) == WorkPriority.LowAmmo)
                                            {
                                                SearchRadius = 70;
                                            }
                                            else
                                            {
                                                SearchRadius = 30;
                                            }

                                            Thing closestThing = GenClosest.ClosestThingReachable(
                                                pawn.Position,
                                                pawn.Map,
                                                ThingRequest.ForDef(th.def),
                                                PathEndMode.ClosestTouch,
                                                TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn),
                                                SearchRadius,
                                                x => !x.IsForbidden(pawn) && pawn.CanReserve(x));

                                            if (closestThing != null)
                                            {
                                                int numToCarry = 0;
                                                if (inventory.CanFitInInventory(th, out numToCarry))
                                                {
                                                    return(new Job(JobDefOf.TakeInventory, th)
                                                    {
                                                        count = numToCarry
                                                    });
                                                }
                                            }
                                        }
                                        else
                                        {
                                            int numToCarry = 0;
                                            if (inventory.CanFitInInventory(th, out numToCarry))
                                            {
                                                return(new Job(JobDefOf.TakeInventory, th)
                                                {
                                                    count = numToCarry,
                                                    expiryInterval = 150,
                                                    checkOverrideOnExpire = true
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // postfind grenade and ammos.
                if (!pawn.Faction.IsPlayer)
                {
                    int               minrange       = 2;
                    int               maxrange       = 14;
                    float             rangevariation = hasPrimary ? minrange : maxrange / 2;
                    Predicate <Thing> validatorPost  = (Thing w) =>
                                                       (isGrenade(w) || w is AmmoThing) &&
                                                       pawn.Position.InHorDistOf(w.Position, fixedsearchrange(pawn, w, maxrange, Mathf.RoundToInt(rangevariation + (maxrange / 2)), Mathf.RoundToInt(rangevariation + minrange))) &&
                                                       pawn.CanReach(w, PathEndMode.Touch, Danger.Deadly, true) &&
                                                       (pawn.Faction.HostileTo(Faction.OfPlayer) || (!pawn.Faction.HostileTo(Faction.OfPlayer) && !pawn.Map.areaManager.Home[w.Position]));

                    List <Thing> allPostThings = (
                        from w in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways)
                        where validatorPost(w)
                        select w
                        ).ToList();

                    // Look for grenades
                    List <Thing> grenadelist = (
                        from g in allPostThings
                        where g.def.IsWeapon && pawn.CanReserve(g, 1)
                        orderby g.Position.DistanceToSquared(pawn.Position) * 2f descending
                        select g
                        ).ToList();

                    if (!grenadelist.NullOrEmpty() && grenadeCountInInventory(pawn, inventory) < 5)
                    {
                        foreach (Thing grenade in grenadelist)
                        {
                            int numToThing = grenade.stackCount > 7 ? 7 : grenade.stackCount;
                            if (inventory.CanFitInInventory(grenade, out numToThing))
                            {
                                return(new Job(JobDefOf.TakeInventory, grenade)
                                {
                                    count = Mathf.RoundToInt(numToThing * 0.8f),
                                    expiryInterval = 150,
                                    checkOverrideOnExpire = true
                                });
                            }
                        }
                    }
                    if (hasPrimary && primaryammouser != null)
                    {
                        List <ThingDef> curAmmoList = (from AmmoLink g in primaryammouser.Props.ammoSet.ammoTypes
                                                       select g.ammo as ThingDef).ToList();
                        if (curAmmoList.Count > 0)
                        {
                            List <Thing> ammolist = (
                                from p in allPostThings
                                where p is AmmoThing && curAmmoList.Contains(p.def) && pawn.CanReserve(p, 1)
                                orderby p.Position.DistanceToSquared(pawn.Position) * 2f descending
                                select p
                                ).ToList();

                            if (ammolist.Count > 0)
                            {
                                for (var i = 0; i < ammolist.Count; i++)
                                {
                                    //try to take more ammo if it really nearby.
                                    int numToThing2 = 0;
                                    if (!inventory.CanFitInInventory(ammolist[i], out numToThing2))
                                    {
                                        break;
                                    }
                                    if (PawnUtility.EnemiesAreNearby(pawn, 25, true))
                                    {
                                        break;
                                    }
                                    if (pawn.Position.InHorDistOf(ammolist[i].Position, 4f))
                                    {
                                        return(new Job(JobDefOf.TakeInventory, ammolist[i])
                                        {
                                            count = numToThing2,
                                            expiryInterval = 150,
                                            checkOverrideOnExpire = true
                                        });
                                    }
                                }
                            }
                        }
                    }
                }

                /*
                 * if (!pawn.Faction.IsPlayer && pawn.apparel != null && GetPriorityWork(pawn) == WorkPriority.Apparel)
                 * {
                 *  if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso))
                 *  {
                 *      Apparel apparel = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.Torso);
                 *      if (apparel != null)
                 *      {
                 *          int numToapparel = 0;
                 *          if (inventory.CanFitInInventory(apparel, out numToapparel))
                 *          {
                 *              return new Job(JobDefOf.Wear, apparel)
                 *              {
                 *                  ignoreForbidden = true
                 *              };
                 *          }
                 *      }
                 *  }
                 *  if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Legs))
                 *  {
                 *      Apparel apparel2 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.Legs);
                 *      if (apparel2 != null)
                 *      {
                 *          int numToapparel2 = 0;
                 *          if (inventory.CanFitInInventory(apparel2, out numToapparel2))
                 *          {
                 *              return new Job(JobDefOf.Wear, apparel2)
                 *              {
                 *                  ignoreForbidden = true
                 *              };
                 *          }
                 *      }
                 *  }
                 *  if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.FullHead))
                 *  {
                 *      Apparel apparel3 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.FullHead);
                 *      if (apparel3 != null)
                 *      {
                 *          int numToapparel3 = 0;
                 *          if (inventory.CanFitInInventory(apparel3, out numToapparel3))
                 *          {
                 *              return new Job(JobDefOf.Wear, apparel3)
                 *              {
                 *                  ignoreForbidden = true,
                 *                  locomotionUrgency = LocomotionUrgency.Sprint
                 *              };
                 *          }
                 *      }
                 *  }
                 * }
                 */
                return(null);
            }
            return(null);
        }
Пример #16
0
        private WorkPriority GetPriorityWork(Pawn pawn)
        {
            CompAmmoUser primaryammouser = pawn.equipment.Primary.TryGetComp <CompAmmoUser>();

            if (pawn.Faction.IsPlayer && pawn.equipment.Primary != null && pawn.equipment.Primary.TryGetComp <CompAmmoUser>() != null)
            {
                Loadout loadout = pawn.GetLoadout();
                // if (loadout != null && !loadout.Slots.NullOrEmpty())
                if (loadout != null && loadout.SlotCount > 0)
                {
                    return(WorkPriority.None);
                }
            }

            if (pawn.kindDef.trader)
            {
                return(WorkPriority.None);
            }
            if (pawn.jobs.curJob != null && pawn.jobs.curJob.def == JobDefOf.Tame)
            {
                return(WorkPriority.None);
            }

            if (pawn.equipment.Primary == null)
            {
                if (Unload(pawn))
                {
                    return(WorkPriority.Unloading);
                }
                else
                {
                    return(WorkPriority.Weapon);
                }
            }

            if (pawn.equipment.Primary != null && primaryammouser != null)
            {
                int ammocount = 0;
                foreach (ThingDef ammoDef in primaryammouser.Props.ammoSet.ammoTypes)
                {
                    Thing ammoThing;
                    ammoThing = pawn.TryGetComp <CompInventory>().ammoList.Find(thing => thing.def == ammoDef);
                    if (ammoThing != null)
                    {
                        ammocount += ammoThing.stackCount;
                    }
                }
                float atw = primaryammouser.currentAmmo.GetStatValueAbstract(CR_StatDefOf.Bulk);
                if ((ammocount < (1.5f / atw)) && ((1.5f / atw) > 3))
                {
                    if (Unload(pawn))
                    {
                        return(WorkPriority.Unloading);
                    }
                    else
                    {
                        return(WorkPriority.LowAmmo);
                    }
                }
                if (!PawnUtility.EnemiesAreNearby(pawn, 30, true))
                {
                    if ((ammocount < (3.5f / atw)) && ((3.5f / atw) > 4))
                    {
                        if (Unload(pawn))
                        {
                            return(WorkPriority.Unloading);
                        }
                        else
                        {
                            return(WorkPriority.Ammo);
                        }
                    }
                }
            }

            if (!pawn.Faction.IsPlayer && pawn.equipment.Primary != null &&
                !PawnUtility.EnemiesAreNearby(pawn, 30, true) ||
                (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso) ||
                 !pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Legs)))
            {
                return(WorkPriority.Apparel);
            }

            else
            {
                return(WorkPriority.None);
            }
        }
Пример #17
0
        public static bool CheckForAutoAttack(Verse.AI.JobDriver_Wait __instance)
        {
            Pawn this_pawn = __instance.pawn;

            if (this_pawn.Downed || this_pawn.stances.FullBodyBusy)
            {
                return(false);
            }
            Map          map      = this_pawn.Map;
            List <Thing> fireList = map.listerThings.ThingsOfDef(ThingDefOf.Fire);

            bool flag  = PawnUtility.EnemiesAreNearby(this_pawn, 1) && !this_pawn.WorkTagIsDisabled(WorkTags.Violent);
            bool flag2 = this_pawn.RaceProps.ToolUser && this_pawn.Faction == Faction.OfPlayer && !this_pawn.WorkTagIsDisabled(WorkTags.Firefighting) && (!this_pawn.InMentalState || this_pawn.MentalState.def.allowBeatfire);

            if (!flag && !flag2)
            {
                return(false);
            }

            __instance.collideWithPawns = false;

            Fire fire = null;

            for (int i = 0; i < 9; i++)
            {
                IntVec3 c = this_pawn.Position + GenAdj.AdjacentCellsAndInside[i];
                if (c.InBounds(map))
                {
                    Thing[]      thingList;
                    List <Thing> thingList1 = c.GetThingList(map);
                    lock (thingList1)
                    {
                        thingList = thingList1.ToArray();
                    }
                    for (int j = 0; j < thingList.Length; j++)
                    {
                        if (flag)
                        {
                            Pawn pawn = thingList[j] as Pawn;
                            if (pawn != null && !pawn.Downed && this_pawn.HostileTo(pawn) && GenHostility.IsActiveThreatTo(pawn, this_pawn.Faction))
                            {
                                this_pawn.meleeVerbs.TryMeleeAttack(pawn, null, false);
                                __instance.collideWithPawns = true;
                                return(false);
                            }
                        }
                        if (flag2)
                        {
                            Fire fire2 = thingList[j] as Fire;
                            if (fire2 != null && (fire == null || fire2.fireSize < fire.fireSize || i == 8) && (fire2.parent == null || fire2.parent != this_pawn))
                            {
                                fire = fire2;
                            }
                        }
                    }
                }
            }
            if (fire != null)
            {
                this_pawn.natives.TryBeatFire(fire);
                return(false);
            }
            if (flag && __instance.job.canUseRangedWeapon && this_pawn.Faction != null && __instance.job.def == JobDefOf.Wait_Combat && (this_pawn.drafter == null || this_pawn.drafter.FireAtWill))
            {
                Verb currentEffectiveVerb = this_pawn.CurrentEffectiveVerb;
                if (currentEffectiveVerb != null && !currentEffectiveVerb.verbProps.IsMeleeAttack)
                {
                    TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat | TargetScanFlags.NeedAutoTargetable;
                    if (currentEffectiveVerb.IsIncendiary())
                    {
                        targetScanFlags |= TargetScanFlags.NeedNonBurning;
                    }
                    Thing thing = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(this_pawn, targetScanFlags, null, 0f, 9999f);
                    if (thing != null)
                    {
                        this_pawn.TryStartAttack(thing);
                        __instance.collideWithPawns = true;
                        return(false);
                    }
                }
            }

            return(false);
        }