Ejemplo n.º 1
0
        public static void PlaceWaitingBuildings()
        {
            GenConstruct_CanPlaceBlueprintAt_Patch.Mode = BlueprintMode.Place;
            foreach (RemoveRoofModel model in _removeRoofModels)
            {
                foreach (Thing thing in model.WaitingThings.ToList())
                {
                    if (thing.DestroyedOrNull() || thing.MapHeld != model.Map)
                    {
                        model.WaitingThings.Remove(thing);
                        continue;
                    }

                    IntVec3 deltaCell = GetDeltaCell(thing, model.MousePos, model.GhostPosition);

                    Thing inner = thing.GetInnerIfMinified();
                    if (GenConstruct.CanPlaceBlueprintAt(inner.def, deltaCell, inner.Rotate(model.Rotation), inner.MapHeld, thing: inner).Accepted)
                    {
                        if (thing is MinifiedThing minifiedThing)
                        {
                            GenConstruct.PlaceBlueprintForInstall(minifiedThing, deltaCell, minifiedThing.MapHeld, inner.Rotate(model.Rotation), Faction.OfPlayer);
                        }
                        else
                        {
                            GenConstruct.PlaceBlueprintForReinstall(thing as Building, deltaCell, thing.MapHeld, thing.Rotate(model.Rotation), Faction.OfPlayer);
                        }

                        model.WaitingThings.Remove(thing);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private AcceptanceReport CanReinstallAllThings(IntVec3 mousePos)
        {
            AcceptanceReport result = AcceptanceReport.WasAccepted;

            GenConstruct_CanPlaceBlueprintAt_Patch.Mode = BlueprintMode.Check;
            this.TraverseDesignateThings(
                mousePos
                , (drawCell, thing) =>
            {
                AcceptanceReport report = GenConstruct.CanPlaceBlueprintAt(
                    thing.def
                    , drawCell
                    , GetRotation(thing)
                    , thing.MapHeld
                    , false
                    , null
                    , thing);
                if (!report.Accepted)
                {
                    result = report;
                    return(true);
                }

                return(false);
            });

            return(result);
        }
        public void ScheduleReplacement(CompAutoReplaceable replaceableComp)
        {
            var building = replaceableComp.parent;

            if (building?.def == null)
            {
                return;
            }
            if ((building.Stuff == null && building.def.MadeFromStuff) || (building.Stuff != null && !building.def.MadeFromStuff))
            {
                RemoteTechController.Instance.Logger.Warning("Could not schedule {0} auto-replacement due to Stuff discrepancy.", building);
                return;
            }
            var report = GenConstruct.CanPlaceBlueprintAt(building.def, replaceableComp.ParentPosition, replaceableComp.ParentRotation, map);

            if (!report.Accepted)
            {
                RemoteTechController.Instance.Logger.Message($"Could not auto-replace {building.LabelCap}: {report.Reason}");
                return;
            }
            var blueprint = GenConstruct.PlaceBlueprintForBuild(building.def, replaceableComp.ParentPosition, map, replaceableComp.ParentRotation, Faction.OfPlayer, building.Stuff);
            var entry     = new ReplacementEntry {
                position     = replaceableComp.ParentPosition,
                unforbidTick = Find.TickManager.TicksGame + RemoteTechController.Instance.BlueprintForbidDuration * GenTicks.TicksPerRealSecond,
                savedVars    = new Dictionary <string, string>()
            };

            InvokeExposableCallbacks(building, entry.savedVars, LoadSaveMode.Saving);
            pendingSettings.Add(entry);
            if (RemoteTechController.Instance.BlueprintForbidDuration > 0)
            {
                blueprint.SetForbidden(true, false);
                pendingForbiddenBlueprints.Add(entry);
            }
        }
        protected override bool TryExecuteWorker(IncidentParms parms)
        {
            bool           result    = false;
            List <IntVec3> targets   = new List <IntVec3>();
            int            numOffset = Mathf.Min((int)(((Map)parms.target).wealthWatcher.WealthTotal / 100000), 7);
            int            num       = Rand.Range(1, 1 + numOffset);

            for (int i = 0; i < num; i++)
            {
                if (this.TryFindRandomPowerConduitInMap((Map)parms.target, out Building tempConduit))
                {
                    IntVec3 intVec = new IntVec3(tempConduit.Position.x, tempConduit.Position.y, tempConduit.Position.z);
                    Rot4    rot    = new Rot4(tempConduit.Rotation.AsByte);
                    targets.Add(intVec);
                    tempConduit.Destroy(DestroyMode.Deconstruct);
                    if (Find.PlaySettings.autoRebuild && tempConduit.def.blueprintDef != null && tempConduit.def.IsResearchFinished && ((Map)parms.target).areaManager.Home[tempConduit.Position])
                    {
                        if (GenConstruct.CanPlaceBlueprintAt(tempConduit.def, intVec, rot, (Map)parms.target, false, null).Accepted)
                        {
                            GenConstruct.PlaceBlueprintForBuild(tempConduit.def, intVec, (Map)parms.target, rot, Faction.OfPlayer, tempConduit.Stuff);
                        }
                    }
                }
            }
            if (!targets.NullOrEmpty())
            {
                result = true;
                LookTargets letterTargets = new LookTargets(this.GetLetterTargets(targets, (Map)parms.target));
                Find.LetterStack.ReceiveLetter(this.def.letterLabel, this.def.letterText, this.def.letterDef, letterTargets);
            }
            return(result);
        }
Ejemplo n.º 5
0
        public void AttemptToPlace(ThingDef thingDef, CellRect rect, Rot4 rotation, Faction faction)
        {
            Map     map = BaseGen.globalSettings.map;
            Thing   thing;
            IntVec3 loc = (from cell in rect.Cells.InRandomOrder(null)
                           where GenConstruct.CanPlaceBlueprintAt(thingDef, cell, rotation, map, false, null).Accepted&& GenAdj.OccupiedRect(cell, rotation, thingDef.Size).AdjacentCellsCardinal.Any(delegate(IntVec3 edgeCell)
            {
                bool result;
                if (edgeCell.InBounds(map))
                {
                    result = edgeCell.GetThingList(map).Any((Thing thing) => thing.def == ThingDefOf.Ship_Beam);
                }
                else
                {
                    result = false;
                }
                return(result);
            })
                           select cell).FirstOrFallback(IntVec3.Invalid);

            if (loc.IsValid)
            {
                thing = ThingMaker.MakeThing(thingDef, null);
                thing.SetFaction(faction, null);
                CompHibernatable compHibernatable = thing.TryGetComp <CompHibernatable>();
                if (compHibernatable != null)
                {
                    compHibernatable.State = HibernatableStateDefOf.Hibernating;
                }
                GenSpawn.Spawn(thing, loc, BaseGen.globalSettings.map, rotation, WipeMode.Vanish, false);
            }
        }
Ejemplo n.º 6
0
        private AcceptanceReport CanReinstall(Thing thing, IntVec3 drawCell)
        {
            GenConstruct_CanPlaceBlueprintAt_Patch.Mode = BlueprintMode.Check;
            AcceptanceReport report = GenConstruct.CanPlaceBlueprintAt(thing.def, drawCell, GetRotation(thing), thing.MapHeld, false, null, thing);

            return(report);
        }
 private void CheckAutoRebuild(Map map)
 {
     if (this.autoRearm && this.CanSetAutoRearm && map != null && GenConstruct.CanPlaceBlueprintAt(this.def, base.Position, base.Rotation, map, false, null, null, base.Stuff).Accepted)
     {
         GenConstruct.PlaceBlueprintForBuild(this.def, base.Position, map, base.Rotation, Faction.OfPlayer, base.Stuff);
     }
 }
Ejemplo n.º 8
0
        //private void UnfogWorker(IntVec3 c)
        public static void Postfix(FogGrid __instance, IntVec3 c, Map ___map)
        {
            Map map = ___map;

            if (c.GetThingList(map).FirstOrDefault(t => t.def.IsBlueprint) is Thing blueprint && !blueprint.IsUnderFog())
            {
                if (!GenConstruct.CanPlaceBlueprintAt(blueprint.def.entityDefToBuild, blueprint.Position, blueprint.Rotation, map, false, blueprint).Accepted)
                {
                    blueprint.Destroy();
                }
                else
                {
                    blueprint.Notify_ColorChanged();                    //does the job, haha.
                }
            }
        }
Ejemplo n.º 9
0
 internal bool <> m__0(IntVec3 cell)
 {
     return(GenConstruct.CanPlaceBlueprintAt(this.thingDef, cell, this.rotation, this.map, false, null).Accepted&& GenAdj.OccupiedRect(cell, this.rotation, this.thingDef.Size).AdjacentCellsCardinal.Any(delegate(IntVec3 edgeCell)
     {
         bool result;
         if (edgeCell.InBounds(this.map))
         {
             result = edgeCell.GetThingList(this.map).Any((Thing thing) => thing.def == ThingDefOf.Ship_Beam);
         }
         else
         {
             result = false;
         }
         return result;
     }));
 }
Ejemplo n.º 10
0
        public ConstructionStatus TargetConstructionStatus(Map map)
        {
            if (BuildableDef == null || target == null || target.HasThing || !target.IsValid)
            {
                return(ConstructionStatus.Invalid);
            }

            if (target.Cell.GetTerrain(map) == blueprintTerrainDef)
            {
                return(ConstructionStatus.Complete);
            }

            foreach (Thing thing in target.Cell.GetThingList(map))
            {
                Blueprint_Build blueprintBuild = thing as Blueprint_Build;
                Frame           frame          = thing as Frame;

                if (blueprintBuild != null && blueprintBuild.stuffToUse == blueprintStuff && thing.def.entityDefToBuild == BuildableDef)
                {
                    return(ConstructionStatus.InProgress);
                }

                if (frame != null && thing.Stuff == blueprintStuff && thing.def.entityDefToBuild == BuildableDef)
                {
                    return(ConstructionStatus.InProgress);
                }

                if (thing.Stuff == blueprintStuff && thing.def == blueprintThingDef && blueprintBuild == null && frame == null)
                {
                    return(ConstructionStatus.Complete);
                }
            }

            if (blueprintTerrainDef != null && !GenConstruct.CanPlaceBlueprintAt(blueprintTerrainDef, target.Cell, blueprintRotation, map, false, null, null, blueprintStuff).Accepted)
            {
                return(ConstructionStatus.Blocked);
            }

            if (blueprintThingDef != null && !GenConstruct.CanPlaceBlueprintAt(blueprintThingDef, target.Cell, blueprintRotation, map, false, null, null, blueprintStuff).Accepted)
            {
                return(ConstructionStatus.Blocked);
            }

            return(ConstructionStatus.None);
        }
Ejemplo n.º 11
0
        public static bool CanPlaceBlueprintAt(IntVec3 spot, ThingDef def, Rot4 rot = default(Rot4))
        {
            if (!spot.IsValid)
            {
                return(false);
            }

            // Cheaty cheaty
            bool isEdifice = def.IsEdifice();

            def.building.isEdifice = true;

            bool result = GenConstruct.CanPlaceBlueprintAt(def, spot, rot, info.map, false, null).Accepted;

            def.building.isEdifice = isEdifice;

            return(result);
        }
        public void AttemptToPlace(ThingDef thingDef, CellRect rect, Rot4 rotation, Faction faction)
        {
            Map     map = BaseGen.globalSettings.map;
            IntVec3 loc = (from cell in rect.Cells.InRandomOrder()
                           where GenConstruct.CanPlaceBlueprintAt(thingDef, cell, rotation, map).Accepted&& GenAdj.OccupiedRect(cell, rotation, thingDef.Size).AdjacentCellsCardinal.Any((IntVec3 edgeCell) => edgeCell.InBounds(map) && edgeCell.GetThingList(map).Any((Thing thing) => thing.def == ThingDefOf.Ship_Beam))
                           select cell).FirstOrFallback(IntVec3.Invalid);

            if (loc.IsValid)
            {
                Thing thing2 = ThingMaker.MakeThing(thingDef);
                thing2.SetFaction(faction);
                CompHibernatable compHibernatable = thing2.TryGetComp <CompHibernatable>();
                if (compHibernatable != null)
                {
                    compHibernatable.State = HibernatableStateDefOf.Hibernating;
                }
                GenSpawn.Spawn(thing2, loc, BaseGen.globalSettings.map, rotation);
            }
        }
Ejemplo n.º 13
0
        public static bool PlaceThing(this Thing wanted, Pawn pawn, IEnumerable <IntVec3> roomCells, Rot4 rot, Room room,
                                      out Job furnitureJobResult)
        {
            rot = wanted.def.rotatable ? rot: Rot4.North;
            foreach (var vec3 in roomCells.InRandomOrder())
            {
                if (!GenConstruct.CanPlaceBlueprintAt(wanted.GetInnerIfMinified().def, vec3, rot, room.Map)
                    .Accepted)
                {
#if DEBUG
                    Log.Message("Not Place-able");
#endif
                    continue;
                }

                var bp = wanted.BlueprintInstall(pawn, vec3, room, rot);

                if (bp == null)
                {
#if DEBUG
                    Log.Message("Couldn't place blueprint, oops");
#endif
                    continue;
                }

                var job = bp.InstallJob(pawn);

                if (job != null)
                {
                    {
                        furnitureJobResult = job;
                        return(true);
                    }
                }
#if DEBUG
                Log.Message("No job for bp");
#endif
            }

            furnitureJobResult = null;
            return(false);
        }
Ejemplo n.º 14
0
        // RimWorld.SiegeBlueprintPlacer
        public static IntVec3 FindHideyHoleSpot(ThingDef holeDef, Rot4 rot, IntVec3 center, Map map)
        {
            if (GenConstruct.CanPlaceBlueprintAt(holeDef, center, rot, map, false, null).Accepted)
            {
                return(center);
            }
            CellRect cellRect = CellRect.CenteredOn(center, 8);

            cellRect.ClipInsideMap(map);
            IntVec3 randomCell = cellRect.RandomCell;

            if (!CellFinder.TryFindRandomCellNear(center, map, 5, (IntVec3 c) => c.Standable(map) &&
                                                  (GenConstruct.CanPlaceBlueprintAt(holeDef, c, rot, map, false, null).Accepted) &&
                                                  (map?.reachability?.CanReach(c, randomCell, PathEndMode.Touch, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false)) ?? false), out randomCell))
            {
                Log.Error("Found no place to build hideyhole for burning vampire.");
                randomCell = IntVec3.Invalid;
            }
            return(randomCell);
        }
Ejemplo n.º 15
0
        //A lot like CheckAutoRebuildOnDestroyed
        public static void CheckAutoRebuildOnLaunch(Thing thing, Map map, BuildableDef buildingDef)
        {
            if (!Settings.Get().autoRebuildTransportPod)
            {
                return;
            }

            if (Find.PlaySettings.autoRebuild && thing.Faction == Faction.OfPlayer && buildingDef.blueprintDef != null && buildingDef.IsResearchFinished && map.areaManager.Home[thing.Position] && GenConstruct.CanPlaceBlueprintAt(buildingDef, thing.Position, thing.Rotation, map, false, null).Accepted)
            {
                GenConstruct.PlaceBlueprintForBuild(buildingDef, thing.Position, map, thing.Rotation, Faction.OfPlayer, thing.Stuff);
            }
        }
Ejemplo n.º 16
0
        public static bool PlaceThing(this Thing wanted, Pawn pawn, IEnumerable <IntVec3> roomCells, Rot4 rot, Room room,
                                      out Job furnitureJobResult)
        {
            var defToPlace = wanted.GetInnerIfMinified().def;

            rot = defToPlace.rotatable ? rot : Rot4.North;
            var roomBorder = room.BorderCells;
            var wallCells  = roomCells.Where(cell => IsNextToBorder(cell, roomBorder)).InRandomOrder();
            var innerCells = roomCells.Where(cell => !wallCells.Contains(cell)).InRandomOrder();
            var firstList  = true;

            foreach (var listOfCells in new List <IEnumerable <IntVec3> > {
                wallCells, innerCells
            })
            {
                foreach (var vec3 in listOfCells)
                {
                    var placeRot = rot;
                    if (defToPlace.rotatable && firstList)
                    {
                        for (var i = 0; i < 4; i++)
                        {
                            if (roomCells.Contains(vec3 + GenAdj.CardinalDirections[i]))
                            {
                                continue;
                            }

                            placeRot = new Rot4(i).Opposite;
#if DEBUG
                            Log.Message($"Found cell next to a wall, will place with rotation {placeRot}");
#endif
                            if (new Random().Next(2) == 0)
                            {
                                break;
                            }
                        }
                    }

                    if (defToPlace.size.Area > 1)
                    {
                        var cellsCovered = GenAdj.OccupiedRect(vec3, placeRot, defToPlace.Size);
                        if (cellsCovered.Any(cell => !roomCells.Contains(cell)))
                        {
#if DEBUG
                            Log.Message("Placed furniture would cover a non-room cell (probably the door-entrance)");
#endif
                            continue;
                        }
                    }

                    if (!GenConstruct.CanPlaceBlueprintAt(defToPlace, vec3, placeRot, room.Map).Accepted)
                    {
#if DEBUG
                        Log.Message("Not Place-able");
#endif
                        continue;
                    }

                    if (vec3.GetFirstBuilding(room.Map)?.def == defToPlace)
                    {
#if DEBUG
                        Log.Message("Placed furniture would have replaced an item");
#endif
                        continue;
                    }

                    var bp = wanted.BlueprintInstall(pawn, vec3, room, placeRot);

                    if (bp == null)
                    {
#if DEBUG
                        Log.Message("Couldn't place blueprint, oops");
#endif
                        continue;
                    }

                    var job = bp.InstallJob(pawn);

                    if (job == null)
                    {
                        continue;
                    }

                    furnitureJobResult = job;
                    return(true);

#if DEBUG
                    Log.Message("No job for bp");
#endif
                }

                firstList = false;
            }

            furnitureJobResult = null;
            return(false);
        }
Ejemplo n.º 17
0
 public static void CheckAutoRebuildTerrainOnDestroyed(TerrainDef terrainDef, IntVec3 pos, Map map)
 {
     if (Find.PlaySettings.autoRebuild && terrainDef.autoRebuildable && terrainDef.blueprintDef != null && terrainDef.IsResearchFinished && map.areaManager.Home[pos] && GenConstruct.CanPlaceBlueprintAt(terrainDef, pos, Rot4.South, map).Accepted)
     {
         GenConstruct.PlaceBlueprintForBuild(terrainDef, pos, map, Rot4.South, Faction.OfPlayer, null);
     }
 }
Ejemplo n.º 18
0
        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);
        }
    protected override IEnumerable <Toil> MakeNewToils()
    {
        /*
         *
         *  Toil Configurations
         *
         */
        var prepareToSpin = new Toil
        {
            initAction = delegate
            {
                if (Prey == null && Corpse == null)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                    return;
                }

                if (Prey != null && Prey.Dead)
                {
                    pawn.CurJob.SetTarget(TargetIndex.A, Prey.Corpse);
                }

                if (!pawn.CanReserveAndReach(TargetA, PathEndMode.Touch, Danger.None))
                {
                    pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                }
            }
        };

        var gotoBody = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);

        gotoBody.AddPreInitAction(delegate
        {
            pawn.ClearAllReservations();
            pawn.Reserve(TargetA, job);
            //this.Map.physicalInteractionReservationManager.ReleaseAllForTarget(TargetA);
            //this.Map.physicalInteractionReservationManager.Reserve(this.GetActor(), TargetA);
            currentActivity = "ROM_SpinPreyJob1".Translate(TargetA.Thing?.LabelShort ?? "");
        });

        var spinDelay = new Toil
        {
            defaultCompleteMode = ToilCompleteMode.Delay,
            defaultDuration     = 500,
            initAction          = delegate { currentActivity = "ROM_SpinPreyJob2".Translate(); }
        };

        spinDelay.WithProgressBarToilDelay(TargetIndex.B);

        var spinBody = new Toil
        {
            initAction = delegate
            {
                //Log.Message("5");
                if (GetActor() is not PawnWebSpinner spinner)
                {
                    return;
                }

                Thing   toLoad;
                IntVec3 newPosition;
                if (Prey.Dead)
                {
                    toLoad      = Prey.Corpse;
                    newPosition = Prey.Corpse.Position;
                }
                else
                {
                    toLoad      = Prey;
                    newPosition = Prey.Position;

                    //Tend prey's wounds by luck
                    if (!Prey.health.HasHediffsNeedingTend())
                    {
                        return;
                    }

                    var unused        = ThingDefOf.MedicineHerbal;
                    var quality       = 0.5f; //Not a doctor or attentive to human needs
                    var hediffsToTend = new List <Hediff>();
                    var hediffs       = Prey.health.hediffSet.hediffs;
                    foreach (var hediff in hediffs)
                    {
                        if (hediff.TendableNow())
                        {
                            hediffsToTend.Add(hediff);
                        }
                    }

                    for (var i = 0; i < hediffsToTend.Count; i++)
                    {
                        hediffsToTend[i].Tended(quality, i);
                    }
                }

                if (!toLoad.Spawned)
                {
                    EndJobWith(JobCondition.Incompletable);
                    return;
                }

                toLoad.DeSpawn();
                toLoad.holdingOwner = null;
                if (!GenConstruct.CanPlaceBlueprintAt(CocoonDef, newPosition, Rot4.North, pawn.Map).Accepted)
                {
                    var cells = GenAdj.CellsAdjacent8Way(new TargetInfo(newPosition, pawn.Map));
                    foreach (var cell in cells)
                    {
                        if (!GenConstruct.CanPlaceBlueprintAt(CocoonDef, cell, Rot4.North, Map).Accepted)
                        {
                            continue;
                        }

                        newPosition = cell;
                        break;
                    }
                }

                var newCocoon = (Building_Cocoon)GenSpawn.Spawn(CocoonDef, newPosition, spinner.Map);
                newCocoon.Spinner = spinner;
                if (spinner.Faction == Faction.OfPlayerSilentFail)
                {
                    newCocoon.SetFactionDirect(Faction.OfPlayerSilentFail);
                }

                //Log.Message("New Spinner: " + newCocoon.Spinner.Label);
                newCocoon.TryGetInnerInteractableThingOwner().TryAdd(toLoad);
                pawn?.CurJob?.SetTarget(TargetIndex.B, newCocoon);
            },
        public void TryStartUseJob(Pawn user)
        {
            Find.DesignatorManager.Deselect();
            if (!user.CanReserveAndReach(this.parent, PathEndMode.Touch, Danger.Deadly, 1))
            {
                return;
            }
            if (!user.CanReach(this.targetPos, PathEndMode.Touch, Danger.Deadly))
            {
                return;
            }
            if (this.parent.HitPoints <= 0)
            {
                Messages.Message("Cannot place a fully damaged tent.", MessageTypeDefOf.RejectInput);
                return;
            }

            CellRect       cellRect   = new CellRect(this.targetPos.x - 2, this.targetPos.z - 2, 5, 4);
            List <IntVec3> everything = new List <IntVec3>();

            everything.AddRange(this.wallCells);
            everything.AddRange(this.doorCells);


            foreach (IntVec3 current in everything)
            {
                if (!GenConstruct.CanPlaceBlueprintAt(ThingDefOf.Wall, current, Rot4.North, user.Map, false, null).Accepted)
                {
                    Messages.Message("Tent placement blocked. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                    return;
                }

                if (current.GetFirstItem(user.Map) != null || current.GetFirstPawn(user.Map) != null || current.GetFirstHaulable(user.Map) != null)
                {
                    Messages.Message("Tent placement blocked by a item, pawn or a building. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                    return;
                }

                Building building = current.GetFirstBuilding(user.Map);
                if (building != null)
                {
                    if (building.def.IsEdifice())
                    {
                        Messages.Message("Tent placement blocked by a item, pawn or a building. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                        return;
                    }
                }
                Plant plant = current.GetPlant(user.Map);
                if (plant != null)
                {
                    if (plant.def.plant.IsTree)
                    {
                        Messages.Message("Tent placement blocked by a tree. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                        return;
                    }
                }
            }
            Job job = new Job(DefDatabase <JobDef> .GetNamed("DeployTent", true), this.parent, this.targetInfo1);

            user.jobs.TryTakeOrderedJob(job);
        }
        private static bool TargetValidator(IntVec3 c, Map map, CompTargetable_Tent t)
        {
            if (!c.InBounds(map) || !c.Standable(map))
            {
                return(false);
            }
            if (!c.Walkable(map))
            {
                return(false);
            }

            t.HandleRotation();
            t.GetPlacements(c);
            CellRect       cellRect   = new CellRect(c.x - 2, c.z - 2, 5, 4);
            List <IntVec3> clist      = new List <IntVec3>();
            Color          color      = new Color(1f, 1f, 1f, 0.4f);
            List <IntVec3> everything = new List <IntVec3>();

            everything.AddRange(t.wallCells);
            everything.AddRange(t.doorCells);


            foreach (IntVec3 current in everything)
            {
                if (!current.InBounds(map))
                {
                    return(false);
                }
                if (!GenConstruct.CanPlaceBlueprintAt(ThingDefOf.Wall, current, Rot4.North, map, false, null).Accepted)
                {
                    color = new Color(1f, 0f, 0f, 0.4f);
                }

                if (current.GetFirstItem(map) != null || current.GetFirstPawn(map) != null || current.GetFirstHaulable(map) != null)
                {
                    color = new Color(1f, 0f, 0f, 0.4f);
                }
                Building building = current.GetFirstBuilding(map);
                if (building != null)
                {
                    if (building.def.IsEdifice())
                    {
                        color = new Color(1f, 0f, 0f, 0.4f);
                    }
                }
                Plant plant = current.GetPlant(map);
                if (plant != null)
                {
                    if (plant.def.plant.IsTree)
                    {
                        color = new Color(1f, 0f, 0f, 0.4f);
                    }
                }
            }
            foreach (IntVec3 doorCell in t.doorCells)
            {
                GhostDrawer.DrawGhostThing(doorCell, t.placingRot, ThingDef.Named("TentDoor"), null, color, AltitudeLayer.Blueprint);
            }


            GenDraw.DrawFieldEdges(t.wallCells, color);

            return(true);
        }
Ejemplo n.º 22
0
    protected override IEnumerable <Toil> MakeNewToils()
    {
        yield return(new Toil
        {
            defaultCompleteMode = ToilCompleteMode.Delay,
            defaultDuration = 500,
            initAction = delegate
            {
                var i = 999;
                var breakNow = false;
                while (i > 0)
                {
                    pawn.CurJob.SetTarget(TargetIndex.A,
                                          RCellFinder.RandomWanderDestFor(pawn, pawn.Position, 5f, null, Danger.Some));
                    var cellRect = GenAdj.OccupiedRect(TargetLocA, Rot4.North, WebDef.Size);
                    foreach (var cellRectCell in cellRect.Cells)
                    {
                        if (cellRectCell.Walkable(Map))
                        {
                            breakNow = true;
                        }
                    }

                    if (GenConstruct.CanPlaceBlueprintAt(WebDef, TargetLocA, Rot4.North, pawn.Map).Accepted)
                    {
                        if (pawn?.Faction == null || pawn?.Faction != Faction.OfPlayerSilentFail)
                        {
                            break;
                        }

                        if (pawn?.Faction == Faction.OfPlayerSilentFail && !TargetA.Cell.IsForbidden(pawn))
                        {
                            breakNow = true;
                        }
                    }
                    else
                    {
                        breakNow = false;
                    }

                    if (breakNow)
                    {
                        break;
                    }

                    i--;
                }
            }
        });

        yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.OnCell));

        yield return(new Toil
        {
            initAction = delegate
            {
                if (GetActor() is not PawnWebSpinner spinner || spinner.Position.CloseToEdge(spinner.Map, 2))
                {
                    return;
                }

                var web = (Building_Web)GenSpawn.Spawn(WebDef, spinner.Position, spinner.Map);
                spinner.Web = web;
                spinner.WebsMade++;
                web.Spinner = spinner;
            },
Ejemplo n.º 23
0
        public override void Destroy(DestroyMode mode = DestroyMode.Vanish)
        {
            bool spawned = base.Spawned;
            Map  map     = base.Map;

            SmoothableWallUtility.Notify_BuildingDestroying(this, mode);
            base.Destroy(mode);
            InstallBlueprintUtility.CancelBlueprintsFor(this);
            if (mode == DestroyMode.Deconstruct && spawned)
            {
                SoundDefOf.Building_Deconstructed.PlayOneShot(new TargetInfo(base.Position, map, false));
            }
            if (Find.PlaySettings.autoRebuild && mode == DestroyMode.KillFinalize && base.Faction == Faction.OfPlayer && spawned && this.def.blueprintDef != null && this.def.IsResearchFinished && map.areaManager.Home[base.Position] && GenConstruct.CanPlaceBlueprintAt(this.def, base.Position, base.Rotation, map, false, null).Accepted)
            {
                GenConstruct.PlaceBlueprintForBuild(this.def, base.Position, map, base.Rotation, Faction.OfPlayer, base.Stuff);
            }
        }
Ejemplo n.º 24
0
        //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
                };
            }
        }
Ejemplo n.º 25
0
 public static void CheckAutoRebuildOnDestroyed(Thing thing, DestroyMode mode, Map map, BuildableDef buildingDef)
 {
     if (Find.PlaySettings.autoRebuild && mode == DestroyMode.KillFinalize && thing.Faction == Faction.OfPlayer && buildingDef.blueprintDef != null && buildingDef.IsResearchFinished && map.areaManager.Home[thing.Position] && GenConstruct.CanPlaceBlueprintAt(buildingDef, thing.Position, thing.Rotation, map).Accepted)
     {
         GenConstruct.PlaceBlueprintForBuild(buildingDef, thing.Position, map, thing.Rotation, Faction.OfPlayer, thing.Stuff);
     }
 }
        public override void DoEffect(Pawn usedBy)
        {
            if (this.target != null && !this.GetTargetingParameters().CanTarget(this.target))
            {
                return;
            }
            base.DoEffect(usedBy);
            if (this.parent.Stuff == null)
            {
                this.parent.SetStuffDirect(ThingDefOf.Cloth);
            }

            CellRect cellRect     = new CellRect(this.targetPos.x - 2, this.targetPos.z - 2, 5, 4);
            double   hitpoints    = (double)this.parent.HitPoints / 10;
            int      wallsToPlace = (int)Math.Floor(hitpoints);
            //int wallsToPlace = 49;
            List <IntVec3> everything = new List <IntVec3>();

            everything.AddRange(this.wallCells);
            everything.AddRange(this.doorCells);


            foreach (IntVec3 current in everything)
            {
                if (!GenConstruct.CanPlaceBlueprintAt(ThingDef.Named("TentWall"), current, Rot4.North, usedBy.Map, false, null).Accepted)
                {
                    Messages.Message("Tent placement blocked. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                    return;
                }

                if (current.GetFirstItem(usedBy.Map) != null || current.GetFirstPawn(usedBy.Map) != null || current.GetFirstHaulable(usedBy.Map) != null)
                {
                    Messages.Message("Tent placement blocked. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                    return;
                }
                Building building = current.GetFirstBuilding(usedBy.Map);
                if (building != null)
                {
                    if (building.def.IsEdifice())
                    {
                        Messages.Message("Tent placement blocked by a item, pawn or a building. Please deploy on a suitable space.", MessageTypeDefOf.RejectInput);
                        return;
                    }
                }
            }
            foreach (IntVec3 current in this.wallCells)
            {
                if (usedBy.Map.roofGrid.RoofAt(current) == null)
                {
                    usedBy.Map.roofGrid.SetRoof(current, RoofDefOf.RoofConstructed);
                }
            }
            foreach (IntVec3 current in this.doorCells)
            {
                if (usedBy.Map.roofGrid.RoofAt(current) == null)
                {
                    usedBy.Map.roofGrid.SetRoof(current, RoofDefOf.RoofConstructed);
                }
            }
            foreach (IntVec3 current in this.roofCells)
            {
                if (usedBy.Map.roofGrid.RoofAt(current) == null)
                {
                    usedBy.Map.roofGrid.SetRoof(current, RoofDefOf.RoofConstructed);
                }
            }

            if (usedBy.Map.roofGrid.RoofAt(supportCell) == null)
            {
                usedBy.Map.roofGrid.SetRoof(supportCell, RoofDefOf.RoofConstructed);
            }


            if (wallsToPlace < wallCells.Count + doorCells.Count)
            {
                Messages.Message("Damaged tent deployed. Some walls will be missing.", MessageTypeDefOf.NegativeEvent);
            }
            int wallsPlaced = 0;

            this.GetPlacements(this.targetPos);

            foreach (IntVec3 current in this.wallCells)
            {
                if (wallsPlaced < wallsToPlace)
                {
                    TrySpawnWall(current, usedBy);
                    wallsPlaced++;
                }
            }

            foreach (IntVec3 DoorPos in this.doorCells)
            {
                if (wallsPlaced < wallsToPlace)
                {
                    Thing door = ThingMaker.MakeThing(ThingDef.Named("TentDoor"), this.parent.Stuff);
                    door.SetFaction(usedBy.Faction, null);
                    door.Rotation = Building_Door.DoorRotationAt(DoorPos, usedBy.Map);
                    GenSpawn.Spawn(door, DoorPos, usedBy.Map);
                    wallsPlaced++;
                }
            }


            this.parent.Destroy(DestroyMode.Vanish);
            SoundDefOf.DesignatePlaceBuilding.PlayOneShotOnCamera();
            Thing tent = ThingMaker.MakeThing(ThingDef.Named("TentDeployed"), this.parent.Stuff);

            tent.SetFaction(usedBy.Faction, null);
            tent.TryGetComp <CompPackTent>().tentName   = this.parent.def.defName;
            tent.TryGetComp <CompPackTent>().placingRot = this.placingRot;
            GenSpawn.Spawn(tent, this.supportCell, usedBy.Map);

            return;
        }
Ejemplo n.º 27
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            /*
             *
             *  Toil Configurations
             *
             */
            Toil prepareToSpin = new Toil();

            prepareToSpin.initAction = delegate
            {
                if (Prey == null && Corpse == null)
                {
                    this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                    return;
                }
                if (Prey.Dead)
                {
                    this.pawn.CurJob.SetTarget(TargetIndex.A, Prey.Corpse);
                }
            };

            Toil gotoBody = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);

            gotoBody.AddPreInitAction(new Action(delegate
            {
                this.pawn.ClearAllReservations();
                this.pawn.Reserve(TargetA, this.job);
                //this.Map.physicalInteractionReservationManager.ReleaseAllForTarget(TargetA);
                //this.Map.physicalInteractionReservationManager.Reserve(this.GetActor(), TargetA);
                currentActivity = "Spinning Cocoon";
            }));

            Toil spinDelay = new Toil
            {
                defaultCompleteMode = ToilCompleteMode.Delay,
                defaultDuration     = 500,
                initAction          = delegate
                {
                    currentActivity = "Spinning Cocoon";
                }
            };

            spinDelay.WithProgressBarToilDelay(TargetIndex.B);
            Toil spinBody = new Toil
            {
                initAction = delegate
                {
                    //Log.Message("5");
                    var spinner = this.GetActor() as Spider;
                    if (spinner != null)
                    {
                        Building_Cocoon newCocoon;
                        Thing           toLoad;
                        IntVec3         newPosition;
                        if (Prey.Dead)
                        {
                            toLoad      = Prey.Corpse;
                            newPosition = Prey.Corpse.Position;
                        }
                        else
                        {
                            toLoad      = Prey;
                            newPosition = Prey.Position;
                        }
                        if (!toLoad.Spawned)
                        {
                            this.EndJobWith(JobCondition.Incompletable); return;
                        }

                        toLoad.DeSpawn();
                        toLoad.holdingOwner = null;
                        if (!GenConstruct.CanPlaceBlueprintAt(CocoonDef, newPosition, Rot4.North, this.pawn.Map).Accepted)
                        {
                            var cells = GenAdj.CellsAdjacent8Way(new TargetInfo(newPosition, this.pawn.Map));
                            foreach (IntVec3 cell in cells)
                            {
                                if (GenConstruct.CanPlaceBlueprintAt(CocoonDef, cell, Rot4.North, this.Map).Accepted)
                                {
                                    newPosition = cell;
                                    break;
                                }
                            }
                        }

                        newCocoon = (Building_Cocoon)GenSpawn.Spawn(CocoonDef, newPosition, spinner.Map);
                        //Log.Message("New Spinner: " + newCocoon.Spinner.Label);
                        newCocoon.TryGetInnerInteractableThingOwner().TryAdd(toLoad);
                        this.pawn?.CurJob?.SetTarget(TargetIndex.B, newCocoon);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            Toil pickupCocoon = Toils_Haul.StartCarryThing(TargetIndex.B);

            pickupCocoon.AddPreInitAction(new Action(delegate
            {
                //this.TargetB.Thing.DeSpawn();
                this.pawn.CurJob.SetTarget(TargetIndex.C, TargetB.Thing);
                this.pawn.Reserve(TargetC, this.job);
                //this.pawn.Map.physicalInteractionReservationManager.Reserve(this.pawn, TargetC);
            }));
            Toil relocateCocoon = Toils_Haul.CarryHauledThingToCell(TargetIndex.C);
            Toil dropCocoon     = Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, relocateCocoon, false).FailOn(() => !GenConstruct.CanPlaceBlueprintAt(CocoonDef, TargetC.Cell, Rot4.North, this.Map).Accepted);

            this.AddFinishAction(new Action(delegate
            {
                this.pawn.Map.physicalInteractionReservationManager.ReleaseAllClaimedBy(this.pawn);
            }));


            /*
             *
             *  Toil Execution
             *
             */
            yield return(new Toil
            {
                initAction = delegate
                {
                    this.Map.attackTargetsCache.UpdateTarget(this.pawn);
                },
                atomicWithPrevious = true,
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            Action onHitAction = delegate
            {
                Pawn prey           = this.Prey;
                bool surpriseAttack = this.firstHit && !prey.IsColonist;
                if (this.pawn.meleeVerbs.TryMeleeAttack(prey, this.job.verbToUse, surpriseAttack))
                {
                    if (!this.notifiedPlayer && PawnUtility.ShouldSendNotificationAbout(prey))
                    {
                        this.notifiedPlayer = true;
                        Messages.Message("MessageAttackedByPredator".Translate(new object[]
                        {
                            prey.LabelShort,
                            this.pawn.LabelIndefinite()
                        }).CapitalizeFirst(), prey, MessageTypeDefOf.ThreatBig);// MessageSound.SeriousAlert);
                    }
                    this.Map.attackTargetsCache.UpdateTarget(this.pawn);
                }
                this.firstHit = false;
            };

            //yield return Toils_Combat.FollowAndMeleeAttack(TargetIndex.A, onHitAction).JumpIf(() => Prey.Downed || Prey.Dead, prepareToSpin).FailOn(() => Find.TickManager.TicksGame > this.startTick + 5000 && (float)(this.job.GetTarget(TargetIndex.A).Cell - this.pawn.Position).LengthHorizontalSquared > 4f);
            yield return(prepareToSpin.FailOn(() => Prey == null));

            yield return(gotoBody.FailOn(() => Prey == null));

            yield return(spinDelay.FailOn(() => Prey == null));

            yield return(spinBody.FailOn(() => Prey == null));
            //yield return pickupCocoon;
            //yield return relocateCocoon;
            //yield return dropCocoon;

            //float durationMultiplier = 1f / this.pawn.GetStatValue(StatDefOf.EatingSpeed, true);
            //yield return Toils_Ingest.ChewIngestible(this.pawn, durationMultiplier, TargetIndex.A, TargetIndex.None).FailOnDespawnedOrNull(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            //yield return Toils_Ingest.FinalizeIngest(this.pawn, TargetIndex.A);
            //yield return Toils_Jump.JumpIf(gotoCorpse, () => this.pawn.needs.food.CurLevelPercentage < 0.9f);
        }
Ejemplo n.º 28
0
        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();
            }
        }