SecretPluginLaboratories/CustomClasses/SerpentsHandManager.cs
2025-07-03 22:05:38 +02:00

277 lines
9.3 KiB
C#

using CommandSystem;
using CustomPlayerEffects;
using HintServiceMeow.Core.Enum;
using HintServiceMeow.Core.Models.Hints;
using HintServiceMeow.Core.Utilities;
using Interactables.Interobjects.DoorUtils;
using InventorySystem.Items.Firearms.Modules;
using LabApi.Events.Handlers;
using LabApi.Features.Permissions;
using LabApi.Features.Wrappers;
using MEC;
using PlayerRoles;
using UnityEngine;
using Logger = LabApi.Features.Console.Logger;
using Random = System.Random;
namespace CustomClasses;
public class SerpentsHandManager
{
public static bool IsSerpentsHand(Player player) => player.CustomInfo.Contains("SerpentsHand");
private readonly CustomClasses _customClasses;
public SerpentsHandManager(CustomClasses customClasses)
{
_customClasses = customClasses;
PlayerEvents.Escaping += ev =>
{
if (!IsSerpentsHand(ev.Player)) return;
var state = (SerpentsHandState) _customClasses.ClassManager.GetSpawnState(typeof(SerpentsHandConfig));
var hadItem = false;
foreach (var playerItem in ev.Player.Items)
{
switch (playerItem.Type)
{
case ItemType.SCP018 or ItemType.SCP207 or ItemType.SCP244a or ItemType.SCP244b
or ItemType.SCP268 or ItemType.SCP330 or ItemType.SCP500 or ItemType.SCP1344 or ItemType.SCP1576
or ItemType.SCP1853 or ItemType.SCP2176 or ItemType.AntiSCP207:
state.Points += 1;
hadItem = true;
break;
case ItemType.GunSCP127:
state.Points += 2;
hadItem = true;
break;
}
}
if (!hadItem) return;
ev.Player.SendBroadcast("You brought back the SCP items...", 5);
ev.Player.SetRole(RoleTypeId.Spectator);
Logger.Info($"New SH Points: {state.Points}");
};
ServerEvents.RoundEnding += ev =>
{
var factions =
Player.ReadyList.Select(x =>
{
return x.Team switch
{
Team.ChaosInsurgency or Team.ClassD => Faction.FoundationEnemy,
Team.FoundationForces or Team.Scientists => Faction.FoundationStaff,
Team.Flamingos => Faction.Flamingos,
Team.SCPs => Faction.SCP,
Team.OtherAlive when IsSerpentsHand(x) => (Faction)35,
_ => Faction.Unclassified
};
}).Where(x=>x!=Faction.Unclassified).GroupBy(x=>x).Select(x=>x.Key).ToArray();
if (factions.Length > 1)
{
ev.IsAllowed = false;
return;
}
var state = (SerpentsHandState) _customClasses.ClassManager.GetSpawnState(typeof(SerpentsHandConfig));
if (state.Points >= 10)
{
ev.LeadingTeam = RoundSummary.LeadingTeam.Flamingos;
}
};
}
public static void PreSpawn(Player player)
{
player.SetRole(RoleTypeId.Tutorial, RoleChangeReason.RespawnMiniwave, RoleSpawnFlags.None);
const string customInfo = "<color=#32CD32>SerpentsHand</color>";
if (!Player.ValidateCustomInfo(customInfo, out var reason))
{
Logger.Error($"Invalid custom info for Serpents Hand: {reason}");
}
else
{
player.CustomInfo = customInfo;
player.InfoArea |= PlayerInfoArea.CustomInfo;
}
}
public IEnumerator<float> UpdateSerpentsHandHint()
{
while (true)
{
yield return Timing.WaitForSeconds(1);
if (_customClasses.ClassManager.GetSpawnState(typeof(SerpentsHandConfig)) is not SerpentsHandState state) continue;
foreach (var player in Player.ReadyList)
{
if (!_customClasses.Hints.ContainsKey(player))
{
_customClasses.Hints[player] = new Hint
{
Text = "", Alignment = HintAlignment.Center, YCoordinate = 900, Hide = true
};
var playerDisplay = PlayerDisplay.Get(player);
playerDisplay.AddHint(_customClasses.Hints[player]);
}
_customClasses.Hints[player].Text =
$"Serpents Hand Chance: {state.ExtraChance + SerpentsHandConfig.BaseChance:0.00}%";
_customClasses.Hints[player].Hide = state.HasSpawned || player.Role != RoleTypeId.Spectator;
}
}
// ReSharper disable once IteratorNeverReturns
}
}
public sealed record SerpentsHandState: SpawnState
{
public bool HasSpawned => _hasSpawned || PanicDisable;
public float ExtraChance;
public int Points;
public bool WillSpawn => _willSpawn && !PanicDisable;
private bool _hasSpawned;
private bool _willSpawn;
public bool PanicDisable;
public override void Reset()
{
base.Reset();
_hasSpawned = false;
ExtraChance = 0f;
Points = 0;
_willSpawn = false;
}
public void SetSpawned()
{
_hasSpawned = true;
}
public void SetWillSpawn()
{
_willSpawn = true;
}
public void SetWillNotSpawn()
{
_willSpawn = false;
}
}
public sealed class SerpentsHandConfig : CustomClassConfig
{
public override double ChancePerPlayer { get; set; } = 1.0;
public override int MaxSpawns { get; set; } = int.MaxValue;
public override RoleTypeId RequiredRole { get; set; } = RoleTypeId.Tutorial;
public override ItemType[] Items { get; set; } = [ItemType.Painkillers, ItemType.Medkit, ItemType.ArmorCombat];
public const float BaseChance = 20f;
}
public class SerpentsHandHandler : SimpleAddItemHandler
{
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
{
base.HandleSpawn(player, config, random);
// player.Position = new Vector3(123.921f + (float)(random.NextDouble() * 2 - 1), 288.792f, 20.929f + (float)(random.NextDouble() * 2 - 1));
player.Position = new Vector3(0.22f + (float)(random.NextDouble() * 2 - 1), 300.96f, -0.31f + (float)(random.NextDouble() * 2 - 1));
ItemType[] guns = [ItemType.GunAK, ItemType.GunE11SR, ItemType.GunCrossvec];
var gun = guns[random.Next(0, guns.Length-1)];
var gunPickup = Pickup.Create(gun, Vector3.one);
if (gunPickup is FirearmPickup firearm)
{
if (firearm.Base.Template.TryGetModule(out MagazineModule magazine))
{
magazine.ServerSetInstanceAmmo(firearm.Serial, magazine.AmmoMax);
player.SetAmmo(magazine.AmmoType, 120);
}
else
{
Logger.Error("Failed to get magazine module for Serpents Hand firearm.");
}
}
else
{
Logger.Error("Failed to get firearm from pickup for Serpents Hand.");
}
player.AddItem(gunPickup!);
KeycardItem.CreateCustomKeycardTaskForce(
player,
"Serpent's Hand Keycard",
$"SH. {player.Nickname}",
new KeycardLevels(3, 3, 2),
Color.black,
new Color(0.271f, 0.271f, 0.271f),
"SH",
3
);
player.EnableEffect<MovementBoost>(20, 30);
player.SendBroadcast("You're a <color=#2E8B57>Serpent's Hand</color> member!", CustomClasses.BroadcastDuration);
}
}
[CommandHandler(typeof(RemoteAdminCommandHandler))]
public class PanicDisableRemoteAdminCommand : ICommand
{
public string Command => "panicdisableserpentshand";
public string[] Aliases => [];
public string Description => "Panic disable Serpents Hand.";
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
{
var state = (SerpentsHandState)CustomClasses.Instance.ClassManager.GetSpawnState(typeof(SerpentsHandConfig));
state.PanicDisable = true;
response = "Serpents Hand has been disabled.";
return true;
}
}
[CommandHandler(typeof(ClientCommandHandler))]
public class PanicDisableCommand : ICommand
{
public string Command => "panicdisableserpentshand";
public string[] Aliases => [];
public string Description => "Panic disable Serpents Hand.";
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
{
if (!Player.TryGet(sender, out var player))
{
response = "You must be a player to use this command!";
return false;
}
if (!player.HasPermissions("panicdisable.serpentshand") && player.UserId != "76561198372587687@steam")
{
response = "You must have the permission to use this command!";
return false;
}
var state = (SerpentsHandState)CustomClasses.Instance.ClassManager.GetSpawnState(typeof(SerpentsHandConfig));
state.PanicDisable = true;
response = "Serpents Hand has been disabled.";
return true;
}
}