Ejemplo n.º 1
0
 protected bool IsValidCellToWander(IntVec3 cell)
 {
     if (cell.Standable() == false)
     {
         return false;
     }
     if (this.pawn.CanReach(new TargetInfo(cell), PathEndMode.OnCell, Danger.None) == false)
     {
         return false;
     }
     foreach (Thing thing in cell.GetThingList())
     {
         if (thing is Fire)
         {
             return false;
         }
     }
     if (cell.GetRoom() != this.TargetLocA.GetRoom())
     {
         return false;
     }
     if (Find.PawnDestinationManager.DestinationIsReserved(cell))
     {
         return false;
     }
     return true;
 }
 public override AcceptanceReport AllowsPlacing(BuildableDef checkingDef, IntVec3 loc, Rot4 rot)
 {
     var room = loc.GetRoom();
     if( room.ContainedBeds.Any( bed => !bed.ForPrisoners ) )
     {
         return (AcceptanceReport) Data.Strings.NoColonistBeds.Translate();
     }
     return (AcceptanceReport) true;
 }
        public override void DrawGhost( ThingDef def, IntVec3 center, Rot4 rot )
        {
            base.DrawGhost( def, center, rot );

            var room = center.GetRoom();
            if ( room == null || room.UsesOutdoorTemperature )
            {
                return;
            }
            GenDraw.DrawFieldEdges( room.Cells.ToList(), GenTemperature.ColorRoomHot );
        }
