using LabApi.Events.Arguments.PlayerEvents; using LabApi.Features.Wrappers; using MapGeneration; using Mirror; using PlayerRoles; using Respawning; using UnityEngine; using MicroHIDItem = InventorySystem.Items.MicroHID.MicroHIDItem; using Random = UnityEngine.Random; namespace GamblingCoin; public class GamblingCoinEventHandler { private readonly WeightedRandomExecutor _executor; public GamblingCoinEventHandler() { var configMessages = Plugin.Singleton.ConfigMessages; var configGameplay = Plugin.Singleton.ConfigGameplay; var configChances = Plugin.Singleton.ConfigChances; _executor = new WeightedRandomExecutor(); _executor .AddAction(_ => { Warhead.DetonationTime += configGameplay.WarheadTimeIncrease; Warhead.Start(suppressSubtitles: true); }, configChances.NukeChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.SpawnWaveMessage, configGameplay.BroadcastDuration); if (GetPlayers().Any(player => player.Role == RoleTypeId.Spectator)) WaveManager.InitiateRespawn(WaveManager.Waves[Random.Range(0, WaveManager.Waves.Count)]); }, configChances.SpawnWaveChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.ItemSpawnMessage, configGameplay.BroadcastDuration); SpawnRandomItemAtPlayer(x.Player, configGameplay.Items.CommonItems); }, configChances.CommonItemChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.UncommonItemSpawnMessage, configGameplay.BroadcastDuration); SpawnRandomItemAtPlayer(x.Player, configGameplay.Items.UncommonItems); }, configChances.UncommonItemChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.RareItemSpawnMessage, configGameplay.BroadcastDuration); SpawnRandomItemAtPlayer(x.Player, configGameplay.Items.RareItems); }, configChances.RareItemChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.EpicItemSpawnMessage, configGameplay.BroadcastDuration); SpawnRandomItemAtPlayer(x.Player, configGameplay.Items.EpicItems); }, configChances.EpicItemChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.LegendaryItemSpawnMessage, configGameplay.BroadcastDuration); var player = x.Player; var items = configGameplay.Items.LegendaryItems; var itemIndex = Random.Range(0, items.Length); var item = items[itemIndex]; var pickup = Pickup.Create(item, player.Position + new Vector3(0, 1, 0)); if (pickup == null) return; if (item is ItemType.MicroHID) { var host = Player.List.First(player1 => player1.IsHost); var micro = host.AddItem(pickup)!.Base; var microItem = (MicroHIDItem)micro; microItem.EnergyManager.ServerSetEnergy(microItem.ItemId.SerialNumber, 100); var newPickup = host.DropItem(micro); newPickup.Position = player.Position + new Vector3(0, 1, 0); return; } pickup.Spawn(); }, configChances.LegendaryItemChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.RandomTeleportMessage, configGameplay.BroadcastDuration); var randomRoom = Map.GetRandomRoom(); if (randomRoom == null) return; var isInOtherZone = randomRoom is { Zone: FacilityZone.Other }; var isDetonated = Warhead.IsDetonated; var isDecontaminating = Decontamination.IsDecontaminating; var isInDetonatedZone = isDetonated && randomRoom.Zone is FacilityZone.HeavyContainment or FacilityZone.LightContainment or FacilityZone.Entrance; var isInDecontaminatedZone = isDecontaminating && randomRoom.Zone is FacilityZone.LightContainment; while (isInOtherZone || isInDetonatedZone || isInDecontaminatedZone) { randomRoom = Map.GetRandomRoom(); if (randomRoom == null) return; isInOtherZone = randomRoom is { Zone: FacilityZone.Other }; isInDetonatedZone = isDetonated && randomRoom.Zone is FacilityZone.HeavyContainment or FacilityZone.LightContainment or FacilityZone.Entrance; isInDecontaminatedZone = isDecontaminating && randomRoom.Zone is FacilityZone.LightContainment; } var newPos = randomRoom.Position; x.Player.Position = newPos + new Vector3(0, configGameplay.TeleportHeightOffset, 0); ; }, configChances.RandomTeleportChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.StealItemMessage, configGameplay.BroadcastDuration); if (x.Player.CurrentItem != null) x.Player.DropItem(x.Player.CurrentItem); }, configChances.StealItemChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.ExplosionMessage, configGameplay.BroadcastDuration); x.Player.ClearInventory(); TimedGrenadeProjectile.SpawnActive(x.Player.Position, ItemType.GrenadeHE, x.Player); }, configChances.ExplosionChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.AntiMicroMessage, configGameplay.BroadcastDuration); GetPlayers().ForEach(p => { p.RemoveItem(ItemType.MicroHID, configGameplay.MaxMicrosToRemove); }); //TODO: remove *all* micros }, configChances.AntiMicroChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.GrenadeMessage, configGameplay.BroadcastDuration); TimedGrenadeProjectile.SpawnActive(x.Player.Position, ItemType.GrenadeHE, x.Player, 2); }, configChances.GrenadeChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.PocketDimensionMessage, configGameplay.BroadcastDuration); PocketDimension.ForceInside(x.Player); }, configChances.PocketDimensionChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.AdvancedPositiveEffectMessage, configGameplay.BroadcastDuration); ApplyRandomEffect(x.Player, configGameplay.Effects.AdvancedPositive); }, configChances.AdvancedPositiveEffectChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.PositiveEffectMessage, configGameplay.BroadcastDuration); ApplyRandomEffect(x.Player, configGameplay.Effects.Positive); }, configChances.PositiveEffectChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.NegativeEffectMessage, configGameplay.BroadcastDuration); ApplyRandomEffect(x.Player, configGameplay.Effects.Negative); }, configChances.NegativeEffectChance) .AddAction(x => { x.Player.SendBroadcast(configMessages.AdvancedNegativeEffectMessage, configGameplay.BroadcastDuration); ApplyRandomEffect(x.Player, configGameplay.Effects.AdvancedNegative); }, configChances.AdvancedNegativeEffectChance) .AddAction(x => { var players = GetPlayers(); var randomPlayer = players[Random.Range(0, GetPlayers().Length)]; while (randomPlayer.RoleBase.Team is Team.Dead or Team.SCPs) randomPlayer = players[Random.Range(0, GetPlayers().Length)]; x.Player.SendBroadcast(configMessages.SwitchInventoryMessage, configGameplay.BroadcastDuration); randomPlayer.SendBroadcast(configMessages.SwitchInventoryMessage, configGameplay.BroadcastDuration); var randomPlayerItems = new List(); randomPlayer.Items.CopyTo(randomPlayerItems); var items = x.Player.Items; randomPlayer.ClearInventory(); foreach (var itemBase in items) randomPlayer.AddItem(itemBase.Type); x.Player.ClearInventory(); foreach (var randomPlayerItem in randomPlayerItems) x.Player.AddItem(randomPlayerItem.Type); }, configChances.SwitchInventoryChance) .AddAction(x => { x.Player.CurrentItem?.DropItem().Destroy(); }, configChances.RemoveCoinChance) .AddAction(x => { var spectators = Player.List.Where(player => player.Role == RoleTypeId.Spectator).ToArray(); var spectator = spectators[Random.Range(0, spectators.Length)]; spectator.SendBroadcast(configMessages.SpawnZombieMessage, configGameplay.BroadcastDuration); spectator.SetRole(RoleTypeId.Scp0492); var spawnRoom = Map.Rooms.First(room => room.Name == RoomName.HczWarhead); if (Warhead.IsDetonated) { spawnRoom = Map.Rooms.First(room => room.Name == RoomName.Outside); } spectator.Position = spawnRoom.Position + new Vector3(0, 1, 0); }, configChances.SpawnZombieChance); return; void ApplyRandomEffect(Player player, AdvancedEffectSettings settings) { var effectChosen = settings.Effects[Random.Range(0, settings.Effects.Length)]; var effectSettings = settings.Settings[effectChosen]; player.ReferenceHub.playerEffectsController.ChangeState(effectChosen, effectSettings.Intensity, effectSettings.Duration, effectSettings.AddDuration); } void SpawnItemAtPlayer(Player player, ItemType item) { var pickup = Pickup.Create(item, player.Position + new Vector3(0, 1, 0)); if (pickup == null) return; pickup.Spawn(); } void SpawnRandomItemAtPlayer(Player player, ItemType[] items) { var itemIndex = Random.Range(0, items.Length); SpawnItemAtPlayer(player, items[itemIndex]); } Player[] GetPlayers() { return Player.ReadyList.ToArray(); } } public void OnFlippedCoin(PlayerFlippedCoinEventArgs ev) { _executor.Execute(ev); } }