├── Lobby
├── API
│ ├── Enums
│ │ └── LobbyLocationType.cs
│ └── LobbyLocationHandler.cs
├── packages.config
├── Patches
│ └── StaminaUsageMultiplierPatch.cs
├── RestrictionsHandler.cs
├── Command
│ ├── LobbyParentCommand.cs
│ ├── DebugCommands
│ │ ├── GetLocalDataCommand.cs
│ │ ├── LocationListCommand.cs
│ │ └── TpLocationCommand.cs
│ └── ControlCommands
│ │ ├── RemoveLocationCommand.cs
│ │ └── AddLocationCommand.cs
├── Properties
│ └── AssemblyInfo.cs
├── Lobby.cs
├── Lobby.csproj
├── Config.cs
└── EventsHandler.cs
├── .gitignore
├── Lobby.sln
└── README.md
/Lobby/API/Enums/LobbyLocationType.cs:
--------------------------------------------------------------------------------
1 | namespace Lobby
2 | {
3 | public enum LobbyLocationType
4 | {
5 | Tower_1,
6 | Tower_2,
7 | Tower_3,
8 | Tower_4,
9 | Tower_5,
10 | Intercom,
11 | GR18,
12 | SCP173
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Lobby/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build results
2 | [Dd]ebug/
3 | [Dd]ebugPublic/
4 | [Rr]elease/
5 | [Rr]eleases/
6 | x64/
7 | x86/
8 | [Aa][Rr][Mm]/
9 | [Aa][Rr][Mm]64/
10 | bld/
11 | [Bb]in/
12 | [Oo]bj/
13 | [Ll]og/
14 | [Ll]ogs/
15 | .vs
16 |
17 | # NuGet Packages
18 | *.nupkg
19 |
20 | # The packages folder can be ignored because of Package Restore
21 | **/[Pp]ackages/*
22 |
23 | # User-specific files
24 | *.rsuser
25 | *.suo
26 | *.user
27 | *.userosscache
28 | *.sln.docstates
--------------------------------------------------------------------------------
/Lobby/Patches/StaminaUsageMultiplierPatch.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using InventorySystem;
3 |
4 | namespace Lobby.Patches
5 | {
6 | [HarmonyPatch(typeof(Inventory), nameof(Inventory.StaminaUsageMultiplier), MethodType.Getter)]
7 | public class StaminaUsageMultiplierPatch
8 | {
9 | private static void Postfix(Inventory __instance, ref float __result)
10 | {
11 | if (Lobby.Instance.Config.InfinityStamina && EventsHandler.IsLobby)
12 | __result = 0;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Lobby/RestrictionsHandler.cs:
--------------------------------------------------------------------------------
1 | using LabApi.Events.Arguments.PlayerEvents;
2 |
3 | namespace Lobby
4 | {
5 | public class RestrictionsHandler
6 | {
7 | private bool IsLobby => EventsHandler.IsLobby;
8 |
9 | public void OnPlayerInteractingDoor(PlayerInteractingDoorEventArgs ev) => ev.IsAllowed = !IsLobby;
10 |
11 | public void OnPlayerInteractingElevator(PlayerInteractingElevatorEventArgs ev)
12 | {
13 | if (IsLobby) ev.IsAllowed = false;
14 | }
15 |
16 | public void OnPlayerSearchingPickup(PlayerSearchingPickupEventArgs ev) => ev.IsAllowed = !IsLobby;
17 |
18 | public void OnPlayerDroppingItem(PlayerDroppingItemEventArgs ev) => ev.IsAllowed = !IsLobby;
19 |
20 | public void OnPlayerDroppingAmmo(PlayerDroppingAmmoEventArgs ev) => ev.IsAllowed = !IsLobby;
21 |
22 | public void OnPlayerThrowingItem(PlayerThrowingItemEventArgs ev) => ev.IsAllowed = !IsLobby;
23 |
24 | public void OnPlayerUsingIntercom(PlayerUsingIntercomEventArgs ev) => ev.IsAllowed = (IsLobby && !Lobby.Instance.Config.AllowIcom ? false : true);
25 | }
26 | }
--------------------------------------------------------------------------------
/Lobby.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.4.33103.184
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lobby", "Lobby\Lobby.csproj", "{F6FFBCFD-6FDB-4185-AB54-20AB167DCA57}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F6FFBCFD-6FDB-4185-AB54-20AB167DCA57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {F6FFBCFD-6FDB-4185-AB54-20AB167DCA57}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {F6FFBCFD-6FDB-4185-AB54-20AB167DCA57}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {F6FFBCFD-6FDB-4185-AB54-20AB167DCA57}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {E12F31A4-0BE3-4079-AB00-A9622456A49F}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Lobby/Command/LobbyParentCommand.cs:
--------------------------------------------------------------------------------
1 | using CommandSystem;
2 | using Lobby.Command.ControlCommands;
3 | using Lobby.Command.DebugCommands;
4 | using System;
5 |
6 | namespace Lobby.Command
7 | {
8 | [CommandHandler(typeof(RemoteAdminCommandHandler))]
9 | public class LobbyParentCommand : ParentCommand
10 | {
11 | public LobbyParentCommand() => LoadGeneratedCommands();
12 |
13 | public override string Command => "lobby";
14 |
15 | public override string[] Aliases { get; } = { "lb", "ly" };
16 |
17 | public override string Description => "Lobby parent command.";
18 |
19 | public override void LoadGeneratedCommands()
20 | {
21 | RegisterCommand(new AddLocationCommand());
22 | RegisterCommand(new RemoveLocationCommand());
23 | RegisterCommand(new LocationListCommand());
24 | RegisterCommand(new TpLocationCommand());
25 | RegisterCommand(new GetLocalDataCommand());
26 | }
27 |
28 | protected override bool ExecuteParent(ArraySegment arguments, ICommandSender sender, out string response)
29 | {
30 | response = "Incorrect command, use: \nlobby addloc\nlobby removeloc\nlobby loclist\nlobby tploc\nlobby getlocaldata";
31 | return false;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Lobby/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Lobby")]
8 | [assembly: AssemblyDescription("A plugin that adds a lobby when waiting for players.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("MrAfitol")]
11 | [assembly: AssemblyProduct("Lobby")]
12 | [assembly: AssemblyCopyright("Copyright © MrAfitol 2022")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("f6ffbcfd-6fdb-4185-ab54-20ab167dca57")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.6.2.0")]
35 | [assembly: AssemblyFileVersion("1.6.2.0")]
36 |
--------------------------------------------------------------------------------
/Lobby/Lobby.cs:
--------------------------------------------------------------------------------
1 | using HarmonyLib;
2 | using LabApi.Events.Handlers;
3 | using LabApi.Features;
4 | using LabApi.Loader.Features.Plugins;
5 | using System;
6 |
7 | namespace Lobby
8 | {
9 | public class Lobby : Plugin
10 | {
11 | public static Lobby Instance { get; private set; }
12 |
13 | public override string Name { get; } = "Lobby";
14 |
15 | public override string Description { get; } = "A plugin that adds a lobby when waiting for players.";
16 |
17 | public override string Author { get; } = "MrAfitol";
18 |
19 | public override Version Version { get; } = new Version(1, 6, 2);
20 |
21 | public override Version RequiredApiVersion { get; } = new Version(LabApiProperties.CompiledVersion);
22 |
23 | public Harmony Harmony { get; private set; }
24 |
25 | public EventsHandler EventsHandler { get; private set; }
26 | public RestrictionsHandler RestrictionsHandler { get; private set; }
27 |
28 | public override void Enable()
29 | {
30 | Instance = this;
31 | Harmony = new Harmony("lobby.scp.sl");
32 | EventsHandler = new EventsHandler();
33 | RestrictionsHandler = new RestrictionsHandler();
34 | ServerEvents.WaitingForPlayers += EventsHandler.OnWaitingForPlayers;
35 | ServerEvents.RoundStarted += EventsHandler.OnRoundStarted;
36 | }
37 |
38 | public override void Disable()
39 | {
40 | ServerEvents.WaitingForPlayers -= EventsHandler.OnWaitingForPlayers;
41 | ServerEvents.RoundStarted -= EventsHandler.OnRoundStarted;
42 | EventsHandler.UnregisterHandlers();
43 | RestrictionsHandler = null;
44 | EventsHandler = null;
45 | Harmony = null;
46 | Instance = null;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/Lobby/Command/DebugCommands/GetLocalDataCommand.cs:
--------------------------------------------------------------------------------
1 | using CommandSystem;
2 | using LabApi.Features.Permissions;
3 | using LabApi.Features.Wrappers;
4 | using System;
5 | using UnityEngine;
6 |
7 | namespace Lobby.Command.DebugCommands
8 | {
9 | public class GetLocalDataCommand : ICommand
10 | {
11 | public string Command => "getlocaldata";
12 |
13 | public string[] Aliases { get; } = { "getlocdat", "getld", "gld" };
14 |
15 | public string Description => "Shows the exact position and rotation in the room where the player is located.";
16 |
17 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
18 | {
19 | Player playerSender = Player.Get(sender);
20 |
21 | if (!playerSender.HasAnyPermission("lobby.*", "lobby.debug.*", "lobby.debug.getld"))
22 | {
23 | response = $"You don't have permission to use this command!";
24 | return false;
25 | }
26 |
27 | if (arguments.Count > 0)
28 | {
29 | response = "Incorrect command, use: \nlobby getlocalpos";
30 | return false;
31 | }
32 |
33 | if (playerSender.Room == null)
34 | {
35 | response = "An error occurred when getting the room you are in.";
36 | return false;
37 | }
38 |
39 | GameObject Point = new GameObject("Point");
40 | Point.transform.position = playerSender.Position;
41 | Point.transform.rotation = playerSender.Rotation;
42 | Point.transform.SetParent(playerSender.Room.Transform);
43 |
44 | response = $"Room name {playerSender.Room.GameObject.name}; Local position: {Point.transform.localPosition.ToString()}; Local Rotation: {Point.transform.localEulerAngles.ToString()}.";
45 | return true;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/Lobby/Command/ControlCommands/RemoveLocationCommand.cs:
--------------------------------------------------------------------------------
1 | using CommandSystem;
2 | using LabApi.Features.Permissions;
3 | using LabApi.Features.Wrappers;
4 | using System;
5 |
6 | namespace Lobby.Command.ControlCommands
7 | {
8 | public class RemoveLocationCommand : ICommand
9 | {
10 | public string Command => "removeloc";
11 |
12 | public string[] Aliases { get; } = { "remloc", "rloc", "rl" };
13 |
14 | public string Description => "Remove a new lobby location.";
15 |
16 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
17 | {
18 | Player playerSender = Player.Get(sender);
19 |
20 | if (!playerSender.HasAnyPermission("lobby.*", "lobby.control.*", "lobby.control.remove"))
21 | {
22 | response = $"You don't have permission to use this command!";
23 | return false;
24 | }
25 |
26 | if (arguments.Count != 2)
27 | {
28 | response = "Incorrect command, use: \nlobby removeloc room (index)\nlobby removeloc static (index)";
29 | return false;
30 | }
31 |
32 | if (!Int32.TryParse(arguments.At(1), out int index))
33 | {
34 | response = "The index must be a number!";
35 | return false;
36 | }
37 |
38 | switch (arguments.At(0))
39 | {
40 | case "room":
41 | if (Lobby.Instance.Config.CustomRoomLocations == null || Lobby.Instance.Config.CustomRoomLocations?.Count - 1 < index)
42 | {
43 | response = $"Custom location at index {index} was not found.";
44 | return false;
45 | }
46 |
47 | Lobby.Instance.Config.CustomRoomLocations.RemoveAt(index);
48 | Lobby.Instance.SaveConfig();
49 |
50 | response = $"Custom location at index {index} has been removed.";
51 | return true;
52 | case "static":
53 | if (Lobby.Instance.Config.CustomLocations == null || Lobby.Instance.Config.CustomLocations?.Count - 1 < index)
54 | {
55 | response = $"Custom location at index {index} was not found.";
56 | return false;
57 | }
58 |
59 | Lobby.Instance.Config.CustomLocations.RemoveAt(index);
60 | Lobby.Instance.SaveConfig();
61 |
62 | response = $"Custom location at index {index} has been removed.";
63 | return true;
64 | default:
65 | response = "Incorrect command, use: \nlobby removeloc room (index)\nlobby removeloc static (index)";
66 | return false;
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Lobby/Command/ControlCommands/AddLocationCommand.cs:
--------------------------------------------------------------------------------
1 | using CommandSystem;
2 | using LabApi.Features.Permissions;
3 | using LabApi.Features.Wrappers;
4 | using System;
5 | using UnityEngine;
6 |
7 | namespace Lobby.Command.ControlCommands
8 | {
9 | public class AddLocationCommand : ICommand
10 | {
11 | public string Command => "addloc";
12 |
13 | public string[] Aliases { get; } = { "add", "ad" };
14 |
15 | public string Description => "Add a new lobby location.";
16 |
17 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
18 | {
19 | Player playerSender = Player.Get(sender);
20 |
21 | if (!playerSender.HasAnyPermission("lobby.*", "lobby.control.*", "lobby.control.add"))
22 | {
23 | response = $"You don't have permission to use this command!";
24 | return false;
25 | }
26 |
27 | if (arguments.Count != 1)
28 | {
29 | response = "Incorrect command, use: \nlobby addloc room\nlobby addloc static";
30 | return false;
31 | }
32 |
33 | switch (arguments.At(0))
34 | {
35 | case "room":
36 | GameObject Point = new GameObject("Point");
37 | Point.transform.position = playerSender.Position;
38 | Point.transform.rotation = playerSender.Rotation;
39 | Point.transform.SetParent(playerSender.Room.Transform);
40 |
41 | CustomRoomLocationData roomLocationData = new CustomRoomLocationData();
42 | roomLocationData.RoomNameType = playerSender.Room.GameObject.name;
43 | roomLocationData.OffsetX = Point.transform.localPosition.x; roomLocationData.OffsetY = Point.transform.localPosition.y + 0.05f; roomLocationData.OffsetZ = Point.transform.localPosition.z;
44 | roomLocationData.RotationX = Point.transform.localEulerAngles.x; roomLocationData.RotationY = Point.transform.localEulerAngles.y; roomLocationData.RotationZ = Point.transform.localEulerAngles.z;
45 |
46 | Lobby.Instance.Config.CustomRoomLocations.Add(roomLocationData);
47 | Lobby.Instance.SaveConfig();
48 | response = "New custom location added to the config.";
49 | return true;
50 | case "static":
51 | CustomLocationData locationData = new CustomLocationData();
52 | locationData.PositionX = playerSender.Position.x; locationData.PositionY = playerSender.Position.y + 0.05f; locationData.PositionZ = playerSender.Position.z;
53 | locationData.RotationX = playerSender.Rotation.x; locationData.RotationY = playerSender.Rotation.y; locationData.RotationZ = playerSender.Rotation.z;
54 |
55 | Lobby.Instance.Config.CustomLocations.Add(locationData);
56 | Lobby.Instance.SaveConfig();
57 | response = "New custom location added to the config.";
58 | return true;
59 | default:
60 | response = "Incorrect command, use: \nlobby addloc room\nlobby addloc static";
61 | return false;
62 | }
63 | }
64 |
65 |
66 | }
67 | }
--------------------------------------------------------------------------------
/Lobby/Command/DebugCommands/LocationListCommand.cs:
--------------------------------------------------------------------------------
1 | using CommandSystem;
2 | using LabApi.Features.Permissions;
3 | using LabApi.Features.Wrappers;
4 | using System;
5 |
6 | namespace Lobby.Command.DebugCommands
7 | {
8 | public class LocationListCommand : ICommand
9 | {
10 | public string Command => "loclist";
11 |
12 | public string[] Aliases { get; } = { "llist", "ll" };
13 |
14 | public string Description => "Display a list of custom locations in the console.";
15 |
16 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
17 | {
18 | Player playerSender = Player.Get(sender);
19 |
20 | if (!playerSender.HasAnyPermission("lobby.*", "lobby.debug.*", "lobby.debug.loclist"))
21 | {
22 | response = $"You don't have permission to use this command!";
23 | return false;
24 | }
25 |
26 | if (arguments.Count != 1)
27 | {
28 | response = "Incorrect command, use: \nlobby loclist all\nlobby loclist room\nlobby loclist static";
29 | return false;
30 | }
31 |
32 | string resString = string.Empty;
33 |
34 | switch (arguments.At(0))
35 | {
36 | case "all":
37 | resString += "Room locations:\n";
38 | if (Lobby.Instance.Config.CustomRoomLocations?.Count > 0)
39 | {
40 | foreach (var item in Lobby.Instance.Config.CustomRoomLocations)
41 | resString += item.RoomNameType + " " + $"({item.OffsetX}, {item.OffsetY}, {item.OffsetZ})\n";
42 | }
43 |
44 | resString += "\nStatic locations:\n";
45 | if (Lobby.Instance.Config.CustomLocations?.Count > 0)
46 | {
47 | foreach (var item in Lobby.Instance.Config.CustomLocations)
48 | resString += $"({item.PositionX}, {item.PositionY}, {item.PositionZ})\n";
49 | }
50 |
51 | response = resString;
52 | return true;
53 | case "room":
54 | resString += "Room locations:\n";
55 | if (Lobby.Instance.Config.CustomRoomLocations?.Count > 0)
56 | {
57 | for (int i = 0; i < Lobby.Instance.Config.CustomRoomLocations.Count; i++)
58 | {
59 | CustomRoomLocationData data = Lobby.Instance.Config.CustomRoomLocations[i];
60 | resString += $"({i}) " + data.RoomNameType + " " + $"({data.OffsetX}, {data.OffsetY}, {data.OffsetZ})\n";
61 | }
62 | }
63 |
64 | response = resString;
65 | return true;
66 | case "static":
67 | resString += "Static locations:\n";
68 | if (Lobby.Instance.Config.CustomLocations?.Count > 0)
69 | {
70 | for (int i = 0; i < Lobby.Instance.Config.CustomLocations.Count; i++)
71 | {
72 | CustomLocationData data = Lobby.Instance.Config.CustomLocations[i];
73 | resString += $"({i}) " + $"({data.PositionX}, {data.PositionY}, {data.PositionZ})\n";
74 | }
75 | }
76 |
77 | response = resString;
78 | return true;
79 | default:
80 | response = "Incorrect command, use: \nlobby loclist all\nlobby loclist room\nlobby loclist static";
81 | return false;
82 | }
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/Lobby/API/LobbyLocationHandler.cs:
--------------------------------------------------------------------------------
1 | using MapGeneration;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using UnityEngine;
6 |
7 | namespace Lobby.API
8 | {
9 | public static class LobbyLocationHandler
10 | {
11 | public static GameObject Point;
12 |
13 | public static Dictionary LocationDatas = new Dictionary()
14 | {
15 | { LobbyLocationType.Tower_1, new CustomRoomLocationData() { RoomNameType = RoomName.Outside.ToString(), OffsetX = 162.893f, OffsetY = 20f, OffsetZ = -13.430f, RotationX = 0, RotationY = 270, RotationZ = 0 } },
16 | { LobbyLocationType.Tower_2, new CustomRoomLocationData() { RoomNameType = RoomName.Outside.ToString(), OffsetX = 108.03f, OffsetY = 15f, OffsetZ = -13.71f, RotationX = 0, RotationY = 90, RotationZ = 0 } },
17 | { LobbyLocationType.Tower_3, new CustomRoomLocationData() { RoomNameType = RoomName.Outside.ToString(), OffsetX = 39.12f, OffsetY = 15f, OffsetZ = -32f, RotationX = 0, RotationY = 270, RotationZ = 0 } },
18 | { LobbyLocationType.Tower_4, new CustomRoomLocationData() { RoomNameType = RoomName.Outside.ToString(), OffsetX = -15.854f, OffsetY = 15f, OffsetZ = -31.543f, RotationX = 0, RotationY = 90, RotationZ = 0 } },
19 | { LobbyLocationType.Tower_5, new CustomRoomLocationData() { RoomNameType = RoomName.Outside.ToString(), OffsetX = 130.43f, OffsetY = -5.6f, OffsetZ = 21f, RotationX = 0, RotationY = 180, RotationZ = 0 } },
20 | { LobbyLocationType.Intercom, new CustomRoomLocationData() { RoomNameType = RoomName.EzIntercom.ToString(), OffsetX = -4.16f, OffsetY = -3.860f, OffsetZ = -2.113f, RotationX = 0, RotationY = 180, RotationZ = 0 } },
21 | { LobbyLocationType.GR18, new CustomRoomLocationData() { RoomNameType = RoomName.LczGlassroom.ToString(), OffsetX = 4.8f, OffsetY = 1f, OffsetZ = 2.3f, RotationX = 0, RotationY = 180, RotationZ = 0 } },
22 | { LobbyLocationType.SCP173, new CustomRoomLocationData() { RoomNameType = RoomName.Lcz173.ToString(), OffsetX = 17f, OffsetY = 13f, OffsetZ = 8f, RotationX = 0, RotationY = -90, RotationZ = 0 } },
23 | };
24 |
25 | public static void SetLocation(LocationData locationData)
26 | {
27 | if (locationData is CustomRoomLocationData customRoomLocation)
28 | {
29 | RoomIdentifier Room;
30 |
31 | if (Enum.TryParse(customRoomLocation.RoomNameType, out RoomName roomName))
32 | {
33 | Room = RoomIdentifier.AllRoomIdentifiers.First(x => x.Name == roomName);
34 |
35 | if (customRoomLocation.RoomNameType == RoomName.EzIntercom.ToString())
36 | EventsHandler.IsIntercom = true;
37 | }
38 | else if (RoomIdentifier.AllRoomIdentifiers.Count(x => x.name.Contains(customRoomLocation.RoomNameType)) > 0)
39 | {
40 | Room = RoomIdentifier.AllRoomIdentifiers.First(x => x.name.Contains(customRoomLocation.RoomNameType));
41 | }
42 | else
43 | {
44 | customRoomLocation = (CustomRoomLocationData)LocationDatas[LobbyLocationType.GR18];
45 | Room = RoomIdentifier.AllRoomIdentifiers.First(x => x.Name == ParseEnum(customRoomLocation.RoomNameType));
46 | }
47 |
48 | Point.transform.SetParent(Room.transform);
49 | Point.transform.localPosition = new Vector3(customRoomLocation.OffsetX, customRoomLocation.OffsetY, customRoomLocation.OffsetZ);
50 | Point.transform.localRotation = Quaternion.Euler(customRoomLocation.RotationX, customRoomLocation.RotationY, customRoomLocation.RotationZ);
51 | }
52 | else if (locationData is CustomLocationData customLocation)
53 | {
54 | Point.transform.localPosition = new Vector3(customLocation.PositionX, customLocation.PositionY, customLocation.PositionZ);
55 | Point.transform.localRotation = Quaternion.Euler(customLocation.RotationX, customLocation.RotationY, customLocation.RotationZ);
56 | }
57 | }
58 |
59 | public static T ParseEnum(string value)
60 | {
61 | return (T)Enum.Parse(typeof(T), value, true);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Lobby
2 | [](https://github.com/MrAfitol/Lobby/releases)
3 | [](https://github.com/MrAfitol/Lobby/releases)
4 |
5 |
6 | A plugin that adds a lobby when waiting for players.
7 |
8 | The idea was inspired from this [plugin](https://github.com/Michal78900/WaitAndChillReborn).
9 | ## How to download?
10 | - *1. Find the SCP SL server config folder*
11 |
12 | *("C:\Users\(user name)\AppData\Roaming\SCP Secret Laboratory\" for windows, "/home/(user name)/.config/SCP Secret Laboratory/" for Linux)*
13 |
14 | - *2. Find the "PluginAPI" folder there, it contains the "plugins" folder.*
15 |
16 | - *3. Select either the port of your server to install the same on that server or the "global" folder to install the plugin for all servers*
17 |
18 | ***Or***
19 |
20 | - *Run the command in console `p install MrAfitol/Lobby`*
21 |
22 | ## View
23 | https://user-images.githubusercontent.com/76150070/208076431-7e7a98e3-d1b3-4365-a989-a09e7fa7f639.mp4
24 |
25 |
26 | ## Config
27 | ```yml
28 | # Main text ({seconds} - Either it shows how much is left until the start, or the server status is "Server is suspended", "Round starting", - Change the next text a rainbow color, - Close a rainbow color tag)
29 | title_text: Waiting for players, {seconds}
30 | # Text showing the number of players ({players} - Text with the number of players, - Change the next text a rainbow color, - Close a rainbow color tag)
31 | player_count_text: {players}
32 | # What will be written if the lobby is locked?
33 | server_pause_text: Server is suspended
34 | # What will be written when there is a second left?
35 | second_left_text: '{seconds} second left'
36 | # What will be written when there is more than a second left?
37 | seconds_left_text: '{seconds} seconds left'
38 | # What will be written when the round starts?
39 | round_start_text: Round starting
40 | # What will be written when there is only one player on the server?
41 | player_join_text: player joined
42 | # What will be written when there is more than one player on the server?
43 | players_join_text: players joined
44 | # Vertical text position.
45 | vertical_pos: 25
46 | # Top text size
47 | top_text_size: 50
48 | # Bottom text size
49 | bottom_text_size: 40
50 | # Top text size in intercom
51 | top_text_icom_size: 150
52 | # Bottom text size in intercom
53 | bottom_text_icom_size: 140
54 | # Enable the movement boost effect?
55 | enable_movement_boost: true
56 | # What is the movement boost intensity? (Max 255)
57 | movement_boost_intensity: 50
58 | # Will infinity stamina be enabled for people in the lobby?
59 | infinity_stamina: true
60 | # What role will people play in the lobby?
61 | lobby_player_role: Tutorial
62 | # Allow people to talk over the intercom?
63 | allow_icom: true
64 | # Display text on Intercom? (Works only when lobby Intercom type)
65 | display_in_icom: true
66 | # What size will the text be in the Intercom? (The larger the value, the smaller it will be)
67 | icom_text_size: 20
68 | # What items will be given when spawning a player in the lobby? (Leave blank to keep inventory empty)
69 | lobby_inventory:
70 | - Coin
71 | # In what locations can people spawn? (If this parameter is empty, one of the custom locations (or custom room locations) will be selected)
72 | lobby_location:
73 | - Tower_1
74 | - Tower_2
75 | - Tower_3
76 | - Tower_4
77 | - Tower_5
78 | - Intercom
79 | - GR18
80 | - SCP173
81 | # This option is for a custom lobby location
82 | custom_room_locations:
83 | - room_name_type: EzGateA
84 | offset_x: 0
85 | offset_y: 1
86 | offset_z: 0
87 | rotation_x: 0
88 | rotation_y: 0
89 | rotation_z: 0
90 | # This option is for a custom lobby location
91 | custom_locations:
92 | - position_x: 39.262001
93 | position_y: 1014.112
94 | position_z: -31.8439999
95 | rotation_x: 0
96 | rotation_y: 0
97 | rotation_z: 0
98 | # The name of the role that can use commands for Lobby.
99 | allowed_rank:
100 | - owner
101 | # User ID that can use commands for the Lobby.
102 | allowed_user_i_d:
103 | - SomeOtherSteamId64@steam
104 | ```
105 |
106 | ## Wiki
107 | **Be sure to check out the [Wiki](https://github.com/MrAfitol/Lobby/wiki)**
108 |
--------------------------------------------------------------------------------
/Lobby/Command/DebugCommands/TpLocationCommand.cs:
--------------------------------------------------------------------------------
1 | using CommandSystem;
2 | using LabApi.Features.Permissions;
3 | using LabApi.Features.Wrappers;
4 | using MapGeneration;
5 | using System;
6 | using System.Linq;
7 | using UnityEngine;
8 |
9 | namespace Lobby.Command.DebugCommands
10 | {
11 | public class TpLocationCommand : ICommand
12 | {
13 | public string Command => "tploc";
14 |
15 | public string[] Aliases { get; } = { "tpl", "tl" };
16 |
17 | public string Description => "Teleport to a custom location.";
18 |
19 | public bool Execute(ArraySegment arguments, ICommandSender sender, out string response)
20 | {
21 | Player playerSender = Player.Get(sender);
22 |
23 | if (!playerSender.HasAnyPermission("lobby.*", "lobby.debug.*", "lobby.debug.tp"))
24 | {
25 | response = $"You don't have permission to use this command!";
26 | return false;
27 | }
28 |
29 | if (arguments.Count != 2)
30 | {
31 | response = "Incorrect command, use: \nlobby tploc room (index)\nlobby tploc static (index)";
32 | return false;
33 | }
34 |
35 | if (!Int32.TryParse(arguments.At(1), out int index))
36 | {
37 | response = "The index must be a number";
38 | return false;
39 | }
40 |
41 | GameObject Point = new GameObject("Point");
42 |
43 | switch (arguments.At(0))
44 | {
45 | case "room":
46 | if (Lobby.Instance.Config.CustomRoomLocations == null || Lobby.Instance.Config.CustomRoomLocations?.Count - 1 < index)
47 | {
48 | response = $"Custom location at index {index} was not found.";
49 | return false;
50 | }
51 |
52 | if (Enum.TryParse(Lobby.Instance.Config.CustomRoomLocations[index].RoomNameType, out RoomName roomName))
53 | Point.transform.SetParent(RoomIdentifier.AllRoomIdentifiers.First(x => x.Name == roomName).transform);
54 | else if (RoomIdentifier.AllRoomIdentifiers.Count(x => x.name.Contains(Lobby.Instance.Config.CustomRoomLocations[index].RoomNameType)) > 0)
55 | Point.transform.SetParent(RoomIdentifier.AllRoomIdentifiers.First(x => x.name.Contains(Lobby.Instance.Config.CustomRoomLocations[index].RoomNameType)).transform);
56 |
57 | Point.transform.localPosition = new Vector3(Lobby.Instance.Config.CustomRoomLocations[index].OffsetX, Lobby.Instance.Config.CustomRoomLocations[index].OffsetY, Lobby.Instance.Config.CustomRoomLocations[index].OffsetZ);
58 | Point.transform.localEulerAngles = new Vector3(Lobby.Instance.Config.CustomRoomLocations[index].RotationX, Lobby.Instance.Config.CustomRoomLocations[index].RotationY, Lobby.Instance.Config.CustomRoomLocations[index].RotationZ);
59 |
60 | playerSender.Position = Point.transform.position;
61 | playerSender.Rotation = Point.transform.rotation;
62 |
63 | GameObject.Destroy(Point);
64 |
65 | response = $"You have successfully teleported to a custom location at index {index}.";
66 | return true;
67 | case "static":
68 | if (Lobby.Instance.Config.CustomLocations == null || Lobby.Instance.Config.CustomLocations?.Count - 1 < index)
69 | {
70 | response = $"Custom location at index {index} was not found.";
71 | return false;
72 | }
73 |
74 | playerSender.Position = new Vector3(Lobby.Instance.Config.CustomLocations[index].PositionX, Lobby.Instance.Config.CustomLocations[index].PositionY, Lobby.Instance.Config.CustomLocations[index].PositionZ);
75 | playerSender.Rotation = Quaternion.Euler(Lobby.Instance.Config.CustomLocations[index].RotationX, Lobby.Instance.Config.CustomLocations[index].RotationY, Lobby.Instance.Config.CustomLocations[index].RotationZ);
76 |
77 | response = $"You have successfully teleported to a custom location at index {index}.";
78 | return true;
79 | default:
80 | response = "Incorrect command, use: \nlobby tploc room (index)\nlobby tploc static (index)";
81 | return false;
82 | }
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/Lobby/Lobby.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F6FFBCFD-6FDB-4185-AB54-20AB167DCA57}
8 | Library
9 | Properties
10 | Lobby
11 | Lobby
12 | v4.8
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | true
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\Lib.Harmony.2.3.3\lib\net48\0Harmony.dll
37 |
38 |
39 | False
40 | $(SCP_Dependencies)\Assembly-CSharp-firstpass.dll
41 |
42 |
43 | False
44 | $(SCP_Dependencies)\Assembly-CSharp-Publicized.dll
45 |
46 |
47 | False
48 | $(SCP_Dependencies)\CommandSystem.Core.dll
49 |
50 |
51 | ..\packages\Northwood.LabAPI.1.0.2\lib\net48\LabApi.dll
52 |
53 |
54 | False
55 | $(SCP_Dependencies)\Mirror.dll
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | False
66 | $(SCP_Dependencies)\UnityEngine.dll
67 |
68 |
69 | False
70 | $(SCP_Dependencies)\UnityEngine.CoreModule.dll
71 |
72 |
73 | $(SCP_Dependencies)\UnityEngine.PhysicsModule.dll
74 |
75 |
76 | ..\packages\YamlDotNet.11.0.1\lib\net45\YamlDotNet.dll
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/Lobby/Config.cs:
--------------------------------------------------------------------------------
1 | using MapGeneration;
2 | using PlayerRoles;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 |
6 | namespace Lobby
7 | {
8 | public class Config
9 | {
10 | [Description("Main text ({seconds} - Either it shows how much is left until the start, or the server status is \"Server is suspended\", \"Round starting\", - Change the next text a rainbow color, - Close a rainbow color tag)")]
11 | public string TitleText { get; set; } = "Waiting for players, {seconds}";
12 |
13 | [Description("Text showing the number of players ({players} - Text with the number of players, - Change the next text a rainbow color, - Close a rainbow color tag)")]
14 | public string PlayerCountText { get; set; } = "{players}";
15 |
16 | [Description("What will be written if the lobby is locked?")]
17 | public string ServerPauseText { get; set; } = "Server is suspended";
18 |
19 | [Description("What will be written when there is a second left?")]
20 | public string SecondLeftText { get; set; } = "{seconds} second left";
21 |
22 | [Description("What will be written when there is more than a second left?")]
23 | public string SecondsLeftText { get; set; } = "{seconds} seconds left";
24 |
25 | [Description("What will be written when the round starts?")]
26 | public string RoundStartText { get; set; } = "Round starting";
27 |
28 | [Description("What will be written when there is only one player on the server?")]
29 | public string PlayerJoinText { get; set; } = "player joined";
30 |
31 | [Description("What will be written when there is more than one player on the server?")]
32 | public string PlayersJoinText { get; set; } = "players joined";
33 |
34 | [Description("Vertical text position.")]
35 | public int VerticalPos { get; set; } = 25;
36 |
37 | [Description("Top text size")]
38 | public int TopTextSize { get; set; } = 50;
39 |
40 | [Description("Bottom text size")]
41 | public int BottomTextSize { get; set; } = 40;
42 |
43 | [Description("Top text size in intercom")]
44 | public int TopTextIcomSize { get; set; } = 150;
45 |
46 | [Description("Bottom text size in intercom")]
47 | public int BottomTextIcomSize { get; set; } = 140;
48 |
49 | [Description("Enable the movement boost effect?")]
50 | public bool EnableMovementBoost { get; set; } = true;
51 |
52 | [Description("What is the movement boost intensity? (Max 255)")]
53 | public byte MovementBoostIntensity { get; set; } = 50;
54 |
55 | [Description("Will infinity stamina be enabled for people in the lobby?")]
56 | public bool InfinityStamina { get; set; } = true;
57 |
58 | [Description("What role will people play in the lobby?")]
59 | public RoleTypeId LobbyPlayerRole { get; set; } = RoleTypeId.Tutorial;
60 |
61 | [Description("Allow people to talk over the intercom?")]
62 | public bool AllowIcom { get; set; } = true;
63 |
64 | [Description("Display text on Intercom? (Works only when lobby Intercom type)")]
65 | public bool DisplayInIcom { get; set; } = true;
66 |
67 | [Description("What size will the text be in the Intercom? (The larger the value, the smaller it will be)")]
68 | public int IcomTextSize { get; set; } = 20;
69 |
70 | [Description("What items will be given when spawning a player in the lobby? (Leave blank to keep inventory empty)")]
71 | public List LobbyInventory { get; set; } = new List()
72 | {
73 | ItemType.Coin
74 | };
75 |
76 | [Description("In what locations can people spawn? (If this parameter is empty, one of the custom locations (or custom room locations) will be selected)")]
77 | public List LobbyLocation { get; set; } = new List()
78 | {
79 | LobbyLocationType.Tower_1,
80 | LobbyLocationType.Tower_2,
81 | LobbyLocationType.Tower_3,
82 | LobbyLocationType.Tower_4,
83 | LobbyLocationType.Tower_5,
84 | LobbyLocationType.Intercom,
85 | LobbyLocationType.GR18,
86 | LobbyLocationType.SCP173
87 | };
88 |
89 | [Description("This option is for a custom lobby location")]
90 | public List CustomRoomLocations { get; set; } = new List()
91 | {
92 | new CustomRoomLocationData()
93 | {
94 | RoomNameType = RoomName.EzGateA.ToString(),
95 | OffsetX = 0,
96 | OffsetY = 1,
97 | OffsetZ = 0,
98 | RotationX = 0,
99 | RotationY = 0,
100 | RotationZ = 0,
101 | },
102 | };
103 |
104 | [Description("This option is for a custom lobby location")]
105 | public List CustomLocations { get; set; } = new List()
106 | {
107 | new CustomLocationData()
108 | {
109 | PositionX = 39.262f,
110 | PositionY = 315f,
111 | PositionZ = -31.844f,
112 | RotationX = 0,
113 | RotationY = 0,
114 | RotationZ = 0,
115 | },
116 | };
117 | }
118 |
119 | public class LocationData
120 | {
121 | }
122 |
123 | public class CustomRoomLocationData : LocationData
124 | {
125 | public string RoomNameType { get; set; }
126 | public float OffsetX { get; set; }
127 | public float OffsetY { get; set; }
128 | public float OffsetZ { get; set; }
129 | public float RotationX { get; set; }
130 | public float RotationY { get; set; }
131 | public float RotationZ { get; set; }
132 | }
133 |
134 | public class CustomLocationData : LocationData
135 | {
136 | public float PositionX { get; set; }
137 | public float PositionY { get; set; }
138 | public float PositionZ { get; set; }
139 | public float RotationX { get; set; }
140 | public float RotationY { get; set; }
141 | public float RotationZ { get; set; }
142 | }
143 | }
--------------------------------------------------------------------------------
/Lobby/EventsHandler.cs:
--------------------------------------------------------------------------------
1 | using CentralAuth;
2 | using CustomPlayerEffects;
3 | using LabApi.Events.Arguments.PlayerEvents;
4 | using LabApi.Events.Handlers;
5 | using LabApi.Features.Wrappers;
6 | using Lobby.API;
7 | using MEC;
8 | using PlayerRoles;
9 | using PlayerRoles.Voice;
10 | using System;
11 | using System.Collections.Generic;
12 | using System.Linq;
13 | using UnityEngine;
14 | using Logger = LabApi.Features.Console.Logger;
15 | using Random = UnityEngine.Random;
16 |
17 | namespace Lobby
18 | {
19 | public class EventsHandler
20 | {
21 | public static bool IsIntercom { get; set; } = false;
22 | public static bool IsLobby { get; set; } = true;
23 |
24 | private CoroutineHandle lobbyTimer, rainbowColor;
25 | private int r = 255, g = 0, b = 0;
26 | private string text;
27 |
28 | #region Events
29 |
30 | public void OnWaitingForPlayers()
31 | {
32 | try
33 | {
34 | LobbyLocationHandler.Point = new GameObject("LobbyPoint");
35 | IsLobby = true;
36 | IsIntercom = false;
37 | Lobby.Instance.Harmony.PatchAll();
38 | RegisterHandlers();
39 | SpawnManager();
40 |
41 | Timing.CallDelayed(0.1f, () =>
42 | {
43 | GameObject.Find("StartRound").transform.localScale = Vector3.zero;
44 |
45 | if (lobbyTimer.IsRunning)
46 | Timing.KillCoroutines(lobbyTimer);
47 | if (rainbowColor.IsRunning)
48 | Timing.KillCoroutines(rainbowColor);
49 |
50 | if (Lobby.Instance.Config.TitleText.Contains("") || Lobby.Instance.Config.PlayerCountText.Contains(""))
51 | rainbowColor = Timing.RunCoroutine(RainbowColor());
52 |
53 | lobbyTimer = Timing.RunCoroutine(LobbyTimer());
54 | });
55 | }
56 | catch (Exception e)
57 | {
58 | Logger.Error("[Event: OnWaitingForPlayers] " + e.ToString());
59 | }
60 | }
61 |
62 | public void OnPlayerJoined(PlayerJoinedEventArgs ev)
63 | {
64 | try
65 | {
66 | if (IsLobby && (GameCore.RoundStart.singleton.NetworkTimer > 1 || GameCore.RoundStart.singleton.NetworkTimer == -2))
67 | {
68 | Timing.CallDelayed(1f, () =>
69 | {
70 | if (!ev.Player.IsOverwatchEnabled)
71 | {
72 | ev.Player.SetRole(Lobby.Instance.Config.LobbyPlayerRole);
73 |
74 | ev.Player.IsGodModeEnabled = true;
75 |
76 | if (Lobby.Instance.Config.LobbyInventory.Count > 0)
77 | {
78 | foreach (var item in Lobby.Instance.Config.LobbyInventory)
79 | {
80 | ev.Player.AddItem(item);
81 | }
82 | }
83 |
84 | Timing.CallDelayed(0.1f, () =>
85 | {
86 | ev.Player.Position = LobbyLocationHandler.Point.transform.position;
87 | ev.Player.Rotation = LobbyLocationHandler.Point.transform.rotation;
88 |
89 | if (Lobby.Instance.Config.EnableMovementBoost)
90 | {
91 | ev.Player.EnableEffect(Lobby.Instance.Config.MovementBoostIntensity);
92 | }
93 | });
94 | }
95 | });
96 | }
97 | }
98 | catch (Exception e)
99 | {
100 | Logger.Error("[Event: OnPlayerJoined] " + e.ToString());
101 | }
102 | }
103 |
104 | public void OnRoundStarted()
105 | {
106 | try
107 | {
108 | UnregisterHandlers();
109 | IsLobby = false;
110 |
111 | if (!string.IsNullOrEmpty(IntercomDisplay._singleton.Network_overrideText)) IntercomDisplay._singleton.Network_overrideText = "";
112 |
113 | foreach (var player in Player.List.Where(x => x.Role != RoleTypeId.Overwatch))
114 | {
115 | player.SetRole(RoleTypeId.Spectator);
116 |
117 | Timing.CallDelayed(0.1f, () =>
118 | {
119 | player.IsGodModeEnabled = false;
120 | if (Lobby.Instance.Config.EnableMovementBoost) player.DisableEffect();
121 | });
122 | }
123 |
124 | Timing.CallDelayed(1f, () =>
125 | {
126 | if (lobbyTimer.IsRunning)
127 | Timing.KillCoroutines(lobbyTimer);
128 | if (rainbowColor.IsRunning)
129 | Timing.KillCoroutines(rainbowColor);
130 | });
131 |
132 | Lobby.Instance.Harmony.UnpatchAll("lobby.scp.sl");
133 | }
134 | catch (Exception e)
135 | {
136 | Logger.Error("[Event: OnRoundStarted] " + e.ToString());
137 | }
138 | }
139 |
140 | #endregion
141 |
142 | #region Methods
143 |
144 | public void RegisterHandlers()
145 | {
146 | try
147 | {
148 | PlayerEvents.InteractingDoor += Lobby.Instance.RestrictionsHandler.OnPlayerInteractingDoor;
149 | PlayerEvents.InteractingElevator += Lobby.Instance.RestrictionsHandler.OnPlayerInteractingElevator;
150 | PlayerEvents.SearchingPickup += Lobby.Instance.RestrictionsHandler.OnPlayerSearchingPickup;
151 | PlayerEvents.DroppingItem += Lobby.Instance.RestrictionsHandler.OnPlayerDroppingItem;
152 | PlayerEvents.DroppingAmmo += Lobby.Instance.RestrictionsHandler.OnPlayerDroppingAmmo;
153 | PlayerEvents.ThrowingItem += Lobby.Instance.RestrictionsHandler.OnPlayerThrowingItem;
154 | PlayerEvents.UsingIntercom += Lobby.Instance.RestrictionsHandler.OnPlayerUsingIntercom;
155 | PlayerEvents.Joined += OnPlayerJoined;
156 | }
157 | catch (Exception e)
158 | {
159 | Logger.Error("[Lobby] [Method: RegisterHandlers] " + e.ToString());
160 | }
161 | }
162 |
163 | public void UnregisterHandlers()
164 | {
165 | try
166 | {
167 | PlayerEvents.InteractingDoor -= Lobby.Instance.RestrictionsHandler.OnPlayerInteractingDoor;
168 | PlayerEvents.InteractingElevator -= Lobby.Instance.RestrictionsHandler.OnPlayerInteractingElevator;
169 | PlayerEvents.SearchingPickup -= Lobby.Instance.RestrictionsHandler.OnPlayerSearchingPickup;
170 | PlayerEvents.DroppingItem -= Lobby.Instance.RestrictionsHandler.OnPlayerDroppingItem;
171 | PlayerEvents.DroppingAmmo -= Lobby.Instance.RestrictionsHandler.OnPlayerDroppingAmmo;
172 | PlayerEvents.ThrowingItem -= Lobby.Instance.RestrictionsHandler.OnPlayerThrowingItem;
173 | PlayerEvents.UsingIntercom -= Lobby.Instance.RestrictionsHandler.OnPlayerUsingIntercom;
174 | PlayerEvents.Joined -= OnPlayerJoined;
175 | }
176 | catch (Exception e)
177 | {
178 | Logger.Error("[Lobby] [Method: UnregisterHandlers] " + e.ToString());
179 | }
180 | }
181 |
182 | private void SpawnManager()
183 | {
184 | try
185 | {
186 | List locationList = new List();
187 |
188 | if (Lobby.Instance.Config.LobbyLocation?.Count > 0)
189 | locationList.AddRange(Lobby.Instance.Config.LobbyLocation
190 | .Where(x => LobbyLocationHandler.LocationDatas.ContainsKey(x))
191 | .Select(x => LobbyLocationHandler.LocationDatas[x]));
192 |
193 | if (Lobby.Instance.Config.CustomLocations?.Count > 0)
194 | locationList.AddRange(Lobby.Instance.Config.CustomLocations);
195 |
196 | if (Lobby.Instance.Config.CustomRoomLocations?.Count > 0)
197 | locationList.AddRange(Lobby.Instance.Config.CustomRoomLocations);
198 |
199 | if (locationList.Count <= 0)
200 | locationList.Add(LobbyLocationHandler.LocationDatas.ElementAt(Random.Range(0, LobbyLocationHandler.LocationDatas.Count - 1)).Value);
201 | LobbyLocationHandler.SetLocation(locationList.RandomItem());
202 | }
203 | catch (Exception e)
204 | {
205 | Logger.Error("[Lobby] [Method: SpawnManager] " + e.ToString());
206 | }
207 | }
208 |
209 | private IEnumerator RainbowColor()
210 | {
211 | r = 255; g = 0; b = 0;
212 |
213 | while (!Round.IsRoundStarted)
214 | {
215 | if (r > 0 && b == 0)
216 | {
217 | r -= 2;
218 | g += 2;
219 | }
220 |
221 | if (g > 0 && r == 0)
222 | {
223 | g -= 2;
224 | b += 2;
225 | }
226 |
227 | if (b > 0 && g == 0)
228 | {
229 | b -= 2;
230 | r += 2;
231 | }
232 |
233 | r = Mathf.Clamp(r, 0, 255);
234 | g = Mathf.Clamp(g, 0, 255);
235 | b = Mathf.Clamp(b, 0, 255);
236 |
237 | yield return Timing.WaitForSeconds(0.4f);
238 | }
239 | }
240 |
241 | private IEnumerator LobbyTimer()
242 | {
243 | while (!Round.IsRoundStarted)
244 | {
245 | text = string.Empty;
246 |
247 | if (Lobby.Instance.Config.VerticalPos < 0)
248 | for (int i = 0; i < ~Lobby.Instance.Config.VerticalPos; i++)
249 | text += "\n";
250 |
251 | text += $"" + Lobby.Instance.Config.TitleText + "";
252 |
253 | text += "\n" + $"" + Lobby.Instance.Config.PlayerCountText + "";
254 |
255 | short NetworkTimer = GameCore.RoundStart.singleton.NetworkTimer;
256 |
257 | switch (NetworkTimer)
258 | {
259 | case -2: text = text.Replace("{seconds}", Lobby.Instance.Config.ServerPauseText); break;
260 | case -1: text = text.Replace("{seconds}", Lobby.Instance.Config.RoundStartText); break;
261 | case 1: text = text.Replace("{seconds}", Lobby.Instance.Config.SecondLeftText.Replace("{seconds}", NetworkTimer.ToString())); break;
262 | case 0: text = text.Replace("{seconds}", Lobby.Instance.Config.RoundStartText); break;
263 | default: text = text.Replace("{seconds}", Lobby.Instance.Config.SecondsLeftText.Replace("{seconds}", NetworkTimer.ToString())); break;
264 | }
265 |
266 | if (Player.Count == 1)
267 | text = text.Replace("{players}", $"{Player.Count} " + Lobby.Instance.Config.PlayerJoinText);
268 | else
269 | text = text.Replace("{players}", $"{Player.Count} " + Lobby.Instance.Config.PlayersJoinText);
270 |
271 | string hex = $"{r:X2}{g:X2}{b:X2}";
272 | text = text.Replace("", $"");
273 | text = text.Replace("", "");
274 |
275 | if (Lobby.Instance.Config.VerticalPos >= 0)
276 | for (int i = 0; i < Lobby.Instance.Config.VerticalPos; i++)
277 | text += "\n";
278 |
279 | if (!IsIntercom || !Lobby.Instance.Config.DisplayInIcom)
280 | {
281 | foreach (Player ply in Player.List)
282 | if (ply.ReferenceHub.Mode != ClientInstanceMode.Unverified && ply.ReferenceHub.Mode != ClientInstanceMode.DedicatedServer && ply != null)
283 | ply.SendHint(text, 1.05f);
284 | }
285 | else IntercomDisplay._singleton.Network_overrideText = $"" + text + "";
286 |
287 | yield return Timing.WaitForSeconds(1f);
288 | }
289 | }
290 |
291 | #endregion
292 | }
293 | }
294 |
--------------------------------------------------------------------------------