Ejemplo n.º 4
0
 protected static List<IntVec3> GetPartyAreaCells(IntVec3 pyrePosition)
 {
     IEnumerable<IntVec3> cellsInRange = GenRadial.RadialCellsAround(pyrePosition, partyAreaRadius, true);
     List<IntVec3> partyAreaCells = new List<IntVec3>();
     foreach (IntVec3 cell in cellsInRange)
     {
         if (cell.GetRoom() == pyrePosition.GetRoom())
         {
             partyAreaCells.Add(cell);
         }
     }
     return partyAreaCells;
 }
        // overhauled version (vanilla is bugged)
        public static PlaceSpotQuality PlaceSpotQualityAt(IntVec3 c, Thing thing, IntVec3 center)
        {
            if (!c.InBounds() || !c.Walkable())
            {
                return PlaceSpotQuality.Unusable;
            }

            List<Thing> list = Find.ThingGrid.ThingsListAt(c);

            // if other things on cell
            int i = 0;
            while (i < list.Count)
            {
                Thing thing2 = list[i];
                if (thing.def.saveCompressible && thing2.def.saveCompressible)
                {
                    return PlaceSpotQuality.Unusable;
                }
                // same thing type
                if (thing2.def.category == ThingCategory.Item)
                {
                    // can stack with
                    if (thing2.def == thing.def && thing2.stackCount < thing.def.stackLimit)
                    {
                        // can absorb
                        // Required, because thing reference is changed to the absorber, if absorbed
                        Thing t = thing2;
                        if (thing.TryAbsorbStack(thing2, true))
                        {
                            // Clean up to prevent haulables lists overflow
                            RemoveHaulableFromLists(t);
                            return PlaceSpotQuality.Perfect;
                        }
                        // cannot absorb all/anything
                        else
                            return PlaceSpotQuality.Unusable;
                    }
                    return PlaceSpotQuality.Unusable;
                }
                else
                {
                    i++;
                }
            }
            // if in same room
            if (c.GetRoom() == center.GetRoom())
            {
                PlaceSpotQuality placeSpotQuality = PlaceSpotQuality.Perfect;
                for (int j = 0; j < list.Count; j++)
                {
                    Thing thing3 = list[j];
                    if (thing3.def.thingClass == typeof(Building_Door))
                    {
                        return PlaceSpotQuality.Bad;
                    }
                    Pawn pawn = thing3 as Pawn;
                    if (pawn != null)
                    {
                        if (pawn.Downed)
                        {
                            return PlaceSpotQuality.Bad;
                        }
                        if (placeSpotQuality > PlaceSpotQuality.Okay)
                        {
                            placeSpotQuality = PlaceSpotQuality.Okay;
                        }
                    }
                    if (thing3.def.category == ThingCategory.Plant && thing3.def.selectable && placeSpotQuality > PlaceSpotQuality.Okay)
                    {
                        placeSpotQuality = PlaceSpotQuality.Okay;
                    }
                }
                return placeSpotQuality;
            }
            if (!center.CanReach(c, PathEndMode.OnCell, TraverseMode.PassDoors, Danger.Deadly))
            {
                return PlaceSpotQuality.Awful;
            }
            return PlaceSpotQuality.Okay;
        }
 /// <summary>
 /// Get the effect zone cells.
 /// </summary>
 public static List<IntVec3> GetEffectZoneCells(IntVec3 alertSpeakerPosition)
 {
     IEnumerable<IntVec3> cellsInRange = GenRadial.RadialCellsAround(alertSpeakerPosition, Building_AlertSpeaker.alertSpeakerMaxRange, true);
     List<IntVec3> effectZoneCells = new List<IntVec3>();
     foreach (IntVec3 cell in cellsInRange)
     {
         if (cell.GetRoom() == alertSpeakerPosition.GetRoom())
         {
             effectZoneCells.Add(cell);
         }
     }
     return effectZoneCells;
 }
        private static string TemperatureString()
        {
            IntVec3 intVec = UI.MouseCell();
            IntVec3 c      = intVec;
            Room    room   = intVec.GetRoom(Find.VisibleMap, RegionType.Set_All);

            if (room == null)
            {
                for (int i = 0; i < 9; i++)
                {
                    IntVec3 intVec2 = intVec + GenAdj.AdjacentCellsAndInside[i];
                    Room    room2;
                    if (intVec2.InBounds(Find.VisibleMap))
                    {
                        room2 = intVec2.GetRoom(Find.VisibleMap, RegionType.Set_All);
                        if (room2 != null)
                        {
                            if (!room2.PsychologicallyOutdoors && !room2.UsesOutdoorTemperature)
                            {
                                goto IL_00a8;
                            }
                            if (!room2.PsychologicallyOutdoors && (room == null || room.PsychologicallyOutdoors))
                            {
                                goto IL_00a8;
                            }
                            if (room2.PsychologicallyOutdoors && room == null)
                            {
                                goto IL_00a8;
                            }
                        }
                    }
                    continue;
IL_00a8:
                    c    = intVec2;
                    room = room2;
                }
            }
            if (room == null && intVec.InBounds(Find.VisibleMap))
            {
                Building edifice = intVec.GetEdifice(Find.VisibleMap);
                if (edifice != null)
                {
                    CellRect.CellRectIterator iterator = edifice.OccupiedRect().ExpandedBy(1).ClipInsideMap(Find.VisibleMap)
                                                         .GetIterator();
                    while (!iterator.Done())
                    {
                        IntVec3 current = iterator.Current;
                        room = current.GetRoom(Find.VisibleMap, RegionType.Set_All);
                        if (room != null && !room.PsychologicallyOutdoors)
                        {
                            c = current;
                            break;
                        }
                        iterator.MoveNext();
                    }
                }
            }
            string str         = (!c.InBounds(Find.VisibleMap) || c.Fogged(Find.VisibleMap) || room == null || room.PsychologicallyOutdoors) ? "Outdoors".Translate() : ((room.OpenRoofCount != 0) ? ("IndoorsUnroofed".Translate() + " (" + room.OpenRoofCount.ToStringCached() + ")") : "Indoors".Translate());
            float  celsiusTemp = (room != null && !c.Fogged(Find.VisibleMap)) ? room.Temperature : Find.VisibleMap.mapTemperature.OutdoorTemp;

            return(str + " " + celsiusTemp.ToStringTemperature("F0"));
        }
        // Token: 0x06000002 RID: 2 RVA: 0x0000224C File Offset: 0x0000044C
        private static void Postfix(IntVec3 c, SteadyEnvironmentEffects __instance)
        {
            Map map = HarmonyPatches.MapFieldInfo.GetValue(__instance) as Map;

            if (map == null)
            {
                return;
            }
            Room room = c.GetRoom(map, RegionType.Set_Passable);

            if (Settings.ColdFog || Settings.IceLayer)
            {
                Thing thing = (from t in c.GetThingList(map)
                               where t.def.defName == "IceOverlay"
                               select t).FirstOrDefault <Thing>();
                if (room == null && thing != null && Settings.IceLayer)
                {
                    thing.Destroy(DestroyMode.Vanish);
                    if (Rand.Range(1, 100) <= 20)
                    {
                        FilthMaker.TryMakeFilth(c, map, ThingDef.Named("FilthWater"), 1);
                    }
                }
                if (room != null && !room.UsesOutdoorTemperature && !room.Fogged && !room.IsDoorway)
                {
                    float num = 0.8f;
                    if (room.Temperature < (float)Settings.FogTemp)
                    {
                        if (thing == null && Settings.IceLayer)
                        {
                            GenSpawn.Spawn(ThingMaker.MakeThing(ThingDef.Named("IceOverlay"), null), c, map);
                        }
                        if (Settings.ColdFog)
                        {
                            Vector3 vector = c.ToVector3Shifted();
                            bool    flag   = true;
                            if (!GenView.ShouldSpawnMotesAt(vector, map) || map.moteCounter.SaturatedLowPriority)
                            {
                                flag = false;
                            }
                            vector += num * new Vector3(Rand.Value - 0.5f, 0f, Rand.Value - 0.5f);
                            if (!GenGrid.InBounds(vector, map))
                            {
                                flag = false;
                            }
                            if (flag)
                            {
                                MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(ThingDef.Named("Mote_FrostGlow"), null);
                                moteThrown.Scale         = Rand.Range(4f, 6f) * num;
                                moteThrown.rotationRate  = Rand.Range(-3f, 3f);
                                moteThrown.exactPosition = vector;
                                moteThrown.SetVelocity((float)(Rand.Bool ? -90 : 90), (float)((double)Settings.FogVelocity * 0.01));
                                GenSpawn.Spawn(moteThrown, IntVec3Utility.ToIntVec3(vector), map);
                            }
                        }
                    }
                    else if (thing != null)
                    {
                        thing.Destroy(DestroyMode.Vanish);
                        if (Rand.Range(1, 100) <= 20)
                        {
                            FilthMaker.TryMakeFilth(c, map, ThingDef.Named("FilthWater"), 1);
                        }
                    }
                }
            }
            if (!Settings.IceLayer)
            {
                Thing thing2 = (from t in c.GetThingList(map)
                                where t.def.defName == "IceOverlay"
                                select t).FirstOrDefault <Thing>();
                if (thing2 != null)
                {
                    thing2.Destroy(DestroyMode.Vanish);
                }
            }
            if (map.roofGrid != null && !map.roofGrid.Roofed(c) && (float)map.weatherManager.curWeatherAge >= 7500f && (map.weatherManager.curWeather.rainRate <= 0f || map.weatherManager.curWeather.snowRate > 0f))
            {
                Thing thing3 = (from t in c.GetThingList(map)
                                where t.def.defName == "FilthWater" || t.def.defName == "FilthWaterSpatter"
                                select t).FirstOrDefault <Thing>();
                if (thing3 != null && Rand.Value <= 0.2f)
                {
                    ((Filth)thing3).ThinFilth();
                }
            }
        }
