Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions SillySCP/API/Features/Scp049DataStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using LabApi.Events.Arguments.PlayerEvents;
using LabApi.Events.Arguments.Scp049Events;
using LabApi.Events.Handlers;
using LabApi.Features.Stores;
using LabApi.Features.Wrappers;
using PlayerRoles;
using SecretAPI.Features;
using UnityEngine;
using Logger = LabApi.Features.Console.Logger;

namespace SillySCP.API.Features
{
public class LastKnownInformation
{
public Vector3 Position { get; set; }

public float Health { get; set; }

public float MaxHealth { get; set; }

public float HumeShield { get; set; }

public float MaxHumeShield { get; set; }
}
public class Scp049DataStore : CustomDataStore
{
public Scp049DataStore(Player player)
: base(player)
{
ActiveStores.Add(this);
}

/// <summary>
/// List of IDs of people who have left which should be SCP-049-2.
/// </summary>
public Dictionary<string, LastKnownInformation> Leavers { get; } = [];

public List<Player> ActivePlayers { get; } = [];

public static List<Scp049DataStore> ActiveStores { get; } = [];
}
}
74 changes: 74 additions & 0 deletions SillySCP/Handlers/Scp049Handler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using LabApi.Events.Arguments.PlayerEvents;
using LabApi.Events.Arguments.Scp049Events;
using LabApi.Events.Handlers;
using LabApi.Features.Console;
using PlayerRoles;
using SecretAPI.Features;
using SillySCP.API.Features;

namespace SillySCP.Handlers
{
public class Scp049Handler : IRegister
{
public void TryRegister()
{
Scp049Events.ResurrectedBody += OnRevived;
PlayerEvents.Dying += OnDying;
PlayerEvents.Joined += OnJoined;
ServerEvents.RoundRestarted += OnRoundRestarted;
}

public void TryUnregister()
{
Scp049Events.ResurrectedBody -= OnRevived;
PlayerEvents.Dying -= OnDying;
PlayerEvents.Joined -= OnJoined;
ServerEvents.RoundRestarted -= OnRoundRestarted;
}

public static void OnRevived(Scp049ResurrectedBodyEventArgs ev)
{
Scp049DataStore store = ev.Player.GetDataStore<Scp049DataStore>();
store.ActivePlayers.Add(ev.Target);
}

public static void OnDying(PlayerDyingEventArgs ev)
{
if(ev.Player.Role == RoleTypeId.Scp049)
Scp049DataStore.ActiveStores.Remove(Scp049DataStore.ActiveStores.FirstOrDefault(store => store.Owner == ev.Player));

if (ev.Player.Role != RoleTypeId.Scp0492)
return;

foreach (Scp049DataStore store in Scp049DataStore.ActiveStores.Where(store => store.ActivePlayers.Contains(ev.Player)))
{
store.ActivePlayers.Remove(ev.Player);
}
}

public static void OnJoined(PlayerJoinedEventArgs ev)
{
Scp049DataStore store = Scp049DataStore.ActiveStores.FirstOrDefault(store => store.Leavers.ContainsKey(ev.Player.UserId));
if (store == null)
return;

store.ActivePlayers.Add(ev.Player);

LastKnownInformation info = store.Leavers[ev.Player.UserId];

ev.Player.Role = RoleTypeId.Scp0492;
ev.Player.MaxHealth = info.MaxHealth;
ev.Player.Health = info.Health;
ev.Player.MaxHumeShield = info.MaxHumeShield;
ev.Player.HumeShield = info.HumeShield;
ev.Player.Position = info.Position;

store.Leavers.Remove(ev.Player.UserId);
}

public static void OnRoundRestarted()
{
Scp049DataStore.ActiveStores.Clear();
}
}
}
86 changes: 86 additions & 0 deletions SillySCP/Patches/DisconnectPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System.Reflection.Emit;
using HarmonyLib;
using Interactables.Interobjects.DoorUtils;
using LabApi.Features.Wrappers;
using MapGeneration;
using PlayerRoles;
using PlayerStatsSystem;
using SillySCP.API.Features;
using UnityEngine;
using Logger = LabApi.Features.Console.Logger;

namespace SillySCP.Patches
{
[HarmonyPatch(typeof(CustomNetworkManager), nameof(CustomNetworkManager.OnServerDisconnect))]
public static class DisconnectPatch
{
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
CodeMatcher matcher = new CodeMatcher(instructions)
.MatchStartForward(
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(PlayerStats), nameof(PlayerStats.DealDamage)))
)
.Advance(-6)
.Insert(
new CodeInstruction(OpCodes.Ldloc_1),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(DisconnectPatch), nameof(OnBeforeDeath)))
);

return matcher.InstructionEnumeration();
}

public static void OnBeforeDeath(ReferenceHub hub)
{
Player player = Player.Get(hub);

if (player is not { Role: RoleTypeId.Scp0492 })
return;

Scp049DataStore store = Scp049DataStore.ActiveStores.FirstOrDefault(store => store.ActivePlayers.Contains(player));
if (store == null)
return;

Vector3 position;

if (player.Room != null)
{
IEnumerable<Door> doors = player.Room.Doors.Where(door =>
door is not ElevatorDoor && !door.IsLocked && door.Permissions.HasFlag(DoorPermissionFlags.None));

float closestDistance = float.MaxValue;
Door closestDoor = null;
foreach (Door door in doors)
{
if (Vector3.Distance(door.Position, player.Position) >= closestDistance)
continue;
closestDistance = Vector3.Distance(door.Position, player.Position);
closestDoor = door;
}

position = closestDoor?.Position ?? player.Room.Position;
position += Vector3.one;

if (player.Room.Name is RoomName.EzGateA or RoomName.EzGateB or RoomName.HczCheckpointToEntranceZone)
{
position = player.Position;
}
}
else
{
position = player.Position;
}

LastKnownInformation info = new()
{
Position = position,
Health = player.Health,
MaxHealth = player.MaxHealth,
HumeShield = player.HumeShield,
MaxHumeShield = player.MaxHumeShield,
};

store.Leavers.Add(player.UserId, info);
store.ActivePlayers.Remove(player);
}
}
}
Loading