# Making the flow

most floors have anywhere from 2-5 different flows and each flow has around 17-21 nodes (aka 17-21 rooms).&#x20;

for each of the flows, you plan on making, create a new file named `f1b_floorname_flow_01` that inherits from `FloorNameDungeonFlows` with the number increasing each time.

A good idea when making the flow is to plan out how many rooms you want then drawing out your flow, whether or not it should be a one-way loop, if it's a hub or combat, chest, shop, boss, etc. That way you have a clear look at how the floor will usually be set up and which rooms connect to which.

here is an example you can drop in your class

```csharp
public static DungeonFlow F1b_FloorName_flow_01()
		{
			try
			{

				DungeonFlow m_CachedFlow = ScriptableObject.CreateInstance<DungeonFlow>();

				DungeonFlowNode entranceNode = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.ENTRANCE, ModRoomPrefabs.Mod_Entrance_Room);
				DungeonFlowNode exitNode = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.EXIT, ModRoomPrefabs.Mod_Exit_Room);
				DungeonFlowNode bossfoyerNode = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.SPECIAL, overrideTable: ModPrefabs.boss_foyertable);
				DungeonFlowNode bossNode = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.BOSS, ModRoomPrefabs.Mod_Boss);

				DungeonFlowNode FloorNameShopNode = GenerateDefaultNode(m_CachedFlow, ModPrefabs.shop02.category, overrideTable: ModPrefabs.shop_room_table);
				DungeonFlowNode FloorNameRewardNode_01 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.CONNECTOR, ModPrefabs.gungeon_rewardroom_1);
				DungeonFlowNode FloorNameRewardNode_02 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.CONNECTOR, ModPrefabs.gungeon_rewardroom_1);


				DungeonFlowNode FloorNameRoomNode_01 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.HUB, oneWayLoopTarget: true);
				DungeonFlowNode FloorNameRoomNode_02 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_04 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_05 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_06 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.HUB, oneWayLoopTarget: true);
				DungeonFlowNode FloorNameRoomNode_07 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_09 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_10 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_11 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.HUB);
				DungeonFlowNode FloorNameRoomNode_12 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_13 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_14 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_16 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_17 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);
				DungeonFlowNode FloorNameRoomNode_18 = GenerateDefaultNode(m_CachedFlow, PrototypeDungeonRoom.RoomCategory.NORMAL);

				m_CachedFlow.name = "F1b_FloorName_Flow_01";
				m_CachedFlow.fallbackRoomTable = ModPrefabs.FloorNameRoomTable;
				m_CachedFlow.phantomRoomTable = null;
				m_CachedFlow.subtypeRestrictions = new List<DungeonFlowSubtypeRestriction>(0);
				m_CachedFlow.flowInjectionData = new List<ProceduralFlowModifierData>(0);
				m_CachedFlow.sharedInjectionData = new List<SharedInjectionData>() { BaseSharedInjectionData };

				m_CachedFlow.Initialize();

				m_CachedFlow.AddNodeToFlow(entranceNode, null);
				// First Looping branch
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_16, entranceNode);
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_01, FloorNameRoomNode_16);
				// Dead End
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_05, FloorNameRoomNode_01);
				// Start of Loop
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_02, FloorNameRoomNode_01);
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_04, FloorNameRoomNode_02);
				m_CachedFlow.AddNodeToFlow(FloorNameRewardNode_01, FloorNameRoomNode_04);
				// Connect End of Loop to first in chain
				m_CachedFlow.LoopConnectNodes(FloorNameRewardNode_01, FloorNameRoomNode_01);

				// Second Looping branch
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_17, entranceNode);
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_06, FloorNameRoomNode_17);
				// Dead End
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_10, FloorNameRoomNode_06);
				// Start of Loop
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_07, FloorNameRoomNode_06);
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_09, FloorNameRoomNode_07);
				m_CachedFlow.AddNodeToFlow(FloorNameRewardNode_02, FloorNameRoomNode_09);
				// Connect End of Loop to first in chain
				m_CachedFlow.LoopConnectNodes(FloorNameRewardNode_02, FloorNameRoomNode_06);

				// Splitting path to Shop or Boss
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_18, entranceNode);
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_11, FloorNameRoomNode_18);
				// Path To Boss
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_12, FloorNameRoomNode_11);
				// Path to Shop
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_13, FloorNameRoomNode_11);
				m_CachedFlow.AddNodeToFlow(FloorNameShopNode, FloorNameRoomNode_13);
				// Dead End
				m_CachedFlow.AddNodeToFlow(FloorNameRoomNode_14, FloorNameRoomNode_11);


				m_CachedFlow.AddNodeToFlow(bossfoyerNode, FloorNameRoomNode_12);
				m_CachedFlow.AddNodeToFlow(bossNode, bossfoyerNode);
				m_CachedFlow.AddNodeToFlow(exitNode, bossNode);

				m_CachedFlow.FirstNode = entranceNode;

				return m_CachedFlow;
			}
			catch (Exception e)
			{
				ETGModConsole.Log(e.ToString());
				return null;
			}
		}
```

