Architecture for the Round System

Godot Version

Godot Engine 4.3

Question

Hello! I am trying to crate a Round System for my multiplayer Godot Engine game.

To be honest I just geniunely don’t know where to start and what architecture to us. I’ve had previous post on that and my idea was to use “manager” scripts. Thanks to really amazing people on this forums I’ve realised that using “manager” scripts is a bad idea when it is possible to omit the use of managers in general.

My round system consists of multiple things. At the very start of the lobby to which the players are connecting there is “intermission screen” being shown by the default. In order for the round to start it is required to have minimum amount of players - 3. Minimum amount of players is required in order to determine the winning team and to end the round during the ongoing round.

If there is 3 players connected to the lobby then the round setup is started and a new map is being generated. The map generation is just a facility with hallways and zones. Each new round it’s purely random and new which allows replayability and funny entertaining gameplay.
The map generation consists of placing specific rooms at the specific positions. (Unfortunately, I did not create the map generation right now because the Godot Engine do not like having arrays inside of arrays in order to create “2D Matrix” which is quite weird in my opinion because many programming languages allow that).


Map generation clarification and some design questions.

Each room Node3D have specific Node3D nodes that are positioned on the places where random items would appear. Technically, specific room and such nodes that are positioned on the place where item would appear have their own list of items that SHOULD appear. Which is… uh another different system I do not know how to correctly come up with. Let’s say specific table in a Room A would have a item spawner node at that node the specific “keycard” items or “document” items should appear. At the same time in the Room A there is closet at which there should specific appear “gun” items randomly (e.g. 0.8 weight for the pistol and 0.2 weight for the rifle).

Should I for that have specific new scene named item_spawner.tscn that is Node3D and would have script attached to it item_spawner.gd? The script would be connected to the round system custom signal. When the signal emitted the item_spawner.gd would get that and spawn items using the weights and random that are in this @export var spawn_items : Dictionary. And uh the dictionary would have item ids and the according weights…

There is additional class by the way with the name of class_name ItemData. This class have the item data which is the item model in the 3D world when the item is dropped or spawned during map generation. This class have item data which is the texture of how this item will appear in inventory. The item data also consists of the item name, item description, item weapon data (e.g. firerate, damage, fire mode). The only problem with my weapon system is that technically some weapons have same type of bullets. And technically, let’s say both of specific weapons even though they have their own current amount of bullets, when reloading the amount of allowed bullets to use should be decreased from the type of bullet mags the player has in his inventory. The inventory slots do not have bullet mags they’re just hidden but visible on the corner of the screen and player is able to drop htem.


After the map has been generated then the round system should spawn players. There is an number order which was created to make the round based game be fair. What is this number order? The number order have numbers like 1,2,3,4. There should be for loop going through this order. When we’re at number 1 we’re spawning ONE PLAYER to the Team A. When we’re at number 2 we’re spawning ONE PLAYER to the Team B.

Each team is quite complicated. As I said it’s random map generation. Specific teams should spawn only at the specific positions. If it’s a Team A then the player should spawn at one of the position points randomly which are at the specific rooms of the generated map. This would mean that the room model Node3D have another Node3D nodes that are meaning the spawn position point for the specified team. I do now know how to design that.

The number order was made for the things to remain fair. Remember when I’ve said that we need minimum of 3 players? The number order is specifically designed for 2 different teams to spawn. And if there is 4 players then 3 different teams will spawn. We’re basically going through the list of all players connected to the lobby and then get the index at which we’re on the player list and using it on the number order. If we have reached the maximum of the number order array then we’re going back to the number order. This system is tested and I have came up with it very long time ago. It is meant to have fair gameplay.


After all players have spawned they should have specific items applied to their inventories. But as I said the teams are complicated. They have ranks. The only different for the players to have ranks is the amount of items they have from the spawn. Let’s say “Team A” is divided into “Captain” and “Lieutenant”. “Captain” can spawn ONLY once and he would have more cooler items than “Lieutenant” players. There also should be random weight which means that it’s quite rate to spawn as “Liuentant” but it is not rare to spawn as “Cadet”. “Captain” though… should ALWAYS be spawned. Even if there is only one player assigned to the team then he will be the “Captain”.

I do now know how to design that bruh. Perhaps, some kind of signals? It’s a multipler game! This means I need MultiplayerSynchronizers but how to setup them for such thing? Specific players having specific inventory with specific items!


After all of that the players should have their own HUDs. If it’s “Team A” they have reddish HUD. If it’s “Team B” then they have bluish HUD and so on. But as I said the system is complicated. There is “Team C” which have special characters that player spawn as ONLY ONCE.

Let’s say one player was assigned to the “Team C” and he has spawned as “super computer” which controls whole facility. The player is able through interface to open camera map, to close/open doors and do everything. How to do that?

All of that heavily depends on the way I have designed the inventory system and the map generation system. But I have tried to clarify some moments on that.

Please give me suggestions on my post and your opinions on some aspects of the map generation system.

The main problems is the fact that this is multiplayer game and that the system for everything is indeed quite complicated and requires multiple subsystems to work in order just for the round to start.


I also forgot to mention in the original post that the round system SHOULD do something when the player has died. Basically… uh all players have their own script with the health. The same script has take_damage function which is fired from the weapon system. Basically, when player shot another player the damage is given to that another player with the specific damage value. The take_damage function may have different ways to decrease the health depending on what the player has e.g. specific level of the armor and specific effects applied to health (e.g. from the medkit 5 seconds effect of the regeneration and little bit immunity to the damage which means that only small portion of the damage is applied).

Technically, everytime player dies the round system SHOULD check if there is possibility to have a winner.
Some teams may be friendly to other teams. There is class_name Team script which has @export var friendly_teams : Array[Team]. Basically, let’s say that “Team A” is friendly to the “Team B”. They cannot shoot each other. This means that if all other teams have no players on them (the players are spectators) then we say that these “Team A” and “Team B” are technically won but the winning screen will just say “Foundation Win”.

At the same time if there is no players on the “Team A” and the “Team B” but there is atleast one player at the “Team C” and other teams do not have any players then the winner is the “Team C”.

Now I do not ask you how to create such function. I just ask how to design an architectue that would call that function to check the winner. The function that checks the winner will be written by me.

By the way we should also somehow to show the specific HUD for the specific players.

If player has spawned during the intermission then he no longer has intermission screen visible while other players who have not spawned will still have intermission screen.

Also during the rounds. Like when round is ended (the winner has been choosen) everyone sees the GUI text of who the winner is. The text is visible for 5 seconds then intermission screen appear to all players.

The intermission as I said should again go for 15-20 seconds. Just for the players to chat and talk about the round that ended. During that time though we generate the map and setup everything for the new round. Would be also cool to implement into system that there is slight chance for the special event round to appear instead of normal round but this is just an addition.