Ejemplo n.º 9
0
        // Token: 0x06000E25 RID: 3621 RVA: 0x00069E88 File Offset: 0x00068288
        private bool CanSpawnAt(IntVec3 c, Map map)
        {
            if (!c.Standable(map) || c.Fogged(map) || map.fertilityGrid.FertilityAt(c) < OGOrkThingDefOf.OG_Plant_Orkoid_Cocoon.plant.fertilityMin || !c.GetRoom(map, RegionType.Set_Passable).PsychologicallyOutdoors || c.GetEdifice(map) != null || !PlantUtility.GrowthSeasonNow(c, map, false))
            {
                return(false);
            }
            Plant plant = c.GetPlant(map);

            if (plant != null && plant.def.plant.growDays > 10f)
            {
                return(false);
            }
            List <Thing> thingList = c.GetThingList(map);

            for (int i = 0; i < thingList.Count; i++)
            {
                if (thingList[i].def == OGOrkThingDefOf.OG_Plant_Orkoid_Cocoon)
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 10
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            LordToil_HangOut toil   = pawn.GetLord().CurLordToil as LordToil_HangOut;
            Pawn             friend = (pawn == toil.friends[0] ? toil.friends[1] : toil.friends[0]);

            if (pawn.needs.food.CurLevel < 0.33f)
            {
                return(null);
            }
            if (friend.needs.food.CurLevel < 0.33f)
            {
                return(null);
            }
            if (LovePartnerRelationUtility.LovePartnerRelationExists(pawn, friend) && pawn.jobs.curDriver != null && pawn.jobs.curDriver.layingDown == LayingDownState.NotLaying && (pawn.IsHashIntervalTick(GenDate.TicksPerHour) || friend.IsHashIntervalTick(GenDate.TicksPerHour)))
            {
                return(new Job(JobDefOf.LayDown, pawn.ownership.OwnedBed));
            }
            if (toil.hangOut != null && toil.hangOut.GetTarget(TargetIndex.A) != null && !pawn.CanReserve(toil.hangOut.GetTarget(TargetIndex.A), toil.hangOut.def.joyMaxParticipants, 0, null))
            {
                Log.Message("can't reserve the target of the hangout");
                /* Try our best to figure out which JoyGiver was used for the unreservable job. */
                int prefix = "JoyGiver".Count();
                var def    = (
                    from j in DefDatabase <JoyGiverDef> .AllDefs
                    where j.jobDef == toil.hangOut.def ||
                    (j.jobDef == null && DefDatabase <JobDef> .GetNamedSilentFail(nameof(j.giverClass).Substring(prefix)) == toil.hangOut.def)
                    select j
                    ).FirstOrDefault();
                if (def != null)
                {
                    Log.Message("giving job of def " + def.defName);
                    do
                    {
                        toil.hangOut = base.TryGiveJobFromJoyGiverDefDirect(def, pawn);
                    } while (toil.hangOut.GetTarget(TargetIndex.A).Thing.GetRoom() != friend.GetRoom());
                }
                else
                {
                    toil.hangOut = null;
                }
            }
            if (toil.hangOut == null || toil.ticksToNextJoy < Find.TickManager.TicksGame)
            {
                toil.hangOut        = base.TryGiveJob(pawn);
                toil.ticksToNextJoy = Find.TickManager.TicksGame + Rand.RangeInclusive(GenDate.TicksPerHour, GenDate.TicksPerHour * 3);
            }
            if (pawn.needs.joy.CurLevel < 0.8f)
            {
                return(toil.hangOut);
            }
            Log.Message("no joy hangout available");
            IntVec3 root = WanderUtility.BestCloseWanderRoot(toil.hangOut.targetA.Cell, pawn);
            Func <Pawn, IntVec3, bool> validator = delegate(Pawn wanderer, IntVec3 loc)
            {
                IntVec3 wanderRoot = root;
                Room    room       = wanderRoot.GetRoom(pawn.Map);
                return(room == null || WanderUtility.InSameRoom(wanderRoot, loc, pawn.Map));
            };

            pawn.mindState.nextMoveOrderIsWait = !pawn.mindState.nextMoveOrderIsWait;
            IntVec3 wanderDest = RCellFinder.RandomWanderDestFor(pawn, root, 5f, validator, PawnUtility.ResolveMaxDanger(pawn, Danger.Some));

            if (!wanderDest.IsValid || pawn.mindState.nextMoveOrderIsWait)
            {
                if ((pawn.Position - friend.Position).LengthHorizontalSquared >= 42f && friend.jobs.curJob.def != JobDefOf.Goto)
                {
                    Log.Message("friend not nearby, going to friend");
                    IntVec3 friendDest = RCellFinder.RandomWanderDestFor(pawn, friend.Position, 5f, validator, PawnUtility.ResolveMaxDanger(pawn, Danger.Some));
                    pawn.Map.pawnDestinationManager.ReserveDestinationFor(pawn, friendDest);
                    return(new Job(JobDefOf.Goto, friendDest));
                }
                Log.Message("waiting");
                return(null);
            }
            Log.Message("wandering");
            pawn.Map.pawnDestinationManager.ReserveDestinationFor(pawn, wanderDest);
            return(new Job(JobDefOf.GotoWander, wanderDest));
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            IntVec3 intVec = (IntVec3)pawn.mindState.duty.focus;

            if (intVec.IsValid && (float)intVec.DistanceToSquared(pawn.Position) < 100f && intVec.GetRoom(pawn.Map, RegionType.Set_Passable) == pawn.GetRoom(RegionType.Set_Passable) && intVec.WithinRegions(pawn.Position, pawn.Map, 9, TraverseMode.NoPassClosedDoors, RegionType.Set_Passable))
            {
                pawn.GetLord().Notify_ReachedDutyLocation(pawn);
                return(null);
            }
            if (!intVec.IsValid)
            {
                IAttackTarget attackTarget;
                if (!(from x in pawn.Map.attackTargetsCache.GetPotentialTargetsFor(pawn)
                      where !x.ThreatDisabled(pawn) && x.Thing.Faction == Faction.OfPlayer && pawn.CanReach(x.Thing, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings)
                      select x).TryRandomElement(out attackTarget))
                {
                    return(null);
                }
                intVec = attackTarget.Thing.Position;
            }
            if (!pawn.CanReach(intVec, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.PassAllDestroyableThings))
            {
                return(null);
            }
            using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, intVec, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), PathEndMode.OnCell))
            {
                IntVec3 cellBeforeBlocker;
                Thing   thing = pawnPath.FirstBlockingBuilding(out cellBeforeBlocker, pawn);
                if (thing != null)
                {
                    Job job = DigUtility.PassBlockerJob(pawn, thing, cellBeforeBlocker, this.canMineMineables, this.canMineNonMineables);
                    if (job != null)
                    {
                        return(job);
                    }
                }
            }
            return(new Job(JobDefOf.Goto, intVec, 500, true));
        }
