public override void SpawnSetup(Map map, bool respawningAfterLoad) { base.SpawnSetup(map, respawningAfterLoad); LongEventHandler.ExecuteWhenFinished(GetTextures); _txtMinus = Prefs.TemperatureMode == TemperatureDisplayMode.Celsius ? "-1°C" : "-2°F"; _txtPlus = Prefs.TemperatureMode == TemperatureDisplayMode.Celsius ? "1°C" : "2°F"; _txtMinTempMinus = "MinTempMinus".Translate(); _txtMinTempPlus = "MinTempPlus".Translate(); _txtMaxTempMinus = "MaxTempMinus".Translate(); _txtMaxTempPlus = "MaxTempPlus".Translate(); _txtWatt = "Watt".Translate(); _txtStatus = "Status".Translate(); _txtStatusWaiting = "StatusWaiting".Translate(); _txtStatusHeating = "StatusHeating".Translate(); _txtStatusCooling = "StatusCooling".Translate(); _txtStatusOutdoor = "StatusOutdoor".Translate(); _txtMinComfortTemp = "MinComfortTemp".Translate(); _txtMaxComfortTemp = "MaxComfortTemp".Translate(); _txtPowerNotConnected = "PowerNotConnected".Translate(); _txtPowerNeeded = "PowerNeeded".Translate(); _txtPowerConnectedRateStored = "PowerConnectedRateStored".Translate(); _powerTrader = GetComp <CompPowerTrader>(); _room = RegionAndRoomQuery.RoomAt(Position, Map); }
/// <summary> /// Find defined things in reach and return an IEnumerable /// </summary> /// <param name="position">The starting position</param> /// <param name="room">The containing room</param> /// <param name="distance">The maximal distance to find targets</param> /// <returns></returns> public static IEnumerable <Thing> FindThingsInRoom(IntVec3 position, Map map, float distance) { Room room = RegionAndRoomQuery.RoomAt(position, map); // LINQ version return(map.listerThings.AllThings.Where(t => t.Position.InHorDistOf(position, distance) && room == RegionAndRoomQuery.RoomAt(t.Position, map))); }
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) && RegionAndRoomQuery.RoomAt(intVec, 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); }
/// <summary> /// Find all pawns in room within a certain distance and return an IEnumerable /// </summary> /// <param name="positon">The source position</param> /// <param name="distance">The maximal distance</param> /// <returns></returns> public static IEnumerable <Pawn> FindAllPawnsInRoom(IntVec3 position, Room room, float distance) { // LINQ version return(room.Map.mapPawns.AllPawnsSpawned.Where(p => !p.InContainerEnclosed && (RegionAndRoomQuery.RoomAt(p.Position, room.Map) == room) && (p.Position.InHorDistOf(position, distance)))); }
/// <summary> /// If the billGiver is our SimpleAssembler, get the room of the output tile. /// Else, retain origin behavior. /// </summary> /// <param name="pawn"></param> /// <param name="allowedRegionTypes"></param> /// <param name="billGiver"></param> /// <returns></returns> public static Room GetRoomOfPawnOrGiver(Pawn pawn, RegionType allowedRegionTypes, IBillGiver billGiver) { if (pawn.kindDef == PRFDefOf.PRFSlavePawn && billGiver is Building_SimpleAssembler assembler) { return(RegionAndRoomQuery.RoomAt(assembler.OutputComp.CurrentCell, billGiver.Map, RegionType.Set_Passable)); } return(pawn.GetRoom(allowedRegionTypes)); }
public static Room GetRoom(this Thing thing, RegionType allowedRegionTypes = RegionType.Set_Passable) { if (!thing.Spawned) { return null; } return RegionAndRoomQuery.RoomAt(thing.Position, thing.Map, allowedRegionTypes); }
public override void TickRare() { base.TickRare(); _txtMinus = Prefs.TemperatureMode == TemperatureDisplayMode.Celsius ? "-1°C" : "-2°F"; _txtPlus = Prefs.TemperatureMode == TemperatureDisplayMode.Celsius ? "1°C" : "2°F"; _room = RegionAndRoomQuery.RoomAt(Position, Map); if (!_powerTrader.PowerOn || _room == null || _room.UsesOutdoorTemperature) { if (_room != null && _room.UsesOutdoorTemperature) { WorkStatus = Status.Outdoor; } _powerTrader.PowerOutput = 0; return; } var currentTemp = _room.Temperature; if (currentTemp >= _minComfortTemp && currentTemp <= _maxComfortTemp) { WorkStatus = Status.Waiting; _powerTrader.PowerOutput = -1.0f; return; } var diffTemp = 0.0f; var powerMod = 1.1f; var energyMul = 1.0f; if (currentTemp < _minComfortTemp) { WorkStatus = Status.Heating; diffTemp = _minComfortTemp - currentTemp; } if (currentTemp > _maxComfortTemp) { WorkStatus = Status.Cooling; diffTemp = _maxComfortTemp - currentTemp; powerMod = 1.6f; } if (Mathf.Abs(diffTemp) < 3) { energyMul += 0.5f; } var efficiencyLoss = EfficiencyLossPerDegreeDifference * Mathf.Abs(diffTemp); var energyLimit = diffTemp * _room.CellCount * energyMul * 0.3333f; var needPower = Mathf.Abs(energyLimit * (powerMod + efficiencyLoss)) + 1.0f; _powerTrader.PowerOutput = -needPower * 5; ChangeTemp(energyLimit); }
/// <summary> /// Search for pawn in the room /// </summary> /// <returns></returns> private bool SearchForPawnInRoom(Map map) { IEnumerable <Pawn> pawns; if (!pawnSearchModeDistanceActive) { pawns = Radar.FindAllPawnsInRoom(RegionAndRoomQuery.RoomAt(Position, map)); } else { pawns = Radar.FindAllPawns(this.Position, map, radarDistancePawn); } return(pawns.Count() > 0); }
public static bool FindFoodStockpile(out IntVec3 cell, Map map) { List <IntVec3> candidate = new List <IntVec3>(); int zoneCount; foreach (Zone_Stockpile zone in map.zoneManager.AllZones.FindAll((Zone z) => z is Zone_Stockpile)) { zoneCount = 0; foreach (Region region in RegionAndRoomQuery.RoomAt(zone.Position, map).Regions) { zoneCount += region.ListerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree).Count; if (zoneCount > 5) { foreach (Region r in RegionAndRoomQuery.RoomAt(zone.Position, map).Regions) { int wallIndex = r.extentsClose.maxZ + 1; int maxZ = r.extentsClose.maxZ; for (int index = r.extentsClose.minX; index <= r.extentsClose.maxX; index++) { IntVec3 wallPosition = new IntVec3(index, 0, wallIndex); Thing wall = map.thingGrid.ThingAt(wallPosition, ThingCategory.Building); Thing passingPoint = map.thingGrid.ThingAt(new IntVec3(index, 0, maxZ), ThingCategory.Building); if (wall != null && wall.def.fillPercent >= 1 && wall.def.graphicData.linkType == LinkDrawerType.CornerFiller && (passingPoint == null || passingPoint.def.passability != Traversability.Impassable)) { candidate.Add(wallPosition); } } } break; } } } if (candidate.Count > 0) { cell = candidate.RandomElement(); return(true); } else { cell = new IntVec3(); return(false); } }
public static Room RoomAtOrAdjacent(IntVec3 c, Map map, RegionType allowedRegionTypes = RegionType.Set_Passable) { Room room = RegionAndRoomQuery.RoomAt(c, map, allowedRegionTypes); if (room != null) { return room; } for (int i = 0; i < 8; i++) { IntVec3 c2 = c + GenAdj.AdjacentCells[i]; room = RegionAndRoomQuery.RoomAt(c2, map, allowedRegionTypes); if (room != null) { return room; } } return room; }
/// <summary> /// This is called seperately when the Mod-Thread is done. /// It is needed to be seperately from SpawnSetup, so that the graphics can be found /// </summary> private void SpawnSetup_Part2() { GetTextures(); DestroyOtherPowerTransmitter(); // Wall: can't have this deactive! bool isWall = RegionAndRoomQuery.RoomAt(this.Position, this.Map) == null; if (isWall) { pawnSearchModeDistanceActive = true; } this.flickableComp = base.GetComp <CompFlickable>(); // Initialized init = true; }
public override void DesignateSingleCell(IntVec3 c) { base.DesignateSingleCell(c); if (Input.GetKey(KeyCode.LeftShift)) { Room room = RegionAndRoomQuery.RoomAt(c, Map); if (room != null) { foreach (IntVec3 vec in room.Cells) { base.DesignateSingleCell(vec); } if (!room.IsHuge) { foreach (IntVec3 vec in room.BorderCells) { base.DesignateSingleCell(vec); } } } } }
public override void Tick() { if (!pawn.Spawned) { pawn.health.RemoveHediff(this); } if (pawn.Downed || pawn.Dead || (pawn.pather != null && pawn.pather.WillCollideWithPawnOnNextPathCell())) { pawn.health.RemoveHediff(this); if (pawn.pather != null) { AlertThief(pawn, pawn.pather.nextCell.GetFirstPawn(pawn.Map)); } else { AlertThief(pawn, null); } } if (pawn.pather != null && GetLastCell(pawn.pather).GetDoor(pawn.Map) != null) { GetLastCell(pawn.pather).GetDoor(pawn.Map).StartManualCloseBy(pawn); } if (pawn.Map != null && lastSpottedTick < Find.TickManager.TicksGame - 125) { lastSpottedTick = Find.TickManager.TicksGame; int num = 0; while (num < 20) { IntVec3 c = pawn.Position + GenRadial.RadialPattern[num]; Room room = RegionAndRoomQuery.RoomAt(c, pawn.Map); if (c.InBounds(pawn.Map)) { if (RegionAndRoomQuery.RoomAt(c, pawn.Map) == room) { List <Thing> thingList = c.GetThingList(pawn.Map); foreach (Thing thing in thingList) { Pawn observer = thing as Pawn; if (observer != null && observer != pawn && observer.Faction != null && (observer.Faction.IsPlayer || observer.Faction.HostileTo(pawn.Faction))) { float observerSight = observer.health.capacities.GetLevel(PawnCapacityDefOf.Sight); observerSight *= 0.805f + (pawn.Map.glowGrid.GameGlowAt(pawn.Position) / 4); if (observer.RaceProps.Animal) { observerSight *= 0.9f; } observerSight = Math.Min(2f, observerSight); float thiefMoving = pawn.health.capacities.GetLevel(PawnCapacityDefOf.Moving); float spotChance = 0.8f * thiefMoving / observerSight; if (Rand.Value > spotChance) { pawn.health.RemoveHediff(this); AlertThief(pawn, observer); } } else if (observer == null) { Building_Turret turret = thing as Building_Turret; if (turret != null && turret.Faction != null && turret.Faction.IsPlayer) { float thiefMoving = pawn.health.capacities.GetLevel(PawnCapacityDefOf.Moving); float spotChance = 0.99f * thiefMoving; if (Rand.Value > spotChance) { pawn.health.RemoveHediff(this); AlertThief(pawn, turret); } } } } } } num++; } Thing holding = pawn.carryTracker.CarriedThing; if (lastCarried != holding) { if (lastCarried != null) { SetGraphicInt(lastCarried, lastCarriedGraphic); } if (holding != null) { lastCarried = holding; lastCarriedGraphic = holding.Graphic; SetGraphicInt(lastCarried, new Graphic_Invisible()); } } } }
static Job FindBedrollJob(Job fallbackJob, Pawn pawn) { if (!pawn.IsColonistPlayerControlled) { return(fallbackJob); } Log.Message(pawn + " looking for inventory beds"); MinifiedThing invBed = (MinifiedThing)FindMinifiedBed(pawn); if (invBed == null) { return(fallbackJob); } Log.Message(pawn + " found " + invBed); Map map = pawn.Map; Building_Bed bed = (Building_Bed)invBed.GetInnerIfMinified(); Func <IntVec3, Rot4, bool> cellValidatorDir = delegate(IntVec3 c, Rot4 direction) { if (RegionAndRoomQuery.RoomAtFast(c, map).isPrisonCell != pawn.IsPrisoner) { return(false); } if (!GenConstruct.CanPlaceBlueprintAt(invBed.GetInnerIfMinified().def, c, direction, map).Accepted) { return(false); } if (c.IsForbidden(pawn)) { return(false); } for (CellRect.CellRectIterator iterator = GenAdj.OccupiedRect(c, direction, bed.def.size).GetIterator(); !iterator.Done(); iterator.MoveNext()) { foreach (Thing t in iterator.Current.GetThingList(map)) { if (!(t is Pawn) && GenConstruct.BlocksConstruction(bed, t)) { return(false); } } if (!(map.zoneManager.ZoneAt(c) is null)) { return(false); } } return(true); }; // North/East would be redundant, except for cells on edge ; oh well, too much code to handle that Predicate <IntVec3> cellValidator = c => cellValidatorDir(c, Rot4.South) || cellValidatorDir(c, Rot4.West); Predicate <IntVec3> goodCellValidator = c => !RegionAndRoomQuery.RoomAt(c, map).PsychologicallyOutdoors&& cellValidator(c); IntVec3 placePosition = IntVec3.Invalid; IntVec3 root = pawn.Position; TraverseParms trav = TraverseParms.For(pawn); if (!CellFinder.TryFindRandomReachableCellNear(root, map, 4, trav, goodCellValidator, null, out placePosition)) { if (!CellFinder.TryFindRandomReachableCellNear(root, map, 12, trav, goodCellValidator, null, out placePosition)) { if (!CellFinder.TryFindRandomReachableCellNear(root, map, 4, trav, cellValidator, null, out placePosition)) { CellFinder.TryFindRandomReachableCellNear(root, map, 12, trav, cellValidator, null, out placePosition); } } } if (placePosition.IsValid) { Rot4 dir = cellValidatorDir(placePosition, Rot4.South) ? Rot4.South : Rot4.West; Blueprint_Install blueprint = GenConstruct.PlaceBlueprintForInstall(invBed, placePosition, map, dir, pawn.Faction); Log.Message(pawn + " placing " + blueprint + " at " + placePosition); return(new Job(JobDefOf.PlaceBedroll, invBed, blueprint) { haulMode = HaulMode.ToContainer }); } Log.Message(pawn + " couldn't find place for " + invBed); return(fallbackJob); }
public static RoomGroup RoomGroupAt(IntVec3 c, Map map) { Room room = RegionAndRoomQuery.RoomAt(c, map, RegionType.Set_All); return (room == null) ? null : room.Group; }
/// <summary> /// Find defined things in reach and return an IEnumerable /// </summary> /// <param name="position">The starting position</param> /// <param name="room">The containing room</param> /// <returns></returns> public static IEnumerable <Thing> FindThingsInRoom(IntVec3 position, Room room) { // LINQ version return(room.Map.listerThings.AllThings.Where(t => room == RegionAndRoomQuery.RoomAt(t.Position, room.Map))); }
//protected override Job TryGiveJob(Pawn pawn) public static void Postfix(ref Job __result, Pawn pawn) { if (__result == null) { return; } if (!pawn.IsColonistPlayerControlled) { return; } Map map = pawn.Map; if (!Settings.Get().alsoColonies&& map.IsPlayerHome) { if (!Settings.Get().alsoColoniesKnown) { Settings.Get().alsoColoniesKnown = true; Settings.Get().Write(); Find.LetterStack.ReceiveLetter("TD.UseBedrollsUpdated".Translate(), TranslatorFormattedStringExtensions.Translate("TD.UpdateNewsColonyMaps", pawn), LetterDefOf.NeutralEvent, pawn); // I don't think this really needs to be hugslibs update news or anything. alsoColoniesKnown defaults } return; } if (__result.targetA.Thing is Building_Bed ownedBed) { if (!Settings.Get().distanceCheck || (ownedBed.Position).DistanceTo(pawn.Position) < Settings.Get().distance) { return; //Have a bed that close enough, no need to get from inventory } } MinifiedThing invBed = (MinifiedThing)FindMinifiedBed(pawn); if (invBed == null) { return; } Log.Message($"{pawn} found {invBed}"); Building_Bed bed = (Building_Bed)invBed.GetInnerIfMinified(); Func <IntVec3, Rot4, bool> cellValidatorDir = delegate(IntVec3 c, Rot4 direction) { if (RegionAndRoomQuery.RoomAt(c, map).isPrisonCell != pawn.IsPrisoner) { return(false); } if (!GenConstruct.CanPlaceBlueprintAt(invBed.GetInnerIfMinified().def, c, direction, map).Accepted) { return(false); } //Support ReplaceStuff allowing blueprints over beds if (EdificeBlocking(invBed.GetInnerIfMinified().def, c, direction, map)) { return(false); } if (!GenConstruct.CanPlaceBlueprintAt(invBed.GetInnerIfMinified().def, c, direction, map).Accepted) { return(false); } //Each cell of bed: foreach (var pos in GenAdj.OccupiedRect(c, direction, bed.def.size)) { if (map.zoneManager.ZoneAt(pos) != null) { return(false); } foreach (Thing t in pos.GetThingList(map)) { if (!(t is Pawn) && GenConstruct.BlocksConstruction(bed, t)) { return(false); } } } return(true); }; IntVec3 root = invBed.PositionHeld; // North/East would be redundant, except for cells on edge ; oh well, too much code to handle that Predicate <IntVec3> cellValidator = delegate(IntVec3 c) { if (!cellValidatorDir(c, Rot4.South) && !cellValidatorDir(c, Rot4.West)) { return(false); } using (PawnPath path = map.pathFinder.FindPath(root, c, pawn)) { return(path.TotalCost < 500); } }; Predicate <IntVec3> goodCellValidator = c => !RegionAndRoomQuery.RoomAt(c, map).PsychologicallyOutdoors&& cellValidator(c); IntVec3 placePosition = IntVec3.Invalid; TraverseParms trav = TraverseParms.For(pawn); if (!CellFinder.TryFindRandomReachableCellNear(root, map, 4, trav, goodCellValidator, null, out placePosition)) { if (!CellFinder.TryFindRandomReachableCellNear(root, map, 12, trav, goodCellValidator, null, out placePosition)) { if (!CellFinder.TryFindRandomReachableCellNear(root, map, 4, trav, cellValidator, null, out placePosition)) { CellFinder.TryFindRandomReachableCellNear(root, map, 12, trav, cellValidator, null, out placePosition); } } } if (placePosition.IsValid) { Rot4 dir = cellValidatorDir(placePosition, Rot4.South) ? Rot4.South : Rot4.West; Blueprint_Install blueprint = GenConstruct.PlaceBlueprintForInstall(invBed, placePosition, map, dir, pawn.Faction); Log.Message($"{pawn} placing {blueprint} at {placePosition}"); __result = new Job(JobDefOf.PlaceBedroll, invBed, blueprint) { haulMode = HaulMode.ToContainer }; } }
/// <summary> /// Find all pawns in room and return an IEnumerable /// </summary> /// <param name="room">Find in which room</param> /// <returns></returns> public static IEnumerable <Pawn> FindAllPawnsInRoom(Room room) { // LINQ version return(room.Map.mapPawns.AllPawnsSpawned.Where(p => !p.InContainerEnclosed && (room == RegionAndRoomQuery.RoomAt(p.Position, room.Map)))); }
private void FindAdjacentRooms() { adjacentRooms.Clear(); if (room.UsesOutdoorTemperature) { return; } Map visibleMap = Find.VisibleMap; List <IntVec3> cells = new List <IntVec3>(); foreach (IntVec3 current in room.Cells) { cells.Add(current); } if (fieldGrid == null) { fieldGrid = new BoolGrid(visibleMap); } else { fieldGrid.ClearAndResizeTo(visibleMap); } int x = visibleMap.Size.x; int z = visibleMap.Size.z; int count = cells.Count; for (int i = 0; i < count; i++) { if (cells[i].InBounds(visibleMap)) { fieldGrid[cells[i].x, cells[i].z] = true; } } for (int j = 0; j < count; j++) { IntVec3 c = cells[j]; if (c.InBounds(visibleMap)) { if (c.z < z - 1 && !fieldGrid[c.x, c.z + 1]) { var door = Find.VisibleMap.thingGrid.ThingsAt(new IntVec3(c.x, c.y, c.z + 1)).ToList().Find(s => s.def.defName == "Door"); if (door != null) { adjacentRooms.Add(RegionAndRoomQuery.RoomAt(new IntVec3(c.x, c.y, c.z + 2), Map)); } } if (c.x < x - 1 && !fieldGrid[c.x + 1, c.z]) { var door = Find.VisibleMap.thingGrid.ThingsAt(new IntVec3(c.x + 1, c.y, c.z)).ToList().Find(s => s.def.defName == "Door"); if (door != null) { adjacentRooms.Add(RegionAndRoomQuery.RoomAt(new IntVec3(c.x + 2, c.y, c.z), Map)); } } if (c.z > 0 && !fieldGrid[c.x, c.z - 1]) { var door = Find.VisibleMap.thingGrid.ThingsAt(new IntVec3(c.x, c.y, c.z - 1)).ToList().Find(s => s.def.defName == "Door"); if (door != null) { adjacentRooms.Add(RegionAndRoomQuery.RoomAt(new IntVec3(c.x, c.y, c.z - 2), Map)); } } if (c.z > 0 && !fieldGrid[c.x - 1, c.z]) { var door = Find.VisibleMap.thingGrid.ThingsAt(new IntVec3(c.x - 1, c.y, c.z)).ToList().Find(s => s.def.defName == "Door"); if (door != null) { adjacentRooms.Add(RegionAndRoomQuery.RoomAt(new IntVec3(c.x - 2, c.y, c.z), Map)); } } } } }
public override void CompTick() { if (pawn.ageTracker.CurLifeStage != XenomorphDefOf.RRY_XenomorphFullyFormed) { if (pawn.CurJobDef == JobDefOf.Ingest) { hidden = false; } else if (pawn.CurJobDef != JobDefOf.Ingest) { hidden = true; } } if (pawn.Faction == null) { if (Find.FactionManager.FirstFactionOfDef(XenomorphDefOf.RRY_Xenomorph) != null) { pawn.SetFaction(Find.FactionManager.FirstFactionOfDef(XenomorphDefOf.RRY_Xenomorph)); } } base.CompTick(); if (Hidden) { if (!hidden) { MakeInvisible(); hidden = true; } if (pawn.Downed || pawn.Dead || (pawn.pather != null && pawn.pather.WillCollideWithPawnOnNextPathCell())) { MakeVisible(); hidden = false; if (pawn.pather != null) { AlertXenomorph(pawn, pawn.pather.nextCell.GetFirstPawn(pawn.Map)); } else { AlertXenomorph(pawn, null); } } /* * if (pawn.pather != null && GetLastCell(pawn.pather).GetDoor(pawn.Map) != null) * { * GetLastCell(pawn.pather).GetDoor(pawn.Map).StartManualCloseBy(pawn); * } */ if (pawn.Map != null && lastSpottedTick < Find.TickManager.TicksGame - 125) { lastSpottedTick = Find.TickManager.TicksGame; int num = 0; while (num < 20) { IntVec3 c = pawn.Position + GenRadial.RadialPattern[num]; Room room = RegionAndRoomQuery.RoomAt(c, pawn.Map); if (c.InBounds(pawn.Map)) { if (RegionAndRoomQuery.RoomAt(c, pawn.Map) == room) { List <Thing> thingList = c.GetThingList(pawn.Map); foreach (Thing thing in thingList) { Pawn observer = thing as Pawn; if (observer != null && observer != pawn && observer.Faction != null && (observer.Faction.HostileTo(pawn.Faction))) { float observerSight = observer.health.capacities.GetLevel(PawnCapacityDefOf.Sight); observerSight *= 0.805f + (pawn.Map.glowGrid.GameGlowAt(pawn.Position) / 4); if (observer.RaceProps.Animal) { observerSight *= 0.9f; } observerSight = Math.Min(2f, observerSight); float thiefMoving = pawn.health.capacities.GetLevel(PawnCapacityDefOf.Moving); float spotChance = 0.8f * thiefMoving / observerSight; if (Rand.Value > spotChance) { MakeVisible(); hidden = false; AlertXenomorph(pawn, observer); } } else if (observer == null) { if (thing is Building_Turret turret && turret.Faction != null && turret.Faction.IsPlayer) { float thiefMoving = pawn.health.capacities.GetLevel(PawnCapacityDefOf.Moving); float spotChance = 0.99f * thiefMoving; if (Rand.Value > spotChance) { MakeVisible(); hidden = false; //pawn.health.RemoveHediff(this); AlertXenomorph(pawn, turret); } } } } } } num++; } Thing holding = pawn.carryTracker.CarriedThing; if (lastCarried != holding) { if (lastCarried != null) { SetGraphicInt(lastCarried, lastCarriedGraphic); } if (holding != null) { lastCarried = holding; lastCarriedGraphic = holding.Graphic; SetGraphicInt(lastCarried, new Graphic_Invisible()); } } } } else { if (hidden) { MakeVisible(); hidden = false; } List <Pawn> thingList = map.mapPawns.AllPawns.Where(x => x != pawn && !x.isXenomorph() && GenSight.LineOfSight(x.Position, pawn.Position, map, true, null, 0, 0) && pawn.Position.DistanceTo(x.Position) <= MinHideDist && !x.Downed && !x.Dead).ToList(); if (thingList.NullOrEmpty() && lastSpottedTick < Find.TickManager.TicksGame - 125) { MakeInvisible(); hidden = true; } } }