From 61192d2766a730487ebd2f00749dc99ebaf85312 Mon Sep 17 00:00:00 2001 From: Vretu <82831707+Vretu-Dev@users.noreply.github.com> Date: Sun, 29 Sep 2024 17:07:43 +0200 Subject: [PATCH] 1.4.0 | Code Refactor & More Configurable - Completely code refactor - More option in config --- UsefulHints/Config.cs | 48 +++++ UsefulHints/EventHandlers/Entities/SCP096.cs | 20 ++ UsefulHints/EventHandlers/Items/Hints.cs | 149 +++++++++++++++ .../Modules/JailbirdPatchHandler.cs | 27 +++ .../EventHandlers/Modules/KillCounter.cs | 39 ++++ .../Modules/LastHumanBroadcast.cs | 84 +++++++++ .../EventHandlers/Modules/RoundSummary.cs | 174 ++++++++++++++++++ .../EventHandlers/Modules/Teammates.cs | 50 +++++ UsefulHints/Patches/JailbirdPatch.cs | 39 ++++ UsefulHints/Properties/AssemblyInfo.cs | 36 ++++ UsefulHints/UsefulHints.cs | 39 ++++ UsefulHints/UsefulHints.csproj | 81 ++++++++ 12 files changed, 786 insertions(+) create mode 100644 UsefulHints/Config.cs create mode 100644 UsefulHints/EventHandlers/Entities/SCP096.cs create mode 100644 UsefulHints/EventHandlers/Items/Hints.cs create mode 100644 UsefulHints/EventHandlers/Modules/JailbirdPatchHandler.cs create mode 100644 UsefulHints/EventHandlers/Modules/KillCounter.cs create mode 100644 UsefulHints/EventHandlers/Modules/LastHumanBroadcast.cs create mode 100644 UsefulHints/EventHandlers/Modules/RoundSummary.cs create mode 100644 UsefulHints/EventHandlers/Modules/Teammates.cs create mode 100644 UsefulHints/Patches/JailbirdPatch.cs create mode 100644 UsefulHints/Properties/AssemblyInfo.cs create mode 100644 UsefulHints/UsefulHints.cs create mode 100644 UsefulHints/UsefulHints.csproj diff --git a/UsefulHints/Config.cs b/UsefulHints/Config.cs new file mode 100644 index 0000000..370cbca --- /dev/null +++ b/UsefulHints/Config.cs @@ -0,0 +1,48 @@ +using CustomPlayerEffects; +using Exiled.API.Enums; +using Exiled.API.Interfaces; +using System.ComponentModel; + +namespace UsefulHints +{ + public class Config : IConfig + { + public bool IsEnabled { get; set; } = true; + public bool Debug { get; set; } = false; + [Description("[Module] Hints:")] + public bool EnableHints { get; set; } = true; + public string Scp096LookMessage { get; set; } = "You looked at SCP-096!"; + public float Scp268Duration { get; set; } = 15f; + public string Scp268TimeLeftMessage { get; set; } = "Remaining: {0}s"; + public string Scp2176TimeLeftMessage { get; set; } = "Remaining: {0}s"; + public string JailbirdUseMessage { get; set; } = "Jailbird has been used {0}/5 times"; + public string Scp207HintMessage { get; set; } = "You are on {0} SCP-207"; + [Description("[Module] Kill Counter:")] + public bool EnableKillCounter { get; set; } = true; + public string KillCountMessage { get; set; } = "{0} kills"; + [Description("[Module] Round Summary:")] + public bool EnableRoundSummary { get; set; } = true; + public ushort RoundSummaryMessageDuration { get; set; } = 10; + public string HumanKillMessage { get; set; } = "{0} had the most kills as Human: {1}"; + public string ScpKillMessage { get; set; } = "{0} had the most kills as SCP: {1}"; + public string TopDamageMessage { get; set; } = "{0} did the most damage: {1}"; + public string FirstScpKillerMessage { get; set; } = "{0} was the first to kill SCP"; + public string EscaperMessage { get; set; } = "{0} escaped first from the facility: {1}:{2}"; + [Description("[Module] Teammates:")] + public bool EnableTeammates { get; set; } = true; + public float TeammateHintDelay { get; set; } = 4f; + public string TeammateHintMessage { get; set; } = "Your Teammates \n{0}"; + public float TeammateMessageDuration { get; set; } = 8f; + public string AloneHintMessage { get; set; } = "You are playing Solo"; + public float AloneMessageDuration { get; set; } = 4f; + [Description("[Module] Last Human Broadcast:")] + public bool EnableLastHumanBroadcast { get; set; } = true; + public string BroadcastForHuman { get; set; } = "You are the last human alive!"; + public string BroadcastForScp { get; set; } = "{0} is the last human alive playing as {1} in {2}"; + [Description("[Module] Jailbird Custom Settings:")] + public bool EnableCustomJailbirdSettings { get; set; } = false; + public EffectType JailbirdEffect { get; set; } = EffectType.Flashed; + public float JailbirdEffectDuration { get; set; } = 4f; + public byte JailbirdEffectIntensity { get; set; } = 1; + } +} \ No newline at end of file diff --git a/UsefulHints/EventHandlers/Entities/SCP096.cs b/UsefulHints/EventHandlers/Entities/SCP096.cs new file mode 100644 index 0000000..422223c --- /dev/null +++ b/UsefulHints/EventHandlers/Entities/SCP096.cs @@ -0,0 +1,20 @@ +using Exiled.Events.EventArgs.Scp096; + +namespace UsefulHints.EventHandlers.Entities +{ + public static class SCP096 + { + public static void RegisterEvents() + { + Exiled.Events.Handlers.Scp096.AddingTarget += OnScp096AddingTarget; + } + public static void UnregisterEvents() + { + Exiled.Events.Handlers.Scp096.AddingTarget -= OnScp096AddingTarget; + } + private static void OnScp096AddingTarget(AddingTargetEventArgs ev) + { + ev.Target.ShowHint(UsefulHints.Instance.Config.Scp096LookMessage, 5); + } + } +} \ No newline at end of file diff --git a/UsefulHints/EventHandlers/Items/Hints.cs b/UsefulHints/EventHandlers/Items/Hints.cs new file mode 100644 index 0000000..6cda0e8 --- /dev/null +++ b/UsefulHints/EventHandlers/Items/Hints.cs @@ -0,0 +1,149 @@ +using System.Linq; +using System.Collections.Generic; +using Exiled.API.Enums; +using Exiled.API.Extensions; +using Exiled.API.Features.Pickups; +using Player = Exiled.API.Features.Player; +using Exiled.Events.EventArgs.Map; +using Exiled.Events.EventArgs.Player; +using InventorySystem.Items.ThrowableProjectiles; +using MEC; + +namespace UsefulHints.EventHandlers.Items +{ + public static class Hints + { + private static readonly Dictionary activeCoroutines = new Dictionary(); + private static Dictionary activeItems = new Dictionary(); + public static void RegisterEvents() + { + Exiled.Events.Handlers.Player.PickingUpItem += OnPickingUpSCP207; + Exiled.Events.Handlers.Player.UsedItem += OnSCP268Used; + Exiled.Events.Handlers.Player.InteractingDoor += OnSCP268Interacting; + Exiled.Events.Handlers.Player.ChangedItem += OnSCP268ChangedItem; + Exiled.Events.Handlers.Map.ExplodingGrenade += OnSCP2176Grenade; + Exiled.Events.Handlers.Server.WaitingForPlayers += OnWaitingForPlayers; + Exiled.Events.Handlers.Player.PickingUpItem += OnPickingUpJailbird; + } + public static void UnregisterEvents() + { + Exiled.Events.Handlers.Player.PickingUpItem -= OnPickingUpSCP207; + Exiled.Events.Handlers.Player.UsedItem -= OnSCP268Used; + Exiled.Events.Handlers.Player.InteractingDoor -= OnSCP268Interacting; + Exiled.Events.Handlers.Player.ChangedItem -= OnSCP268ChangedItem; + Exiled.Events.Handlers.Map.ExplodingGrenade -= OnSCP2176Grenade; + Exiled.Events.Handlers.Server.WaitingForPlayers -= OnWaitingForPlayers; + Exiled.Events.Handlers.Player.PickingUpItem -= OnPickingUpJailbird; + } + // SCP 207 Handler + private static void OnPickingUpSCP207(PickingUpItemEventArgs ev) + { + if (ev.Pickup.Type == ItemType.SCP207) + { + CustomPlayerEffects.StatusEffectBase scp207Effect = ev.Player.ActiveEffects.FirstOrDefault(effect => effect.GetEffectType() == EffectType.Scp207); + + if (scp207Effect != null) + { + ev.Player.ShowHint($"{string.Format(UsefulHints.Instance.Config.Scp207HintMessage, scp207Effect.Intensity)}", 4); + } + } + } + // SCP 268 Handler + private static void OnSCP268Used(UsedItemEventArgs ev) + { + if (ev.Item.Type == ItemType.SCP268) + { + if (activeCoroutines.ContainsKey(ev.Player)) + { + Timing.KillCoroutines(activeCoroutines[ev.Player]); + activeCoroutines.Remove(ev.Player); + } + + var coroutine = Timing.RunCoroutine(Scp268Timer(ev.Player)); + activeCoroutines.Add(ev.Player, coroutine); + activeItems.Add(ev.Player, ev.Item.Type); + } + } + private static void OnSCP268Interacting(InteractingDoorEventArgs ev) + { + if (activeCoroutines.ContainsKey(ev.Player) && activeItems.ContainsKey(ev.Player) && activeItems[ev.Player] == ItemType.SCP268) + { + Timing.KillCoroutines(activeCoroutines[ev.Player]); + activeCoroutines.Remove(ev.Player); + activeItems.Remove(ev.Player); + } + } + private static void OnSCP268ChangedItem(ChangedItemEventArgs ev) + { + if (activeCoroutines.ContainsKey(ev.Player) && activeItems.ContainsKey(ev.Player) && activeItems[ev.Player] == ItemType.SCP268) + { + Timing.KillCoroutines(activeCoroutines[ev.Player]); + activeCoroutines.Remove(ev.Player); + activeItems.Remove(ev.Player); + } + } + private static IEnumerator Scp268Timer(Player player) + { + float duration = UsefulHints.Instance.Config.Scp268Duration; + + while (duration > 0) + { + player.ShowHint($"{new string('\n', 10)}{string.Format(UsefulHints.Instance.Config.Scp268TimeLeftMessage, (int)duration)}", 1.15f); + yield return Timing.WaitForSeconds(1f); + duration -= 1f; + } + activeCoroutines.Remove(player); + } + // SCP 2176 Handler + private static void OnSCP2176Grenade(ExplodingGrenadeEventArgs ev) + { + if (ev.Projectile.Base is Scp2176Projectile) + { + if (ev.Player != null) + { + if (activeCoroutines.ContainsKey(ev.Player)) + { + Timing.KillCoroutines(activeCoroutines[ev.Player]); + activeCoroutines.Remove(ev.Player); + } + + var coroutine = Timing.RunCoroutine(Scp2176Timer(ev.Player)); + activeCoroutines.Add(ev.Player, coroutine); + } + } + } + private static IEnumerator Scp2176Timer(Player player) + { + float duration = 13f; + + while (duration > 0) + { + player.ShowHint($"{new string('\n', 10)}{string.Format(UsefulHints.Instance.Config.Scp2176TimeLeftMessage, (int)duration)}", 1.15f); + yield return Timing.WaitForSeconds(1f); + duration -= 1f; + } + activeCoroutines.Remove(player); + } + // Reset Coroutines + private static void OnWaitingForPlayers() + { + activeCoroutines.Clear(); + } + // Jailbird Handler + private static void OnPickingUpJailbird(PickingUpItemEventArgs ev) + { + if (ev.Pickup is JailbirdPickup jailbirdPickup) + { + int remainingCharges = jailbirdPickup.TotalCharges; + if (remainingCharges < 4) + { + ev.Player.ShowHint($"{string.Format(UsefulHints.Instance.Config.JailbirdUseMessage, remainingCharges)}", 4); + } + else + { + ev.Player.ShowHint($"{string.Format(UsefulHints.Instance.Config.JailbirdUseMessage, remainingCharges)}", 4); + } + } + } + } +} \ No newline at end of file diff --git a/UsefulHints/EventHandlers/Modules/JailbirdPatchHandler.cs b/UsefulHints/EventHandlers/Modules/JailbirdPatchHandler.cs new file mode 100644 index 0000000..ee6552b --- /dev/null +++ b/UsefulHints/EventHandlers/Modules/JailbirdPatchHandler.cs @@ -0,0 +1,27 @@ +using HarmonyLib; +using System; + +namespace UsefulHints.EventHandlers.Modules +{ + public static class JailbirdPatchHandler + { + public static Harmony Harmony { get; private set; } + public static string HarmonyName { get; private set; } + public static void RegisterEvents() + { + if (UsefulHints.Instance.Config.EnableCustomJailbirdSettings) + { + HarmonyName = $"com-vretu.uh-{DateTime.UtcNow.Ticks}"; + Harmony = new Harmony(HarmonyName); + Harmony.PatchAll(); + } + } + public static void UnregisterEvents() + { + if (UsefulHints.Instance.Config.EnableCustomJailbirdSettings) + { + Harmony.UnpatchAll(HarmonyName); + } + } + } +} \ No newline at end of file diff --git a/UsefulHints/EventHandlers/Modules/KillCounter.cs b/UsefulHints/EventHandlers/Modules/KillCounter.cs new file mode 100644 index 0000000..f62d013 --- /dev/null +++ b/UsefulHints/EventHandlers/Modules/KillCounter.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Player = Exiled.API.Features.Player; +using Exiled.Events.EventArgs.Player; + +namespace UsefulHints.EventHandlers.Modules +{ + public static class KillCounter + { + private static readonly Dictionary playerKills = new Dictionary(); + public static void RegisterEvents() + { + Exiled.Events.Handlers.Player.Died += OnPlayerDied; + } + public static void UnregisterEvents() + { + Exiled.Events.Handlers.Player.Died -= OnPlayerDied; + } + private static void OnPlayerDied(DiedEventArgs ev) + { + if (UsefulHints.Instance.Config.EnableKillCounter) + { + if (ev.Attacker != null && ev.Attacker != ev.Player) + { + Player killer = ev.Attacker; + + if (playerKills.ContainsKey(killer)) + { + playerKills[killer]++; + } + else + { + playerKills[killer] = 1; + } + killer.ShowHint(string.Format(UsefulHints.Instance.Config.KillCountMessage, playerKills[killer]), 4); + } + } + } + } +} diff --git a/UsefulHints/EventHandlers/Modules/LastHumanBroadcast.cs b/UsefulHints/EventHandlers/Modules/LastHumanBroadcast.cs new file mode 100644 index 0000000..9ac3106 --- /dev/null +++ b/UsefulHints/EventHandlers/Modules/LastHumanBroadcast.cs @@ -0,0 +1,84 @@ +using System.Linq; +using Exiled.API.Enums; +using Exiled.API.Features; +using Exiled.Events.EventArgs.Player; +using PlayerRoles; + +namespace UsefulHints.EventHandlers.Modules +{ + public static class LastHumanBroadcast + { + public static void RegisterEvents() + { + Exiled.Events.Handlers.Player.Died += OnPlayerDied; + } + public static void UnregisterEvents() + { + Exiled.Events.Handlers.Player.Died -= OnPlayerDied; + } + private static void OnPlayerDied(DiedEventArgs ev) + { + if (UsefulHints.Instance.Config.EnableLastHumanBroadcast) + { + var aliveHumans = Player.List.Where(p => p.IsAlive && IsHuman(p)); + + if (aliveHumans.Count() == 1) + { + Player lastAlive = aliveHumans.First(); + + lastAlive.Broadcast(10, UsefulHints.Instance.Config.BroadcastForHuman); + + var zone = GetZoneName(lastAlive); + var teamName = GetRoleTeamName(lastAlive); + + string message = string.Format(UsefulHints.Instance.Config.BroadcastForScp, lastAlive.Nickname, teamName, zone); + + foreach (var scp in Player.List.Where(p => p.Role.Team == Team.SCPs)) + { + scp.Broadcast(10, message); + } + } + } + } + private static bool IsHuman(Player player) + { + return player.Role.Team == Team.FoundationForces || player.Role.Team == Team.ClassD || player.Role.Team == Team.Scientists || player.Role.Team == Team.ChaosInsurgency; + } + private static string GetZoneName(Player player) + { + ZoneType zone = player.CurrentRoom.Zone; + + switch (zone) + { + case ZoneType.LightContainment: + return "Light Containment"; + case ZoneType.HeavyContainment: + return "Heavy Containment"; + case ZoneType.Entrance: + return "Entrance Zone"; + case ZoneType.Surface: + return "Surface"; + default: + return "Unknown Zone"; + } + } + private static string GetRoleTeamName(Player player) + { + Team team = player.Role.Team; + + switch (team) + { + case Team.FoundationForces: + return "Mobile Task Force"; + case Team.ClassD: + return "Class D"; + case Team.Scientists: + return "Scientist"; + case Team.ChaosInsurgency: + return "Chaos Insurgency"; + default: + return "Unknown Team"; + } + } + } +} diff --git a/UsefulHints/EventHandlers/Modules/RoundSummary.cs b/UsefulHints/EventHandlers/Modules/RoundSummary.cs new file mode 100644 index 0000000..f9f5f17 --- /dev/null +++ b/UsefulHints/EventHandlers/Modules/RoundSummary.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using Exiled.API.Features; +using Player = Exiled.API.Features.Player; +using Exiled.Events.EventArgs.Player; +using Exiled.Events.EventArgs.Server; +using PlayerRoles; +using static Broadcast; + +namespace UsefulHints.EventHandlers.Modules +{ + public static class RoundSummary + { + private static Dictionary scpKills = new Dictionary(); + private static Dictionary humanKills = new Dictionary(); + private static Dictionary humanDamage = new Dictionary(); + + private static Player firstEscaper = null; + private static Player firstScpKiller = null; + private static DateTime roundStartTime; + private static TimeSpan escapeTime; + + public static void RegisterEvents() + { + Exiled.Events.Handlers.Player.Died += OnPlayerDied; + Exiled.Events.Handlers.Player.Dying += OnPlayerDying; + Exiled.Events.Handlers.Player.Escaping += OnPlayerEscaping; + Exiled.Events.Handlers.Player.Hurting += OnPlayerHurting; + Exiled.Events.Handlers.Server.RoundEnded += OnRoundEnded; + Exiled.Events.Handlers.Server.RestartingRound += OnRestartingRound; + Exiled.Events.Handlers.Server.RoundStarted += OnRoundStarted; + } + public static void UnregisterEvents() + { + Exiled.Events.Handlers.Player.Died -= OnPlayerDied; + Exiled.Events.Handlers.Player.Dying -= OnPlayerDying; + Exiled.Events.Handlers.Player.Escaping -= OnPlayerEscaping; + Exiled.Events.Handlers.Player.Hurting -= OnPlayerHurting; + Exiled.Events.Handlers.Server.RoundEnded -= OnRoundEnded; + Exiled.Events.Handlers.Server.RestartingRound -= OnRestartingRound; + Exiled.Events.Handlers.Server.RoundStarted -= OnRoundStarted; + } + private static void OnRoundStarted() + { + roundStartTime = DateTime.Now; + } + // Handler for player hurting another player + private static void OnPlayerHurting(HurtingEventArgs ev) + { + Player attacker = ev.Attacker; + Player victim = ev.Player; + + if (attacker != null && attacker != victim && attacker.Role.Team != Team.SCPs && victim.Role.Team == Team.SCPs) + { + if (!humanDamage.ContainsKey(attacker)) + humanDamage[attacker] = 0; + + humanDamage[attacker] += (int)Math.Round(ev.Amount); + } + } + // Handler for "When Player dying" (FirstScpKiller) + private static void OnPlayerDying(DyingEventArgs ev) + { + Player attacker = ev.Attacker; + Player victim = ev.Player; + + if (victim.Role.Team == Team.SCPs && victim.Role.Type != RoleTypeId.Scp0492) + { + if (firstScpKiller == null) + { + firstScpKiller = attacker; + } + } + } + // Handler for "When Player died" (SCP and Human kill count) + private static void OnPlayerDied(DiedEventArgs ev) + { + Player attacker = ev.Attacker; + + if (attacker != null && attacker != ev.Player) + { + if (attacker.Role.Team == Team.SCPs) + { + if (!scpKills.ContainsKey(attacker)) + scpKills[attacker] = 0; + + scpKills[attacker]++; + } + else + { + if (!humanKills.ContainsKey(attacker)) + humanKills[attacker] = 0; + + humanKills[attacker]++; + } + } + } + // Handler for Escaped Player + private static void OnPlayerEscaping(EscapingEventArgs ev) + { + if (firstEscaper == null) + { + firstEscaper = ev.Player; + escapeTime = DateTime.Now - roundStartTime; + } + } + // Handler for End Round messages + private static void OnRoundEnded(RoundEndedEventArgs ev) + { + if (UsefulHints.Instance.Config.EnableRoundSummary) + { + string text = ""; + + Player humanKiller = GetTopKiller(humanKills); + Player scpKiller = GetTopKiller(scpKills); + Player topDamageDealer = GetTopDamageDealer(humanDamage); + + if (humanKiller != null) + text += string.Format(UsefulHints.Instance.Config.HumanKillMessage, humanKiller.Nickname, humanKills[humanKiller]) + "\n"; + if (scpKiller != null) + text += string.Format(UsefulHints.Instance.Config.ScpKillMessage, scpKiller.Nickname, scpKills[scpKiller]) + "\n"; + if (topDamageDealer != null) + text += string.Format(UsefulHints.Instance.Config.TopDamageMessage, topDamageDealer.Nickname, humanDamage[topDamageDealer]) + "\n"; + if (firstEscaper != null) + text += string.Format(UsefulHints.Instance.Config.EscaperMessage, firstEscaper.Nickname, escapeTime.Minutes, escapeTime.Seconds) + "\n"; + if (firstScpKiller != null) + text += string.Format(UsefulHints.Instance.Config.FirstScpKillerMessage, firstScpKiller.Nickname) + "\n"; + if (!string.IsNullOrEmpty(text)) + Map.Broadcast(UsefulHints.Instance.Config.RoundSummaryMessageDuration, text, BroadcastFlags.Normal, true); + } + } + // Reset Handlers + private static void OnRestartingRound() + { + scpKills.Clear(); + humanKills.Clear(); + humanDamage.Clear(); + firstEscaper = null; + firstScpKiller = null; + } + // Helper to find player with most kills + private static Player GetTopKiller(Dictionary kills) + { + Player topKiller = null; + int maxKills = 0; + + foreach (var entry in kills) + { + if (entry.Value > maxKills) + { + topKiller = entry.Key; + maxKills = entry.Value; + } + } + return topKiller; + } + // Helper to find player with most damage + private static Player GetTopDamageDealer(Dictionary damage) + { + Player topDealer = null; + float maxDamage = 0; + + foreach (var entry in damage) + { + if (entry.Value > maxDamage) + { + topDealer = entry.Key; + maxDamage = entry.Value; + } + } + return topDealer; + } + } +} diff --git a/UsefulHints/EventHandlers/Modules/Teammates.cs b/UsefulHints/EventHandlers/Modules/Teammates.cs new file mode 100644 index 0000000..67950db --- /dev/null +++ b/UsefulHints/EventHandlers/Modules/Teammates.cs @@ -0,0 +1,50 @@ +using System.Linq; +using System.Collections.Generic; +using Player = Exiled.API.Features.Player; +using MEC; + +namespace UsefulHints.EventHandlers.Modules +{ + public static class Teammates + { + public static void RegisterEvents() + { + Exiled.Events.Handlers.Server.RoundStarted += OnRoundStartedTeammates; + } + public static void UnregisterEvents() + { + Exiled.Events.Handlers.Server.RoundStarted -= OnRoundStartedTeammates; + } + private static IEnumerator DelayedDisplayTeammates() + { + yield return Timing.WaitForSeconds(UsefulHints.Instance.Config.TeammateHintDelay); + DisplayTeammates(); + } + private static void OnRoundStartedTeammates() + { + Timing.RunCoroutine(DelayedDisplayTeammates()); + } + private static void DisplayTeammates() + { + if (UsefulHints.Instance.Config.EnableTeammates) + { + foreach (var player in Player.List) + { + List teammates = Player.List + .Where(p => p.Role.Team == player.Role.Team && p != player) + .Select(p => p.Nickname) + .ToList(); + + if (teammates.Count > 0) + { + player.ShowHint(string.Format(UsefulHints.Instance.Config.TeammateHintMessage, string.Join("\n", teammates)), UsefulHints.Instance.Config.TeammateMessageDuration); + } + else + { + player.ShowHint(string.Format(UsefulHints.Instance.Config.AloneHintMessage), UsefulHints.Instance.Config.AloneMessageDuration); + } + } + } + } + } +} diff --git a/UsefulHints/Patches/JailbirdPatch.cs b/UsefulHints/Patches/JailbirdPatch.cs new file mode 100644 index 0000000..c90279e --- /dev/null +++ b/UsefulHints/Patches/JailbirdPatch.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using Exiled.API.Features; +using Exiled.API.Features.Pools; +using HarmonyLib; +using InventorySystem.Items.Jailbird; + +namespace UsefulHints.Patches +{ + [HarmonyPatch(typeof(JailbirdHitreg), "ServerAttack")] + public static class JailbirdPatch + { + public static void EnableEffect(HitboxIdentity hitboxIdentity) + { + Player val = Player.Get(hitboxIdentity.TargetHub); + val.EnableEffect(UsefulHints.Instance.Config.JailbirdEffect, UsefulHints.Instance.Config.JailbirdEffectIntensity, UsefulHints.Instance.Config.JailbirdEffectDuration, true); + Log.Debug("Effect Activated"); + } + + [HarmonyTranspiler] + public static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + List newInstructions = ListPool.Pool.Get(instructions); + int index = newInstructions.FindLastIndex((CodeInstruction code) => code.opcode == OpCodes.Ldfld && (FieldInfo)code.operand == AccessTools.Field(typeof(ReferenceHub), "playerEffectsController")) + 3; + newInstructions.InsertRange(index, new CodeInstruction[2] + { + new CodeInstruction(OpCodes.Ldloc_S, 12), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(JailbirdPatch), nameof(EnableEffect), new Type[1] { typeof(HitboxIdentity) })) + }); + for (int z = 0; z < newInstructions.Count; z++) + { + yield return newInstructions[z]; + } + ListPool.Pool.Return(newInstructions); + } + } +} \ No newline at end of file diff --git a/UsefulHints/Properties/AssemblyInfo.cs b/UsefulHints/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..59e4bd6 --- /dev/null +++ b/UsefulHints/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Ogólne informacje o zestawie są kontrolowane poprzez następujący +// zestaw atrybutów. Zmień wartości tych atrybutów, aby zmodyfikować informacje +// powiązane z zestawem. +[assembly: AssemblyTitle("UsefulHints")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("UsefulHints")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Ustawienie elementu ComVisible na wartość false sprawia, że typy w tym zestawie są niewidoczne +// dla składników COM. Jeśli potrzebny jest dostęp do typu w tym zestawie z +// COM, ustaw wartość true dla atrybutu ComVisible tego typu. +[assembly: ComVisible(false)] + +// Następujący identyfikator GUID jest identyfikatorem biblioteki typów w przypadku udostępnienia tego projektu w modelu COM +[assembly: Guid("8e4e5067-3ada-48dd-a6c4-57b8aecd24cd")] + +// Informacje o wersji zestawu zawierają następujące cztery wartości: +// +// Wersja główna +// Wersja pomocnicza +// Numer kompilacji +// Poprawka +// +// Możesz określić wszystkie wartości lub użyć domyślnych numerów kompilacji i poprawki +// przy użyciu symbolu „*”, tak jak pokazano poniżej: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/UsefulHints/UsefulHints.cs b/UsefulHints/UsefulHints.cs new file mode 100644 index 0000000..e1f8a13 --- /dev/null +++ b/UsefulHints/UsefulHints.cs @@ -0,0 +1,39 @@ +using System; +using Exiled.API.Features; + +namespace UsefulHints +{ + public class UsefulHints : Plugin + { + public override string Name => "Useful Hints"; + public override string Author => "Vretu"; + public override string Prefix { get; } = "UH"; + public override Version Version => new Version(1, 4, 0); + public override Version RequiredExiledVersion { get; } = new Version(8, 9, 8); + public static UsefulHints Instance { get; private set; } + public override void OnEnabled() + { + Instance = this; + if(Config.EnableHints){ EventHandlers.Entities.SCP096.RegisterEvents(); } + if(Config.EnableHints){ EventHandlers.Items.Hints.RegisterEvents(); } + EventHandlers.Modules.JailbirdPatchHandler.RegisterEvents(); + EventHandlers.Modules.KillCounter.RegisterEvents(); + EventHandlers.Modules.LastHumanBroadcast.RegisterEvents(); + EventHandlers.Modules.RoundSummary.RegisterEvents(); + EventHandlers.Modules.Teammates.RegisterEvents(); + base.OnEnabled(); + } + public override void OnDisabled() + { + Instance = null; + if(Config.EnableHints){ EventHandlers.Entities.SCP096.UnregisterEvents(); } + if(Config.EnableHints){ EventHandlers.Items.Hints.UnregisterEvents(); } + EventHandlers.Modules.JailbirdPatchHandler.UnregisterEvents(); + EventHandlers.Modules.KillCounter.UnregisterEvents(); + EventHandlers.Modules.LastHumanBroadcast.UnregisterEvents(); + EventHandlers.Modules.RoundSummary.UnregisterEvents(); + EventHandlers.Modules.Teammates.UnregisterEvents(); + base.OnDisabled(); + } + } +} \ No newline at end of file diff --git a/UsefulHints/UsefulHints.csproj b/UsefulHints/UsefulHints.csproj new file mode 100644 index 0000000..98d63b8 --- /dev/null +++ b/UsefulHints/UsefulHints.csproj @@ -0,0 +1,81 @@ + + + + + Debug + AnyCPU + {8E4E5067-3ADA-48DD-A6C4-57B8AECD24CD} + Library + Properties + UsefulHints + UsefulHints + v4.8 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Exiled References\Assembly-CSharp-firstpass.dll + + + ..\..\Exiled References\Mirror.dll + + + + + + + + + + + ..\..\Exiled References\UnityEngine.dll + + + ..\..\Exiled References\UnityEngine.CoreModule.dll + + + ..\..\Exiled References\UnityEngine.PhysicsModule.dll + + + + + + + + + + + + + + + + + + 8.12.2 + + + 2.3.3 + + + + + \ No newline at end of file