public static void TentBlueprintRect(Thing constructible, ref Thing __result) { if (constructible is TentBlueprint_Install tbi && tbi.ThingToInstall is NCS_Tent tent) { __result = null; foreach (var se in tent.sketch.Entities) { foreach (var t in se.OccupiedRect.MovedBy(constructible.Position).SelectMany(c => c.GetThingList(constructible.Map))) { if ( (se is SketchRoof && ( //allow early fail out so edge cases only have to be checked once (cells in SketchRoof will be a super set of the cells from other entities) t is Plant || // only check plants under roofs, other stuff will be checked again if it collides with buildables (walls/ doors) !(t is Pawn p && p.IsColonistPlayerControlled) )) && t != tbi.MiniToInstallOrBuildingToReinstall && !(t.TryGetComp <TentSpawnedComp>() is TentSpawnedComp tsc && tsc.tent.Equals(tent)) && // Ignore buildings spawned by the tent (since they'll get vanished) GenConstruct.BlocksConstruction(constructible, t) ) { __result = t; return; } } } } }
public static bool IsGoodStoreCell(IntVec3 c, Map map, Thing t, Pawn carrier, Faction faction) { if (carrier != null && c.IsForbidden(carrier)) { return(false); } if (!(bool)_noStorageBlockersInMethod.Invoke(null, new object[] { c, map, t })) { Log.Error("Storage blockers found at " + c + " for " + t); return(false); } if (carrier != null) { if (!carrier.CanReserveNew(c)) { Log.Error("Carrier " + carrier + " can't reserve new at " + c); return(false); } } else if (faction != null) { var pawn = GetReservationClaimant(map.reservationManager, c, faction); if (pawn != null) { // Pawn Drone, ProjectRimFactory.Drones.Pawn_Drone, PRFDrone, Dorks Log.Error("Pawn " + pawn + ", " + pawn.def.thingClass.FullName + ", " + pawn.def.defName + ", " + pawn.Faction + " already reserved " + c); return(false); } } if (c.ContainsStaticFire(map)) { Log.Message("Fire at " + c); return(false); } List <Thing> thingList = c.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i] is IConstructible && GenConstruct.BlocksConstruction(thingList[i], t)) { Log.Error("BlocksConstruction at " + c); return(false); } } return(carrier == null || carrier.Map.reachability.CanReach(t.SpawnedOrAnyParentSpawned ? t.PositionHeld : carrier.PositionHeld, c, PathEndMode.ClosestTouch, TraverseParms.For(carrier, Danger.Deadly, TraverseMode.ByPawn, false, false, false))); }
public static Thing FirstReservableBlockingThing(Thing constructible, Pawn pawnToIgnore) { Thing thing = constructible is Blueprint b?GenConstruct.MiniToInstallOrBuildingToReinstall(b) : null; foreach (var pos in constructible.OccupiedRect()) { foreach (Thing t in pos.GetThingList(constructible.Map)) { if (GenConstruct.BlocksConstruction(constructible, t) && t != pawnToIgnore && t != thing && pawnToIgnore.CanReserve(t)) { return(t); } } } return(null); }
private static void ResolveDeadLock(RemoveRoofModel model) { foreach (Thing thing in model.WaitingThings.ToList()) { Thing lastFound = thing; List <Thing> foundThings = new List <Thing>() { lastFound }; while (true) { IntVec3 spawnCell = GetDeltaCell(lastFound, model.MousePos, model.GhostPosition); List <IntVec3> rect = GenAdj.OccupiedRect(spawnCell, lastFound.Rotate(model.Rotation), lastFound.def.size).ToList(); if (lastFound.def.hasInteractionCell) { rect.Add(Verse.ThingUtility.InteractionCellWhenAt(lastFound.def, spawnCell, lastFound.Rotate(model.Rotation), lastFound.MapHeld)); } IEnumerable <Thing> thingsOnCell = rect.SelectMany(c => c.GetThingList(lastFound.MapHeld).Where(t => t.def.blueprintDef != null && t.def.Minifiable)); lastFound = thingsOnCell.FirstOrDefault(t => GenConstruct.BlocksConstruction(lastFound, t) && model.WaitingThings.Contains(t)) ?? ThingUtility.BlockAdjacentInteractionCell(lastFound, spawnCell, lastFound.Rotate(model.Rotation)); if (lastFound == null || foundThings.Contains(lastFound)) { break; } foundThings.Add(lastFound); } if (lastFound == null) { continue; } else { thing.Map.designationManager.AddDesignation(new Designation(thing, DesignationDefOf.Uninstall)); } } }
public static IEnumerable <Thing> MakeWayFor(Thing blueprint, ThingCategory category) { if (blueprint.Faction != Faction.OfPlayer) { yield break; } Map map = blueprint.Map; foreach (IntVec3 cell in GenAdj.CellsOccupiedBy(blueprint)) { foreach (Thing thing in cell.GetThingList(map)) { if (thing.def.category == category) { if (GenConstruct.BlocksConstruction(blueprint, thing)) { yield return(thing); } } } } }
// RimWorld.PawnUtility.PawnBlockingPathAt public static Thing ThingBlockingPathAt(IntVec3 c, Thing thing) { List <Thing> thingList = c.GetThingList(thing.Map); if (thingList.Count == 0) { return(null); } for (int i = 0; i < thingList.Count; i++) { Thing thing2 = thingList[i]; if (thing.def.EverHaulable) { if (GenConstruct.BlocksConstruction(thing, thing2)) //&& thing != pawnToIgnore && thing != thingToIgnore) { return(thing); } } } return(null); }
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 override void DesignateSingleCell(IntVec3 c) { if (_mode == Mode.Select) { List <Thing> things = this.ReinstallableInCell(c); if (things.Any()) { if (_originFound == false) { _originFound = true; _origin = c; } DesignatedThings.AddRange(things); things.ForEach(thing => DesignateThing(thing)); } } else if (_mode == Mode.Place) { GenConstruct_CanPlaceBlueprintAt_Patch.Mode = BlueprintMode.Place; HashSet <Thing> placedThings = new HashSet <Thing>(); Dictionary <Thing, Thing> twinThings = new Dictionary <Thing, Thing>(); Dictionary <Thing, Blueprint_Install> blueprintWork = new Dictionary <Thing, Blueprint_Install>(); Dictionary <Thing, IntVec3> siblingWork = new Dictionary <Thing, IntVec3>(); IntVec3 mousePos = UI.MouseCell(); foreach (Thing designatedThing in DesignatedThings) { IntVec3 drawCell = GetDeltaCell(designatedThing, mousePos, _ghostPos); List <Thing> things = drawCell.GetThingList(designatedThing.MapHeld); bool foundTwin = false; bool foundSibling = false; foreach (Thing thingOnCell in things) { if (DesignatedThings.Contains(thingOnCell)) { if (designatedThing.IdenticalWith(_rotation, thingOnCell)) { if (blueprintWork.TryGetValue(thingOnCell, out Blueprint_Install install)) { Thing twin = this.GetTailInTwinThings(twinThings, designatedThing); _setBuildingToReinstall.Invoke(install, new[] { twin }); blueprintWork[twin] = install; blueprintWork.Remove(thingOnCell); placedThings.Add(twin); } else if (siblingWork.TryGetValue(thingOnCell, out IntVec3 position)) { Thing twin = this.GetTailInTwinThings(twinThings, designatedThing); _ghostPos[twin] = position; siblingWork.Remove(thingOnCell); siblingWork[twin] = position; placedThings.Add(thingOnCell); } else { twinThings[thingOnCell] = designatedThing; _ghostPos[designatedThing] = _ghostPos[thingOnCell]; placedThings.Add(thingOnCell); } this.Map.designationManager.TryRemoveDesignationOn(thingOnCell, MoveBaseDefOf.MoveBase); foundTwin = true; break; } else if (!GenConstruct.BlocksConstruction(designatedThing, thingOnCell)) { continue; } else { foundSibling = true; Thing twin = this.GetTailInTwinThings(twinThings, designatedThing); siblingWork[twin] = _ghostPos[twin] = _ghostPos[designatedThing]; break; } } } if (foundTwin || foundSibling) { continue; } Thing twin1 = this.GetTailInTwinThings(twinThings, designatedThing); AcceptanceReport report = GenConstruct.CanPlaceBlueprintAt( twin1.def , drawCell , GetRotation(twin1) , twin1.MapHeld , false , null , twin1); if (report.Accepted) { Building building = twin1 as Building; blueprintWork[building] = GenConstruct.PlaceBlueprintForReinstall(building, drawCell, building.MapHeld, GetRotation(building), Faction.OfPlayer); placedThings.Add(building); } } RemoveRoofModel model = InitModel( DesignatedThings , DesignatedThings.Except(placedThings).ToList() , DesignatedThings.First().MapHeld , mousePos , _rotation , _ghostPos); ResolveDeadLock(model); this.KeepDesignation = true; _mode = Mode.Select; Find.DesignatorManager.Deselect(); } }
//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 }; } }