Ejemplo n.º 12
0
        public static IEnumerable <Filth> SelectAllFilth(Pawn pawn, LocalTargetInfo target, int Limit = int.MaxValue)
        {
            Room room = null;

            if (target.Thing == null)
            {
                if (target.Cell == null)
                {
                    Log.Error("Invalid target: cell or thing it must be");
                }
                else
                {
                    room = GridsUtility.GetRoom(target.Cell, pawn.Map);
                }
            }
            else
            {
                room = target.Thing.GetRoom();
            }

            if (room == null)
            {
                return(new List <Filth>());
            }

            PathGrid pathGrid = pawn.Map.pathing.For(pawn).pathGrid;

            if (pathGrid == null)
            {
                return(new List <Filth>());
            }

            if (cleanFilth == null)
            {
                cleanFilth = DefDatabase <WorkGiverDef> .GetNamed("CleanFilth");
            }

            if (cleanFilth.Worker == null)
            {
                return(new List <Filth>());
            }

            IEnumerable <Filth> enumerable = null;

            if (room.IsHuge || room.CellCount > largeRoomSize)
            {
                enumerable = new List <Filth>();
                for (int i = 0; i < 200; i++)
                {
                    IntVec3 intVec = target.Cell + GenRadial.RadialPattern[i];
                    if (intVec.InBounds(pawn.Map) && intVec.InAllowedArea(pawn) && intVec.GetRoom(pawn.Map) == room)
                    {
                        ((List <Filth>)enumerable).AddRange(intVec.GetThingList(pawn.Map).OfType <Filth>().Where(f => !f.Destroyed &&
                                                                                                                 ((WorkGiver_Scanner)cleanFilth.Worker).HasJobOnThing(pawn, f)).Take(Limit == 0 ? int.MaxValue : Limit));
                    }
                    if (Limit > 0 && enumerable.Count() >= Limit)
                    {
                        break;
                    }
                }
            }
            else
            {
                enumerable = room.ContainedAndAdjacentThings.OfType <Filth>().Where(delegate(Filth f)
                {
                    if (f == null || f.Destroyed || !f.Position.InAllowedArea(pawn) || !((WorkGiver_Scanner)cleanFilth.Worker).HasJobOnThing(pawn, f))
                    {
                        return(false);
                    }

                    Room room2 = f.GetRoom();
                    if (room2 == null || room2 != room && !room2.IsDoorway)
                    {
                        return(false);
                    }

                    return(true);
                }).Take(Limit == 0 ? int.MaxValue : Limit);
            }
            return(enumerable);
        }