here is a diagram of what this would look like&#x20;

![](https://1229800202-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQAkTlyeVttU3CJdmYk%2F-Mg3OLk3MOXYNl-86eW5%2F-Mg3YBs3byMI93TuXT_p%2Fflow_diagram.png?alt=media\&token=8fc06be0-a1f5-4947-8b64-6e2999d3f8ad)

Now we head back to FloorNameDungeon and we scroll down until we see this:&#x20;

![](https://1229800202-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQAkTlyeVttU3CJdmYk%2F-Mg3OLk3MOXYNl-86eW5%2F-Mg3Yj4DLxKSwdGRseCC%2Fimage.png?alt=media\&token=9e526b10-14eb-4fc5-b428-41d7f52970fd)

simply drop all the flows you have made into that list&#x20;

![](https://1229800202-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQAkTlyeVttU3CJdmYk%2F-Mg3OLk3MOXYNl-86eW5%2F-Mg3YrV13qjdc3wGmJID%2Fimage.png?alt=media\&token=c34f008d-59c5-4b98-9bac-a3211e5b36d3)

now we go to FloorNameDungeonFlows and scroll down till you see the comment saying:&#x20;

> we will add our custom flow here soon.

simply add your flows to KnownFlows there&#x20;

![](https://1229800202-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQAkTlyeVttU3CJdmYk%2F-Mg3OLk3MOXYNl-86eW5%2F-Mg3ZqdRb_p2Z6XwJpIC%2Fimage.png?alt=media\&token=78388001-a5c2-470d-af8a-e10ebc3df759)

We can now test our floor.&#x20;

In our module we will init everything in this order:&#x20;

```csharp
				ModPrefabs.InitCustomPrefabs();
				ModRoomPrefabs.InitCustomRooms();
				FloorNameDungeonFlows.InitDungeonFlows();
				FloorNameDungeon.InitCustomDungeon();
				Hook hook = new Hook(
				   typeof(GameManager).GetMethod("Awake", BindingFlags.NonPublic | BindingFlags.Instance),
				   typeof(Module).GetMethod("GameManager_Awake", BindingFlags.NonPublic | BindingFlags.Instance),
				   typeof(GameManager)
			   );
```

and add this method:&#x20;

```csharp
private void GameManager_Awake(Action<GameManager> orig, GameManager self)
		{
			orig(self);
			FloorNameDungeon.InitCustomDungeon();
		}
```

we now need a command to load our floor. Drop this in your modules init:

```csharp
ETGModConsole.Commands.AddGroup("floor", args =>
                {
                });
                ETGModConsole.Commands.GetGroup("floor").AddUnit("load", this.LoadFloor);
```

and make this method

```csharp
private void LoadFloor(string[] obj)
		{
			GameManager.Instance.LoadCustomLevel(FloorNameDungeon.FloorNameDefinition.dungeonSceneName);
		}
```

now test!

![](https://1229800202-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQAkTlyeVttU3CJdmYk%2F-Mg3kJfUV9Ak4O96S6zU%2F-Mg3kuV7lqV8NnXsDmBe%2Fimage.png?alt=media\&token=5dcbd7a4-fd13-4177-ac7e-2c4d99f1b223)

(if it is starting you on something other than your entrance, make sure in your entrance the room category is entrance, ***set via code, not rat***.)
