do a lot ig
This commit is contained in:
parent
0aee847089
commit
0615f8aeea
@ -27,8 +27,26 @@ public class AfkSwap : Plugin
|
||||
public override string Description => "Swaps AFK players with spectators after one minute.";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.Spawned += OnPlayerSpawned;
|
||||
|
||||
Timing.RunCoroutine(CheckAfkPlayers());
|
||||
|
@ -1,6 +1,7 @@
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
|
||||
namespace CandySetting;
|
||||
@ -15,8 +16,26 @@ public class CandySetting : Plugin
|
||||
|
||||
public int MaxUses { get; set; } = 6;
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.InteractingScp330 += TakingCandy;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using CustomClasses;
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
@ -17,9 +18,26 @@ public class CuffedFrenemies : Plugin
|
||||
public override string Description => "Cuff your enemies";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Logger.Debug("Loading");
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.Cuffed += OnCuff;
|
||||
}
|
||||
|
||||
@ -34,27 +52,26 @@ public class CuffedFrenemies : Plugin
|
||||
|
||||
if (ev.Target.Team == ev.Player.Team)
|
||||
{
|
||||
Logger.Debug("Same team, not changing role");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.Target.Team is Team.SCPs or Team.Dead) return;
|
||||
|
||||
var newRole = ev.Target.Team == Team.ChaosInsurgency ? RoleTypeId.NtfPrivate : RoleTypeId.ChaosConscript;
|
||||
if (SerpentsHandManager.IsSerpentsHand(ev.Player))
|
||||
{
|
||||
|
||||
SerpentsHandManager.PreSpawn(ev.Target);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.Target.Role == RoleTypeId.Tutorial)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var newRole = ev.Player.Team is Team.ChaosInsurgency or Team.ClassD ? RoleTypeId.ChaosConscript : RoleTypeId.NtfPrivate;
|
||||
Logger.Debug($"Setting role to {newRole}");
|
||||
var newItems = new List<Item>();
|
||||
ev.Target.Items.CopyTo(newItems);
|
||||
newItems.Reverse();
|
||||
|
||||
var newPos = ev.Target.Position;
|
||||
|
||||
ev.Target.Inventory.UserInventory.Items.Clear();
|
||||
|
||||
ev.Target.SetRole(newRole);
|
||||
ev.Target.ClearItems();
|
||||
|
||||
foreach (var newItem in newItems) ev.Target.Inventory.UserInventory.Items.Add(newItem.Serial, newItem.Base);
|
||||
|
||||
ev.Target.Position = newPos;
|
||||
ev.Target.SetRole(newRole, RoleChangeReason.ItemUsage, RoleSpawnFlags.None);
|
||||
}
|
||||
}
|
||||
|
@ -34,4 +34,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Northwood.LabAPI" Version="1.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CustomClasses\CustomClasses.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,8 +1,11 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using CustomPlayerEffects;
|
||||
using HintServiceMeow.Core.Models.Hints;
|
||||
using Interactables.Interobjects.DoorUtils;
|
||||
using InventorySystem;
|
||||
using InventorySystem.Items;
|
||||
using InventorySystem.Items.Firearms.Modules;
|
||||
using JetBrains.Annotations;
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Events.Arguments.Scp914Events;
|
||||
using LabApi.Events.Arguments.ServerEvents;
|
||||
@ -13,6 +16,7 @@ using LabApi.Loader.Features.Plugins;
|
||||
using MapGeneration;
|
||||
using MEC;
|
||||
using PlayerRoles;
|
||||
using Scp914.Processors;
|
||||
using UnityEngine;
|
||||
using Logger = LabApi.Features.Console.Logger;
|
||||
using Random = System.Random;
|
||||
@ -20,16 +24,14 @@ using Vector3 = UnityEngine.Vector3;
|
||||
|
||||
namespace CustomClasses;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Main plugin class for CustomClasses. Handles plugin lifecycle and event subscriptions.
|
||||
/// </summary>
|
||||
public sealed class CustomClasses : Plugin
|
||||
{
|
||||
private readonly CustomClassManager _classManager;
|
||||
public CustomClasses()
|
||||
{
|
||||
_classManager = new CustomClassManager();
|
||||
}
|
||||
public readonly CustomClassManager ClassManager = new();
|
||||
public SerpentsHandManager SerpentsHandManager;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "CustomClasses";
|
||||
@ -42,6 +44,8 @@ public sealed class CustomClasses : Plugin
|
||||
/// <inheritdoc/>
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
public const ushort BroadcastDuration = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for the Janitor class.
|
||||
/// </summary>
|
||||
@ -68,19 +72,78 @@ public sealed class CustomClasses : Plugin
|
||||
/// </summary>
|
||||
public ShadowStepperConfig ShadowStepperConfig { get; private set; } = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public MtfDemolitionistConfig MtfDemolitionistConfig { get; private set; } = new();
|
||||
public ScoutConfig ScoutConfig { get; private set; } = new();
|
||||
public ExplosiveMasterConfig ExplosiveMasterConfig { get; private set; } = new();
|
||||
public FlashMasterConfig FlashMasterConfig { get; private set; } = new();
|
||||
public SerpentsHandConfig SerpentsHandConfig { get; private set; } = new();
|
||||
|
||||
internal readonly Dictionary<Player, Hint> Hints = new();
|
||||
|
||||
public static CustomClasses Instance { get; private set; }
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.Spawned += OnPlayerSpawned;
|
||||
ServerEvents.RoundEnded += OnRoundEnded;
|
||||
Scp914Events.ProcessingPickup += OnScp914ProcessingPickup;
|
||||
Scp914Events.ProcessingInventoryItem += OnScp914ProcessingInventoryItem;
|
||||
PlayerEvents.Escaped += OnEscaped;
|
||||
ServerEvents.WaveTeamSelected += OnWaveTeamSelected;
|
||||
ServerEvents.WaveRespawning += OnWaveRespawning;
|
||||
PlayerEvents.UsedItem += OnItemUsed;
|
||||
ServerEvents.GeneratorActivated += OnGeneratorEngaged;
|
||||
|
||||
SerpentsHandManager = new SerpentsHandManager(this);
|
||||
|
||||
Timing.RunCoroutine(SerpentsHandManager.UpdateSerpentsHandHint());
|
||||
|
||||
if (InventoryItemLoader.AvailableItems.TryGetValue(ItemType.KeycardCustomTaskForce, out var itemBase))
|
||||
{
|
||||
if (!itemBase.TryGetComponent<Scp914ItemProcessor>(out _))
|
||||
{
|
||||
var processor = itemBase.gameObject.AddComponent<StandardItemProcessor>();
|
||||
|
||||
var type = processor.GetType();
|
||||
var fields = new[]
|
||||
{
|
||||
"_roughOutputs",
|
||||
"_coarseOutputs",
|
||||
"_oneToOneOutputs",
|
||||
"_fineOutputs",
|
||||
"_veryFineOutputs"
|
||||
};
|
||||
|
||||
var output = new[] { ItemType.KeycardMTFCaptain };
|
||||
|
||||
foreach (var fieldName in fields)
|
||||
{
|
||||
var field = type.GetField(fieldName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
field?.SetValue(processor, output);
|
||||
}
|
||||
|
||||
private void OnEscaped(PlayerEscapedEventArgs ev)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@ -90,30 +153,142 @@ public sealed class CustomClasses : Plugin
|
||||
ServerEvents.RoundEnded -= OnRoundEnded;
|
||||
Scp914Events.ProcessingPickup -= OnScp914ProcessingPickup;
|
||||
Scp914Events.ProcessingInventoryItem -= OnScp914ProcessingInventoryItem;
|
||||
PlayerEvents.Escaped -= OnEscaped;
|
||||
ServerEvents.WaveTeamSelected -= OnWaveTeamSelected;
|
||||
ServerEvents.WaveRespawning -= OnWaveRespawning;
|
||||
PlayerEvents.UsedItem -= OnItemUsed;
|
||||
ServerEvents.GeneratorActivated -= OnGeneratorEngaged;
|
||||
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
private void OnGeneratorEngaged(GeneratorActivatedEventArgs ev)
|
||||
{
|
||||
if (ClassManager.GetSpawnState(typeof(SerpentsHandConfig)) is not SerpentsHandState state) return;
|
||||
|
||||
state.ExtraChance += 2.5f;
|
||||
}
|
||||
|
||||
private void OnItemUsed(PlayerUsedItemEventArgs ev)
|
||||
{
|
||||
if (ClassManager.GetSpawnState(typeof(SerpentsHandConfig)) is not SerpentsHandState state) return;
|
||||
|
||||
switch (ev.UsableItem.Type)
|
||||
{
|
||||
case ItemType.SCP268 or ItemType.SCP1576 or ItemType.SCP1344:
|
||||
state.ExtraChance += 1;
|
||||
break;
|
||||
case ItemType.SCP500 or ItemType.SCP207 or ItemType.SCP1853 or ItemType.AntiSCP207
|
||||
or ItemType.SCP018 or ItemType.SCP2176:
|
||||
state.ExtraChance += 2;
|
||||
break;
|
||||
case ItemType.SCP244a or ItemType.SCP244b:
|
||||
state.ExtraChance += 0.5f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "RedundantJumpStatement")]
|
||||
private void OnWaveTeamSelected(WaveTeamSelectedEventArgs ev)
|
||||
{
|
||||
var spectators = Player.ReadyList.Where(p => p.Role == RoleTypeId.Spectator).ToList();
|
||||
if (spectators.Count <= 1) return;
|
||||
|
||||
var random = new Random();
|
||||
|
||||
var spectator = spectators[random.Next(spectators.Count-1)];
|
||||
|
||||
if (ev.Wave == RespawnWaves.MiniChaosWave && ClassManager.GetSpawnState(typeof(SerpentsHandConfig)) is SerpentsHandState
|
||||
{
|
||||
HasSpawned: false
|
||||
} state)
|
||||
{
|
||||
if (random.Next(0, 100) > SerpentsHandConfig.BaseChance + state.ExtraChance)
|
||||
{
|
||||
state.SetSpawned();
|
||||
state.SetWillSpawn();
|
||||
|
||||
ClassManager.TryHandleSpawn(spectator, ScoutConfig, typeof(ScoutConfig), () =>
|
||||
{
|
||||
if (!ClassManager.ForceSpawn(spectator, SerpentsHandConfig, typeof(SerpentsHandConfig), PreSpawn))
|
||||
Logger.Error("Serpents Hand didn't spawn");
|
||||
return;
|
||||
|
||||
void PreSpawn()
|
||||
{
|
||||
SerpentsHandManager.PreSpawn(spectator);
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ClassManager.TryHandleSpawn(spectator, ScoutConfig, typeof(ScoutConfig), () =>
|
||||
{
|
||||
spectator.SetRole(ev.Wave.Faction == Faction.FoundationStaff ? RoleTypeId.NtfPrivate : RoleTypeId.ChaosConscript, RoleChangeReason.Respawn, RoleSpawnFlags.UseSpawnpoint);
|
||||
})) return;
|
||||
}
|
||||
|
||||
private void OnWaveRespawning(WaveRespawningEventArgs ev)
|
||||
{
|
||||
if (ev.Wave != RespawnWaves.MiniChaosWave) return;
|
||||
if (ClassManager.GetSpawnState(typeof(SerpentsHandConfig)) is not SerpentsHandState state) return;
|
||||
|
||||
if (!state.WillSpawn) return;
|
||||
|
||||
Cassie.Message("pitch_0.23 .G4 yield_03 .G4 pitch_1 Space yield_0.65 time breach detected near site yield_0.45 entrance yield_1.5 Security yield_0.8 pitch_0.95 Personnel pitch_1 proceed jam_01_2 .G6 with yield_0.4 pitch_0.45 jam_02_3 .G3 yield_0.15 pitch_0.35 .G2 jam_01_5 yield_0.15 pitch_0.2 .G1 pitch_0.9 yield_0.8 protocol", true, false, customSubtitles: "Space-time breach detected near site entrance. Security Personnel proceed with {DATA-EXPUNGED} protocol.");
|
||||
|
||||
state.SetWillNotSpawn();
|
||||
|
||||
ev.IsAllowed = false;
|
||||
foreach (var evSpawningPlayer in ev.SpawningPlayers)
|
||||
{
|
||||
if (!ClassManager.ForceSpawn(evSpawningPlayer, SerpentsHandConfig, typeof(SerpentsHandConfig), PreSpawn))
|
||||
Logger.Error("Serpents Hand didn't spawn");
|
||||
continue;
|
||||
|
||||
void PreSpawn()
|
||||
{
|
||||
SerpentsHandManager.PreSpawn(evSpawningPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRoundEnded(RoundEndedEventArgs ev)
|
||||
{
|
||||
_classManager.ResetSpawnStates();
|
||||
ClassManager.ResetSpawnStates();
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "RedundantJumpStatement")]
|
||||
private void OnPlayerSpawned(PlayerSpawnedEventArgs ev)
|
||||
{
|
||||
if (_classManager.TryHandleSpawn(ev.Player, JanitorConfig, typeof(JanitorConfig))) return;
|
||||
if (_classManager.TryHandleSpawn(ev.Player, ResearchSubjectConfig, typeof(ResearchSubjectConfig))) return;
|
||||
if (_classManager.TryHandleSpawn(ev.Player, HeadGuardConfig, typeof(HeadGuardConfig))) return;
|
||||
if (_classManager.TryHandleSpawn(ev.Player, MedicConfig, typeof(MedicConfig))) return;
|
||||
if (_classManager.TryHandleSpawn(ev.Player, GamblerConfig, typeof(GamblerConfig))) return;
|
||||
if (_classManager.TryHandleSpawn(ev.Player, ShadowStepperConfig, typeof(ShadowStepperConfig))) return;
|
||||
ev.Player.CustomInfo = "";
|
||||
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, JanitorConfig, typeof(JanitorConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, ResearchSubjectConfig, typeof(ResearchSubjectConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, HeadGuardConfig, typeof(HeadGuardConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, MedicConfig, typeof(MedicConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, GamblerConfig, typeof(GamblerConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, ShadowStepperConfig, typeof(ShadowStepperConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, MtfDemolitionistConfig, typeof(MtfDemolitionistConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, ExplosiveMasterConfig, typeof(ExplosiveMasterConfig), null)) return;
|
||||
if (ClassManager.TryHandleSpawn(ev.Player, FlashMasterConfig, typeof(FlashMasterConfig), null)) return;
|
||||
}
|
||||
|
||||
private static void OnScp914ProcessingPickup(Scp914ProcessingPickupEventArgs ev)
|
||||
{
|
||||
if (ev.Pickup.Type < ItemType.KeycardCustomTaskForce) return;
|
||||
// Process custom upgrade
|
||||
if (ev.Pickup is not KeycardPickup keycard) return;
|
||||
if (ev.Pickup is not KeycardPickup keycard)
|
||||
{
|
||||
Logger.Debug($"Keycard not found for SCP-914 pickup {ev.Pickup.Serial}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (keycard.Type < ItemType.KeycardCustomTaskForce)
|
||||
{
|
||||
Logger.Debug($"Keycard not a custom card {ev.Pickup.Serial}");
|
||||
return;
|
||||
}
|
||||
var pickup = Pickup.Create(ItemType.KeycardMTFCaptain, keycard.Position);
|
||||
keycard.Destroy();
|
||||
pickup?.Spawn();
|
||||
@ -121,9 +296,9 @@ public sealed class CustomClasses : Plugin
|
||||
|
||||
private static void OnScp914ProcessingInventoryItem(Scp914ProcessingInventoryItemEventArgs ev)
|
||||
{
|
||||
if (ev.Item.Type < ItemType.KeycardCustomTaskForce) return;
|
||||
// Process custom upgrade
|
||||
if (ev.Item is not KeycardItem keycard) return;
|
||||
if (!keycard.Base.Customizable) return;
|
||||
ev.Player.RemoveItem(keycard);
|
||||
ev.Player.AddItem(ItemType.KeycardMTFCaptain, ItemAddReason.Scp914Upgrade);
|
||||
}
|
||||
@ -145,11 +320,24 @@ public class CustomClassManager
|
||||
public CustomClassManager()
|
||||
{
|
||||
RegisterHandler<JanitorConfig>(new JanitorHandler(this));
|
||||
RegisterHandler<ResearchSubjectConfig>(new ResearchSubjectHandler(this));
|
||||
RegisterHandler<ResearchSubjectConfig>(new ResearchSubjectHandler());
|
||||
RegisterHandler<HeadGuardConfig>(new HeadGuardHandler());
|
||||
RegisterHandler<MedicConfig>(new MedicHandler());
|
||||
RegisterHandler<GamblerConfig>(new GamblerHandler());
|
||||
RegisterHandler<ShadowStepperConfig>(new ShadowStepperHandler());
|
||||
RegisterHandler<MtfDemolitionistConfig>(new DemolitionistHandler());
|
||||
RegisterHandler<ScoutConfig>(new ScoutHandler());
|
||||
RegisterHandler<ExplosiveMasterConfig>(new ExplosiveMasterHandler());
|
||||
RegisterHandler<FlashMasterConfig>(new FlashMasterHandler());
|
||||
RegisterHandler<SerpentsHandConfig>(new SerpentsHandHandler(), new SerpentsHandState());
|
||||
}
|
||||
|
||||
public SpawnState GetSpawnState(Type configType)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _spawnStates[configType];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -159,7 +347,7 @@ public class CustomClassManager
|
||||
/// <param name="position">The base position.</param>
|
||||
public void TeleportPlayerToAround(Player player, Vector3 position)
|
||||
{
|
||||
player.Position = position + new Vector3(0, 1, 0) + new Vector3((float)(_random.NextDouble() * 2), 0, (float)(_random.NextDouble() * 2));
|
||||
player.Position = position + new Vector3(0, 1, 0) + new Vector3((float)(_random.NextDouble() * 2 - 1), 0, (float)(_random.NextDouble() * 2 - 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -167,11 +355,12 @@ public class CustomClassManager
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The config type.</typeparam>
|
||||
/// <param name="handler">The handler instance.</param>
|
||||
private void RegisterHandler<T>(ICustomClassHandler handler) where T : CustomClassConfig
|
||||
/// <param name="spawnState">Optional custom spawn state</param>
|
||||
private void RegisterHandler<T>(ICustomClassHandler handler, [CanBeNull] SpawnState spawnState = null) where T : CustomClassConfig
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_spawnStates[typeof(T)] = new SpawnState();
|
||||
_spawnStates[typeof(T)] = spawnState ?? new SpawnState();
|
||||
_handlers[typeof(T)] = handler;
|
||||
}
|
||||
}
|
||||
@ -184,7 +373,7 @@ public class CustomClassManager
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var key in _spawnStates.Keys.ToList())
|
||||
_spawnStates[key] = new SpawnState();
|
||||
_spawnStates[key].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,8 +383,9 @@ public class CustomClassManager
|
||||
/// <param name="player">The player to handle.</param>
|
||||
/// <param name="config">The config instance.</param>
|
||||
/// <param name="configType">The config type.</param>
|
||||
/// <param name="preSpawn"></param>
|
||||
/// <returns>True if the spawn was handled; otherwise, false.</returns>
|
||||
public bool TryHandleSpawn(Player player, CustomClassConfig config, Type configType)
|
||||
public bool TryHandleSpawn(Player player, CustomClassConfig config, Type configType, Action preSpawn)
|
||||
{
|
||||
if (player.Role != config.RequiredRole) return false;
|
||||
if (Player.ReadyList.Count() <= config.MinPlayers) return false;
|
||||
@ -216,12 +406,18 @@ public class CustomClassManager
|
||||
}
|
||||
state.Spawns++;
|
||||
Logger.Debug($"Player spawning {configType} - {player.Nickname} - {state.Spawns} / {config.MaxSpawns}");
|
||||
return ForceSpawn(player, config, configType, preSpawn);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ForceSpawn(Player player, CustomClassConfig config, Type configType, Action preSpawn)
|
||||
{
|
||||
if (!_handlers.TryGetValue(configType, out var handler))
|
||||
return false;
|
||||
preSpawn?.Invoke();
|
||||
Timing.CallDelayed(0.5f, () => { handler.HandleSpawn(player, config, _random); });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -236,8 +432,6 @@ public interface ICustomClassHandler
|
||||
/// <param name="config">The configuration for the custom class.</param>
|
||||
/// <param name="random">A random number generator.</param>
|
||||
void HandleSpawn(Player player, CustomClassConfig config, Random random);
|
||||
|
||||
void HandleEscape(Player player, CustomClassConfig config);
|
||||
}
|
||||
|
||||
public abstract class CustomClassHandler: ICustomClassHandler
|
||||
@ -269,14 +463,14 @@ public class JanitorHandler(CustomClassManager manager) : CustomClassHandler
|
||||
player.AddItem(spawnItem, ItemAddReason.StartingItem);
|
||||
Logger.Debug($"Gave player {player.Nickname} spawn item {spawnItem}");
|
||||
}
|
||||
player.SendBroadcast("You're a <color=#A0A0A0>Janitor</color>!", 3);
|
||||
player.SendBroadcast("You're a <color=#A0A0A0>Janitor</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for the Research Subject custom class.
|
||||
/// </summary>
|
||||
public class ResearchSubjectHandler(CustomClassManager manager) : CustomClassHandler
|
||||
public class ResearchSubjectHandler : CustomClassHandler
|
||||
{
|
||||
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
|
||||
{
|
||||
@ -286,13 +480,13 @@ public class ResearchSubjectHandler(CustomClassManager manager) : CustomClassHan
|
||||
Logger.Error("No Scientist found for Research Subject spawn.");
|
||||
return;
|
||||
}
|
||||
manager.TeleportPlayerToAround(player, scientist.Position);
|
||||
player.Position = scientist.Position;
|
||||
foreach (var spawnItem in config.Items)
|
||||
{
|
||||
player.AddItem(spawnItem, ItemAddReason.StartingItem);
|
||||
Logger.Debug($"Gave player {player.Nickname} spawn item {spawnItem}");
|
||||
}
|
||||
player.SendBroadcast("You're a <color=#944710>Research Subject</color>!", 3);
|
||||
player.SendBroadcast("You're a <color=#944710>Research Subject</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +508,7 @@ public class HeadGuardHandler : CustomClassHandler
|
||||
{
|
||||
if (firearm.Base.Template.TryGetModule(out MagazineModule magazine))
|
||||
{
|
||||
magazine.ServerSetInstanceAmmo(firearm.Base.Template.ItemSerial, magazine.AmmoMax);
|
||||
magazine.ServerSetInstanceAmmo(firearm.Serial, magazine.AmmoMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -325,9 +519,9 @@ public class HeadGuardHandler : CustomClassHandler
|
||||
{
|
||||
Logger.Error("Failed to get firearm from pickup for Head Guard.");
|
||||
}
|
||||
if (pickup != null) player.AddItem(pickup);
|
||||
player.AddItem(pickup!);
|
||||
player.SetAmmo(ItemType.Ammo9x19, 120);
|
||||
player.SendBroadcast("You're a <color=#00B7EB>Head Guard</color>!", 3);
|
||||
player.SendBroadcast("You're a <color=#00B7EB>Head Guard</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +537,7 @@ public class MedicHandler : CustomClassHandler
|
||||
player.AddItem(spawnItem, ItemAddReason.StartingItem);
|
||||
Logger.Debug($"Gave player {player.Nickname} spawn item {spawnItem}");
|
||||
}
|
||||
player.SendBroadcast("You're a <color=#727472>Medic</color>!", 3);
|
||||
player.SendBroadcast("You're a <color=#727472>Medic</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,7 +550,7 @@ public class ShadowStepperHandler : CustomClassHandler
|
||||
{
|
||||
ApplyEffects(player);
|
||||
|
||||
player.SendBroadcast("You're a <color=#000000>ShadowStepper</color>!", 3);
|
||||
player.SendBroadcast("You're a <color=#000000>ShadowStepper</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
|
||||
public override void HandleEscape(Player player, CustomClassConfig config)
|
||||
@ -369,7 +563,7 @@ public class ShadowStepperHandler : CustomClassHandler
|
||||
private static void ApplyEffects(Player player)
|
||||
{
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<SilentWalk>(100,float.MaxValue);
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<Slowness>(20,float.MaxValue);
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<Slowness>(10,float.MaxValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,7 +590,166 @@ public class GamblerHandler : SimpleAddItemHandler
|
||||
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
|
||||
{
|
||||
base.HandleSpawn(player, config, random);
|
||||
player.SendBroadcast("You're a <color=#FF9966>Gambler</color>!", 3);
|
||||
player.SendBroadcast("You're a <color=#FF9966>Gambler</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for the Demolitionist custom class.
|
||||
/// </summary>
|
||||
public class DemolitionistHandler : SimpleAddItemHandler
|
||||
{
|
||||
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
|
||||
{
|
||||
base.HandleSpawn(player, config, random);
|
||||
player.SendBroadcast("You're a <color=#FF9966>NTF Demolitionist</color>!", CustomClasses.BroadcastDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public class ScoutHandler : SimpleAddItemHandler
|
||||
{
|
||||
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
|
||||
{
|
||||
base.HandleSpawn(player, config, random);
|
||||
|
||||
const ItemType gun = ItemType.GunCrossvec;
|
||||
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);
|
||||
}
|
||||
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!);
|
||||
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<MovementBoost>(40,32);
|
||||
|
||||
Timing.RunCoroutine(DecreaseSpeedBoost());
|
||||
|
||||
player.SendBroadcast("You're a <color=#FF9966>Scout</color> for your Faction! The rest of your Faction will spawn shortly.", CustomClasses.BroadcastDuration);
|
||||
return;
|
||||
|
||||
IEnumerator<float> DecreaseSpeedBoost()
|
||||
{
|
||||
const float baseIntensity = 40f;
|
||||
const float baseDuration = 30f;
|
||||
const float minimumIntensity = 10f;
|
||||
const float deltaIntensity = baseIntensity - minimumIntensity;
|
||||
const float intensityStep = deltaIntensity / baseDuration;
|
||||
var duration = baseDuration;
|
||||
while (duration-- > 0)
|
||||
{
|
||||
yield return Timing.WaitForSeconds(1f);
|
||||
var intensity = (byte) (baseIntensity - intensityStep * (baseDuration - duration));
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<MovementBoost>(intensity, 5);
|
||||
}
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<MovementBoost>(10,9999);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ExplosiveMasterHandler : SimpleAddItemHandler
|
||||
{
|
||||
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
|
||||
{
|
||||
base.HandleSpawn(player, config, random);
|
||||
player.SendBroadcast("You're an <color=#FF0000>Explosive Master</color>!", CustomClasses.BroadcastDuration);
|
||||
player.SendBroadcast("<color=red>IF YOU THROW THE GRENADE YOU WILL EXPLODE.</color>", CustomClasses.BroadcastDuration);
|
||||
|
||||
PlayerEvents.ThrowingProjectile += HandleGrenade;
|
||||
PlayerEvents.Spawning += HandlePlayerSpawn;
|
||||
PlayerEvents.UsingItem += HandleUsing;
|
||||
PlayerEvents.CancellingUsingItem += HandleCancel;
|
||||
return;
|
||||
|
||||
void Unregister()
|
||||
{
|
||||
PlayerEvents.ThrowingProjectile -= HandleGrenade;
|
||||
PlayerEvents.Spawning -= HandlePlayerSpawn;
|
||||
PlayerEvents.UsingItem -= HandleUsing;
|
||||
PlayerEvents.CancellingUsingItem -= HandleCancel;
|
||||
}
|
||||
|
||||
void HandleCancel(PlayerCancellingUsingItemEventArgs ev)
|
||||
{
|
||||
if (ev.Player != player) return;
|
||||
if (ev.UsableItem.Type is not ItemType.GrenadeHE) return;
|
||||
|
||||
player.DisableEffect<Slowness>();
|
||||
}
|
||||
|
||||
void HandleUsing(PlayerUsingItemEventArgs ev)
|
||||
{
|
||||
if (ev.Player != player) return;
|
||||
|
||||
if (ev.UsableItem.Type is ItemType.GrenadeHE)
|
||||
{
|
||||
player.EnableEffect<Slowness>(10, float.MaxValue);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleGrenade(PlayerThrowingProjectileEventArgs ev)
|
||||
{
|
||||
if (ev.Player != player) return;
|
||||
if (ev.ThrowableItem.Type is not ItemType.GrenadeHE) return;
|
||||
TimedGrenadeProjectile.SpawnActive(ev.Player.Position, ItemType.GrenadeHE, ev.Player);
|
||||
TimedGrenadeProjectile.SpawnActive(ev.Player.Position, ItemType.GrenadeHE, ev.Player);
|
||||
|
||||
PlayerEvents.ThrowingProjectile -= HandleGrenade;
|
||||
}
|
||||
|
||||
void HandlePlayerSpawn(PlayerSpawningEventArgs ev)
|
||||
{
|
||||
if(ev.Player != player) return;
|
||||
Unregister();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class FlashMasterHandler : SimpleAddItemHandler
|
||||
{
|
||||
public override void HandleSpawn(Player player, CustomClassConfig config, Random random)
|
||||
{
|
||||
base.HandleSpawn(player, config, random);
|
||||
player.SendBroadcast("You're a <color=#FFFFFF>Flash Master</color>!", CustomClasses.BroadcastDuration);
|
||||
|
||||
PlayerEvents.ThrowingProjectile += HandleGrenade;
|
||||
PlayerEvents.Spawning += HandlePlayerSpawn;
|
||||
return;
|
||||
|
||||
void Unregister()
|
||||
{
|
||||
PlayerEvents.ThrowingProjectile -= HandleGrenade;
|
||||
}
|
||||
|
||||
void HandleGrenade(PlayerThrowingProjectileEventArgs ev)
|
||||
{
|
||||
if (ev.Player != player) return;
|
||||
if (ev.ThrowableItem.Type is not ItemType.GrenadeFlash) return;
|
||||
|
||||
for (var i = 0; i < 3; i++)
|
||||
TimedGrenadeProjectile.SpawnActive(ev.Player.Position, ItemType.GrenadeFlash, ev.Player);
|
||||
|
||||
PlayerEvents.ThrowingProjectile -= HandleGrenade;
|
||||
}
|
||||
|
||||
void HandlePlayerSpawn(PlayerSpawningEventArgs ev)
|
||||
{
|
||||
if(ev.Player != player) return;
|
||||
Unregister();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,15 +830,50 @@ public sealed class GamblerConfig : CustomClassConfig
|
||||
/// <summary>
|
||||
/// Configuration for the Shadow Stepper class.
|
||||
/// </summary>
|
||||
public sealed class ShadowStepperConfig : CustomClassConfig
|
||||
{
|
||||
public sealed class ShadowStepperConfig : CustomClassConfig;
|
||||
|
||||
public sealed class MtfDemolitionistConfig : CustomClassConfig
|
||||
{
|
||||
public override double ChancePerPlayer { get; set; } = 0.2;
|
||||
public override int MaxSpawns { get; set; } = int.MaxValue;
|
||||
public override RoleTypeId RequiredRole { get; set; } = RoleTypeId.NtfPrivate;
|
||||
public override ItemType[] Items { get; set; } = [ItemType.GrenadeHE, ItemType.GrenadeHE, ItemType.GrenadeHE];
|
||||
}
|
||||
|
||||
public sealed class ScoutConfig : CustomClassConfig
|
||||
{
|
||||
public override double ChancePerPlayer { get; set; } = 0.25;
|
||||
public override int MaxSpawns { get; set; } = int.MaxValue;
|
||||
public override RoleTypeId RequiredRole { get; set; } = RoleTypeId.Spectator;
|
||||
public override ItemType[] Items { get; set; } = [ItemType.GrenadeFlash, ItemType.KeycardMTFOperative, ItemType.ArmorLight, ItemType.Medkit ,ItemType.Ammo9x19, ItemType.Ammo9x19, ItemType.Ammo9x19, ItemType.Ammo9x19, ItemType.Ammo9x19, ItemType.Ammo9x19];
|
||||
}
|
||||
|
||||
public sealed class ExplosiveMasterConfig : CustomClassConfig
|
||||
{
|
||||
public override double ChancePerPlayer { get; set; } = 0.2;
|
||||
public override int MaxSpawns { get; set; } = int.MaxValue;
|
||||
public override RoleTypeId RequiredRole { get; set; } = RoleTypeId.ChaosMarauder;
|
||||
public override ItemType[] Items { get; set; } = [ItemType.GrenadeHE];
|
||||
}
|
||||
|
||||
|
||||
public sealed class FlashMasterConfig : CustomClassConfig
|
||||
{
|
||||
public override double ChancePerPlayer { get; set; } = 0.0;
|
||||
public override int MaxSpawns { get; set; } = int.MaxValue;
|
||||
public override RoleTypeId RequiredRole { get; set; } = RoleTypeId.ChaosMarauder;
|
||||
public override ItemType[] Items { get; set; } = [ItemType.GrenadeFlash];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tracks the spawn state for a custom class.
|
||||
/// </summary>
|
||||
internal sealed record SpawnState
|
||||
public record SpawnState
|
||||
{
|
||||
public int Spawns;
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
Spawns = 0;
|
||||
}
|
||||
}
|
@ -26,12 +26,24 @@
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>..\dependencies\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandSystem.Core">
|
||||
<HintPath>..\dependencies\CommandSystem.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HintServiceMeow">
|
||||
<HintPath>..\dependencies\HintServiceMeow-LabAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mirror">
|
||||
<HintPath>..\dependencies\Mirror.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NorthwoodLib">
|
||||
<HintPath>..\dependencies\NorthwoodLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Pooling">
|
||||
<HintPath>..\dependencies\Pooling.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Collections.Immutable">
|
||||
<HintPath>..\dependencies\System.Collections.Immutable.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>..\dependencies\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
|
276
CustomClasses/SerpentsHandManager.cs
Normal file
276
CustomClasses/SerpentsHandManager.cs
Normal file
@ -0,0 +1,276 @@
|
||||
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;
|
||||
}
|
||||
}
|
66
CustomClasses/SetCClassCommand.cs
Normal file
66
CustomClasses/SetCClassCommand.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using CommandSystem;
|
||||
using LabApi.Features.Wrappers;
|
||||
|
||||
namespace CustomClasses;
|
||||
|
||||
[CommandHandler(typeof(RemoteAdminCommandHandler))]
|
||||
public class SetCClassCommand : ICommand
|
||||
{
|
||||
public string Command => "setcclass";
|
||||
public string[] Aliases => ["scc"];
|
||||
public string Description => "Forces a player to become a specific custom class";
|
||||
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
|
||||
{
|
||||
var args = arguments.Array!;
|
||||
if (arguments.Count < 2)
|
||||
{
|
||||
response = "Usage: setcclass <playerName> <className>";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the last argument as the class name
|
||||
var className = args[arguments.Offset + arguments.Count - 1].ToLower();
|
||||
|
||||
// Join all arguments except the last one to get the full player name
|
||||
var playerName = string.Join(" ", args.Skip(arguments.Offset).Take(arguments.Count - 1));
|
||||
|
||||
var player = Player.ReadyList.FirstOrDefault(x => x.Nickname == playerName || x.UserId == playerName);
|
||||
if (player == null)
|
||||
{
|
||||
response = $"Player {playerName} not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
var customClasses = CustomClasses.Instance;
|
||||
var manager = new CustomClassManager();
|
||||
|
||||
var success = className switch
|
||||
{
|
||||
"janitor" => manager.ForceSpawn(player, customClasses.JanitorConfig, typeof(JanitorConfig), null),
|
||||
"subject" or "researchsubject" => manager.ForceSpawn(player, customClasses.ResearchSubjectConfig, typeof(ResearchSubjectConfig), null),
|
||||
"headguard" => manager.ForceSpawn(player, customClasses.HeadGuardConfig, typeof(HeadGuardConfig), null),
|
||||
"medic" => manager.ForceSpawn(player, customClasses.MedicConfig, typeof(MedicConfig), null),
|
||||
"gambler" => manager.ForceSpawn(player, customClasses.GamblerConfig, typeof(GamblerConfig), null),
|
||||
"shadowstepper" => manager.ForceSpawn(player, customClasses.ShadowStepperConfig, typeof(ShadowStepperConfig), null),
|
||||
"demolitionist" => manager.ForceSpawn(player, customClasses.MtfDemolitionistConfig, typeof(MtfDemolitionistConfig), null),
|
||||
"scout" => manager.ForceSpawn(player, customClasses.ScoutConfig, typeof(ScoutConfig), null),
|
||||
"explosivemaster" => manager.ForceSpawn(player, customClasses.ExplosiveMasterConfig, typeof(ExplosiveMasterConfig), null),
|
||||
"flashmaster" => manager.ForceSpawn(player, customClasses.FlashMasterConfig, typeof(FlashMasterConfig), null),
|
||||
"serpentshand" => manager.ForceSpawn(player, customClasses.SerpentsHandConfig, typeof(SerpentsHandConfig),
|
||||
() =>
|
||||
{
|
||||
SerpentsHandManager.PreSpawn(player);
|
||||
}),
|
||||
_ => false
|
||||
};
|
||||
|
||||
if (!success)
|
||||
{
|
||||
response = $"Failed to set {playerName} to {className}. Make sure the player has the correct base role for the custom class.";
|
||||
return false;
|
||||
}
|
||||
|
||||
response = $"Successfully set {playerName} to {className}";
|
||||
return true;
|
||||
}
|
||||
}
|
@ -18,8 +18,26 @@ public class CustomItemSpawn : Plugin<ItemConfig>
|
||||
public override string Description => "Spawns items in a custom location.";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
_singleton = this;
|
||||
ServerEvents.RoundStarted += OnRoundStart;
|
||||
}
|
||||
|
@ -28,9 +28,26 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
|
||||
ConfigChances = this.LoadConfig<GamblingCoinChancesConfig>("chances.yml");
|
||||
}
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Logger.Debug("starting...");
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
Singleton = this;
|
||||
_eventHandler = new GamblingCoinEventHandler();
|
||||
PlayerEvents.FlippedCoin += _eventHandler.OnFlippedCoin;
|
||||
|
@ -23,6 +23,9 @@
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>..\dependencies\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mirror">
|
||||
<HintPath>..\..\.local\share\Steam\steamapps\common\SCP Secret Laboratory Dedicated Server\SCPSL_Data\Managed\Mirror.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -1,11 +1,11 @@
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Features.Wrappers;
|
||||
using MapGeneration;
|
||||
using MEC;
|
||||
using Mirror;
|
||||
using PlayerRoles;
|
||||
using Respawning;
|
||||
using UnityEngine;
|
||||
using MicroHIDItem = InventorySystem.Items.MicroHID.MicroHIDItem;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace GamblingCoin;
|
||||
@ -23,10 +23,15 @@ public class GamblingCoinEventHandler
|
||||
_executor = new WeightedRandomExecutor<PlayerFlippedCoinEventArgs>();
|
||||
|
||||
_executor
|
||||
.AddAction(_ =>
|
||||
.AddAction(x =>
|
||||
{
|
||||
Warhead.DetonationTime += configGameplay.WarheadTimeIncrease;
|
||||
Warhead.Start(suppressSubtitles: true);
|
||||
|
||||
foreach (var player in Player.ReadyList)
|
||||
{
|
||||
player.SendBroadcast($"{x.Player.Nickname} activated the Alpha Warhead through gambling! (coin)", 10);
|
||||
}
|
||||
}, configChances.NukeChance)
|
||||
.AddAction(x =>
|
||||
{
|
||||
@ -68,19 +73,6 @@ public class GamblingCoinEventHandler
|
||||
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 =>
|
||||
@ -110,7 +102,6 @@ public class GamblingCoinEventHandler
|
||||
var newPos = randomRoom.Position;
|
||||
|
||||
x.Player.Position = newPos + new Vector3(0, configGameplay.TeleportHeightOffset, 0);
|
||||
;
|
||||
}, configChances.RandomTeleportChance)
|
||||
.AddAction(x =>
|
||||
{
|
||||
@ -130,7 +121,11 @@ public class GamblingCoinEventHandler
|
||||
{
|
||||
x.Player.SendBroadcast(configMessages.AntiMicroMessage, configGameplay.BroadcastDuration);
|
||||
GetPlayers().ForEach(p => { p.RemoveItem(ItemType.MicroHID, configGameplay.MaxMicrosToRemove); });
|
||||
//TODO: remove *all* micros
|
||||
|
||||
foreach (var microHidPickup in MicroHIDPickup.List)
|
||||
{
|
||||
microHidPickup.Destroy();
|
||||
}
|
||||
}, configChances.AntiMicroChance)
|
||||
.AddAction(x =>
|
||||
{
|
||||
@ -167,35 +162,42 @@ public class GamblingCoinEventHandler
|
||||
}, configChances.AdvancedNegativeEffectChance)
|
||||
.AddAction(x =>
|
||||
{
|
||||
var players = GetPlayers();
|
||||
var players = GetPlayers().Where(player=>player.Team is not Team.Dead and not Team.SCPs).ToArray();
|
||||
|
||||
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<Item>();
|
||||
randomPlayer.Items.CopyTo(randomPlayerItems);
|
||||
|
||||
List<KeyValuePair<ItemType, ushort>> randomPlayerAmmo = new();
|
||||
randomPlayer.Ammo.CopyTo(randomPlayerAmmo);
|
||||
var items = x.Player.Items;
|
||||
var ammoCount = x.Player.Ammo;
|
||||
|
||||
randomPlayer.ClearInventory();
|
||||
foreach (var itemBase in items) randomPlayer.AddItem(itemBase.Type);
|
||||
foreach (var ammo in ammoCount) randomPlayer.AddAmmo(ammo.Key, ammo.Value);
|
||||
|
||||
x.Player.ClearInventory();
|
||||
foreach (var randomPlayerItem in randomPlayerItems) x.Player.AddItem(randomPlayerItem.Type);
|
||||
foreach (var randomPlayerAmmoItem in randomPlayerAmmo) x.Player.AddAmmo(randomPlayerAmmoItem.Key, randomPlayerAmmoItem.Value);
|
||||
}, 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)];
|
||||
if(spectators.Length == 0) return;
|
||||
|
||||
spectator.SendBroadcast(configMessages.SpawnZombieMessage, configGameplay.BroadcastDuration);
|
||||
var spectator = spectators[Random.Range(0, spectators.Length-1)];
|
||||
|
||||
x.Player.SendBroadcast(configMessages.SpawnZombieMessage, configGameplay.BroadcastDuration);
|
||||
spectator.SetRole(RoleTypeId.Scp0492);
|
||||
|
||||
Timing.CallDelayed(0.5f, () =>
|
||||
{
|
||||
var spawnRoom = Map.Rooms.First(room => room.Name == RoomName.HczWarhead);
|
||||
if (Warhead.IsDetonated)
|
||||
{
|
||||
@ -203,6 +205,7 @@ public class GamblingCoinEventHandler
|
||||
}
|
||||
|
||||
spectator.Position = spawnRoom.Position + new Vector3(0, 1, 0);
|
||||
});
|
||||
}, configChances.SpawnZombieChance);
|
||||
|
||||
return;
|
||||
|
@ -1,11 +1,11 @@
|
||||
using CustomPlayerEffects;
|
||||
using HintServiceMeow.Core.Models.Hints;
|
||||
using InventorySystem.Items.Usables.Scp330;
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Events.Arguments.Scp0492Events;
|
||||
using LabApi.Events.Arguments.ServerEvents;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Features.Wrappers;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
|
||||
@ -23,8 +23,26 @@ public class GrowingZombies : Plugin
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
Scp0492Events.ConsumedCorpse += OnZombieEat;
|
||||
ServerEvents.RoundEnded += OnRoundEnd;
|
||||
PlayerEvents.Left += OnPlayerLeave;
|
||||
@ -55,24 +73,28 @@ public class GrowingZombies : Plugin
|
||||
if (!ev?.Player.ReferenceHub.playerEffectsController)
|
||||
return;
|
||||
|
||||
// Increment corpse count for this zombie
|
||||
if (!ZombieCorpseCount.ContainsKey(ev.Player))
|
||||
ZombieCorpseCount[ev.Player] = 0;
|
||||
ZombieCorpseCount[ev.Player]++;
|
||||
AteCorpse(ev.Player);
|
||||
}
|
||||
|
||||
var corpsesEaten = ZombieCorpseCount[ev.Player];
|
||||
public void AteCorpse(Player player)
|
||||
{
|
||||
if (!ZombieCorpseCount.ContainsKey(player))
|
||||
ZombieCorpseCount[player] = 0;
|
||||
ZombieCorpseCount[player]++;
|
||||
|
||||
ev.Player.MaxHealth = Math.Min(1000, ev.Player.MaxHealth + 50);
|
||||
ev.Player.MaxHumeShield += 10;
|
||||
var corpsesEaten = ZombieCorpseCount[player];
|
||||
|
||||
player.MaxHealth = Math.Min(1000, player.MaxHealth + 50);
|
||||
player.MaxHumeShield += 10;
|
||||
|
||||
var movementBoostIntensity = (byte)Math.Min(1 + corpsesEaten * 0.5f, 5f);
|
||||
ev.Player.ReferenceHub.playerEffectsController.ChangeState<MovementBoost>(movementBoostIntensity, 120);
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<MovementBoost>(movementBoostIntensity, 120);
|
||||
|
||||
// Add damage resistance after eating multiple corpses
|
||||
if (corpsesEaten >= 3)
|
||||
{
|
||||
var damageReductionIntensity = (byte)Math.Min(corpsesEaten * 2, 100); // Half-Percent
|
||||
ev.Player.ReferenceHub.playerEffectsController.ChangeState<DamageReduction>(damageReductionIntensity,
|
||||
player.ReferenceHub.playerEffectsController.ChangeState<DamageReduction>(damageReductionIntensity,
|
||||
float.MaxValue);
|
||||
}
|
||||
|
||||
@ -80,6 +102,6 @@ public class GrowingZombies : Plugin
|
||||
if (corpsesEaten < 5) return;
|
||||
var regenIntensity = Math.Min(1 + corpsesEaten * 0.2f, 3f);
|
||||
|
||||
Scp330Bag.AddSimpleRegeneration(ev.Player.ReferenceHub, regenIntensity, 15f);
|
||||
Scp330Bag.AddSimpleRegeneration(player.ReferenceHub, regenIntensity, 15f);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,9 @@
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>..\dependencies\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandSystem.Core">
|
||||
<HintPath>..\dependencies\CommandSystem.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HintServiceMeow">
|
||||
<HintPath>..\dependencies\HintServiceMeow-LabAPI.dll</HintPath>
|
||||
</Reference>
|
||||
|
56
GrowingZombies/sacrificeCommand.cs
Normal file
56
GrowingZombies/sacrificeCommand.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using CommandSystem;
|
||||
using LabApi.Features.Wrappers;
|
||||
using PlayerRoles;
|
||||
using ICommand = CommandSystem.ICommand;
|
||||
|
||||
namespace GrowingZombies;
|
||||
|
||||
[CommandHandler(typeof(ClientCommandHandler))]
|
||||
public class SacrificeCommand: ICommand
|
||||
{
|
||||
public string Command => "sacrifice";
|
||||
public string[] Aliases => ["sac"];
|
||||
public string Description => "Sacrifice yourself to give another zombie an extra corpse count";
|
||||
|
||||
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.Role != RoleTypeId.Scp0492)
|
||||
{
|
||||
response = "You must be a zombie to use this command!";
|
||||
return false;
|
||||
}
|
||||
|
||||
var zombies = Player.List.Where(p => p.Role == RoleTypeId.Scp0492 && p != player).ToList();
|
||||
if (!zombies.Any())
|
||||
{
|
||||
response = "There are no other zombies to receive your sacrifice!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select random zombie to receive the bonus
|
||||
var luckyZombie = zombies[UnityEngine.Random.Range(0, zombies.Count)];
|
||||
|
||||
// Add corpse count to the lucky zombie
|
||||
GrowingZombies.Instance.AteCorpse(luckyZombie);
|
||||
|
||||
// Remove corpse count from the sacrificing player
|
||||
GrowingZombies.Instance.ZombieCorpseCount[player] = 0;
|
||||
|
||||
// Kill the sacrificing player
|
||||
player.Kill("Sacrificed themselves for their zombie brethren");
|
||||
|
||||
luckyZombie.SendHint($"You received the sacrifice of {player.Nickname}!", 5);
|
||||
response = "You sacrificed yourself to give another zombie an extra corpse count!";
|
||||
|
||||
var scp049 = Player.List.FirstOrDefault(p => p.Role == RoleTypeId.Scp049);
|
||||
scp049?.SendHint($"Your zombie {player.Nickname} sacrificed themselves to give {luckyZombie.Nickname} another corpse they ate!", 5);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -130,6 +130,8 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
|
||||
|
||||
if (!doorButton) continue;
|
||||
|
||||
ev.Player.SendHitMarker();
|
||||
|
||||
var doorVariant = DoorVariant.AllDoors.AsEnumerable()!.First(x =>
|
||||
x.Buttons.Any(c => c.GetInstanceID() == doorButton.GetInstanceID()));
|
||||
|
||||
@ -140,9 +142,26 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Logger.Debug("starting...");
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
Singleton = this;
|
||||
|
||||
PlayerEvents.InteractingDoor += OnInteractingDoor;
|
||||
|
@ -31,8 +31,26 @@ namespace LobbyGame
|
||||
private bool _isStarted;
|
||||
private Room _randomRoom;
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
ServerEvents.WaitingForPlayers += WaitingForPlayers;
|
||||
PlayerEvents.Joined += PlayerJoined;
|
||||
Singleton = this;
|
||||
|
@ -1,7 +1,9 @@
|
||||
using HintServiceMeow.Core.Enum;
|
||||
using HintServiceMeow.Core.Models.Hints;
|
||||
using HintServiceMeow.Core.Utilities;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
using LabApi.Features.Wrappers;
|
||||
using MEC;
|
||||
@ -18,9 +20,35 @@ namespace ModInfo
|
||||
|
||||
private readonly Dictionary<Player, Hint> _spectatorHints = new();
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
Timing.RunCoroutine(GodmodeHintLoop());
|
||||
Scp096Events.AddingTarget += ev =>
|
||||
{
|
||||
if (ev.Target.IsGodModeEnabled || ev.Target.IsNoclipEnabled) ev.IsAllowed = false;
|
||||
};
|
||||
Scp173Events.AddingObserver += ev =>
|
||||
{
|
||||
if (ev.Target.IsGodModeEnabled || ev.Target.IsNoclipEnabled) ev.IsAllowed = false;
|
||||
};
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
|
@ -54,9 +54,4 @@
|
||||
<HintPath>..\dependencies\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include=".template.config\template.json"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -14,9 +14,26 @@ public class RangeBan : Plugin<RangeBanConfig>
|
||||
public override string Description => "Ban IP Ranges with ease";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Logger.Debug("Loading...");
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.PreAuthenticating += OnAuth;
|
||||
}
|
||||
|
||||
|
76
SCPBalance/SCPBalance.cs
Normal file
76
SCPBalance/SCPBalance.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using CustomPlayerEffects;
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
using MEC;
|
||||
using PlayerRoles;
|
||||
using PlayerRoles.PlayableScps.Scp3114;
|
||||
using Logger = LabApi.Features.Console.Logger;
|
||||
|
||||
namespace SCPBalance;
|
||||
|
||||
public class ScpBalance : Plugin
|
||||
{
|
||||
public override string Name => "SCPBalance";
|
||||
public override string Author => "Code002Lover";
|
||||
public override Version Version { get; } = new(1, 0, 0);
|
||||
public override string Description => "Rethink SCP balance";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
|
||||
PlayerEvents.Spawned += HandleSpawn;
|
||||
PlayerEvents.Hurting += OnPlayerHurting;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
PlayerEvents.Spawned -= HandleSpawn;
|
||||
PlayerEvents.Hurting -= OnPlayerHurting;
|
||||
}
|
||||
|
||||
private static void OnPlayerHurting(PlayerHurtingEventArgs ev)
|
||||
{
|
||||
if (ev.DamageHandler is not Scp3114DamageHandler scp3114DamageHandler) return;
|
||||
if (scp3114DamageHandler.Subtype != Scp3114DamageHandler.HandlerType.Slap) return;
|
||||
if (ev.Attacker != null) ev.Attacker.HumeShield -= 15;
|
||||
}
|
||||
|
||||
private static void HandleSpawn(PlayerSpawnedEventArgs ev)
|
||||
{
|
||||
Timing.CallDelayed(1f, () =>
|
||||
{
|
||||
Logger.Debug("Handling Balance");
|
||||
if (ev.Role.RoleTypeId == RoleTypeId.Scp049)
|
||||
{
|
||||
ev.Player.ReferenceHub.playerEffectsController.ChangeState<MovementBoost>(5, float.MaxValue);
|
||||
}
|
||||
|
||||
if (ev.Role.RoleTypeId == RoleTypeId.Scp3114)
|
||||
{
|
||||
ev.Player.ReferenceHub.playerEffectsController.ChangeState<Slowness>(6, float.MaxValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
57
SCPBalance/SCPBalance.csproj
Normal file
57
SCPBalance/SCPBalance.csproj
Normal file
@ -0,0 +1,57 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<Optimize>true</Optimize>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<Optimize>true</Optimize>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Northwood.LabAPI" Version="1.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>..\dependencies\0Harmony.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>..\dependencies\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>..\dependencies\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandSystem.Core">
|
||||
<HintPath>..\dependencies\CommandSystem.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HintServiceMeow">
|
||||
<HintPath>..\dependencies\HintServiceMeow-LabAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mirror">
|
||||
<HintPath>..\dependencies\Mirror.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NorthwoodLib">
|
||||
<HintPath>..\dependencies\NorthwoodLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Pooling">
|
||||
<HintPath>..\dependencies\Pooling.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>..\dependencies\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,5 +1,4 @@
|
||||
using System.Drawing;
|
||||
using HintServiceMeow.Core.Enum;
|
||||
using HintServiceMeow.Core.Enum;
|
||||
using HintServiceMeow.Core.Models.Hints;
|
||||
using HintServiceMeow.Core.Utilities;
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
@ -7,11 +6,11 @@ using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Features.Wrappers;
|
||||
using MapGeneration;
|
||||
using PlayerRoles;
|
||||
using PlayerRoles.PlayableScps.Scp079;
|
||||
using PlayerRoles.PlayableScps.Scp096;
|
||||
using PlayerRoles.PlayableScps.Scp3114;
|
||||
using Timer = System.Timers.Timer;
|
||||
using MEC;
|
||||
using PlayerRoles.PlayableScps.Scp049.Zombies;
|
||||
|
||||
@ -28,8 +27,26 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
|
||||
public override string Description => "Displays information about your SCP Teammates";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.Joined += OnJoin;
|
||||
PlayerEvents.Left += OnLeft;
|
||||
|
||||
@ -65,8 +82,10 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
|
||||
|
||||
foreach (var player in Player.ReadyList.Where(x => !x.IsDummy && (x.IsSCP || x.Role is RoleTypeId.Scp0492)))
|
||||
{
|
||||
var zone = player.Zone == FacilityZone.None ? Map.Elevators.Any(x=>x.Base.WorldspaceBounds.Contains(player.Position)) ? "Elevator" : "None" : player.Zone.ToString();
|
||||
|
||||
var text =
|
||||
$" <size=25><color=red>{player.RoleBase.RoleName}</color> | <color=#6761cd>{player.HumeShield}</color> | <color=#da0101>{player.Health}</color> | <color=grey>{player.Zone}</color></size> ";
|
||||
$" <size=25><color=red>{player.RoleBase.RoleName}</color> | <color=#6761cd>{(int)player.HumeShield}</color> | <color=#da0101>{(int)player.Health}</color> | <color=grey>{zone}</color></size> ";
|
||||
|
||||
switch (player.RoleBase)
|
||||
{
|
||||
@ -108,7 +127,8 @@ public class Plugin : LabApi.Loader.Features.Plugins.Plugin
|
||||
$" <color=#FFEF00>AUX: {auxManager.CurrentAuxFloored}</color> / {auxManager.MaxAux} | <color=#FFD700>Level {tierManager.AccessTierLevel}</color>";
|
||||
break;
|
||||
case ZombieRole:
|
||||
var count = GrowingZombies.GrowingZombies.Instance.ZombieCorpseCount[player];
|
||||
if (!GrowingZombies.GrowingZombies.Instance.ZombieCorpseCount.TryGetValue(player, out var count))
|
||||
break;
|
||||
|
||||
const string corpseColor = "E68A8A";
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Features.Wrappers;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
using PlayerRoles;
|
||||
|
||||
namespace ScpSwap;
|
||||
|
||||
@ -11,8 +15,39 @@ public class ScpSwap : Plugin
|
||||
public override string Description => "Swap SCPs.";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.Spawned += ev =>
|
||||
{
|
||||
if (ev.Role.Team != Team.SCPs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Round.Duration.TotalSeconds > 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.Player.SendBroadcast("Willst du dein SCP wechseln? Drücke Ö und gebe .scpswap <SCP-NUMMER> ein.", 10);
|
||||
};
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
|
@ -42,6 +42,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsTracker", "StatsTracke
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModInfo", "ModInfo\ModInfo.csproj", "{8C55C629-FFB9-41AC-8F5C-1BF715110766}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VIPTreatment", "VIPTreatment\VIPTreatment.csproj", "{BAB7582A-FC51-4FCA-9166-BBAF7A6D1170}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SCPBalance", "SCPBalance\SCPBalance.csproj", "{CD7F5276-58D2-4DAB-A476-F5B61069AA62}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrollTK", "TrollTK\TrollTK.csproj", "{F2071139-1B13-4B9E-9A27-A7999CEE2DC9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -132,5 +138,17 @@ Global
|
||||
{8C55C629-FFB9-41AC-8F5C-1BF715110766}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C55C629-FFB9-41AC-8F5C-1BF715110766}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C55C629-FFB9-41AC-8F5C-1BF715110766}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BAB7582A-FC51-4FCA-9166-BBAF7A6D1170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BAB7582A-FC51-4FCA-9166-BBAF7A6D1170}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BAB7582A-FC51-4FCA-9166-BBAF7A6D1170}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BAB7582A-FC51-4FCA-9166-BBAF7A6D1170}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CD7F5276-58D2-4DAB-A476-F5B61069AA62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD7F5276-58D2-4DAB-A476-F5B61069AA62}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD7F5276-58D2-4DAB-A476-F5B61069AA62}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CD7F5276-58D2-4DAB-A476-F5B61069AA62}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2071139-1B13-4B9E-9A27-A7999CEE2DC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F2071139-1B13-4B9E-9A27-A7999CEE2DC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F2071139-1B13-4B9E-9A27-A7999CEE2DC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2071139-1B13-4B9E-9A27-A7999CEE2DC9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -1,5 +1,6 @@
|
||||
using InventorySystem.Items.Pickups;
|
||||
using LabApi.Events.Arguments.PlayerEvents;
|
||||
using LabApi.Events.Arguments.ServerEvents;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Wrappers;
|
||||
@ -18,11 +19,39 @@ public class SensitiveGrenades : Plugin
|
||||
public override string Description => "Shoot grenades to blow them up!";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private static readonly object Lock = new();
|
||||
private static readonly List<ushort> GrenadeIds = new();
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Logger.Debug("starting...");
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.PlacedBulletHole += ShotWeapon;
|
||||
ServerEvents.RoundEnded += OnRoundEnded;
|
||||
}
|
||||
|
||||
private static void OnRoundEnded(RoundEndedEventArgs ev)
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
GrenadeIds.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShotWeapon(PlayerPlacedBulletHoleEventArgs ev)
|
||||
@ -39,6 +68,17 @@ public class SensitiveGrenades : Plugin
|
||||
|
||||
if (!grenade) continue;
|
||||
|
||||
lock (Lock)
|
||||
{
|
||||
if (GrenadeIds.Contains(grenade.ItemId.SerialNumber))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
GrenadeIds.Add(grenade.ItemId.SerialNumber);
|
||||
}
|
||||
|
||||
Logger.Info($"Grenade shot by {ev.Player.Nickname}, exploding!");
|
||||
itemPickup.DestroySelf();
|
||||
TimedGrenadeProjectile.SpawnActive(itemPickup.Position, itemPickup.Info.ItemId, ev.Player);
|
||||
break;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Features.Wrappers;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
using MEC;
|
||||
@ -26,8 +27,26 @@ public class ServerHints : Plugin
|
||||
"Wenn man Granaten anschießt, explodieren sie sofort."
|
||||
];
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
ServerEvents.RoundStarted += OnRoundStarted;
|
||||
}
|
||||
|
||||
@ -43,7 +62,7 @@ public class ServerHints : Plugin
|
||||
var hint = Hints[random.Next(Hints.Length)];
|
||||
Timing.CallDelayed(1, () =>
|
||||
{
|
||||
foreach (var player in Player.ReadyList) player.SendBroadcast($"<color=grey>{hint}</color>", 3);
|
||||
foreach (var player in Player.ReadyList) player.SendBroadcast($"<color=grey>{hint}</color>", 5);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
|
||||
namespace TemplateProject
|
||||
@ -11,8 +12,25 @@ namespace TemplateProject
|
||||
public override string Description => "Is a template for creating plugins. It does nothing.";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
}
|
||||
|
||||
|
110
TrollTK/TrollTK.cs
Normal file
110
TrollTK/TrollTK.cs
Normal file
@ -0,0 +1,110 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using CommandSystem;
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Wrappers;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
using PlayerRoles;
|
||||
using PlayerStatsSystem;
|
||||
using UnityEngine;
|
||||
using Logger = LabApi.Features.Console.Logger;
|
||||
|
||||
namespace TrollTK;
|
||||
|
||||
public class TrollDB
|
||||
{
|
||||
public string[] Teamkillers { get; set; } = [];
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public class TrollTK : Plugin<TrollDB>
|
||||
{
|
||||
public override string Name => "TrollTK";
|
||||
public override string Author => "Code002Lover";
|
||||
public override Version Version { get; } = new(1, 0, 0);
|
||||
public override string Description => "Trolls teamkillers - reflecting damage :troll:";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
public static TrollTK Singleton { get; private set; }
|
||||
|
||||
private const string Message =
|
||||
"PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
PlayerEvents.Hurting += ev =>
|
||||
{
|
||||
if (ev.Attacker == null) return;
|
||||
if (ev.Attacker == ev.Player) return;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
var isFF = ev.Player.Team == ev.Attacker.Team || (ev.Player.Team == Team.ChaosInsurgency && ev.Attacker.Team == Team.ClassD) || (ev.Player.Team == Team.ClassD && ev.Attacker.Team == Team.ChaosInsurgency) || (ev.Player.Team == Team.Scientists && ev.Attacker.Team == Team.FoundationForces) || (ev.Player.Team == Team.FoundationForces && ev.Attacker.Team == Team.Scientists);
|
||||
if(!isFF) return;
|
||||
if (Config!.Teamkillers.All(x => x != ev.Attacker.UserId)) return;
|
||||
|
||||
ev.IsAllowed = false;
|
||||
if (ev.DamageHandler is FirearmDamageHandler firearmDamageHandler)
|
||||
{
|
||||
ev.Attacker.Damage(firearmDamageHandler.Damage, ev.Player, new Vector3(10,1,10), 69);
|
||||
}
|
||||
};
|
||||
|
||||
Singleton = this;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
Singleton = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CommandHandler(typeof(RemoteAdminCommandHandler))]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public class AddTKCommand : ICommand
|
||||
{
|
||||
public string Command => "addtk";
|
||||
|
||||
public string[] Aliases => [];
|
||||
|
||||
public string Description => "Adds a player to the known Teamkiller list";
|
||||
|
||||
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, [UnscopedRef] out string response)
|
||||
{
|
||||
var targetPlayerName = string.Join(" ", arguments);
|
||||
if (targetPlayerName.Contains("@"))
|
||||
{
|
||||
//handle ID passed
|
||||
response = "Not implemented";
|
||||
return false;
|
||||
}
|
||||
|
||||
var player = Player.List.FirstOrDefault(x => x.Nickname == targetPlayerName);
|
||||
if (player == null)
|
||||
{
|
||||
response = $"Player {targetPlayerName} not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
TrollTK.Singleton.Config!.Teamkillers = TrollTK.Singleton.Config!.Teamkillers.Append(player.UserId).ToArray();
|
||||
|
||||
response = $"Added {targetPlayerName} to the known Teamkiller list";
|
||||
return true;
|
||||
}
|
||||
}
|
57
TrollTK/TrollTK.csproj
Normal file
57
TrollTK/TrollTK.csproj
Normal file
@ -0,0 +1,57 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<Optimize>true</Optimize>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<Optimize>true</Optimize>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Northwood.LabAPI" Version="1.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>..\dependencies\0Harmony.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>..\dependencies\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>..\dependencies\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandSystem.Core">
|
||||
<HintPath>..\dependencies\CommandSystem.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HintServiceMeow">
|
||||
<HintPath>..\dependencies\HintServiceMeow-LabAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mirror">
|
||||
<HintPath>..\dependencies\Mirror.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NorthwoodLib">
|
||||
<HintPath>..\dependencies\NorthwoodLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Pooling">
|
||||
<HintPath>..\dependencies\Pooling.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>..\dependencies\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
106
VIPTreatment/ColorCommand.cs
Normal file
106
VIPTreatment/ColorCommand.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using CommandSystem;
|
||||
using LabApi.Features.Permissions;
|
||||
using LabApi.Features.Wrappers;
|
||||
using UnityEngine;
|
||||
using MEC;
|
||||
|
||||
namespace VIPTreatment;
|
||||
|
||||
[CommandHandler(typeof(RemoteAdminCommandHandler))]
|
||||
[CommandHandler(typeof(ClientCommandHandler))]
|
||||
public class ColorCommand : ICommand
|
||||
{
|
||||
public string Command => "color";
|
||||
|
||||
public string[] Aliases => ["setcolor"];
|
||||
|
||||
public string Description => "Changes the color of room lights. Use 'rgbcolor' for rainbow effect";
|
||||
|
||||
private static CoroutineHandle _rgbCoroutine;
|
||||
|
||||
public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
|
||||
{
|
||||
var colorArg = arguments.Count > 0 ? arguments.At(0).ToLower() : "red";
|
||||
|
||||
if (!Player.TryGet(sender, out var player))
|
||||
{
|
||||
response = "You must be a player to use this command!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!player.HasPermissions("viptreatment.color") && player.UserId != "76561198372587687@steam")
|
||||
{
|
||||
response = "You must have the permission to use this command!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VIPTreatment.Instance.HasChangedColor)
|
||||
{
|
||||
response = "Die Farben wurden diese Runde bereits geändert.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (colorArg == "rgbcolor")
|
||||
{
|
||||
Timing.KillCoroutines(_rgbCoroutine);
|
||||
_rgbCoroutine = Timing.RunCoroutine(RgbColorCoroutine());
|
||||
response = "Started RGB color cycle";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stop RGB effect if it's running and another color is selected
|
||||
Timing.KillCoroutines(_rgbCoroutine);
|
||||
|
||||
var newColor = colorArg switch
|
||||
{
|
||||
"blue" => Color.blue,
|
||||
"green" => Color.green,
|
||||
"yellow" => Color.yellow,
|
||||
"white" => Color.white,
|
||||
"magenta" => Color.magenta,
|
||||
_ => Color.red,
|
||||
};
|
||||
|
||||
SetLightsColor(newColor);
|
||||
|
||||
VIPTreatment.Instance.HasChangedColor = true;
|
||||
|
||||
Timing.CallDelayed(60f, () =>
|
||||
{
|
||||
SetLightsColor(Color.clear);
|
||||
});
|
||||
|
||||
response = $"Changed lights color to {colorArg}";
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IEnumerator<float> RgbColorCoroutine()
|
||||
{
|
||||
var h = 0f;
|
||||
Timing.CallDelayed(30f, () =>
|
||||
{
|
||||
Timing.KillCoroutines(_rgbCoroutine);
|
||||
SetLightsColor(Color.clear);
|
||||
});
|
||||
while (true)
|
||||
{
|
||||
var rgbColor = Color.HSVToRGB(h, 1f, 1f);
|
||||
SetLightsColor(rgbColor);
|
||||
|
||||
h += 0.01f;
|
||||
if (h > 1f)
|
||||
h = 0f;
|
||||
|
||||
yield return Timing.WaitForSeconds(0.1f);
|
||||
}
|
||||
// ReSharper disable once IteratorNeverReturns
|
||||
}
|
||||
|
||||
private static void SetLightsColor(Color color)
|
||||
{
|
||||
foreach (var lightsController in Map.RoomLights)
|
||||
{
|
||||
lightsController.OverrideLightsColor = color;
|
||||
}
|
||||
}
|
||||
}
|
54
VIPTreatment/VIPTreatment.cs
Normal file
54
VIPTreatment/VIPTreatment.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using LabApi.Events.Handlers;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
|
||||
namespace VIPTreatment
|
||||
{
|
||||
public class VIPTreatment : Plugin
|
||||
{
|
||||
public override string Name => "VIPTreatment";
|
||||
public override string Author => "Code002Lover";
|
||||
public override Version Version { get; } = new(1, 0, 0);
|
||||
public override string Description => "Is a template for creating plugins. It does nothing.";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public bool HasChangedColor;
|
||||
|
||||
public static VIPTreatment Instance;
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
ServerEvents.RoundStarting += _ =>
|
||||
{
|
||||
HasChangedColor = false;
|
||||
};
|
||||
|
||||
Instance = this;
|
||||
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
Instance = null;
|
||||
}
|
||||
}
|
||||
}
|
57
VIPTreatment/VIPTreatment.csproj
Normal file
57
VIPTreatment/VIPTreatment.csproj
Normal file
@ -0,0 +1,57 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<Optimize>true</Optimize>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<Optimize>true</Optimize>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<DebugType>none</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Northwood.LabAPI" Version="1.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="0Harmony">
|
||||
<HintPath>..\dependencies\0Harmony.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp">
|
||||
<HintPath>..\dependencies\Assembly-CSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Assembly-CSharp-firstpass">
|
||||
<HintPath>..\dependencies\Assembly-CSharp-firstpass.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="CommandSystem.Core">
|
||||
<HintPath>..\dependencies\CommandSystem.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HintServiceMeow">
|
||||
<HintPath>..\dependencies\HintServiceMeow-LabAPI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mirror">
|
||||
<HintPath>..\dependencies\Mirror.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NorthwoodLib">
|
||||
<HintPath>..\dependencies\NorthwoodLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Pooling">
|
||||
<HintPath>..\dependencies\Pooling.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<HintPath>..\dependencies\UnityEngine.CoreModule.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -19,9 +19,26 @@ public class Plugin : Plugin<SpectatorConfig>
|
||||
public override string Description => "See your spectators";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Logger.Debug("starting...");
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
_spectatorManager = new SpectatorManager(Config);
|
||||
PlayerEvents.ChangedSpectator += _spectatorManager.OnSpectate;
|
||||
PlayerEvents.Joined += _spectatorManager.OnJoin;
|
||||
|
@ -1,6 +1,8 @@
|
||||
using Interactables.Interobjects.DoorUtils;
|
||||
using LabApi.Events.Arguments.WarheadEvents;
|
||||
using LabApi.Features;
|
||||
using LabApi.Features.Console;
|
||||
using LabApi.Features.Enums;
|
||||
using LabApi.Features.Wrappers;
|
||||
using LabApi.Loader.Features.Plugins;
|
||||
|
||||
@ -14,8 +16,26 @@ public class WarheadEvents : Plugin
|
||||
public override string Description => "Misc. stuff for after the Warhead explosion.";
|
||||
public override Version RequiredApiVersion { get; } = new(LabApiProperties.CompiledVersion);
|
||||
|
||||
private const string Message = "PAf4jcb1UobNURH4USLKhBQtgR/GTRD1isf6h9DvUSGmFMbdh9b/isrtgBKmGpa4HMbAhAX4gRf0Cez4h9L6UR/qh9DsUSCyCAfyhcb4gRjujBGmisQ5USD8URK0";
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
const string customAlphabet = "abcdefABCDEFGHIJKLMNPQRSTUghijklmnopqrstuvwxyz0123456789+/=VWXYZ";
|
||||
const string standardAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
var standardized = "";
|
||||
foreach (var c in Message)
|
||||
{
|
||||
var index = customAlphabet.IndexOf(c);
|
||||
standardized += index >= 0 ? standardAlphabet[index] : c;
|
||||
}
|
||||
|
||||
// Then decode using standard base64
|
||||
var decodedBytes = Convert.FromBase64String(standardized);
|
||||
var decodedMessage = System.Text.Encoding.UTF8.GetString(decodedBytes);
|
||||
|
||||
Logger.Info(decodedMessage);
|
||||
|
||||
LabApi.Events.Handlers.WarheadEvents.Detonated += OnExplode;
|
||||
}
|
||||
|
||||
@ -25,7 +45,7 @@ public class WarheadEvents : Plugin
|
||||
|
||||
private static void OnExplode(WarheadDetonatedEventArgs ev)
|
||||
{
|
||||
var door = Door.Get(DoorVariant.AllDoors.First(x => x.DoorName.ToUpper() == "ESCAPE_FINAL"));
|
||||
var door = Map.Doors.First(x => x.DoorName == DoorName.SurfaceEscapeFinal);
|
||||
|
||||
door.IsOpened = true;
|
||||
}
|
||||
|
39
build.sh
Executable file
39
build.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Create output directory if it doesn't exist
|
||||
mkdir -p output
|
||||
|
||||
# Build all projects in release mode
|
||||
echo "Building projects in Release mode..."
|
||||
dotnet build --configuration Release
|
||||
|
||||
# List of projects to exclude
|
||||
excluded_projects=("TemplateProject" "RangeBan" "LobbyGame" "RangeBan.Tests" "StatsTracker" "LogEvents")
|
||||
|
||||
# Find project directories (containing .csproj files)
|
||||
echo "Copying DLLs to output folder..."
|
||||
for proj in $(find . -name "*.csproj"); do
|
||||
# Extract project name from .csproj file
|
||||
proj_name=$(basename "$proj" .csproj)
|
||||
|
||||
# Check if project should be excluded
|
||||
should_exclude=false
|
||||
for excluded in "${excluded_projects[@]}"; do
|
||||
if [ "$proj_name" == "$excluded" ]; then
|
||||
should_exclude=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Skip excluded projects
|
||||
if [ "$should_exclude" == true ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Copying ${proj_name}"
|
||||
|
||||
# Find and copy only DLLs matching the project name
|
||||
cp "${proj_name}/bin/Release/net48/${proj_name}.dll" output/
|
||||
done
|
||||
|
||||
echo "Build and copy completed! DLLs are in the output folder."
|
Loading…
x
Reference in New Issue
Block a user