# Making the Entrance

We are now onto the last part of our floor tutorial!\
Congratulations. You've almost finished. now we just need to make the entrance.

For this example, I will make a pit to load the floor, but you can use other things as well.

Make the entrance of your floor in RAT. Do not add any pits.&#x20;

Go back to `ModRoomPrefabs` and add a new PrototypeDungeonRoom

```csharp
public static PrototypeDungeonRoom Keep_Entrance_Room;
```

Ideally, we want our room to have an icon, if we want this we go add new objects to our asset bundle, one empty gameobject, and one texture (the icon).

Go into `ModPrefabs` and add `public static GameObject Entrance_Icon;`\
in InitCustomPrefabs drop&#x20;

```csharp
Entrance_Icon = ModAssets.LoadAsset<GameObject>("Entrance_Icon");
ItemAPI.ItemBuilder.AddSpriteToObject(Entrance_Icon, ModAssets.LoadAsset<Texture2D>("Entrance_Icon"), false, false);
```

inside the InitCustomRoom add&#x20;

```csharp
Keep_Entrance_Room = RoomFactory.BuildFromResource("DPSMod/Resources/ModRooms/Keep_Entrance_Room.room");
Keep_Entrance_Room.associatedMinimapIcon = ModPrefabs.Entrance_Icon; //not required
```

