277 lines
9.3 KiB
C#
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;
|
|
}
|
|
}
|