Beispiel #1
0
        private static IEnumerable <Blueprint> PlaceTentBlueprints()
        {
            // main chapiteau
            ThingDef tentDef;
            Rot4     rot = info.setupCentre.RotationFacing(info.bannerCell).Opposite;
            IntVec3  tentSpot;

            if (availableCrates.Any(c => c.def == _DefOf.Carn_Crate_TentHuge))
            {
                tentDef  = _DefOf.Carn_TentChap;
                tentSpot = FindRadialPlacementFor(tentDef, rot, info.setupCentre, 11);
                if (tentSpot.IsValid)
                {
                    RemoveFirstCrateOf(_DefOf.Carn_Crate_TentHuge);
                    CarnUtils.ClearThingsFor(info.map, tentSpot, tentDef.size, rot, 2);
                    yield return(PlaceBlueprint(tentDef, tentSpot, rot));
                }
                else
                {
                    Log.Error("Could not find placement for " + tentDef + ", which is a major attraction. Tell Xnope to get it together.");
                }
            }



            // lodging tents
            tentDef  = _DefOf.Carn_TentLodge;
            rot      = Rot4.Random;
            tentSpot = FindRadialPlacementFor(tentDef, rot, info.carnivalArea.ContractedBy(9).FurthestCellFrom(CellsUtil.AverageColonistPosition(info.map)), 7);

            IntVec3 lineDirection = rot.ToIntVec3(1); // shifted clockwise by 1

            int  numFailures  = 0;
            bool firstNewPass = true;

            while (numFailures < 30 && availableCrates.Any(t => t.def == _DefOf.Carn_Crate_TentLodge))
            {
                // Following works as intended iff size.x == size.y

                if (!firstNewPass)
                {
                    // try adding tent next in a an adjacent line
                    tentSpot += lineDirection * ((tentDef.size.x + 1));
                }

                if (CanPlaceBlueprintAt(tentSpot, tentDef, rot))
                {
                    // bingo
                    firstNewPass = false;
                    RemoveFirstCrateOf(_DefOf.Carn_Crate_TentLodge);
                    CarnUtils.ClearThingsFor(info.map, tentSpot, tentDef.size, rot, 1);
                    yield return(PlaceBlueprint(tentDef, tentSpot, rot));
                }
                else if (numFailures % 3 != 0)
                {
                    // try different line directions
                    rot.AsByte++;
                    lineDirection = rot.ToIntVec3(1);
                    numFailures++;
                }
                else
                {
                    // Find new placement if next spot and any of its rotations don't work
                    tentSpot = FindRadialPlacementFor(tentDef, rot, tentSpot, (int)info.baseRadius / 2);

                    if (!tentSpot.IsValid)
                    {
                        // suboptimal random placement
                        tentSpot = FindRandomPlacementFor(tentDef, rot, false, 5);
                    }

                    firstNewPass = true;
                }
            }

            if (numFailures == 30 && availableCrates.Any(t => t.def == _DefOf.Carn_Crate_TentLodge))
            {
                Log.Error("Tried too many times to place tents. Some may not be built.");
            }

            // manager tent
            if (!availableCrates.Any(c => c.def == _DefOf.Carn_Crate_TentMan))
            {
                yield break;
            }

            rot     = Rot4.Random;
            tentDef = _DefOf.Carn_TentLodgeMan;

            // Try to place near other tents
            tentSpot = FindRadialCardinalPlacementFor(tentDef, rot, tentSpot, 10);

            if (tentSpot.IsValid)
            {
                RemoveFirstCrateOf(_DefOf.Carn_Crate_TentMan);
                CarnUtils.ClearThingsFor(info.map, tentSpot, tentDef.size, rot, 1);
                yield return(PlaceBlueprint(tentDef, tentSpot, rot));
            }
            else
            {
                // suboptimal placement
                tentSpot = FindRadialPlacementFor(tentDef, rot, info.setupCentre, (int)info.baseRadius / 2);
                if (tentSpot.IsValid)
                {
                    RemoveFirstCrateOf(_DefOf.Carn_Crate_TentMan);
                    CarnUtils.ClearThingsFor(info.map, tentSpot, tentDef.size, rot, 1);
                    yield return(PlaceBlueprint(tentDef, tentSpot, rot));
                }
                else
                {
                    Log.Error("Found no valid placement for manager tent. It will not be placed.");
                }
            }
        }