Ejemplo n.º 13
0
        public static bool UseWholeRoomAsPartyArea(IntVec3 partySpot, Map map)
        {
            Room room = partySpot.GetRoom(map, RegionType.Set_Passable);

            return(room != null && !room.IsHuge && !room.PsychologicallyOutdoors && room.CellCount <= 324);
        }
Ejemplo n.º 14
0
        public static bool InPartyArea(IntVec3 cell, IntVec3 partySpot, Map map)
        {
            bool result;

            if (PartyUtility.UseWholeRoomAsPartyArea(partySpot, map) && cell.GetRoom(map, RegionType.Set_Passable) == partySpot.GetRoom(map, RegionType.Set_Passable))
            {
                result = true;
            }
            else if (cell.InHorDistOf(partySpot, 10f))
            {
                Building      edifice        = cell.GetEdifice(map);
                TraverseParms traverseParams = TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.None, false);
                if (edifice != null)
                {
                    result = map.reachability.CanReach(partySpot, edifice, PathEndMode.ClosestTouch, traverseParams);
                }
                else
                {
                    result = map.reachability.CanReach(partySpot, cell, PathEndMode.ClosestTouch, traverseParams);
                }
            }
            else
            {
                result = false;
            }
            return(result);
        }
        public static bool IsValidMarriageSpotFor(IntVec3 cell, Pawn firstFiance, Pawn secondFiance, StringBuilder outFailReason = null)
        {
            bool result;

            if (!firstFiance.Spawned || !secondFiance.Spawned)
            {
                Log.Warning("Can't check if a marriage spot is valid because one of the fiances isn't spawned.", false);
                result = false;
            }
            else if (firstFiance.Map != secondFiance.Map)
            {
                result = false;
            }
            else if (!MarriageSpotUtility.IsValidMarriageSpot(cell, firstFiance.Map, outFailReason))
            {
                result = false;
            }
            else
            {
                if (!cell.Roofed(firstFiance.Map))
                {
                    if (!JoyUtility.EnjoyableOutsideNow(firstFiance, outFailReason))
                    {
                        return(false);
                    }
                    if (!JoyUtility.EnjoyableOutsideNow(secondFiance, outFailReason))
                    {
                        return(false);
                    }
                }
                if (cell.GetDangerFor(firstFiance, firstFiance.Map) != Danger.None)
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotDangerous".Translate(new object[]
                        {
                            firstFiance.LabelShort
                        }));
                    }
                    result = false;
                }
                else if (cell.GetDangerFor(secondFiance, secondFiance.Map) != Danger.None)
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotDangerous".Translate(new object[]
                        {
                            secondFiance.LabelShort
                        }));
                    }
                    result = false;
                }
                else if (cell.IsForbidden(firstFiance))
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotForbidden".Translate(new object[]
                        {
                            firstFiance.LabelShort
                        }));
                    }
                    result = false;
                }
                else if (cell.IsForbidden(secondFiance))
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotForbidden".Translate(new object[]
                        {
                            secondFiance.LabelShort
                        }));
                    }
                    result = false;
                }
                else if (!firstFiance.CanReserve(cell, 1, -1, null, false) || !secondFiance.CanReserve(cell, 1, -1, null, false))
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotReserved".Translate());
                    }
                    result = false;
                }
                else if (!firstFiance.CanReach(cell, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn))
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotUnreachable".Translate(new object[]
                        {
                            firstFiance.LabelShort
                        }));
                    }
                    result = false;
                }
                else if (!secondFiance.CanReach(cell, PathEndMode.OnCell, Danger.None, false, TraverseMode.ByPawn))
                {
                    if (outFailReason != null)
                    {
                        outFailReason.Append("MarriageSpotUnreachable".Translate(new object[]
                        {
                            secondFiance.LabelShort
                        }));
                    }
                    result = false;
                }
                else
                {
                    if (!firstFiance.IsPrisoner && !secondFiance.IsPrisoner)
                    {
                        Room room = cell.GetRoom(firstFiance.Map, RegionType.Set_Passable);
                        if (room != null && room.isPrisonCell)
                        {
                            if (outFailReason != null)
                            {
                                outFailReason.Append("MarriageSpotInPrisonCell".Translate());
                            }
                            return(false);
                        }
                    }
                    result = true;
                }
            }
            return(result);
        }
        public override void DesignateMultiCell(IEnumerable <IntVec3> cells)
        {
            // bail out if empty
            if (cells == null || cells.Count() == 0)
            {
                Messages.Message("Fluffy.Blueprints.CannotCreateBluePrint_NothingSelected".Translate(), MessageSound.RejectInput);
                return;
            }

            // get list of buildings in the cells, note that this includes frames and blueprints, and so _may include floors!_
            List <Thing> things = new List <Thing>(cells.SelectMany(cell => cell.GetThingList(Map)
                                                                    .Where(thing => thing.IsValidBlueprintThing()))
                                                   .Distinct());

            // get list of creatable terrains
            List <Pair <TerrainDef, IntVec3> > terrains = new List <Pair <TerrainDef, IntVec3> >();

            terrains.AddRange(cells.Select(cell => new Pair <TerrainDef, IntVec3>(cell.GetTerrain(Map), cell))
                              .Where(p => p.First.IsValidBlueprintTerrain()));

            // get edges of blueprint area
            // (might be bigger than selected region, but never smaller).
            var allCells = cells.Concat(things.SelectMany(thing => thing.OccupiedRect().Cells));

            int left   = allCells.Min(cell => cell.x);
            int top    = allCells.Max(cell => cell.z);
            int right  = allCells.Max(cell => cell.x);
            int bottom = allCells.Min(cell => cell.z);

            // total size ( +1 because x = 2 ... x = 4 => 4 - 2 + 1 cells )
            IntVec2 size = new IntVec2(right - left + 1, top - bottom + 1);

            // fetch origin for default (North) orientation
            IntVec3 origin = Resources.CenterPosition(new IntVec3(left, 0, bottom), size, Rot4.North);

            // create list of buildables
            List <BuildableInfo> buildables = new List <BuildableInfo>();

            foreach (var thing in things)
            {
                buildables.Add(new BuildableInfo(thing, origin));
            }
            foreach (var terrain in terrains)
            {
                buildables.Add(new BuildableInfo(terrain.First, terrain.Second, origin));
            }

            // try to get a decent default name: check if selection contains only a single room - if so, that's a decent name.
            Room   room        = origin.GetRoom(Map);
            string defaultName = null;

            if (room != null && room.Role != RoomRoleDefOf.None)
            {
                defaultName = room.Role.LabelCap;
            }
            // TODO: multiple (same) rooms, etc.

            // add to controller - controller handles adding to designations
            Blueprint blueprint = new Blueprint(buildables, size, defaultName);

            Controller.Add(blueprint);

#if DEBUG
            blueprint.Debug();
#endif
        }