![](https://1229800202-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQAkTlyeVttU3CJdmYk%2F-Mg3oFCvDGJY9gxKfWQQ%2F-Mg3w_yPNRxUdA9YpcWa%2Fimage.png?alt=media\&token=02718e1e-51d1-4837-9ad8-4902653f662e)

(Tiny pumpkin is the room icon lol. its blurry here but i just forgot to change its filter mode to point)

now we head back towards `FloorNameDungeonFlows`\
inside `InitDungeonFlows`&#x20;

This section has to do with our entrance

```csharp
m_KeepEntranceRooms = ScriptableObject.CreateInstance<GenericRoomTable>();
            m_KeepEntranceRooms.includedRoomTables = new List<GenericRoomTable>(0);
            m_KeepEntranceRooms.includedRooms = new WeightedRoomCollection()
            {
                elements = new List<WeightedRoom>() {
                    //we will place the entrance to our floor here.
                }
            };


            SecretFloorNameEntranceInjector = new ProceduralFlowModifierData()
            {
                annotation = "Secret Floor Entrance Room",
                DEBUG_FORCE_SPAWN = false,
                OncePerRun = false,
                placementRules = new List<ProceduralFlowModifierData.FlowModifierPlacementType>() {
                    ProceduralFlowModifierData.FlowModifierPlacementType.RANDOM_NODE_CHILD
                },
                roomTable = m_KeepEntranceRooms,
                // exactRoom = SewersInjectionData.InjectionData[0].exactRoom,
                exactRoom = null,
                RequiresMasteryToken = false,
                chanceToLock = 0,
                selectionWeight = 1,
                chanceToSpawn = 1,
                RequiredValidPlaceable = null,
                prerequisites = new DungeonPrerequisite[0],
                CanBeForcedSecret = true,
                RandomNodeChildMinDistanceFromEntrance = 0,
                exactSecondaryRoom = null,
                framedCombatNodes = 0,
            };

            CastleInjectionData.InjectionData.Add(SecretFloorNameEntranceInjector); 
```

here we add our room&#x20;

```csharp
m_KeepEntranceRooms.includedRooms = new WeightedRoomCollection()
            {
                elements = new List<WeightedRoom>() {
                    //we will place the entrance to our floor here.
                }
            };
```

```csharp
m_KeepEntranceRooms.includedRooms = new WeightedRoomCollection()
            {
                elements = new List<WeightedRoom>() {
                    ModRoomPrefabs.GenerateWeightedRoom(ModRoomPrefabs.Keep_Entrance_Room, Weight: 1f)
                }
            };
```

we can add more rooms if we want some variance and it will randomly select one of these rooms.

Add this to your toolbox:

```csharp
public static SpeculativeRigidbody GenerateOrAddToRigidBody(GameObject targetObject, CollisionLayer collisionLayer, PixelCollider.PixelColliderGeneration colliderGenerationMode = PixelCollider.PixelColliderGeneration.Tk2dPolygon, bool collideWithTileMap = false, bool CollideWithOthers = true, bool CanBeCarried = true, bool CanBePushed = false, bool RecheckTriggers = false, bool IsTrigger = false, bool replaceExistingColliders = false, bool UsesPixelsAsUnitSize = false, IntVector2? dimensions = null, IntVector2? offset = null)
        {
            SpeculativeRigidbody m_CachedRigidBody = GameObjectExtensions.GetOrAddComponent<SpeculativeRigidbody>(targetObject);
            m_CachedRigidBody.CollideWithOthers = CollideWithOthers;
            m_CachedRigidBody.CollideWithTileMap = collideWithTileMap;
            m_CachedRigidBody.Velocity = Vector2.zero;
            m_CachedRigidBody.MaxVelocity = Vector2.zero;
            m_CachedRigidBody.ForceAlwaysUpdate = false;
            m_CachedRigidBody.CanPush = false;
            m_CachedRigidBody.CanBePushed = CanBePushed;
            m_CachedRigidBody.PushSpeedModifier = 1f;
            m_CachedRigidBody.CanCarry = false;
            m_CachedRigidBody.CanBeCarried = CanBeCarried;
            m_CachedRigidBody.PreventPiercing = false;
            m_CachedRigidBody.SkipEmptyColliders = false;
            m_CachedRigidBody.RecheckTriggers = RecheckTriggers;
            m_CachedRigidBody.UpdateCollidersOnRotation = false;
            m_CachedRigidBody.UpdateCollidersOnScale = false;

            IntVector2 Offset = IntVector2.Zero;
            IntVector2 Dimensions = IntVector2.Zero;
            if (colliderGenerationMode != PixelCollider.PixelColliderGeneration.Tk2dPolygon)
            {
                if (dimensions.HasValue)
                {
                    Dimensions = dimensions.Value;
                    if (!UsesPixelsAsUnitSize)
                    {
                        Dimensions = (new IntVector2(Dimensions.x * 16, Dimensions.y * 16));
                    }
                }
                if (offset.HasValue)
                {
                    Offset = offset.Value;
                    if (!UsesPixelsAsUnitSize)
                    {
                        Offset = (new IntVector2(Offset.x * 16, Offset.y * 16));
                    }
                }
            }
            PixelCollider m_CachedCollider = new PixelCollider()
            {
                ColliderGenerationMode = colliderGenerationMode,
                CollisionLayer = collisionLayer,
                IsTrigger = IsTrigger,
                BagleUseFirstFrameOnly = (colliderGenerationMode == PixelCollider.PixelColliderGeneration.Tk2dPolygon),
                SpecifyBagelFrame = string.Empty,
                BagelColliderNumber = 0,
                ManualOffsetX = Offset.x,
                ManualOffsetY = Offset.y,
                ManualWidth = Dimensions.x,
                ManualHeight = Dimensions.y,
                ManualDiameter = 0,
                ManualLeftX = 0,
                ManualLeftY = 0,
                ManualRightX = 0,
                ManualRightY = 0
            };

            if (replaceExistingColliders | m_CachedRigidBody.PixelColliders == null)
            {
                m_CachedRigidBody.PixelColliders = new List<PixelCollider> { m_CachedCollider };
            }
            else
            {
                m_CachedRigidBody.PixelColliders.Add(m_CachedCollider);
            }

            if (m_CachedRigidBody.sprite && colliderGenerationMode == PixelCollider.PixelColliderGeneration.Tk2dPolygon)
            {
                Bounds bounds = m_CachedRigidBody.sprite.GetBounds();
                m_CachedRigidBody.sprite.GetTrueCurrentSpriteDef().colliderVertices = new Vector3[] { bounds.center - bounds.extents, bounds.center + bounds.extents };
                // m_CachedRigidBody.ForceRegenerate();
                // m_CachedRigidBody.RegenerateCache();
            }

            return m_CachedRigidBody;
        }
```

now we need a new object in our assetbundle. we will place this in our entrance room. Go to ModPrefabs and add `public static GameObject FloorNameEntrance;`

Get it like so\
`FloorNameEntrance = ModAssets.LoadAsset("FloorNameEntrance");`\
you can add a sprite to this object if you wish.&#x20;

\
create a new file called KeepEntranceControllerthat inherits from BraveBehaviour, IPlaceConfigurable.

just copy _**AAAALLLLLLLL**_ this in

```csharp
public KeepEntranceController()
        {
            targetLevelName = "tt_floorname";
            PitOffset = new IntVector2(5, 2);
            m_Triggered = false;
            m_Destroyed = false;
        }

        public string targetLevelName;
        public IntVector2 PitOffset;

        private bool m_Triggered;
        private bool m_Destroyed;

        private RoomHandler m_ParentRoom;

        private IEnumerator Start()
        {
            yield return null;
            while (GameManager.Instance.IsLoadingLevel && Dungeon.IsGenerating) { yield return null; }
            yield return null;

            //IntVector2 baseCellPosition = (transform.position.IntXY(VectorConversions.Floor) + new IntVector2(4, 1.5));

            // specRigidbody.OnHitByBeam = (Action<BasicBeamController>)Delegate.Combine(specRigidbody.OnHitByBeam, new Action<BasicBeamController>(HandleBeamCollision));
            GameObject PitManager = new GameObject("Pit Manager") { layer = 0 };
            PitManager.transform.position = (transform.position + new Vector3(5, 1.5f));
            tk2dSprite PitDummySprite = PitManager.AddComponent<tk2dSprite>();
            //Toolbox.DuplicateSprite(PitDummySprite, null);
            tk2dSprite pitSprite = PitManager.GetComponent<tk2dSprite>();
            pitSprite.renderer.enabled = false;

            toolbox.GenerateOrAddToRigidBody(PitManager, CollisionLayer.Trap, PixelCollider.PixelColliderGeneration.Manual, IsTrigger: true, dimensions: new IntVector2(2, 2));

            KeepEntrancePitController HallPitManager = PitManager.AddComponent<KeepEntrancePitController>();
            HallPitManager.targetLevelName = targetLevelName;
            yield break;
        }

        


        /*private void HandleBeamCollision(BasicBeamController obj) {
            GoopModifier component = obj.GetComponent<GoopModifier>();
            if (component && component.goopDefinition != null && component.goopDefinition.CanBeIgnited && component.goopDefinition.fireEffect != null) { OnFireStarted(); }
        }*/

        public void ConfigureOnPlacement(RoomHandler room)
        {
            m_ParentRoom = room;

            

            IntVector2 basePosition = (transform.position.IntXY(VectorConversions.Floor) + PitOffset);
            IntVector2 cellPos = basePosition;
            IntVector2 cellPos2 = (basePosition + new IntVector2(1, 0));
            IntVector2 cellPos3 = (basePosition + new IntVector2(1, 1));
            IntVector2 cellPos4 = (basePosition + new IntVector2(0, 1));
            CellData cellData = GameManager.Instance.Dungeon.data[cellPos];
            CellData cellData2 = GameManager.Instance.Dungeon.data[cellPos2];
            CellData cellData3 = GameManager.Instance.Dungeon.data[cellPos3];
            CellData cellData4 = GameManager.Instance.Dungeon.data[cellPos4];

            cellData.type = CellType.PIT;
            cellData2.type = CellType.PIT;
            cellData3.type = CellType.PIT;
            cellData4.type = CellType.PIT;

            cellData.forceAllowGoop = false;
            cellData2.forceAllowGoop = false;
            cellData3.forceAllowGoop = false;
            cellData4.forceAllowGoop = false;

            cellData.fallingPrevented = false;
            cellData2.fallingPrevented = false;
            cellData3.fallingPrevented = false;
            cellData4.fallingPrevented = false;
        }

        private void Update() { }
        private void LateUpdate() { }

        protected override void OnDestroy()
        {
            m_Destroyed = true;
            base.OnDestroy();
        }
    }

    public class KeepEntrancePitController : DungeonPlaceableBehaviour, IPlaceConfigurable
    {

        public KeepEntrancePitController() { targetLevelName = "tt_floorname"; }

        public string targetLevelName;

        private void Start()
        {
            
            SpeculativeRigidbody Rigidbody = specRigidbody;
            Rigidbody.OnEnterTrigger = (SpeculativeRigidbody.OnTriggerDelegate)Delegate.Combine(Rigidbody.OnEnterTrigger, new SpeculativeRigidbody.OnTriggerDelegate(HandleTriggerEntered));
            SpeculativeRigidbody Rigidbody2 = specRigidbody;
            Rigidbody2.OnExitTrigger = (SpeculativeRigidbody.OnTriggerExitDelegate)Delegate.Combine(Rigidbody2.OnExitTrigger, new SpeculativeRigidbody.OnTriggerExitDelegate(HandleTriggerExited));
        }

        private void HandleTriggerEntered(SpeculativeRigidbody specRigidbody, SpeculativeRigidbody sourceSpecRigidbody, CollisionData collisionData)
        {
            PlayerController component = specRigidbody.GetComponent<PlayerController>();
            if (component) { component.LevelToLoadOnPitfall = targetLevelName; }
        }

        private void HandleTriggerExited(SpeculativeRigidbody specRigidbody, SpeculativeRigidbody sourceSpecRigidbody)
        {
            PlayerController component = specRigidbody.GetComponent<PlayerController>();
            if (component) { component.LevelToLoadOnPitfall = string.Empty; }
        }

        public void ConfigureOnPlacement(RoomHandler room) { }

        private void Update() {
            

        }

        protected override void OnDestroy() { base.OnDestroy(); }
    }
```

make sure to change values according to your needs.

now we head back to ModPrefabs and do&#x20;

```csharp
FloorNameEntrance.AddComponent<KeepEntranceController>();
```

And in ModRoomPrefabs do&#x20;

```
RoomBuilder.AddObjectToRoom(Keep_Entrance_Room, new Vector2(3.5f, 12) /* needs tweaking */ , toolbox.GenerateDungeonPlacable(ModPrefabs.FloorNameEntrance, useExternalPrefab: true));
```

tada! congratulations, you have just done one of the hardest things in modding! nice work and i cant wait to see the results :).
