From d0ac97188361b51f64b8381132649e2641ac10d3 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Sat, 4 Jul 2026 23:30:50 +0800 Subject: [PATCH 01/21] =?UTF-8?q?feat:=20=E7=AD=89=E7=BA=A7=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=9F=BA=E7=A1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Commands/Level/XpCommand.cs | 47 +++++++++++++++++++++++++ Configs/TranslateConfig.cs | 7 ++++ DataBase/InfoExtension.cs | 2 ++ DataBase/Serialization/PlayerData.cs | 2 ++ EasyTools.csproj | 2 ++ Events/CustomEventHandler.cs | 49 +++++++++++++++++++++++++- Utils/LevelUtils.cs | 51 ++++++++++++++++++++++++++++ 7 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 Commands/Level/XpCommand.cs create mode 100644 Utils/LevelUtils.cs diff --git a/Commands/Level/XpCommand.cs b/Commands/Level/XpCommand.cs new file mode 100644 index 0000000..206a65b --- /dev/null +++ b/Commands/Level/XpCommand.cs @@ -0,0 +1,47 @@ +using CommandSystem; +using EasyTools.Configs; +using EasyTools.DataBase; +using EasyTools.DataBase.Serialization; +using EasyTools.Events; +using EasyTools.Utils; +using LabApi.Features.Wrappers; +using System; + +namespace EasyTools.Commands.Level +{ + [CommandHandler(typeof(ClientCommandHandler))] + public class XpCommand : ICommand + { + public string Command => "xp"; + + public string[] Aliases => []; + + public string Description => "查询经验"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + TranslateConfig TranslateConfig = CustomEventHandler.TranslateConfig; + Player player; + + if (sender is null || (player = Player.Get(sender)) is null) + { + response = TranslateConfig.RescueCommandError; + return false; + } + + if (!CustomEventHandler.DataBaseConfig.database_enable) + { + response = TranslateConfig.LevelCommandFailed; + return false; + } + + PlayerData data = player.GetData(); + double xp = data.PlayerXp; + int level = LevelUtils.GetLevelFromXp(xp, 1); + double needXp = LevelUtils.GetXpUntilNextLevel(xp, 1); + + response = $"你的等级: {level} | 当前经验: {xp} | 升级还需: {needXp} XP"; + return true; + } + } +} diff --git a/Configs/TranslateConfig.cs b/Configs/TranslateConfig.cs index 0f38434..46066f5 100644 --- a/Configs/TranslateConfig.cs +++ b/Configs/TranslateConfig.cs @@ -90,5 +90,12 @@ public class TranslateConfig { Scp914KnobSetting.Fine, "精加" }, { Scp914KnobSetting.VeryFine, "超精加工" } }; + /// + /// + /// + [Description("等级系统_查询失败")] + public string LevelCommandFailed { get; set; } = "查询失败,等级系统未启用"; + [Description("等级系统_查询成功")] + public string LevelCommandOk { get; set; } = "您当前的经验值为: "; } } diff --git a/DataBase/InfoExtension.cs b/DataBase/InfoExtension.cs index 8c01266..756aace 100644 --- a/DataBase/InfoExtension.cs +++ b/DataBase/InfoExtension.cs @@ -35,6 +35,8 @@ public static PlayerData GetData(this Player ply) PlayerDamage = 0, RolePlayed = 0, PlayerShot = 0, + PlayerXp = 0.0, + PlayerLevel = 0.0 }; using LiteDatabase database = new(CustomEventHandler.DataBaseConfig.database_path); database.GetCollection("Players").Insert(toInsert); diff --git a/DataBase/Serialization/PlayerData.cs b/DataBase/Serialization/PlayerData.cs index 5933e59..69477c3 100644 --- a/DataBase/Serialization/PlayerData.cs +++ b/DataBase/Serialization/PlayerData.cs @@ -16,6 +16,8 @@ public class PlayerData public float PlayerDamage { get; set; } public int RolePlayed { get; set; } public int PlayerShot { get; set; } + public double PlayerXp { get; set; } + public double PlayerLevel { get; set; } [BsonId] public string ID { get; set; } } diff --git a/EasyTools.csproj b/EasyTools.csproj index de27bde..b153c12 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -126,6 +126,7 @@ + @@ -142,6 +143,7 @@ + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index fb68bee..3fc9b96 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -1,8 +1,8 @@ using EasyTools.BadgeSystem; using EasyTools.Configs; +using EasyTools.DataBase; using EasyTools.DataBase.Serialization; using EasyTools.Utils; -using Hints; using InventorySystem.Items; using LabApi.Events.Arguments.PlayerEvents; using LabApi.Events.Arguments.Scp914Events; @@ -70,6 +70,11 @@ public override void OnServerRoundStarted() } _huds.Values.ToList().ForEach(h => h.Start()); }); + + if (DataBaseConfig.database_enable) + { + Timing.RunCoroutine(InfoExtension.CollectInfo()); + } } public override void OnServerRoundEnded(RoundEndedEventArgs ev) @@ -98,6 +103,16 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) ChatUtils.InitForPlayer(player); + if (DataBaseConfig.database_enable) + { + InfoExtension.PlayerList.Add(player); + PlayerData data = player.GetData(); + data.NickName = player.Nickname; + data.LastJoinedTime = DateTime.Now; + data.UpdateData(); + LevelUtils.UpdatePlayerNameWithLevelPrefix(player); + } + if (Config.EnableLogger) { string playerInfo = $"[JOIN] Date: {DateTime.Now} | Player: {player.Nickname} | IP: {player.IpAddress} | Steam64ID: {player.UserId}"; @@ -121,6 +136,14 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) if (player == null || string.IsNullOrEmpty(player.UserId)) return; + if (DataBaseConfig.database_enable) + { + InfoExtension.PlayerList.Remove(player); + PlayerData data = player.GetData(); + data.LastJoinedTime = DateTime.Now; + data.UpdateData(); + } + if (Config.EnableLogger) { string playerInfo = $"[EXIT] Date: {DateTime.Now} | Player: {player.Nickname} | IP: {player.IpAddress} | Steam64ID: {player.UserId}"; @@ -210,7 +233,31 @@ public override void OnPlayerSpawned(PlayerSpawnedEventArgs ev) { Player.AddItem(ItemType.Coin); }); + + public override void OnPlayerDeath(PlayerDeathEventArgs ev) + { + // 避免处理非玩家击杀或无效情况 + if (ev.Attacker == null || ev.Player == null) + return; + + bool tgtwasSCP = ev.Player.IsSCP && ev.Player.Role != RoleTypeId.Scp0492; + + + // 给击杀者添加经验 + PlayerData data = ev.Player.GetData(); + + + if (tgtwasSCP) + { + data.PlayerXp += 50.0; } + else + { + data.PlayerXp += 5.0; + } + + data.PlayerLevel = LevelUtils.GetLevelFromXp(data.PlayerXp, 1); + LevelUtils.UpdatePlayerNameWithLevelPrefix(ev.Attacker); } diff --git a/Utils/LevelUtils.cs b/Utils/LevelUtils.cs new file mode 100644 index 0000000..8709132 --- /dev/null +++ b/Utils/LevelUtils.cs @@ -0,0 +1,51 @@ +using EasyTools.DataBase; +using LabApi.Features.Wrappers; +using System; + +namespace EasyTools.Utils +{ + public static class LevelUtils + { + /// + /// 根据经验值计算当前等级 + /// + public static int GetLevelFromXp(double xp, double a) + { + if (xp < 0) xp = 0; + double level = -50.0 + Math.Sqrt((4.0 * xp / a) + 9800.0) / 2.0; + return (int)Math.Ceiling(level); + } + + /// + /// 从0级升到指定等级所需的总经验 + /// + public static double GetTotalXpForLevel(int level, double a) + { + if (level < 0) level = 0; + return Math.Ceiling((level * level + 100.0 * level + 50.0) * a); + } + + /// + /// 当前经验值下,升级到下一级还需要的经验 + /// + public static double GetXpUntilNextLevel(double currentXp, double a) + { + int currentLevel = GetLevelFromXp(currentXp, a); + if (currentLevel < 0) currentLevel = 0; + double nextLevelTotal = GetTotalXpForLevel(currentLevel + 1, a); + return Math.Max(0, nextLevelTotal - currentXp); + } + + // 玩家名称更新方法 + public static void UpdatePlayerNameWithLevelPrefix(Player player) + { + if (player == null || player.IsNpc) return; + + string originalName = player.Nickname; + + // 设置新名称(前缀+原始名称) + string newName = $"[Level.{player.GetData().PlayerLevel}]{originalName}"; + player.DisplayName = newName; + } + } +} From 48fbdae8e218c798b288935f4c7effb5bc702472 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Sat, 4 Jul 2026 23:41:43 +0800 Subject: [PATCH 02/21] =?UTF-8?q?feat:=20=E5=87=BB=E6=9D=80SCP=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=BB=8F=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 3cxc <81449257+3cxc@users.noreply.github.com> --- Events/CustomEventHandler.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 3fc9b96..5eb8630 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -258,6 +258,25 @@ public override void OnPlayerDeath(PlayerDeathEventArgs ev) data.PlayerLevel = LevelUtils.GetLevelFromXp(data.PlayerXp, 1); LevelUtils.UpdatePlayerNameWithLevelPrefix(ev.Attacker); + } + + public override void OnPlayerDeath(PlayerDeathEventArgs ev) + { + // 避免处理非玩家击杀或无效情况 + if (ev.Attacker == null || ev.Player == null) + return; + + bool tgtwasSCP = ev.Player.IsSCP && ev.Player.Role != RoleTypeId.Scp0492; + + + // 给击杀者添加经验 + PlayerData data = ev.Player.GetData(); + + + if (tgtwasSCP) + { + data.PlayerXp += 50.0; + } } From 73c779abdd806906cc772008e6cf8747370b6276 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:50:40 +0800 Subject: [PATCH 03/21] =?UTF-8?q?refactor:=20=E5=B0=86=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=B1=BB=E4=BB=8E=20Utils=20=E7=A7=BB=E5=87=BA=E5=B9=B6?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Util 重命名为 ServerBroadcastHelper - ScpReal 重命名为 ScpAutoHealHelper - LevelUtils 重命名为 LevelExtensions --- Commands/Level/XpCommand.cs | 7 +++---- Configs/Config.cs | 3 +-- EasyTools.csproj | 8 ++++---- Events/CustomEventHandler.cs | 15 ++++++++------- .../InfoExtensions.cs | 7 ++++--- .../LevelExtensions.cs | 9 ++++----- Utils/ScpReal.cs => Helper/ScpAutoHealHelper.cs | 4 ++-- Utils/Util.cs => Helper/ServerBroadcastHelper.cs | 7 +++---- Plugins.cs | 1 + 9 files changed, 30 insertions(+), 31 deletions(-) rename DataBase/InfoExtension.cs => Extensions/InfoExtensions.cs (96%) rename Utils/LevelUtils.cs => Extensions/LevelExtensions.cs (88%) rename Utils/ScpReal.cs => Helper/ScpAutoHealHelper.cs (97%) rename Utils/Util.cs => Helper/ServerBroadcastHelper.cs (79%) diff --git a/Commands/Level/XpCommand.cs b/Commands/Level/XpCommand.cs index 206a65b..0e147f7 100644 --- a/Commands/Level/XpCommand.cs +++ b/Commands/Level/XpCommand.cs @@ -1,9 +1,8 @@ using CommandSystem; using EasyTools.Configs; -using EasyTools.DataBase; using EasyTools.DataBase.Serialization; using EasyTools.Events; -using EasyTools.Utils; +using EasyTools.Extensions; using LabApi.Features.Wrappers; using System; @@ -37,8 +36,8 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s PlayerData data = player.GetData(); double xp = data.PlayerXp; - int level = LevelUtils.GetLevelFromXp(xp, 1); - double needXp = LevelUtils.GetXpUntilNextLevel(xp, 1); + int level = LevelExtensions.GetLevelFromXp(xp, 1); + double needXp = LevelExtensions.GetXpUntilNextLevel(xp, 1); response = $"你的等级: {level} | 当前经验: {xp} | 升级还需: {needXp} XP"; return true; diff --git a/Configs/Config.cs b/Configs/Config.cs index de3d032..7468dae 100644 --- a/Configs/Config.cs +++ b/Configs/Config.cs @@ -1,5 +1,4 @@ -using LabApi.Features.Wrappers; -using LabApi.Loader.Features.Paths; +using LabApi.Loader.Features.Paths; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/EasyTools.csproj b/EasyTools.csproj index b153c12..a5b3827 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -134,7 +134,7 @@ - + @@ -143,11 +143,11 @@ - + - - + + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index e0340d9..c58053f 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -1,7 +1,8 @@ using EasyTools.BadgeSystem; using EasyTools.Configs; -using EasyTools.DataBase; using EasyTools.DataBase.Serialization; +using EasyTools.Extensions; +using EasyTools.Helper; using EasyTools.Utils; using InventorySystem.Items; using LabApi.Events.Arguments.PlayerEvents; @@ -61,19 +62,19 @@ public override void OnServerRoundStarted() { if (Config.EnableAutoServerMessage) { - Timing.RunCoroutine(Util.AutoServerBroadcast()); + Timing.RunCoroutine(ServerBroadcastHelper.AutoServerBroadcast()); } if (Config.EnableHealSCP) { - Timing.RunCoroutine(ScpReal.AutoReal()); + Timing.RunCoroutine(ScpAutoHealHelper.AutoReal()); } _huds.Values.ToList().ForEach(h => h.Start()); }); if (DataBaseConfig.database_enable) { - Timing.RunCoroutine(InfoExtension.CollectInfo()); + Timing.RunCoroutine(InfoExtensions.CollectInfo()); } } @@ -105,12 +106,12 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) if (DataBaseConfig.database_enable) { - InfoExtension.PlayerList.Add(player); + InfoExtensions.PlayerList.Add(player); PlayerData data = player.GetData(); data.NickName = player.Nickname; data.LastJoinedTime = DateTime.Now; data.UpdateData(); - LevelUtils.UpdatePlayerNameWithLevelPrefix(player); + player.UpdatePlayerNameWithLevelPrefix(); } if (Config.EnableLogger) @@ -138,7 +139,7 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) if (DataBaseConfig.database_enable) { - InfoExtension.PlayerList.Remove(player); + InfoExtensions.PlayerList.Remove(player); PlayerData data = player.GetData(); data.LastJoinedTime = DateTime.Now; data.UpdateData(); diff --git a/DataBase/InfoExtension.cs b/Extensions/InfoExtensions.cs similarity index 96% rename from DataBase/InfoExtension.cs rename to Extensions/InfoExtensions.cs index 756aace..a48bc63 100644 --- a/DataBase/InfoExtension.cs +++ b/Extensions/InfoExtensions.cs @@ -1,4 +1,5 @@ -using EasyTools.DataBase.Serialization; +using EasyTools.DataBase; +using EasyTools.DataBase.Serialization; using EasyTools.Events; using LabApi.Features.Wrappers; using LiteDB; @@ -6,9 +7,9 @@ using System; using System.Collections.Generic; -namespace EasyTools.DataBase +namespace EasyTools.Extensions { - public static class InfoExtension + public static class InfoExtensions { /// diff --git a/Utils/LevelUtils.cs b/Extensions/LevelExtensions.cs similarity index 88% rename from Utils/LevelUtils.cs rename to Extensions/LevelExtensions.cs index 8709132..eb5e274 100644 --- a/Utils/LevelUtils.cs +++ b/Extensions/LevelExtensions.cs @@ -1,10 +1,9 @@ -using EasyTools.DataBase; -using LabApi.Features.Wrappers; +using LabApi.Features.Wrappers; using System; -namespace EasyTools.Utils +namespace EasyTools.Extensions { - public static class LevelUtils + public static class LevelExtensions { /// /// 根据经验值计算当前等级 @@ -37,7 +36,7 @@ public static double GetXpUntilNextLevel(double currentXp, double a) } // 玩家名称更新方法 - public static void UpdatePlayerNameWithLevelPrefix(Player player) + public static void UpdatePlayerNameWithLevelPrefix(this Player player) { if (player == null || player.IsNpc) return; diff --git a/Utils/ScpReal.cs b/Helper/ScpAutoHealHelper.cs similarity index 97% rename from Utils/ScpReal.cs rename to Helper/ScpAutoHealHelper.cs index 0bf955a..6f524d8 100644 --- a/Utils/ScpReal.cs +++ b/Helper/ScpAutoHealHelper.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using UnityEngine; -namespace EasyTools.Utils +namespace EasyTools.Helper { - public class ScpReal + public class ScpAutoHealHelper { private static readonly Dictionary _lastMove = []; diff --git a/Utils/Util.cs b/Helper/ServerBroadcastHelper.cs similarity index 79% rename from Utils/Util.cs rename to Helper/ServerBroadcastHelper.cs index ffd34e7..64ffd64 100644 --- a/Utils/Util.cs +++ b/Helper/ServerBroadcastHelper.cs @@ -1,12 +1,11 @@ using EasyTools.Events; using LabApi.Features.Wrappers; using MEC; -using System; using System.Collections.Generic; -namespace EasyTools.Utils +namespace EasyTools.Helper { - public class Util + public static class ServerBroadcastHelper { public static IEnumerator AutoServerBroadcast() { @@ -18,7 +17,7 @@ public static IEnumerator AutoServerBroadcast() } //随机公告 - int tmp = new Random().Next(0, CustomEventHandler.Config.AutoServerMessageText.Count - 1); + int tmp = UnityEngine.Random.Range(0, CustomEventHandler.Config.AutoServerMessageText.Count); Server.SendBroadcast(CustomEventHandler.Config.AutoServerMessageText[tmp], CustomEventHandler.Config.AutoServerMessageTimer, global::Broadcast.BroadcastFlags.Normal); yield return Timing.WaitForSeconds(CustomEventHandler.Config.AutoServerMessageTime * 60f); diff --git a/Plugins.cs b/Plugins.cs index 72556f6..4c3091e 100644 --- a/Plugins.cs +++ b/Plugins.cs @@ -22,6 +22,7 @@ public override void LoadConfigs() CustomEventHandler.CustomRoleConfig = this.LoadConfig("customRoleConfig.yml"); CustomEventHandler.DataBaseConfig = this.LoadConfig("dataBaseConfig.yml"); CustomEventHandler.HUDInfoConfig = this.LoadConfig("HUDInfoConfig.yml"); + CustomEventHandler.CoinConfig = this.LoadConfig("coinConfig.yml"); CustomEventHandler.data_914 = new HintData ( From 43815fdbbf4432dfc4e84a302cd157b272c4bd28 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:52:31 +0800 Subject: [PATCH 04/21] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=8A=BD?= =?UTF-8?q?=E5=8D=A1=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将奖励配置、随机算法和奖励发放的逻辑分离,提高代码可维护性 --- Configs/CoinConfig.cs | 73 ++++++++++++++++++ Configs/TranslateConfig.cs | 5 ++ EasyTools.csproj | 2 + Events/CustomEventHandler.cs | 130 +++------------------------------ Extensions/RewardExtensions.cs | 84 +++++++++++++++++++++ 5 files changed, 176 insertions(+), 118 deletions(-) create mode 100644 Configs/CoinConfig.cs create mode 100644 Extensions/RewardExtensions.cs diff --git a/Configs/CoinConfig.cs b/Configs/CoinConfig.cs new file mode 100644 index 0000000..de4e433 --- /dev/null +++ b/Configs/CoinConfig.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.ComponentModel; + +namespace EasyTools.Configs +{ + public class CoinConfig + { + [Description("抽卡奖励列表,权重总和为 100(自动归一化也可),支持修改概率和奖励内容")] + public List Rewards { get; set; } = new List + { + // ---- 变成 SCP(每种0.075%,总和0.3%) ---- + new RewardSetting { Weight = 0.075f, Type = RewardType.ChangeRole, Param = "Scp939", Name = "SCP-939" }, + new RewardSetting { Weight = 0.075f, Type = RewardType.ChangeRole, Param = "Scp3114", Name = "SCP-3114" }, + new RewardSetting { Weight = 0.075f, Type = RewardType.ChangeRole, Param = "Scp106", Name = "SCP-106" }, + new RewardSetting { Weight = 0.075f, Type = RewardType.ChangeRole, Param = "Scp049", Name = "SCP-049" }, + + // ---- 0.7% 特殊武器 ---- + new RewardSetting { Weight = 0.7f, Type = RewardType.GiveItem, Param = "GunSCP127", Name = "SCP-127" }, + + // ---- 4% 指挥官卡 ---- + new RewardSetting { Weight = 4.0f, Type = RewardType.GiveItem, Param = "KeycardMTFCaptain", Name = "指挥官卡" }, + + // ---- 5% 可乐 ---- + new RewardSetting { Weight = 5.0f, Type = RewardType.GiveItem, Param = "SCP207", Name = "可乐" }, + + // ---- 15% 随机枪械(两种枪各7.5%) ---- + new RewardSetting { Weight = 7.5f, Type = RewardType.GiveItem, Param = "GunE11SR", Name = "狗官枪" }, + new RewardSetting { Weight = 7.5f, Type = RewardType.GiveItem, Param = "GunAK", Name = "大机枪" }, + + // ---- 10% 中士卡 ---- + new RewardSetting { Weight = 10.0f, Type = RewardType.GiveItem, Param = "KeycardMTFOperative", Name = "中士卡" }, + + // ---- 10% 再来一次 ---- + new RewardSetting { Weight = 10.0f, Type = RewardType.ExtraCoin, Name = "又获得了一个硬币" }, + + // ---- 10% 随机传送 ---- + new RewardSetting { Weight = 10.0f, Type = RewardType.TeleportToSCP, Name = "被传送到SCP旁边" }, + + // ---- 20% 医疗物品(SCP-500 和医疗包各10%) ---- + new RewardSetting { Weight = 10.0f, Type = RewardType.GiveItem, Param = "SCP500", Name = "SCP-500" }, + new RewardSetting { Weight = 10.0f, Type = RewardType.GiveItem, Param = "Medkit", Name = "医疗物品" }, + + // ---- 25% 什么都没有 ---- + new RewardSetting { Weight = 25.0f, Type = RewardType.None, Name = "损失了一个硬币" }, + }; + } + + public class RewardSetting + { + [Description("显示名称(用于广播)")] + public string Name { get; set; } = "未知奖励"; + + [Description("相对权重")] + public float Weight { get; set; } = 10f; + + [Description("奖励类型")] + public RewardType Type { get; set; } = RewardType.None; + + [Description("参数(根据类型不同:角色ID、物品ID、枪械列表等)")] + public string Param { get; set; } = string.Empty; + } + + public enum RewardType + { + None, // 什么都没发生 + ChangeRole, // 变身SCP(Param = 角色ID) + GiveItem, // 给物品(Param = 物品ID) + GiveRandomGun, // 随机给一把枪(Param = 逗号分隔的枪械ID) + TeleportToSCP, // 传送到随机SCP旁(Param留空) + ExtraCoin, // 返还硬币(Param留空) + GiveMedical // 随机给医疗包或SCP500(Param留空) + } +} diff --git a/Configs/TranslateConfig.cs b/Configs/TranslateConfig.cs index 46066f5..d059608 100644 --- a/Configs/TranslateConfig.cs +++ b/Configs/TranslateConfig.cs @@ -97,5 +97,10 @@ public class TranslateConfig public string LevelCommandFailed { get; set; } = "查询失败,等级系统未启用"; [Description("等级系统_查询成功")] public string LevelCommandOk { get; set; } = "您当前的经验值为: "; + /// + /// + /// + public string RewardFailedBroadcastTemplate { get; set; } = "\n你的背包空间不足,无法继续抽卡!"; + public string RewardOkBroadcastTemplate { get; set; } = "\n🎉 恭喜!玩家 {nickName} 通过抛硬币{result}!"; } } diff --git a/EasyTools.csproj b/EasyTools.csproj index a5b3827..5ea0da1 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -128,6 +128,7 @@ + @@ -142,6 +143,7 @@ + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index c58053f..eb600c2 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -37,6 +37,8 @@ public class CustomEventHandler : CustomEventsHandler public static HUDInfoConfig HUDInfoConfig; + public static CoinConfig CoinConfig; + public static CoroutineHandle Badge_Coroutine; public static readonly Dictionary _huds = new(); @@ -388,11 +390,12 @@ public override void OnServerCommandExecuted(CommandExecutedEventArgs ev) public override void OnPlayerFlippingCoin(PlayerFlippingCoinEventArgs ev) { - if (!ev.IsAllowed) return; - if (!Config.Coin) return; + if (!ev.IsAllowed || !Config.Coin) return; + if (ev.Player.Items.Count() == 8) { - ev.Player.SendBroadcast($"\n你的背包空间不足,无法继续抽卡!", 2); + ev.Player.SendBroadcast(TranslateConfig.RewardFailedBroadcastTemplate, 2); + ev.IsAllowed = false; return; } @@ -400,124 +403,15 @@ public override void OnPlayerFlippingCoin(PlayerFlippingCoinEventArgs ev) player.RemoveItem(ItemType.Coin); - // 生成0-100的随机数 - float randomValue = UnityEngine.Random.Range(0f, 100f); + // 按权重随机选择奖励 + RewardSetting reward = CoinConfig.Rewards.PickReward(); + if (reward == null) return; - // 初始化奖励变量 - string rewardName = ""; - bool success = false; - - // 概率判断(从低到高) - if (randomValue < 0.3f) // 0.3% 变成SCP - { - int scpType = UnityEngine.Random.Range(0, 4); - switch (scpType) - { - case 0: - player.Role = RoleTypeId.Scp939; - rewardName = "变成了狗子"; - break; - case 1: - player.Role = RoleTypeId.Scp3114; - rewardName = "变成了3114"; - break; - case 2: - player.Role = RoleTypeId.Scp106; - rewardName = "变成了老头"; - break; - case 3: - player.Role = RoleTypeId.Scp049; - rewardName = "变成了49"; - break; - default: - player.Role = RoleTypeId.Scp939; - rewardName = "变成了狗子"; - break; - } - success = true; - } - else if (randomValue < 1f && !success) // 0.7% 特殊武器 - { - player.AddItem(ItemType.GunSCP127); - rewardName = "获得了127"; - success = true; - } - else if (randomValue < 5f && !success) // 4% 黑卡 - { - player.AddItem(ItemType.KeycardMTFCaptain); - rewardName = "获得了指挥官卡"; - success = true; - } - else if (randomValue < 10f && !success) // 5% 可乐 - { - player.AddItem(ItemType.SCP207); - rewardName = "获得了可乐"; - success = true; - } - else if (randomValue < 25f && !success) // 10% 枪 - { - bool weaponIndex = UnityEngine.Random.Range(0, 2) == 0; - if (weaponIndex) - { - player.AddItem(ItemType.GunE11SR); - rewardName = "获得了狗官枪"; - } - else - { - player.AddItem(ItemType.GunAK); - rewardName = "获得了大机枪"; - } - success = true; - } - else if (randomValue < 35f && !success) // 10% 红卡 - { - player.AddItem(ItemType.KeycardMTFOperative); - rewardName = "获得了中士卡"; - success = true; - } - else if (randomValue < 45f && !success) // 10% 再来一次 - { - player.AddItem(ItemType.Coin); - rewardName = "又获得了一个硬币"; - success = true; - } - else if (randomValue < 55f && !success) // 10% 随机传送 - { - foreach (Player p in Player.ReadyList) - { - if (p.IsSCP && p.Role != RoleTypeId.Scp079) - { - player.Position = p.Position + Vector3.right; - player.Rotation = p.Rotation; - } - } - rewardName = "被传送到SCP旁边"; - success = true; - } - else if (randomValue < 75f && !success) // 20% 医疗 - { - bool healthIndex = UnityEngine.Random.Range(0, 2) == 0; - - if (healthIndex) - { - player.AddItem(ItemType.SCP500); - } - else - { - player.AddItem(ItemType.Medkit); - } - rewardName = "获得了医疗物品"; - success = true; - } - else // 25% 什么都没有 - { - rewardName = "损失了一个硬币"; - success = true; - } + // 执行奖励 + string result = player.ApplyReward(reward); // 通知玩家 - Server.SendBroadcast($"\n🎉 恭喜!玩家 {player.Nickname} 通过抛硬币{rewardName}!", 3); - + Server.SendBroadcast(TranslateConfig.RewardOkBroadcastTemplate.Replace("{nickName}", player.Nickname).Replace("{result}", result), 3); } public override void OnScp914Activating(Scp914ActivatingEventArgs ev) diff --git a/Extensions/RewardExtensions.cs b/Extensions/RewardExtensions.cs new file mode 100644 index 0000000..7280967 --- /dev/null +++ b/Extensions/RewardExtensions.cs @@ -0,0 +1,84 @@ +using EasyTools.Configs; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace EasyTools.Extensions +{ + public static class RewardExtensions + { + public static RewardSetting PickReward(this List rewards) + { + float totalWeight = rewards.Sum(r => r.Weight); + float roll = UnityEngine.Random.Range(0f, totalWeight); + float cumulative = 0f; + foreach (var reward in rewards) + { + cumulative += reward.Weight; + if (roll < cumulative) + return reward; + } + return rewards.LastOrDefault(); + } + + public static string ApplyReward(this Player player, RewardSetting reward) + { + switch (reward.Type) + { + case RewardType.ChangeRole: + if (Enum.TryParse(reward.Param, out RoleTypeId role)) + { + player.Role = role; + return $"变成了 {reward.Name}"; + } + return "变身失败(配置错误)"; + + case RewardType.GiveItem: + if (Enum.TryParse(reward.Param, out ItemType item)) + { + player.AddItem(item); + return $"获得了 {reward.Name}"; + } + return "获得物品失败(配置错误)"; + + case RewardType.GiveRandomGun: + string[] guns = reward.Param.Split(','); + string chosen = guns[UnityEngine.Random.Range(0, guns.Length)]; + if (Enum.TryParse(chosen.Trim(), out ItemType gun)) + { + player.AddItem(gun); + return $"获得了 {chosen}"; + } + return "获得武器失败(配置错误)"; + + case RewardType.TeleportToSCP: + var scps = Player.ReadyList.Where(p => p.IsSCP && p.Role != RoleTypeId.Scp079).ToList(); + if (scps.Any()) + { + var target = scps[UnityEngine.Random.Range(0, scps.Count)]; + player.Position = target.Position + Vector3.right; + player.Rotation = target.Rotation; + return "被传送到SCP旁边"; + } + // 没有SCP时返还硬币(防止纯损失) + player.AddItem(ItemType.Coin); + return "...SCP都不在了,返还硬币"; + + case RewardType.ExtraCoin: + player.AddItem(ItemType.Coin); + return "又获得了一个硬币"; + + case RewardType.GiveMedical: + bool give500 = UnityEngine.Random.Range(0, 2) == 0; + player.AddItem(give500 ? ItemType.SCP500 : ItemType.Medkit); + return "获得了医疗物品"; + + default: + return "损失了一个硬币"; + } + } + } +} From 43b02849bf647b20e8a436ebbca2a42e4baea77f Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:53:23 +0800 Subject: [PATCH 05/21] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=8E=A9?= =?UTF-8?q?=E5=AE=B6=E8=BF=9B=E5=87=BA=E6=97=A5=E5=BF=97=E5=86=99=E5=85=A5?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 37 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index eb600c2..c87e7b5 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -122,8 +122,23 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) string path = Path.Combine(CustomEventHandler.Config.PlayerLogPath, $"{Server.Port}.log"); Log.Info(playerInfo); - File.AppendAllText(path, playerInfo + Environment.NewLine); + try + { + // 递归创建目录 + string dir = Path.GetDirectoryName(path); + if (!string.IsNullOrEmpty(dir)) + { + Directory.CreateDirectory(dir); + } + + File.AppendAllText(path, playerInfo + Environment.NewLine); + } + catch (Exception e) + { + Log.Error(e.Message); + } } + if (BadgeConfig.Enable) { Badge.Handler(player); @@ -364,22 +379,14 @@ public override void OnServerCommandExecuted(CommandExecutedEventArgs ev) Log.Info(note); try { - if (!File.Exists(path)) + // 递归创建目录 + string dir = Path.GetDirectoryName(path); + if (!string.IsNullOrEmpty(dir)) { - FileStream fs1 = new(path, FileMode.Create, FileAccess.Write); - StreamWriter sw = new(fs1); - sw.WriteLine(note); - sw.Close(); - fs1.Close(); - } - else - { - FileStream fs = new(path, FileMode.Append, FileAccess.Write); - StreamWriter sr = new(fs); - sr.WriteLine(note); - sr.Close(); - fs.Close(); + Directory.CreateDirectory(dir); } + + File.AppendAllText(path, note + Environment.NewLine); } catch (Exception e) { From f7661512e16e0be0c7d6f82870fe2872c03ce2bb Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:54:08 +0800 Subject: [PATCH 06/21] =?UTF-8?q?style:=20=E4=BF=AE=E6=94=B9=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=BE=93=E5=87=BA=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index c87e7b5..e79c12b 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -374,7 +374,7 @@ public override void OnServerCommandExecuted(CommandExecutedEventArgs ev) if (!player.RemoteAdminAccess) return; - string note = $"Date: {DateTime.Now} | Player: {player.Nickname} | Command: {command} | Steam64ID: {player.UserId}"; + string note = $"[AC] Date: {DateTime.Now} | Player: {player.Nickname} | Command: {command} | Steam64ID: {player.UserId}"; string path = Path.Combine(CustomEventHandler.Config.AdminLogPath, $"{Server.Port}.log"); Log.Info(note); try From b388c8399e51e2b4b43481942400b6912fbbe464 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:54:52 +0800 Subject: [PATCH 07/21] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=8E=A9?= =?UTF-8?q?=E5=AE=B6=E9=80=80=E5=87=BA=E6=97=A5=E5=BF=97=E8=BE=93=E5=87=BA?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index e79c12b..89588c1 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -151,6 +151,8 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) public override void OnPlayerLeft(PlayerLeftEventArgs ev) { Player player = ev.Player; + string nickName = player.Nickname; + string userId = player.UserId; if (player == null || string.IsNullOrEmpty(player.UserId)) return; @@ -164,7 +166,7 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) if (Config.EnableLogger) { - string playerInfo = $"[EXIT] Date: {DateTime.Now} | Player: {ev.Player.Nickname} | IP: {ev.Player.IpAddress} | Steam64ID: {ev.Player.UserId}"; + string playerInfo = $"[EXIT] Date: {DateTime.Now} | Player: {nickName} | Steam64ID: {userId}"; string path = Path.Combine(CustomEventHandler.Config.PlayerLogPath, $"{Server.Port}.log"); Log.Info(playerInfo); From 8592ddf1a1025b894faec5e89095fde818505d12 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:56:42 +0800 Subject: [PATCH 08/21] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=87=BB?= =?UTF-8?q?=E6=9D=80=E7=8E=A9=E5=AE=B6=E6=97=B6=E7=BB=8F=E9=AA=8C=E5=A5=96?= =?UTF-8?q?=E5=8A=B1=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 45 ++++++++++++++---------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 89588c1..28db3d8 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -259,48 +259,37 @@ public override void OnPlayerSpawned(PlayerSpawnedEventArgs ev) } } - public override void OnPlayerDeath(PlayerDeathEventArgs ev) + public override void OnPlayerDying(PlayerDyingEventArgs ev) { // 避免处理非玩家击杀或无效情况 if (ev.Attacker == null || ev.Player == null) return; - bool tgtwasSCP = ev.Player.IsSCP && ev.Player.Role != RoleTypeId.Scp0492; - // 给击杀者添加经验 - PlayerData data = ev.Player.GetData(); + PlayerData data = ev.Attacker.GetData(); - if (tgtwasSCP) + if (ev.Attacker.IsSCP) { - data.PlayerXp += 50.0; + data.PlayerXp += 5.0; } - else + else if (ev.Player.IsSCP) { - data.PlayerXp += 5.0; + if (ev.Player.Role == RoleTypeId.Scp0492) + { + data.PlayerXp += 30.0; + } + else + { + data.PlayerXp += 50.0; + } } - - data.PlayerLevel = LevelUtils.GetLevelFromXp(data.PlayerXp, 1); - LevelUtils.UpdatePlayerNameWithLevelPrefix(ev.Attacker); - } - - public override void OnPlayerDeath(PlayerDeathEventArgs ev) - { - // 避免处理非玩家击杀或无效情况 - if (ev.Attacker == null || ev.Player == null) - return; - - bool tgtwasSCP = ev.Player.IsSCP && ev.Player.Role != RoleTypeId.Scp0492; - - - // 给击杀者添加经验 - PlayerData data = ev.Player.GetData(); - - - if (tgtwasSCP) + else { - data.PlayerXp += 50.0; + data.PlayerXp += 5.0; } + data.PlayerLevel = LevelExtensions.GetLevelFromXp(data.PlayerXp, 1); + ev.Attacker.UpdatePlayerNameWithLevelPrefix(); } public override void OnPlayerHurting(PlayerHurtingEventArgs ev) From 75deabc3ed15b966f2c9ca164d1fa37eb3b049bc Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:57:11 +0800 Subject: [PATCH 09/21] =?UTF-8?q?test:=20=E6=9A=82=E6=97=B6=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E7=A9=BA=E5=80=BC=E5=88=A4=E5=AE=9A=E4=BB=A5=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E5=87=BB=E6=9D=80=E6=9C=BA=E5=99=A8=E4=BA=BA=E5=A5=96?= =?UTF-8?q?=E5=8A=B1=E7=BB=8F=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 28db3d8..495d0b4 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -262,8 +262,8 @@ public override void OnPlayerSpawned(PlayerSpawnedEventArgs ev) public override void OnPlayerDying(PlayerDyingEventArgs ev) { // 避免处理非玩家击杀或无效情况 - if (ev.Attacker == null || ev.Player == null) - return; + //if (ev.Attacker == null || ev.Player == null) + // return; // 给击杀者添加经验 PlayerData data = ev.Attacker.GetData(); From d67f0003b2c84e978b2fb6ffca48dddc55895f05 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:57:34 +0800 Subject: [PATCH 10/21] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E4=BA=BA?= =?UTF-8?q?=E7=B1=BB=E9=98=B5=E8=90=A5=E9=80=83=E7=A6=BB=E7=BB=99=E4=BA=88?= =?UTF-8?q?=E7=BB=8F=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 495d0b4..2923b64 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -339,6 +339,15 @@ public override void OnPlayerEscaping(PlayerEscapingEventArgs ev) ev.IsAllowed = true; } } + + PlayerData data = ev.Player.GetData(); + data.PlayerXp += 20.0; + + data.PlayerLevel = LevelExtensions.GetLevelFromXp(data.PlayerXp, 1); + ev.Player.UpdatePlayerNameWithLevelPrefix(); + + // 通知玩家 + ev.Player.SendBroadcast("\n逃脱成功,获得20经验值", 3); } public override void OnPlayerInteractingScp330(PlayerInteractingScp330EventArgs ev) From fc95fa71f4f40cb5c03e3623d6427a80815cb215 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:38:14 +0800 Subject: [PATCH 11/21] =?UTF-8?q?refactor:=20=E9=87=8D=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Extensions/{InfoExtensions.cs => DataExtensions.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Extensions/{InfoExtensions.cs => DataExtensions.cs} (98%) diff --git a/Extensions/InfoExtensions.cs b/Extensions/DataExtensions.cs similarity index 98% rename from Extensions/InfoExtensions.cs rename to Extensions/DataExtensions.cs index a48bc63..98feecc 100644 --- a/Extensions/InfoExtensions.cs +++ b/Extensions/DataExtensions.cs @@ -9,7 +9,7 @@ namespace EasyTools.Extensions { - public static class InfoExtensions + public static class DataExtensions { /// From cade3f8c9079424f0e94434003c224d10ca76ea3 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Tue, 14 Jul 2026 23:18:26 +0800 Subject: [PATCH 12/21] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BB=93=E6=9E=84=E7=B1=BB=E5=92=8CAPI=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {DataBase => API}/DataAPI.cs | 4 ++-- Commands/Level/XpCommand.cs | 2 +- .../Serialization => DataStructures}/HintData.cs | 2 +- .../Serialization => DataStructures}/PlayerData.cs | 13 ++++++++++++- .../Serialization => DataStructures}/PlayerHint.cs | 4 ++-- EasyTools.csproj | 10 +++++----- Events/CustomEventHandler.cs | 10 +++++----- Extensions/DataExtensions.cs | 4 ++-- Plugins.cs | 1 - 9 files changed, 30 insertions(+), 20 deletions(-) rename {DataBase => API}/DataAPI.cs (91%) rename {DataBase/Serialization => DataStructures}/HintData.cs (84%) rename {DataBase/Serialization => DataStructures}/PlayerData.cs (66%) rename {DataBase/Serialization => DataStructures}/PlayerHint.cs (97%) diff --git a/DataBase/DataAPI.cs b/API/DataAPI.cs similarity index 91% rename from DataBase/DataAPI.cs rename to API/DataAPI.cs index fad3c11..36646eb 100644 --- a/DataBase/DataAPI.cs +++ b/API/DataAPI.cs @@ -1,9 +1,9 @@ -using EasyTools.DataBase.Serialization; +using EasyTools.DataStructures; using EasyTools.Events; using LiteDB; using System.Collections.Generic; -namespace EasyTools.DataBase +namespace EasyTools.API { public static class DataAPI { diff --git a/Commands/Level/XpCommand.cs b/Commands/Level/XpCommand.cs index 0e147f7..ea2d3fc 100644 --- a/Commands/Level/XpCommand.cs +++ b/Commands/Level/XpCommand.cs @@ -1,6 +1,6 @@ using CommandSystem; using EasyTools.Configs; -using EasyTools.DataBase.Serialization; +using EasyTools.DataStructures; using EasyTools.Events; using EasyTools.Extensions; using LabApi.Features.Wrappers; diff --git a/DataBase/Serialization/HintData.cs b/DataStructures/HintData.cs similarity index 84% rename from DataBase/Serialization/HintData.cs rename to DataStructures/HintData.cs index becfc59..9e6bb54 100644 --- a/DataBase/Serialization/HintData.cs +++ b/DataStructures/HintData.cs @@ -1,4 +1,4 @@ -namespace EasyTools.DataBase.Serialization +namespace EasyTools.DataStructures { public struct HintData { diff --git a/DataBase/Serialization/PlayerData.cs b/DataStructures/PlayerData.cs similarity index 66% rename from DataBase/Serialization/PlayerData.cs rename to DataStructures/PlayerData.cs index 69477c3..324f270 100644 --- a/DataBase/Serialization/PlayerData.cs +++ b/DataStructures/PlayerData.cs @@ -1,7 +1,7 @@ using LiteDB; using System; -namespace EasyTools.DataBase.Serialization +namespace EasyTools.DataStructures { [Serializable] public class PlayerData @@ -18,7 +18,18 @@ public class PlayerData public int PlayerShot { get; set; } public double PlayerXp { get; set; } public double PlayerLevel { get; set; } + public PermissionLevel PermissionLevel { get; set; } = PermissionLevel.Player; + public string Badge { get; set; } = ""; + public string BadgeColor { get; set; } = "rainbow"; [BsonId] public string ID { get; set; } } + + public enum PermissionLevel + { + Player = 0, + Moderator = 1, + Admin = 2, + Owner = 3 + } } diff --git a/DataBase/Serialization/PlayerHint.cs b/DataStructures/PlayerHint.cs similarity index 97% rename from DataBase/Serialization/PlayerHint.cs rename to DataStructures/PlayerHint.cs index f3f9f0d..1fc7366 100644 --- a/DataBase/Serialization/PlayerHint.cs +++ b/DataStructures/PlayerHint.cs @@ -3,10 +3,10 @@ using HintServiceMeow.Core.Models.Hints; using HintServiceMeow.Core.Utilities; using LabApi.Features.Wrappers; -using System.Collections.Generic; using System; +using System.Collections.Generic; -namespace EasyTools.DataBase.Serialization +namespace EasyTools.DataStructures { public struct PlayerHint : IDisposable { diff --git a/EasyTools.csproj b/EasyTools.csproj index 5ea0da1..d743cc0 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -134,11 +134,11 @@ - - - - - + + + + + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 2923b64..d554b35 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -1,6 +1,6 @@ using EasyTools.BadgeSystem; -using EasyTools.Configs; -using EasyTools.DataBase.Serialization; +using EasyTools.Configs; +using EasyTools.DataStructures; using EasyTools.Extensions; using EasyTools.Helper; using EasyTools.Utils; @@ -76,7 +76,7 @@ public override void OnServerRoundStarted() if (DataBaseConfig.database_enable) { - Timing.RunCoroutine(InfoExtensions.CollectInfo()); + Timing.RunCoroutine(DataExtensions.CollectInfo()); } } @@ -108,7 +108,7 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) if (DataBaseConfig.database_enable) { - InfoExtensions.PlayerList.Add(player); + DataExtensions.PlayerList.Add(player); PlayerData data = player.GetData(); data.NickName = player.Nickname; data.LastJoinedTime = DateTime.Now; @@ -158,7 +158,7 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) if (DataBaseConfig.database_enable) { - InfoExtensions.PlayerList.Remove(player); + DataExtensions.PlayerList.Remove(player); PlayerData data = player.GetData(); data.LastJoinedTime = DateTime.Now; data.UpdateData(); diff --git a/Extensions/DataExtensions.cs b/Extensions/DataExtensions.cs index 98feecc..559758a 100644 --- a/Extensions/DataExtensions.cs +++ b/Extensions/DataExtensions.cs @@ -1,5 +1,5 @@ -using EasyTools.DataBase; -using EasyTools.DataBase.Serialization; +using EasyTools.API; +using EasyTools.DataStructures; using EasyTools.Events; using LabApi.Features.Wrappers; using LiteDB; diff --git a/Plugins.cs b/Plugins.cs index 4c3091e..cc92113 100644 --- a/Plugins.cs +++ b/Plugins.cs @@ -1,5 +1,4 @@ using EasyTools.Configs; -using EasyTools.DataBase.Serialization; using EasyTools.Events; using LabApi.Events.CustomHandlers; using LabApi.Features; From 8515653444b08160a501a8a5cbdebebf0129e1bb Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:34:02 +0800 Subject: [PATCH 13/21] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E7=8E=A9?= =?UTF-8?q?=E5=AE=B6=E8=81=8A=E5=A4=A9=E4=BF=A1=E6=81=AF=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Commands/Chat/AcCommand.cs | 4 ++-- Commands/Chat/BcCommand.cs | 4 ++-- Commands/Chat/CCommand.cs | 4 ++-- Configs/TranslateConfig.cs | 2 +- EasyTools.csproj | 2 +- Events/CustomEventHandler.cs | 3 +-- Utils/ChatUtils.cs => Extensions/ChatHintExtensions.cs | 8 ++++---- 7 files changed, 13 insertions(+), 14 deletions(-) rename Utils/ChatUtils.cs => Extensions/ChatHintExtensions.cs (94%) diff --git a/Commands/Chat/AcCommand.cs b/Commands/Chat/AcCommand.cs index 0c2f14a..c9c1015 100644 --- a/Commands/Chat/AcCommand.cs +++ b/Commands/Chat/AcCommand.cs @@ -1,7 +1,7 @@ using CommandSystem; using EasyTools.Configs; using EasyTools.Events; -using EasyTools.Utils; +using EasyTools.Extensions; using LabApi.Features.Wrappers; using System; using Log = LabApi.Features.Console.Logger; @@ -34,7 +34,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s return false; } - ChatUtils.SendMessage(player, ChatMessage.MessageType.AdminPrivateChat, $"{string.Join(" ", arguments)}"); + player.SendHintMessage(ChatMessage.MessageType.AdminPrivateChat, $"{string.Join(" ", arguments)}"); Log.Info(player.Nickname + " 发送了 " + arguments.At(0)); response = TranslateConfig.ChatCommandOk; diff --git a/Commands/Chat/BcCommand.cs b/Commands/Chat/BcCommand.cs index e1c77ec..6c2e147 100644 --- a/Commands/Chat/BcCommand.cs +++ b/Commands/Chat/BcCommand.cs @@ -1,7 +1,7 @@ using CommandSystem; using EasyTools.Configs; using EasyTools.Events; -using EasyTools.Utils; +using EasyTools.Extensions; using LabApi.Features.Wrappers; using System; using Log = LabApi.Features.Console.Logger; @@ -34,7 +34,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s return false; } - ChatUtils.SendMessage(player, ChatMessage.MessageType.BroadcastChat, $"{string.Join(" ", arguments)}"); + player.SendHintMessage(ChatMessage.MessageType.BroadcastChat, $"{string.Join(" ", arguments)}"); Log.Info(player.Nickname + " 发送了 " + arguments.At(0)); response = TranslateConfig.RescueCommandOk; diff --git a/Commands/Chat/CCommand.cs b/Commands/Chat/CCommand.cs index 2f77026..739bbdb 100644 --- a/Commands/Chat/CCommand.cs +++ b/Commands/Chat/CCommand.cs @@ -1,7 +1,7 @@ using CommandSystem; using EasyTools.Configs; using EasyTools.Events; -using EasyTools.Utils; +using EasyTools.Extensions; using LabApi.Features.Wrappers; using System; using Log = LabApi.Features.Console.Logger; @@ -34,7 +34,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s return false; } - ChatUtils.SendMessage(player, ChatMessage.MessageType.TeamChat, $"{string.Join(" ", arguments)}"); + player.SendHintMessage(ChatMessage.MessageType.TeamChat, $"{string.Join(" ", arguments)}"); Log.Info(player.Nickname + " 发送了 " + arguments.At(0)); diff --git a/Configs/TranslateConfig.cs b/Configs/TranslateConfig.cs index d059608..fc64497 100644 --- a/Configs/TranslateConfig.cs +++ b/Configs/TranslateConfig.cs @@ -1,4 +1,4 @@ -using EasyTools.Utils; +using EasyTools.Extensions; using PlayerRoles; using Scp914; using System.Collections.Generic; diff --git a/EasyTools.csproj b/EasyTools.csproj index d743cc0..2c7ffc2 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -142,7 +142,7 @@ - + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index d554b35..bae3abd 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -3,7 +3,6 @@ using EasyTools.DataStructures; using EasyTools.Extensions; using EasyTools.Helper; -using EasyTools.Utils; using InventorySystem.Items; using LabApi.Events.Arguments.PlayerEvents; using LabApi.Events.Arguments.Scp914Events; @@ -104,7 +103,7 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) if (player == null || string.IsNullOrEmpty(player.UserId)) return; - ChatUtils.InitForPlayer(player); + player.InitChatHint(); if (DataBaseConfig.database_enable) { diff --git a/Utils/ChatUtils.cs b/Extensions/ChatHintExtensions.cs similarity index 94% rename from Utils/ChatUtils.cs rename to Extensions/ChatHintExtensions.cs index 382c408..de964cf 100644 --- a/Utils/ChatUtils.cs +++ b/Extensions/ChatHintExtensions.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.Linq; -namespace EasyTools.Utils +namespace EasyTools.Extensions { public class ChatMessage(Player sender, ChatMessage.MessageType type, string message) @@ -39,7 +39,7 @@ public enum MessageType public RoleTypeId SenderRole { get; } = sender.Role; } - public class ChatUtils + public static class ChatHintExtensions { private static CoroutineHandle _coroutine; @@ -117,7 +117,7 @@ private static IEnumerator MessageCoroutineMethod() } } - public static void InitForPlayer(Player player) + public static void InitChatHint(this Player player) { if (!_coroutine.IsRunning) _coroutine = Timing.RunCoroutine(MessageCoroutineMethod()); @@ -138,7 +138,7 @@ public static void InitForPlayer(Player player) PlayerDisplay.Get(player.ReferenceHub).AddHint(MessageSlot[player]); } - public static void SendMessage(Player sender, ChatMessage.MessageType type, string message) => SendMessage(new ChatMessage(sender, type, message)); + public static void SendHintMessage(this Player sender, ChatMessage.MessageType type, string message) => SendMessage(new ChatMessage(sender, type, message)); public static void SendMessage(ChatMessage message) { From 81833d0c5ef5c79bbabd36d4eac11a9c21681811 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:35:33 +0800 Subject: [PATCH 14/21] =?UTF-8?q?refactor:=20=E9=99=90=E5=88=B6=20allow=5F?= =?UTF-8?q?spawn=5Fscp=5F3114=20=E7=9A=84=E8=AE=BF=E9=97=AE=E7=BA=A7?= =?UTF-8?q?=E5=88=AB=E4=B8=BA=20private?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Events/CustomEventHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index bae3abd..d23b489 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -183,7 +183,7 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) } } - public static volatile bool allow_spawn_scp_3114 = true; //用以确保不会重复生成SCP-3114 + private static volatile bool allow_spawn_scp_3114 = true; //用以确保不会重复生成SCP-3114 public override void OnPlayerSpawning(PlayerSpawningEventArgs ev) { From de0e5f16172d360a40a2803c09aafec67532d944 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:39:50 +0800 Subject: [PATCH 15/21] =?UTF-8?q?feat:=20SCP=E5=BC=80=E5=B1=80=E4=BA=A4?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Commands/Scp/SwapAcceptCommand.cs | 67 +++++++++++++++++++++++++ Commands/Scp/SwapDenyCommand.cs | 55 ++++++++++++++++++++ Commands/Scp/SwapScpCommand.cs | 83 +++++++++++++++++++++++++++++++ EasyTools.csproj | 3 ++ Events/CustomEventHandler.cs | 6 +++ 5 files changed, 214 insertions(+) create mode 100644 Commands/Scp/SwapAcceptCommand.cs create mode 100644 Commands/Scp/SwapDenyCommand.cs create mode 100644 Commands/Scp/SwapScpCommand.cs diff --git a/Commands/Scp/SwapAcceptCommand.cs b/Commands/Scp/SwapAcceptCommand.cs new file mode 100644 index 0000000..8d23b2b --- /dev/null +++ b/Commands/Scp/SwapAcceptCommand.cs @@ -0,0 +1,67 @@ +using CommandSystem; +using EasyTools.Events; +using LabApi.Features.Wrappers; +using System; +using Log = LabApi.Features.Console.Logger; + +namespace EasyTools.Commands.Scp +{ + [CommandHandler(typeof(ClientCommandHandler))] + public class SwapAcceptCommand : ICommand + { + public string Command => "swapaccept"; + + public string[] Aliases => ["spa"]; + + public string Description => "同意与其他SCP的交换请求"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + Player player; + + if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) + { + response = "失败,可能指令未启用或者身份不允许等"; + return false; + } + + if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > 300) + { + response = "失败,交换指令只能在开局三分钟内使用"; + return false; + } + + // 检查是否有发给自己的请求 + if (!CustomEventHandler.SwapRequests.TryGetValue(player, out Player requester)) + { + response = "没有待处理的交换请求"; + return false; + } + + // 检查发起请求的玩家是否仍然在线且为 SCP + if (requester == null || !requester.IsSCP) + { + CustomEventHandler.SwapRequests.Remove(player); + response = "请求已失效,对方已离线或不再是 SCP。"; + return false; + } + + // 交换并从列表中移除 + var tempRole = requester.Role; + requester.Role = player.Role; + player.Role = tempRole; + + CustomEventHandler.SwapRequests.Remove(player); + + // 通知玩家 + string msg = $"交换成功! {requester.Nickname} 与 {player.Nickname} 已交换 SCP 身份。"; + requester.SendBroadcast(msg, 5); + player.SendBroadcast(msg, 5); + + Log.Info($"{player.Nickname} 与 {requester.Nickname} 交换成功"); + + response = "交换成功"; + return true; + } + } +} diff --git a/Commands/Scp/SwapDenyCommand.cs b/Commands/Scp/SwapDenyCommand.cs new file mode 100644 index 0000000..e0f1966 --- /dev/null +++ b/Commands/Scp/SwapDenyCommand.cs @@ -0,0 +1,55 @@ +using CommandSystem; +using EasyTools.Events; +using LabApi.Features.Wrappers; +using System; +using Log = LabApi.Features.Console.Logger; + +namespace EasyTools.Commands.Scp +{ + [CommandHandler(typeof(ClientCommandHandler))] + public class SwapDenyCommand : ICommand + { + public string Command => "swapdeny"; + + public string[] Aliases => ["spd"]; + + public string Description => "拒绝与其他SCP的交换请求"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + Player player; + + if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) + { + response = "失败,可能指令未启用或者身份不允许等"; + return false; + } + + if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > 300) + { + response = "失败,交换指令只能在开局三分钟内使用"; + return false; + } + + // 检查是否有发给自己的请求 + if (!CustomEventHandler.SwapRequests.TryGetValue(player, out Player requester)) + { + response = "没有待处理的交换请求"; + return false; + } + + // 清理请求 + CustomEventHandler.SwapRequests.Remove(player); + + // 通知玩家 + player.SendBroadcast($"你拒绝了与 {requester.Nickname} 的交换请求", 5); + requester.SendBroadcast($"{player.Nickname} 拒绝了你的交换请求", 5); + + + Log.Info($"{player.Nickname} 与 {requester.Nickname} 交换失败"); + + response = "交换失败"; + return true; + } + } +} diff --git a/Commands/Scp/SwapScpCommand.cs b/Commands/Scp/SwapScpCommand.cs new file mode 100644 index 0000000..6a03c7e --- /dev/null +++ b/Commands/Scp/SwapScpCommand.cs @@ -0,0 +1,83 @@ +using CommandSystem; +using EasyTools.Events; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; +using System.Linq; +using Log = LabApi.Features.Console.Logger; + +namespace EasyTools.Commands.Scp +{ + [CommandHandler(typeof(ClientCommandHandler))] + public class SwapScpCommand : ICommand + { + public string Command => "swap"; + + public string[] Aliases => ["sp"]; + + public string Description => "申请与其他SCP交换"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + Player player; + + if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) + { + response = "失败,可能指令未启用或者身份不允许等"; + return false; + } + + if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > 300) + { + response = "失败,交换指令只能在开局三分钟内使用"; + return false; + } + + if (arguments.Count == 0) + { + response = "失败,未指定你要交换的目标(Scp079|Scp096|Scp106|Scp173|Scp049|Scp3114)"; + return false; + } + + string input = arguments.At(0); + if (!Enum.TryParse(input, out RoleTypeId targetRole)) + { + response = $"无效的 SCP 编号:{input}。可用的有 Scp079|Scp096|Scp106|Scp173|Scp049|Scp3114 (必须带Scp)"; + return false; + } + + // 防止与自己交换 + if (player.Role == targetRole) + { + response = "你不能与自己交换。"; + return false; + } + + // 确保目标SCP存在 + Player target = Player.List.FirstOrDefault(p => p.IsSCP && p.Role == targetRole); + if (target == null) + { + response = $"当前没有 {targetRole} 在线。"; + return false; + } + + // 检查是否已存在请求 + if (CustomEventHandler.SwapRequests.ContainsKey(target)) + { + response = $"已有一个交换请求发送给 {target.Nickname},请等待对方回应。"; + return false; + } + + // 保存请求 + CustomEventHandler.SwapRequests[target] = player; + + // 通知目标玩家 + target.SendBroadcast($"{player.Nickname} 想与你交换 SCP 身份!输入 .swapaccept 接受,或 .swapdeny 拒绝。", 10); + + Log.Info($"{player.Nickname} 申请与 {arguments.At(0)} 交换"); + + response = "申请成功"; + return true; + } + } +} diff --git a/EasyTools.csproj b/EasyTools.csproj index 2c7ffc2..c01fa4b 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -127,6 +127,9 @@ + + + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index d23b489..7c76f62 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -44,6 +44,10 @@ public class CustomEventHandler : CustomEventsHandler public static HintData data_914, data_elevator; + public static DateTime RoundStartTime { get; private set; } + + // SCP交换列表 + public static volatile Dictionary SwapRequests = new Dictionary(); public override void OnServerWaitingForPlayers() { base.OnServerWaitingForPlayers(); @@ -59,6 +63,8 @@ public override void OnServerWaitingForPlayers() public override void OnServerRoundStarted() { + RoundStartTime = DateTime.Now; + Timing.CallDelayed(10f, () => { if (Config.EnableAutoServerMessage) From e651d90bfdd0c9f27747a699abf973bc4e61ea8c Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:40:22 +0800 Subject: [PATCH 16/21] =?UTF-8?q?feat:=20SCP=E6=96=AD=E7=BA=BF=E8=A1=A5?= =?UTF-8?q?=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Commands/Scp/ReplaceScpCommand.cs | 65 +++++++++++++++++++++++++++++++ EasyTools.csproj | 1 + Events/CustomEventHandler.cs | 48 +++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 Commands/Scp/ReplaceScpCommand.cs diff --git a/Commands/Scp/ReplaceScpCommand.cs b/Commands/Scp/ReplaceScpCommand.cs new file mode 100644 index 0000000..64a71dd --- /dev/null +++ b/Commands/Scp/ReplaceScpCommand.cs @@ -0,0 +1,65 @@ +using CommandSystem; +using EasyTools.Events; +using LabApi.Features.Wrappers; +using PlayerRoles; +using System; +using UnityEngine; + +namespace EasyTools.Commands.Scp +{ + [CommandHandler(typeof(ClientCommandHandler))] + public class ReplaceScpCommand : ICommand + { + public string Command => "replace"; + + public string[] Aliases => ["rscp"]; + + public string Description => "申请补位一个断线SCP"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + Player player; + + if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) + { + response = "失败,可能指令未启用或者身份不允许等"; + return false; + } + + if (arguments.Count == 0) + { + response = "请指定要补位的 SCP 编号(Scp079|Scp096|Scp106|Scp173|Scp049|Scp3114)"; + return false; + } + + if (arguments.Count == 0) + { + response = "失败,未指定你要交换的目标(Scp079|Scp096|Scp106|Scp173|Scp049|Scp3114)"; + return false; + } + + string input = arguments.At(0); + if (!Enum.TryParse(input, out RoleTypeId targetRole)) + { + response = $"无效的 SCP 编号:{input}。可用的有 Scp079|Scp096|Scp106|Scp173|Scp049|Scp3114 (必须带Scp)"; + return false; + } + + if (!CustomEventHandler.Replacements.TryGetValue(targetRole, out var entry) || Time.time > entry.ExpireTime) + { + response = $"当前没有 {targetRole} 的补位名额或已过期。"; + return false; + } + + if (entry.Applicants.Contains(player)) + { + response = "你已经申请过该角色了,请等待系统分配。"; + return false; + } + + entry.Applicants.Add(player); + response = $"你已申请补位 {targetRole},等待 {10 - (Time.time - (entry.ExpireTime - 10f)):0.0} 秒后系统随机选择。"; + return true; + } + } +} diff --git a/EasyTools.csproj b/EasyTools.csproj index c01fa4b..1a6b08c 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -127,6 +127,7 @@ + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 7c76f62..9543570 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -48,6 +48,16 @@ public class CustomEventHandler : CustomEventsHandler // SCP交换列表 public static volatile Dictionary SwapRequests = new Dictionary(); + + // SCP补位列表 + public static readonly Dictionary Replacements = new(); + + public class ReplacementEntry + { + public List Applicants = new(); + public float ExpireTime; // Time.time + 10f + } + public override void OnServerWaitingForPlayers() { base.OnServerWaitingForPlayers(); @@ -187,6 +197,44 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) { _huds.Remove(player); } + + // 清理该玩家在所有补位申请中的记录(防止幽灵申请) + foreach (var entry in Replacements.Values) + entry.Applicants.Remove(player); + + if (player.IsSCP && player.Health > 0) + { + var role = player.Role; + + Replacements[role] = new ReplacementEntry + { + ExpireTime = Time.time + 10f + }; + + Timing.CallDelayed(10f, () => ExecuteReplacement(role)); + } + } + + private void ExecuteReplacement(RoleTypeId role) + { + if (!Replacements.TryGetValue(role, out var entry)) + return; + + // 从补位名单中筛选仍在线的人类玩家 + var valid = entry.Applicants.Where(p => p != null && p.IsHuman).ToList(); + + if (valid.Count == 0) + { + Server.SendBroadcast($"{role} 补位无人申请,该角色空缺。", 5); + return; + } + + // 随机选择 + var chosen = valid[UnityEngine.Random.Range(0, valid.Count)]; + chosen.Role = role; + + Server.SendBroadcast($"补位成功!{chosen.Nickname} 成为了 {role}。", 10); + Log.Info($"{chosen.Nickname} 补位成为 {role}"); } private static volatile bool allow_spawn_scp_3114 = true; //用以确保不会重复生成SCP-3114 From f1aeb805a36d8eea97137fa677cedb09ea8bc8fc Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 12:06:23 +0800 Subject: [PATCH 17/21] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E7=9B=AE=E5=BD=95=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Commands/{ => System}/KillMeCommand.cs | 2 +- EasyTools.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Commands/{ => System}/KillMeCommand.cs (97%) diff --git a/Commands/KillMeCommand.cs b/Commands/System/KillMeCommand.cs similarity index 97% rename from Commands/KillMeCommand.cs rename to Commands/System/KillMeCommand.cs index 47f8718..70fc5cb 100644 --- a/Commands/KillMeCommand.cs +++ b/Commands/System/KillMeCommand.cs @@ -5,7 +5,7 @@ using RelativePositioning; using System; -namespace EasyTools.Commands +namespace EasyTools.Commands.System { [CommandHandler(typeof(ClientCommandHandler))] public class KillMeCommand : ICommand diff --git a/EasyTools.csproj b/EasyTools.csproj index 1a6b08c..aa1aa1f 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -125,7 +125,7 @@ - + From d29d7da6026b789f30afdfd3d0e75e02c720f197 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 12:20:14 +0800 Subject: [PATCH 18/21] =?UTF-8?q?feat:=20=E6=96=B0=E7=89=88=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BadgeSystem/Badge.cs | 131 ------------ Commands/System/BadgeCommand.cs | 90 ++++++++ Commands/System/PermissionCommand.cs | 64 ++++++ EasyTools.csproj | 5 +- Events/CustomEventHandler.cs | 17 +- Extensions/BadgeExtensions.cs | 116 +++++++++++ Plugins.cs | 1 + Utils/Ini.cs | 298 --------------------------- 8 files changed, 282 insertions(+), 440 deletions(-) delete mode 100644 BadgeSystem/Badge.cs create mode 100644 Commands/System/BadgeCommand.cs create mode 100644 Commands/System/PermissionCommand.cs create mode 100644 Extensions/BadgeExtensions.cs delete mode 100644 Utils/Ini.cs diff --git a/BadgeSystem/Badge.cs b/BadgeSystem/Badge.cs deleted file mode 100644 index 182ac77..0000000 --- a/BadgeSystem/Badge.cs +++ /dev/null @@ -1,131 +0,0 @@ -using EasyTools.Events; -using LabApi.Features.Wrappers; -using MEC; -using NewXp.IniApi; -using System.Collections.Generic; -using System.IO; -using Log = LabApi.Features.Console.Logger; - -namespace EasyTools.BadgeSystem -{ - public class Badge - { - public static string[] FMoreColo = - [ - "pink", - "silver", - "cyan", - "aqua", - "tomato", - "yellow", - "magenta", - "orange", - "lime", - "green", - "red", - "brown", - "red", - "orange", - "yellow", - "green", - "blue_green", - "magenta", - "pink", - "brown", - "silver", - "light_green", - "crimson", - "cyan", - "aqua", - "deep_pink", - "tomato", - "blue_green", - "lime", - "emerald", - "carmine", - "nickel", - "mint", - "army_green", - "pumpkin" - ]; - - public static List rainbw = new List(); - - public static IEnumerator Rainbw() - { - while (true) - { - foreach (var item in rainbw) - { - item.GroupColor = FMoreColo.RandomItem(); - } - yield return Timing.WaitForSeconds(CustomEventHandler.BadgeConfig.each); - } - - } - - public static void Handler(Player player) - { - string filePath = Path.Combine(CustomEventHandler.BadgeConfig.Pach, player.UserId + ".ini"); - - if (!File.Exists(filePath)) - { - IniFile iniFile = new IniFile(); - iniFile.Section("DIR").Set("称号", "空", "称号"); - iniFile.Section("DIR").Set("称号颜色", "空"); - iniFile.Section("DIR").Set("管理权限组", "空"); - iniFile.Save(filePath); - } - else - { - - IniFile iniFile = new IniFile(filePath); - iniFile.Save(filePath); - if (iniFile.Section("DIR").Get("管理权限组") == "空") - { - if (iniFile.Section("DIR").Get("称号") != "空") - { - player.GroupName = iniFile.Section("DIR").Get("称号"); - switch (iniFile.Section("DIR").Get("称号颜色")) - { - case "rainbow": - rainbw.Add(player); - break; - default: - player.GroupColor = iniFile.Section("DIR").Get("称号颜色"); - break; - } - } - - } - else - { - Server.RunCommand($"/setgroup {player.PlayerId} {iniFile.Section("DIR").Get("管理权限组")}"); - Log.Info($"已经给予{player.Nickname}-{player.UserId}==={iniFile.Section("DIR").Get("管理权限组")}权限"); - if (iniFile.Section("DIR").Get("称号") != "空") - { - player.GroupName = iniFile.Section("DIR").Get("称号"); - switch (iniFile.Section("DIR").Get("称号颜色")) - { - case "rainbow": - rainbw.Add(player); - break; - default: - player.GroupColor = iniFile.Section("DIR").Get("称号颜色"); - break; - } - } - } - } - } - - public static void Remove(Player player) - { - if (Badge.rainbw.Contains(player)) - { - Badge.rainbw.Remove(player); - } - } - - } -} diff --git a/Commands/System/BadgeCommand.cs b/Commands/System/BadgeCommand.cs new file mode 100644 index 0000000..1c481cc --- /dev/null +++ b/Commands/System/BadgeCommand.cs @@ -0,0 +1,90 @@ +using CommandSystem; +using EasyTools.DataStructures; +using EasyTools.Events; +using EasyTools.Extensions; +using LabApi.Features.Wrappers; +using System; + +namespace EasyTools.Commands.System +{ + [CommandHandler(typeof(ClientCommandHandler))] + public class BadgeCommand : ICommand + { + public string Command => "badge"; + + public string[] Aliases => []; + + public string Description => "设置玩家称号"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + Player player; + + if (sender is null || (player = Player.Get(sender)) is null) + { + response = CustomEventHandler.TranslateConfig.RescueCommandError; + return false; + } + + PlayerData data = player.GetData(); + + if (data.PermissionLevel == PermissionLevel.Player) + { + response = CustomEventHandler.TranslateConfig.RescueCommandFailed; + return false; + } + + if (arguments.Count == 0) + { + response = "请输入要给予称号的 SteamId"; + return false; + } + + Player target = Player.Get(arguments.At(0)); + + if (target == null) + { + response = "无法查找到玩家"; + return false; + } + + PlayerData targetData = target.GetData(); + + if (arguments.Count < 2) + { + response = "请输入要设置的称号"; + return false; + } + + if (targetData.PermissionLevel != PermissionLevel.Player) + { + switch (targetData.PermissionLevel) + { + case PermissionLevel.Moderator: + targetData.Badge = $"{arguments.At(1)}(Lv{(int)PermissionLevel.Moderator}.MODERATOR)"; + break; + case PermissionLevel.Admin: + targetData.Badge = $"{arguments.At(1)}(Lv{(int)PermissionLevel.Admin}.ADMIN)"; + break; + case PermissionLevel.Owner: + targetData.Badge = $"{arguments.At(1)}(Lv{(int)PermissionLevel.Owner}.OWNER)"; + break; + default: + targetData.Badge = $"{arguments.At(1)}(Lv{(int)PermissionLevel.Moderator}.MODERATOR)"; + break; + } + } else targetData.Badge = arguments.At(1); + + // 无颜色参数时默认为 rainbow + string color = arguments.Count >= 3 ? arguments.At(2) : "rainbow"; + targetData.BadgeColor = color; + + targetData.UpdateData(); + target.ApplyBadge(); + + string colorDisplay = color == "rainbow" ? "彩虹色" : color; + response = $"已将 {arguments.At(0)} 的称号设置为 {targetData.Badge},颜色为 {colorDisplay}"; + return true; + } + } +} diff --git a/Commands/System/PermissionCommand.cs b/Commands/System/PermissionCommand.cs new file mode 100644 index 0000000..dc72196 --- /dev/null +++ b/Commands/System/PermissionCommand.cs @@ -0,0 +1,64 @@ +using CommandSystem; +using EasyTools.DataStructures; +using EasyTools.Extensions; +using LabApi.Features.Wrappers; +using System; + +namespace EasyTools.Commands.System +{ + [CommandHandler(typeof(GameConsoleCommandHandler))] + public class PermissionCommand : ICommand + { + public string Command => "eperm"; + + public string[] Aliases => []; + + public string Description => "玩家权限管理"; + + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + if (arguments.Count == 0) + { + response = "请输入要给予权限的 SteamId"; + return false; + } + + Player player = Player.Get(arguments.At(0)); + + if (player == null) + { + response = "无法查找到玩家"; + return false; + } + + if (arguments.Count == 1) + { + response = "请输入要给予的权限组 (moderator|admin|owner)"; + return false; + } + + if(!Enum.TryParse(arguments.At(1), true, out PermissionLevel level)) + { + response = "权限组无效,请输入 (moderator|admin|owner)"; + return false; + } + + PlayerData data = player.GetData(); + data.PermissionLevel = level; + data.Badge = level switch + { + PermissionLevel.Moderator => "(Lv1.MODERATOR)", + PermissionLevel.Admin => "(Lv2.ADMIN)", + PermissionLevel.Owner => "(Lv3.OWNER)", + _ => data.Badge + }; + data.BadgeColor = "rainbow"; + data.UpdateData(); + player.ApplyPermission(); + player.ApplyBadge(); + + response = $"设置成功"; + return true; + } + } +} diff --git a/EasyTools.csproj b/EasyTools.csproj index aa1aa1f..ae297d4 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -121,7 +121,9 @@ - + + + @@ -148,7 +150,6 @@ - diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 9543570..8ee541c 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -1,4 +1,3 @@ -using EasyTools.BadgeSystem; using EasyTools.Configs; using EasyTools.DataStructures; using EasyTools.Extensions; @@ -64,8 +63,8 @@ public override void OnServerWaitingForPlayers() if (BadgeConfig.Enable) { - Badge.rainbw.Clear(); - Badge_Coroutine = Timing.RunCoroutine(Badge.Rainbw()); + BadgeExtensions.rainbw.Clear(); + Badge_Coroutine = Timing.RunCoroutine(BadgeExtensions.Rainbw()); } Server.FriendlyFire = false; @@ -129,6 +128,8 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) data.LastJoinedTime = DateTime.Now; data.UpdateData(); player.UpdatePlayerNameWithLevelPrefix(); + player.ApplyPermission(); + player.ApplyBadge(); } if (Config.EnableLogger) @@ -154,11 +155,6 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) } } - if (BadgeConfig.Enable) - { - Badge.Handler(player); - } - _huds[player] = new PlayerHint(player, data_914, data_elevator); } @@ -190,7 +186,10 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) if (BadgeConfig.Enable) { - Badge.Remove(player); + if (BadgeExtensions.rainbw.Contains(player)) + { + BadgeExtensions.rainbw.Remove(player); + } } if (_huds.ContainsKey(player)) diff --git a/Extensions/BadgeExtensions.cs b/Extensions/BadgeExtensions.cs new file mode 100644 index 0000000..87dc170 --- /dev/null +++ b/Extensions/BadgeExtensions.cs @@ -0,0 +1,116 @@ +using EasyTools.DataStructures; +using EasyTools.Events; +using LabApi.Features.Wrappers; +using MEC; +using System; +using System.Collections.Generic; +using Log = LabApi.Features.Console.Logger; + +namespace EasyTools.Extensions +{ + public static class BadgeExtensions + { + public static string[] FMoreColo = + [ + "pink", + "silver", + "cyan", + "aqua", + "tomato", + "yellow", + "magenta", + "orange", + "lime", + "green", + "red", + "brown", + "red", + "orange", + "yellow", + "green", + "blue_green", + "magenta", + "pink", + "brown", + "silver", + "light_green", + "crimson", + "cyan", + "aqua", + "deep_pink", + "tomato", + "blue_green", + "lime", + "emerald", + "carmine", + "nickel", + "mint", + "army_green", + "pumpkin" + ]; + + public static List rainbw = new List(); + + public static IEnumerator Rainbw() + { + while (true) + { + foreach (var item in rainbw) + { + item.GroupColor = FMoreColo.RandomItem(); + } + yield return Timing.WaitForSeconds(CustomEventHandler.BadgeConfig.each); + } + } + + public static void ApplyBadge(this Player player) + { + PlayerData data = player.GetData(); + + if (data.Badge != "") + { + player.GroupName = data.Badge; + + if (data.BadgeColor != "") + { + switch (data.BadgeColor) + { + case "rainbow": + rainbw.Add(player); + break; + default: + player.GroupColor = data.BadgeColor; + break; + } + } + } + } + + public static void ApplyPermission(this Player player) + { + PlayerData data = player.GetData(); + if (data.PermissionLevel != PermissionLevel.Player) + { + string group; + switch (data.PermissionLevel) + { + case PermissionLevel.Moderator: + group = "moderator"; + break; + case PermissionLevel.Admin: + group = "admin"; + break; + case PermissionLevel.Owner: + group = "owner"; + break; + default: + group = "moderator"; + break; + }; + + Server.RunCommand($"/setgroup {player.PlayerId} {group}"); + Log.Info($"[AC] Date: {DateTime.Now} | Player: {player.Nickname} | Perm: {group} | Steam64ID: {player.UserId}"); + } + } + } +} diff --git a/Plugins.cs b/Plugins.cs index cc92113..7f77d1b 100644 --- a/Plugins.cs +++ b/Plugins.cs @@ -1,4 +1,5 @@ using EasyTools.Configs; +using EasyTools.DataStructures; using EasyTools.Events; using LabApi.Events.CustomHandlers; using LabApi.Features; diff --git a/Utils/Ini.cs b/Utils/Ini.cs deleted file mode 100644 index 4a0d3a3..0000000 --- a/Utils/Ini.cs +++ /dev/null @@ -1,298 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace NewXp.IniApi -{ - /// - /// Represents a property in an INI file. - /// - public class IniProperty - { - /// - /// Property name (key). - /// - public string Name { get; set; } - - /// - /// Property value. - /// - public string Value { get; set; } - - /// - /// Set the comment to display above this property. - /// - public string Comment { get; set; } - } - - /// - /// Represents a section in an INI file. - /// - public class IniSection - { - private readonly IDictionary _properties; - - /// - /// Section name. - /// - public string Name { get; set; } - - /// - /// Set the comment to display above this section. - /// - public string Comment { get; set; } - - /// - /// Get the properties in this section. - /// - public IniProperty[] Properties => _properties.Values.ToArray(); - - /// - /// Create a new IniSection. - /// - /// - public IniSection(string name) - { - Name = name; - _properties = new Dictionary(); - } - - /// - /// Get a property value. - /// - /// Name of the property. - /// Value of the property or null if it doesn't exist. - public string Get(string name) - { - if (_properties.ContainsKey(name)) - return _properties[name].Value; - - return null; - } - - /// - /// Get a property value, coercing the type of the value - /// into the type given by the generic parameter. - /// - /// Name of the property. - /// The type to coerce the value into. - /// - public T Get(string name) - { - if (_properties.ContainsKey(name)) - return (T)Convert.ChangeType(_properties[name].Value, typeof(T)); - - return default(T); - } - - /// - /// Set a property value. - /// - /// Name of the property. - /// Value of the property. - /// A comment to display above the property. - public void Set(string name, string value, string comment = null) - { - if (string.IsNullOrWhiteSpace(value)) - { - RemoveProperty(name); - return; - } - - if (!_properties.ContainsKey(name)) - _properties.Add(name, new IniProperty { Name = name, Value = value, Comment = comment }); - else - { - _properties[name].Value = value; - if (comment != null) - _properties[name].Comment = comment; - } - } - - /// - /// Remove a property from this section. - /// - /// The property name to remove. - public void RemoveProperty(string propertyName) - { - if (_properties.ContainsKey(propertyName)) - _properties.Remove(propertyName); - } - } - - /// - /// Represenst an INI file that can be read from or written to. - /// - public class IniFile - { - private readonly IDictionary _sections; - - /// - /// If True, writes extra spacing between the property name and the property value. - /// (foo=bar) vs (foo = bar) - /// - public bool WriteSpacingBetweenNameAndValue { get; set; } - - /// - /// The character a comment line will begin with. Default '#'. - /// - public char CommentChar { get; set; } - - /// - /// Get the sections in this IniFile. - /// - public IniSection[] Sections => _sections.Values.ToArray(); - - /// - /// Create a new IniFile instance. - /// - public IniFile() - { - _sections = new Dictionary(); - CommentChar = '#'; - } - - /// - /// Load an INI file from the file system. - /// - /// Path to the INI file. - public IniFile(string path) : this() - { - Load(path); - } - - /// - /// Load an INI file. - /// - /// A TextReader instance. - public IniFile(TextReader reader) : this() - { - Load(reader); - } - - private void Load(string path) - { - using (var file = new StreamReader(path)) - Load(file); - } - - private void Load(TextReader reader) - { - IniSection section = null; - - string line; - while ((line = reader.ReadLine()) != null) - { - line = line.Trim(); - - // skip empty lines - if (line == string.Empty) - continue; - - // skip comments - if (line.StartsWith(";") || line.StartsWith("#")) - continue; - - if (line.StartsWith("[") && line.EndsWith("]")) - { - var sectionName = line.Substring(1, line.Length - 2); - if (!_sections.ContainsKey(sectionName)) - { - section = new IniSection(sectionName); - _sections.Add(sectionName, section); - } - continue; - } - - if (section != null) - { - var keyValue = line.Split(new[] { "=" }, 2, StringSplitOptions.RemoveEmptyEntries); - if (keyValue.Length != 2) - continue; - - section.Set(keyValue[0].Trim(), keyValue[1].Trim()); - } - } - } - - /// - /// Get a section by name. If the section doesn't exist, it is created. - /// - /// The name of the section. - /// A section. If the section doesn't exist, it is created. - public IniSection Section(string sectionName) - { - IniSection section; - if (!_sections.TryGetValue(sectionName, out section)) - { - section = new IniSection(sectionName); - _sections.Add(sectionName, section); - } - - return section; - } - - /// - /// Remove a section. - /// - /// Name of the section to remove. - public void RemoveSection(string sectionName) - { - if (_sections.ContainsKey(sectionName)) - _sections.Remove(sectionName); - } - - /// - /// Create a new INI file. - /// - /// Path to the INI file to create. - public void Save(string path) - { - using (var file = new StreamWriter(path)) - Save(file); - } - - /// - /// Create a new INI file. - /// - /// A TextWriter instance. - public void Save(TextWriter writer) - { - foreach (var section in _sections.Values) - { - if (section.Properties.Length == 0) - continue; - - if (section.Comment != null) - writer.WriteLine($"{CommentChar} {section.Comment}"); - - writer.WriteLine($"[{section.Name}]"); - - foreach (var property in section.Properties) - { - if (property.Comment != null) - writer.WriteLine($"{CommentChar} {property.Comment}"); - - var format = WriteSpacingBetweenNameAndValue ? "{0} = {1}" : "{0}={1}"; - writer.WriteLine(format, property.Name, property.Value); - } - - writer.WriteLine(); - } - } - - /// - /// Returns the content of this INI file as a string. - /// - /// The text content of this INI file. - public override string ToString() - { - using (var sw = new StringWriter()) - { - Save(sw); - return sw.ToString(); - } - } - } -} From 0a5098890f601da72e0a54f507f8f0d8d97088fa Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:44:46 +0800 Subject: [PATCH 19/21] =?UTF-8?q?refactor:=20=E9=87=8D=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=8F=98=E9=87=8F=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Configs/BadgeConfig.cs | 2 +- Configs/CoinConfig.cs | 6 +++--- Configs/HUDInfoConfig.cs | 18 +++++++++--------- Configs/TranslateConfig.cs | 10 +++++----- Events/CustomEventHandler.cs | 36 +++++++++++++++++------------------ Extensions/BadgeExtensions.cs | 2 +- Plugins.cs | 20 +++++++++---------- 7 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Configs/BadgeConfig.cs b/Configs/BadgeConfig.cs index a31c8a1..3ba98ee 100644 --- a/Configs/BadgeConfig.cs +++ b/Configs/BadgeConfig.cs @@ -9,6 +9,6 @@ public class BadgeConfig [Description("存储路径")] public string Pach { get; set; } = "/home/shiroko/.config/DIRSave"; [Description("彩色称号更新频率")] - public int each { get; set; } = 1; + public int Each { get; set; } = 1; } } diff --git a/Configs/CoinConfig.cs b/Configs/CoinConfig.cs index de4e433..f3fc7c1 100644 --- a/Configs/CoinConfig.cs +++ b/Configs/CoinConfig.cs @@ -25,7 +25,7 @@ public class CoinConfig // ---- 15% 随机枪械(两种枪各7.5%) ---- new RewardSetting { Weight = 7.5f, Type = RewardType.GiveItem, Param = "GunE11SR", Name = "狗官枪" }, - new RewardSetting { Weight = 7.5f, Type = RewardType.GiveItem, Param = "GunAK", Name = "大机枪" }, + new RewardSetting { Weight = 7.5f, Type = RewardType.GiveItem, Param = "GunAK", Name = "AK-47" }, // ---- 10% 中士卡 ---- new RewardSetting { Weight = 10.0f, Type = RewardType.GiveItem, Param = "KeycardMTFOperative", Name = "中士卡" }, @@ -47,7 +47,7 @@ public class CoinConfig public class RewardSetting { - [Description("显示名称(用于广播)")] + [Description("显示名称")] public string Name { get; set; } = "未知奖励"; [Description("相对权重")] @@ -56,7 +56,7 @@ public class RewardSetting [Description("奖励类型")] public RewardType Type { get; set; } = RewardType.None; - [Description("参数(根据类型不同:角色ID、物品ID、枪械列表等)")] + [Description("额外参数")] public string Param { get; set; } = string.Empty; } diff --git a/Configs/HUDInfoConfig.cs b/Configs/HUDInfoConfig.cs index 4e29d95..261f621 100644 --- a/Configs/HUDInfoConfig.cs +++ b/Configs/HUDInfoConfig.cs @@ -5,27 +5,27 @@ namespace EasyTools.Configs public class HUDInfoConfig { [Description("是否显示SCP914提示信息")] - public bool info_914 { get; set; } = true; + public bool EnableScp914Info { get; set; } = true; [Description("是否显示电梯提示信息")] - public bool info_elevator { get; set; } = true; + public bool EnableElevatorInfo { get; set; } = true; /// ///////////////////////////////////////////////// [Description("914显示,X轴坐标(0为正中,-为左,+为右):")] - public float _914_x { get; set; } = 0; + public float Scp914DisplayX { get; set; } = 0; [Description("914显示,Y轴坐标(屏幕最上端大概100,最下端大概1000):")] - public float _914_y { get; set; } = 80; + public float Scp914DisplayY { get; set; } = 80; [Description("914显示,字体大小:")] - public int _914_font { get; set; } = 20; + public int Scp914FontSize { get; set; } = 20; /// ///////////////////////////////////////////////// [Description("电梯显示,X轴坐标(0为正中,-为左,+为右):")] - public float _elev_x { get; set; } = 0; + public float ElevatorDisplayX { get; set; } = 0; [Description("电梯显示,Y轴坐标(屏幕最上端大概100,最下端大概1000):")] - public float _elev_y { get; set; } = 800; + public float ElevatorDisplayY { get; set; } = 800; [Description("电梯显示,字体大小:")] - public int _elev_font { get; set; } = 20; + public int ElevatorFontSize { get; set; } = 20; [Description("电梯提示显示可见范围(操作者为中心):")] - public float elev_range { get; set; } = 10f; + public float ElevatorHintRange { get; set; } = 10f; } } diff --git a/Configs/TranslateConfig.cs b/Configs/TranslateConfig.cs index fc64497..5435b97 100644 --- a/Configs/TranslateConfig.cs +++ b/Configs/TranslateConfig.cs @@ -78,11 +78,11 @@ public class TranslateConfig /// /// [Description("电梯显示模板(HEX color写死, {p_operator}表示操作人, 没有的话自动为未知):")] - public string elev_template { get; set; } = "[Elevator] 电梯使用者: {p_operator}"; - [Description("SCP914显示模板(HEX color写死, {mode}表示操作模式, {p_operator}表示操作人, 没有的话自动为未知):")] - public string scp914_template { get; set; } = "[Scp914] 已启动! 模式: {mode}, 操作人: {p_operator}"; - [Description("SCP914, Rough模式翻译:")] - public Dictionary scp914_trans { get; set; } = new Dictionary() + public string ElevatorTemplate { get; set; } = "[Elevator] 电梯使用者: {p_operator}"; + [Description("SCP-914 显示模板(HEX color写死, {mode}表示操作模式, {p_operator}表示操作人, 没有的话自动为未知):")] + public string Scp914Template { get; set; } = "[Scp914] 已启动! 模式: {mode}, 操作人: {p_operator}"; + [Description("SCP-914 模式翻译:")] + public Dictionary Scp914ModeTranslations { get; set; } = new Dictionary() { { Scp914KnobSetting.Rough, "粗加" }, { Scp914KnobSetting.Coarse, "半粗" }, diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 8ee541c..7638e42 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -37,11 +37,11 @@ public class CustomEventHandler : CustomEventsHandler public static CoinConfig CoinConfig; - public static CoroutineHandle Badge_Coroutine; + public static CoroutineHandle BadgeCoroutine; - public static readonly Dictionary _huds = new(); + public static readonly Dictionary PlayerHuds = new(); - public static HintData data_914, data_elevator; + public static HintData Scp914HintData, ElevatorHintData; public static DateTime RoundStartTime { get; private set; } @@ -64,7 +64,7 @@ public override void OnServerWaitingForPlayers() if (BadgeConfig.Enable) { BadgeExtensions.rainbw.Clear(); - Badge_Coroutine = Timing.RunCoroutine(BadgeExtensions.Rainbw()); + BadgeCoroutine = Timing.RunCoroutine(BadgeExtensions.Rainbw()); } Server.FriendlyFire = false; @@ -85,7 +85,7 @@ public override void OnServerRoundStarted() { Timing.RunCoroutine(ScpAutoHealHelper.AutoReal()); } - _huds.Values.ToList().ForEach(h => h.Start()); + PlayerHuds.Values.ToList().ForEach(h => h.Start()); }); if (DataBaseConfig.database_enable) @@ -100,7 +100,7 @@ public override void OnServerRoundEnded(RoundEndedEventArgs ev) if (BadgeConfig.Enable) { - Timing.KillCoroutines(Badge_Coroutine); + Timing.KillCoroutines(BadgeCoroutine); } if (Config.EnableFriendFire) @@ -155,7 +155,7 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) } } - _huds[player] = new PlayerHint(player, data_914, data_elevator); + PlayerHuds[player] = new PlayerHint(player, Scp914HintData, ElevatorHintData); } @@ -175,7 +175,7 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) data.UpdateData(); } - if (Config.EnableLogger) + if (Config.EnablePlayerLogger) { string playerInfo = $"[EXIT] Date: {DateTime.Now} | Player: {nickName} | Steam64ID: {userId}"; string path = Path.Combine(CustomEventHandler.Config.PlayerLogPath, $"{Server.Port}.log"); @@ -192,9 +192,9 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) } } - if (_huds.ContainsKey(player)) + if (PlayerHuds.ContainsKey(player)) { - _huds.Remove(player); + PlayerHuds.Remove(player); } // 清理该玩家在所有补位申请中的记录(防止幽灵申请) @@ -475,37 +475,37 @@ public override void OnPlayerFlippingCoin(PlayerFlippingCoinEventArgs ev) public override void OnScp914Activating(Scp914ActivatingEventArgs ev) { - if (HUDInfoConfig.info_914 == false) return; + if (HUDInfoConfig.EnableScp914Info == false) return; Scp914.Scp914KnobSetting knob = ev.KnobSetting; - string mode = TranslateConfig.scp914_trans[knob]; + string mode = TranslateConfig.Scp914ModeTranslations[knob]; var p_operator = ev.Player.Nickname ?? "未知"; - string msg = TranslateConfig.scp914_template.Replace("{mode}", mode) + string msg = TranslateConfig.Scp914Template.Replace("{mode}", mode) .Replace("{p_operator}", p_operator); foreach (var p in Player.List) { if (p.IsAlive && p != null && p.Room.Name == RoomName.Lcz914)// 检测914附近玩家,然后告诉他们914正在运行 { - _huds[p].Show914(msg); + PlayerHuds[p].Show914(msg); } } } public override void OnPlayerInteractingElevator(PlayerInteractingElevatorEventArgs ev) { - if (HUDInfoConfig.info_elevator == false) return; + if (HUDInfoConfig.EnableElevatorInfo == false) return; IEnumerable near = Player.List.Where(p => - Vector3.Distance(p.Position, ev.Player.Position) <= HUDInfoConfig.elev_range); + Vector3.Distance(p.Position, ev.Player.Position) <= HUDInfoConfig.ElevatorHintRange); var p_operator = ev.Player.Nickname ?? "未知"; - string text = TranslateConfig.elev_template.Replace("{p_operator}", p_operator); + string text = TranslateConfig.ElevatorTemplate.Replace("{p_operator}", p_operator); foreach (var p in near) { - _huds[p].ShowElevator(text); + PlayerHuds[p].ShowElevator(text); } } } diff --git a/Extensions/BadgeExtensions.cs b/Extensions/BadgeExtensions.cs index 87dc170..0c2fc3b 100644 --- a/Extensions/BadgeExtensions.cs +++ b/Extensions/BadgeExtensions.cs @@ -59,7 +59,7 @@ public static IEnumerator Rainbw() { item.GroupColor = FMoreColo.RandomItem(); } - yield return Timing.WaitForSeconds(CustomEventHandler.BadgeConfig.each); + yield return Timing.WaitForSeconds(CustomEventHandler.BadgeConfig.Each); } } diff --git a/Plugins.cs b/Plugins.cs index 7f77d1b..6dd5e52 100644 --- a/Plugins.cs +++ b/Plugins.cs @@ -24,18 +24,18 @@ public override void LoadConfigs() CustomEventHandler.HUDInfoConfig = this.LoadConfig("HUDInfoConfig.yml"); CustomEventHandler.CoinConfig = this.LoadConfig("coinConfig.yml"); - CustomEventHandler.data_914 = new HintData + CustomEventHandler.Scp914HintData = new HintData ( - CustomEventHandler.HUDInfoConfig._914_x, - CustomEventHandler.HUDInfoConfig._914_y, - CustomEventHandler.HUDInfoConfig._914_font + CustomEventHandler.HUDInfoConfig.Scp914DisplayX, + CustomEventHandler.HUDInfoConfig.Scp914DisplayY, + CustomEventHandler.HUDInfoConfig.Scp914FontSize ); - CustomEventHandler.data_elevator = new HintData + CustomEventHandler.ElevatorHintData = new HintData ( - CustomEventHandler.HUDInfoConfig._elev_x, - CustomEventHandler.HUDInfoConfig._elev_y, - CustomEventHandler.HUDInfoConfig._elev_font + CustomEventHandler.HUDInfoConfig.ElevatorDisplayX, + CustomEventHandler.HUDInfoConfig.ElevatorDisplayY, + CustomEventHandler.HUDInfoConfig.ElevatorFontSize ); if (!Directory.Exists(CustomEventHandler.BadgeConfig.Pach)) @@ -72,8 +72,8 @@ public override void Disable() Instance = null; - foreach (var hud in CustomEventHandler._huds.Values) hud.Dispose(); - CustomEventHandler._huds.Clear(); + foreach (var hud in CustomEventHandler.PlayerHuds.Values) hud.Dispose(); + CustomEventHandler.PlayerHuds.Clear(); } } From 3997e6727d88cec78f7beabd3d45c775193cf5d8 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:48:35 +0800 Subject: [PATCH 20/21] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E7=A1=AC?= =?UTF-8?q?=E5=B8=81=E6=8A=BD=E5=8D=A1=E7=B3=BB=E7=BB=9F=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Configs/CoinConfig.cs | 6 ++++++ Configs/Config.cs | 4 ---- Configs/TranslateConfig.cs | 2 ++ Events/CustomEventHandler.cs | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Configs/CoinConfig.cs b/Configs/CoinConfig.cs index f3fc7c1..d811bdb 100644 --- a/Configs/CoinConfig.cs +++ b/Configs/CoinConfig.cs @@ -5,6 +5,12 @@ namespace EasyTools.Configs { public class CoinConfig { + [Description("开启硬币抽卡?")] + public bool Enable { get; set; } = true; + + [Description("开局发放硬币?")] + public bool EnableRoundCoin { get; set; } = true; + [Description("抽卡奖励列表,权重总和为 100(自动归一化也可),支持修改概率和奖励内容")] public List Rewards { get; set; } = new List { diff --git a/Configs/Config.cs b/Configs/Config.cs index 7468dae..7f33e80 100644 --- a/Configs/Config.cs +++ b/Configs/Config.cs @@ -96,11 +96,7 @@ public class Config public int HealSCPQuantity { get; set; } = 2; /// ///////////////////////////////////////////////// - [Description("开启硬币抽卡?")] - public bool Coin { get; set; } = true; - [Description("开局发放硬币?")] - public bool EnableRoundCoin { get; set; } = true; /// ///////////////////////////////////////////////// [Description("开启回合结束友伤?")] diff --git a/Configs/TranslateConfig.cs b/Configs/TranslateConfig.cs index 5435b97..caf0972 100644 --- a/Configs/TranslateConfig.cs +++ b/Configs/TranslateConfig.cs @@ -100,7 +100,9 @@ public class TranslateConfig /// /// /// + [Description("使用硬币抽卡时背包空间不足提示")] public string RewardFailedBroadcastTemplate { get; set; } = "\n你的背包空间不足,无法继续抽卡!"; + [Description("使用硬币抽卡成功提示")] public string RewardOkBroadcastTemplate { get; set; } = "\n🎉 恭喜!玩家 {nickName} 通过抛硬币{result}!"; } } diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 7638e42..4faae8d 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -299,7 +299,7 @@ public override void OnPlayerSpawned(PlayerSpawnedEventArgs ev) }); } - if (Config.EnableRoundCoin) + if (CoinConfig.EnableRoundCoin) { if (Player.Role == RoleTypeId.ClassD || Player.Role == RoleTypeId.FacilityGuard || Player.Role == RoleTypeId.Scientist) { @@ -449,7 +449,7 @@ public override void OnServerCommandExecuted(CommandExecutedEventArgs ev) public override void OnPlayerFlippingCoin(PlayerFlippingCoinEventArgs ev) { - if (!ev.IsAllowed || !Config.Coin) return; + if (!ev.IsAllowed || !CoinConfig.Enable) return; if (ev.Player.Items.Count() == 8) { From b9c7030afa24ca037a5cd28e5a5b1bf96c236a63 Mon Sep 17 00:00:00 2001 From: 3cxc <81449257+3cxc@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:51:47 +0800 Subject: [PATCH 21/21] =?UTF-8?q?refactor!:=20=E9=87=8D=E6=9E=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=E7=B3=BB=E7=BB=9F,=20=E7=AD=89?= =?UTF-8?q?=E7=BA=A7=E7=B3=BB=E7=BB=9F,=20=E7=A7=B0=E5=8F=B7=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F,=20=E6=8C=87=E4=BB=A4=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API/DataAPI.cs | 2 +- Commands/Chat/AcCommand.cs | 2 +- Commands/Chat/BcCommand.cs | 4 +- Commands/Chat/CCommand.cs | 2 +- Commands/Level/XpCommand.cs | 10 +-- Commands/Scp/ReplaceScpCommand.cs | 11 ++- Commands/Scp/SwapAcceptCommand.cs | 14 +++- Commands/Scp/SwapDenyCommand.cs | 14 +++- Commands/Scp/SwapScpCommand.cs | 12 ++- Commands/System/BadgeCommand.cs | 7 +- Commands/System/KillMeCommand.cs | 14 +++- Commands/System/PermissionCommand.cs | 9 +- Configs/BadgeConfig.cs | 2 - Configs/Config.cs | 59 ++++++++++--- Configs/CustomRoleConfig.cs | 12 --- Configs/DataBaseConfig.cs | 15 ---- Configs/LevelSystemConfig.cs | 24 ++++++ Configs/TranslateConfig.cs | 29 ++++--- EasyTools.csproj | 3 +- Events/CustomEventHandler.cs | 121 ++++++++++++++------------- Extensions/BadgeExtensions.cs | 6 +- Extensions/DataExtensions.cs | 6 +- Plugins.cs | 11 +-- 23 files changed, 235 insertions(+), 154 deletions(-) delete mode 100644 Configs/CustomRoleConfig.cs delete mode 100644 Configs/DataBaseConfig.cs create mode 100644 Configs/LevelSystemConfig.cs diff --git a/API/DataAPI.cs b/API/DataAPI.cs index 36646eb..4d1ef0b 100644 --- a/API/DataAPI.cs +++ b/API/DataAPI.cs @@ -16,7 +16,7 @@ public static bool TryGetData(string id, out PlayerData data) { return true; } - using LiteDatabase database = new(CustomEventHandler.DataBaseConfig.database_path); + using LiteDatabase database = new(CustomEventHandler.Config.DataBasePath); if ((data = database.GetCollection("Players")?.FindById(id)) != null) { diff --git a/Commands/Chat/AcCommand.cs b/Commands/Chat/AcCommand.cs index c9c1015..bb59d58 100644 --- a/Commands/Chat/AcCommand.cs +++ b/Commands/Chat/AcCommand.cs @@ -24,7 +24,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null) { - response = TranslateConfig.ChatCommandError; + response = TranslateConfig.CommandNotAllowed; return false; } diff --git a/Commands/Chat/BcCommand.cs b/Commands/Chat/BcCommand.cs index 6c2e147..837d241 100644 --- a/Commands/Chat/BcCommand.cs +++ b/Commands/Chat/BcCommand.cs @@ -24,7 +24,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null) { - response = TranslateConfig.ChatCommandError; + response = TranslateConfig.CommandNotAllowed; return false; } @@ -37,7 +37,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s player.SendHintMessage(ChatMessage.MessageType.BroadcastChat, $"{string.Join(" ", arguments)}"); Log.Info(player.Nickname + " 发送了 " + arguments.At(0)); - response = TranslateConfig.RescueCommandOk; + response = TranslateConfig.ChatCommandOk; return true; } } diff --git a/Commands/Chat/CCommand.cs b/Commands/Chat/CCommand.cs index 739bbdb..4963a04 100644 --- a/Commands/Chat/CCommand.cs +++ b/Commands/Chat/CCommand.cs @@ -24,7 +24,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null) { - response = TranslateConfig.ChatCommandError; + response = TranslateConfig.CommandNotAllowed; return false; } diff --git a/Commands/Level/XpCommand.cs b/Commands/Level/XpCommand.cs index ea2d3fc..deced71 100644 --- a/Commands/Level/XpCommand.cs +++ b/Commands/Level/XpCommand.cs @@ -24,20 +24,20 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null) { - response = TranslateConfig.RescueCommandError; + response = TranslateConfig.CommandFailed; return false; } - if (!CustomEventHandler.DataBaseConfig.database_enable) + if (!CustomEventHandler.LevelSystemConfig.EnableLevelSystem) { - response = TranslateConfig.LevelCommandFailed; + response = CustomEventHandler.TranslateConfig.CommandNotEnabled; return false; } PlayerData data = player.GetData(); double xp = data.PlayerXp; - int level = LevelExtensions.GetLevelFromXp(xp, 1); - double needXp = LevelExtensions.GetXpUntilNextLevel(xp, 1); + int level = LevelExtensions.GetLevelFromXp(xp, CustomEventHandler.LevelSystemConfig.XpScaleFactor); + double needXp = LevelExtensions.GetXpUntilNextLevel(xp, CustomEventHandler.LevelSystemConfig.XpScaleFactor); response = $"你的等级: {level} | 当前经验: {xp} | 升级还需: {needXp} XP"; return true; diff --git a/Commands/Scp/ReplaceScpCommand.cs b/Commands/Scp/ReplaceScpCommand.cs index 64a71dd..bf0e400 100644 --- a/Commands/Scp/ReplaceScpCommand.cs +++ b/Commands/Scp/ReplaceScpCommand.cs @@ -22,7 +22,13 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) { - response = "失败,可能指令未启用或者身份不允许等"; + response = CustomEventHandler.TranslateConfig.CommandNotAllowed; + return false; + } + + if (CustomEventHandler.Config.EnableSCPReplace) + { + response = CustomEventHandler.TranslateConfig.CommandNotEnabled; return false; } @@ -58,7 +64,8 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s } entry.Applicants.Add(player); - response = $"你已申请补位 {targetRole},等待 {10 - (Time.time - (entry.ExpireTime - 10f)):0.0} 秒后系统随机选择。"; + float remaining = entry.ExpireTime - Time.time; + response = $"你已申请补位 {targetRole},等待 {remaining:0.0} 秒后系统随机选择。"; return true; } } diff --git a/Commands/Scp/SwapAcceptCommand.cs b/Commands/Scp/SwapAcceptCommand.cs index 8d23b2b..d910bfd 100644 --- a/Commands/Scp/SwapAcceptCommand.cs +++ b/Commands/Scp/SwapAcceptCommand.cs @@ -21,20 +21,26 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) { - response = "失败,可能指令未启用或者身份不允许等"; + response = CustomEventHandler.TranslateConfig.CommandNotAllowed; return false; } - if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > 300) + if (CustomEventHandler.Config.EnableSCPStartExchange) { - response = "失败,交换指令只能在开局三分钟内使用"; + response = CustomEventHandler.TranslateConfig.CommandNotEnabled; + return false; + } + + if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > CustomEventHandler.Config.SCPStartExchangeTime) + { + response = CustomEventHandler.TranslateConfig.SwapCommandTimeLimitBroadcastTemplate; return false; } // 检查是否有发给自己的请求 if (!CustomEventHandler.SwapRequests.TryGetValue(player, out Player requester)) { - response = "没有待处理的交换请求"; + response = CustomEventHandler.TranslateConfig.SwapCommandNoRequestBroadcastTemplate; return false; } diff --git a/Commands/Scp/SwapDenyCommand.cs b/Commands/Scp/SwapDenyCommand.cs index e0f1966..13bb609 100644 --- a/Commands/Scp/SwapDenyCommand.cs +++ b/Commands/Scp/SwapDenyCommand.cs @@ -21,20 +21,26 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) { - response = "失败,可能指令未启用或者身份不允许等"; + response = CustomEventHandler.TranslateConfig.CommandNotAllowed; return false; } - if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > 300) + if (CustomEventHandler.Config.EnableSCPStartExchange) { - response = "失败,交换指令只能在开局三分钟内使用"; + response = CustomEventHandler.TranslateConfig.CommandNotEnabled; + return false; + } + + if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > CustomEventHandler.Config.SCPStartExchangeTime) + { + response = CustomEventHandler.TranslateConfig.SwapCommandTimeLimitBroadcastTemplate; return false; } // 检查是否有发给自己的请求 if (!CustomEventHandler.SwapRequests.TryGetValue(player, out Player requester)) { - response = "没有待处理的交换请求"; + response = CustomEventHandler.TranslateConfig.SwapCommandNoRequestBroadcastTemplate; return false; } diff --git a/Commands/Scp/SwapScpCommand.cs b/Commands/Scp/SwapScpCommand.cs index 6a03c7e..72724b4 100644 --- a/Commands/Scp/SwapScpCommand.cs +++ b/Commands/Scp/SwapScpCommand.cs @@ -23,13 +23,19 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null || !(player = Player.Get(sender)).IsSCP) { - response = "失败,可能指令未启用或者身份不允许等"; + response = CustomEventHandler.TranslateConfig.CommandNotAllowed; return false; } - if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > 300) + if (CustomEventHandler.Config.EnableSCPStartExchange) { - response = "失败,交换指令只能在开局三分钟内使用"; + response = CustomEventHandler.TranslateConfig.CommandNotEnabled; + return false; + } + + if ((DateTime.Now - CustomEventHandler.RoundStartTime).TotalSeconds > CustomEventHandler.Config.SCPStartExchangeTime) + { + response = CustomEventHandler.TranslateConfig.SwapCommandTimeLimitBroadcastTemplate; return false; } diff --git a/Commands/System/BadgeCommand.cs b/Commands/System/BadgeCommand.cs index 1c481cc..99eec12 100644 --- a/Commands/System/BadgeCommand.cs +++ b/Commands/System/BadgeCommand.cs @@ -22,7 +22,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null) { - response = CustomEventHandler.TranslateConfig.RescueCommandError; + response = CustomEventHandler.TranslateConfig.CommandFailed; return false; } @@ -30,7 +30,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (data.PermissionLevel == PermissionLevel.Player) { - response = CustomEventHandler.TranslateConfig.RescueCommandFailed; + response = CustomEventHandler.TranslateConfig.CommandNotAllowed; return false; } @@ -73,7 +73,8 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s targetData.Badge = $"{arguments.At(1)}(Lv{(int)PermissionLevel.Moderator}.MODERATOR)"; break; } - } else targetData.Badge = arguments.At(1); + } + else targetData.Badge = arguments.At(1); // 无颜色参数时默认为 rainbow string color = arguments.Count >= 3 ? arguments.At(2) : "rainbow"; diff --git a/Commands/System/KillMeCommand.cs b/Commands/System/KillMeCommand.cs index 70fc5cb..c02ea4a 100644 --- a/Commands/System/KillMeCommand.cs +++ b/Commands/System/KillMeCommand.cs @@ -23,21 +23,27 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (sender is null || (player = Player.Get(sender)) is null) { - response = TranslateConfig.RescueCommandError; + response = TranslateConfig.CommandFailed; return false; } WaypointBase.GetRelativePosition(player.Position, out byte id, out _); - if (!player.IsAlive || !CustomEventHandler.Config.KillMeCommand) + if (!CustomEventHandler.Config.KillMeCommand) { - response = TranslateConfig.RescueCommandFailed; + response = TranslateConfig.CommandNotEnabled; + return false; + } + + if (!player.IsAlive) + { + response = TranslateConfig.CommandNotAllowed; return false; } player.Kill(); - response = TranslateConfig.RescueCommandOk; + response = TranslateConfig.CommandOk; return true; } } diff --git a/Commands/System/PermissionCommand.cs b/Commands/System/PermissionCommand.cs index dc72196..83210ce 100644 --- a/Commands/System/PermissionCommand.cs +++ b/Commands/System/PermissionCommand.cs @@ -1,5 +1,6 @@ using CommandSystem; using EasyTools.DataStructures; +using EasyTools.Events; using EasyTools.Extensions; using LabApi.Features.Wrappers; using System; @@ -17,6 +18,12 @@ public class PermissionCommand : ICommand public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) { + if (!CustomEventHandler.Config.EnableAdmin) + { + response = CustomEventHandler.TranslateConfig.CommandNotEnabled; + return false; + } + if (arguments.Count == 0) { response = "请输入要给予权限的 SteamId"; @@ -37,7 +44,7 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s return false; } - if(!Enum.TryParse(arguments.At(1), true, out PermissionLevel level)) + if (!Enum.TryParse(arguments.At(1), true, out PermissionLevel level)) { response = "权限组无效,请输入 (moderator|admin|owner)"; return false; diff --git a/Configs/BadgeConfig.cs b/Configs/BadgeConfig.cs index 3ba98ee..b3eed6d 100644 --- a/Configs/BadgeConfig.cs +++ b/Configs/BadgeConfig.cs @@ -6,8 +6,6 @@ public class BadgeConfig { [Description("是否启用称号系统")] public bool Enable { get; set; } = true; - [Description("存储路径")] - public string Pach { get; set; } = "/home/shiroko/.config/DIRSave"; [Description("彩色称号更新频率")] public int Each { get; set; } = 1; } diff --git a/Configs/Config.cs b/Configs/Config.cs index 7f33e80..1087ab9 100644 --- a/Configs/Config.cs +++ b/Configs/Config.cs @@ -8,16 +8,23 @@ namespace EasyTools.Configs { public class Config { + [Description("数据库存储路径")] + public string DataBasePath { get; set; } = Path.Combine(PathManager.Configs.FullName ?? Environment.CurrentDirectory, @"EasyTools.db"); + + /// ///////////////////////////////////////////////// [Description("是否打开开局给D级人员一张卡")] public bool EnableRoundSupplies { get; set; } = true; + [Description("给D级人员什么卡?")] public ItemType ClassDCard { get; set; } = ItemType.KeycardJanitor; /// ///////////////////////////////////////////////// [Description("启用服务器定时广播")] public bool EnableAutoServerMessage { get; set; } = true; + [Description("服务器定时广播多久一次")] public int AutoServerMessageTime { get; set; } = 5; + [Description("服务器定时广播显示多久")] public ushort AutoServerMessageTimer { get; set; } = 5; @@ -27,30 +34,41 @@ public class Config /// ///////////////////////////////////////////////// [Description("启用.bc和.c聊天系统")] public bool EnableChatSystem { get; set; } = true; + [Description("聊天系统大小,默认20")] public int ChatSystemSize { get; set; } = 20; [Description("启用玩家反馈管理系统")] public bool EnableAcSystem { get; set; } = true; + [Description("一个人的聊天信息显示多久,单位为秒")] public int MessageTime { get; set; } = 10; [Description("聊天消息的格式,可用的标签为{Message},{MessageType}, {MessageTypeColor}, {SenderNickname},{SenderTeam},{SenderRole} ,{SenderTeamColor}, {CountDown}")] public string MessageTemplate { get; set; } = "[{CountDown}][{SenderTeam}][{SenderRole}][{MessageType}]{SenderNickname}: {Message}"; + + /// ///////////////////////////////////////////////// + [Description("是否启用管理权限系统")] + public bool EnableAdmin { get; set; } = true; // ///////////////////////////////////////////////// + [Description("是否启用玩家在线时长统计")] + public bool EnablePlayTime { get; set; } = true; + + /// ///////////////////////////////////////////////// [Description("防卡死命令")] public bool KillMeCommand { get; set; } = true; /// ///////////////////////////////////////////////// [Description("启用修改SCP血量系统")] public bool EnableChangeSCPHPSystem { get; set; } = true; + [Description("SCP173,SCP939,SCP049,SCP049-2,SCP096,SCP106血量")] - public List SCPsHP { get; set; } = [4200, 2700, 2300, 400, 2500, 2300]; + public List SCPsHP { get; set; } = [5200, 3000, 2800, 600, 3100, 2800]; /// ///////////////////////////////////////////////// [Description("是否开启保安下班")] - public bool GuardsCanEscape { get; set; } = false; + public bool GuardsCanEscape { get; set; } = true; [Description("选择保安下班变成的角色 (NtfSergeant, NtfCaptain, NtfPrivate, NtfSpecialist)")] public string EscapedGuardRole { get; set; } = "NtfCaptain"; @@ -63,8 +81,11 @@ public class Config public int PinkCandyWeight { get; set; } = 2; /// ///////////////////////////////////////////////// - [Description("Logger module settings / 日志模块设置")] - public bool EnableLogger { get; set; } = true; + [Description("是否记录玩家进出日志")] + public bool EnablePlayerLogger { get; set; } = true; + + [Description("是否记录管理员操作相关日志")] + public bool EnableAdminLogger { get; set; } = true; [Description("Player logger settings / 玩家日志保存路径")] public string PlayerLogPath { get; set; } = Path.Combine(PathManager.Configs.FullName ?? Environment.CurrentDirectory, "JoinLogs"); @@ -74,18 +95,15 @@ public class Config /// ///////////////////////////////////////////////// [Description("Is 207 harmless? / 是否开启207(可乐)无害?")] - public bool Harmless207 { get; set; } = true; - + public bool Harmless207 { get; set; } = false; [Description("Is 1853 harmless? / 是否开启1853(洗手液)无害?")] public bool Harmless1853 { get; set; } = true; - /// ///////////////////////////////////////////////// [Description("SCP静止回血?")] public bool EnableHealSCP { get; set; } = true; - [Description("等待多少秒后开始回血")] public float HealSCPSecend { get; set; } = 6; @@ -96,10 +114,31 @@ public class Config public int HealSCPQuantity { get; set; } = 2; /// ///////////////////////////////////////////////// + [Description("开启回合结束友伤?")] + public bool EnableFriendFire { get; set; } = true; + + /// ///////////////////////////////////////////////// + + [Description("开启SCP开局交换?")] + public bool EnableSCPStartExchange { get; set; } = true; + [Description("允许SCP开局交换的时间(以秒为单位)")] + public int SCPStartExchangeTime { get; set; } = 300; + + [Description("开启SCP掉线时补位?")] + public bool EnableSCPReplace { get; set; } = true; + + [Description("允许玩家输入补位指令的时间(以秒为单位)")] + public float SCPReplaceTime { get; set; } = 15f; /// ///////////////////////////////////////////////// - [Description("开启回合结束友伤?")] - public bool EnableFriendFire { get; set; } = true; + [Description("开启开局生成 SCP-3114?")] + public bool EnableSCP3114 { get; set; } = false; + + [Description("当服务器有多少玩家时才会生成 SCP-3114?")] + public int SCP3114Limit { get; set; } = 8; + + [Description("SCP-3114的生成概率(默认50%)")] + public float SCP3114Weight { get; set; } = 0.1f; } } diff --git a/Configs/CustomRoleConfig.cs b/Configs/CustomRoleConfig.cs deleted file mode 100644 index cec486b..0000000 --- a/Configs/CustomRoleConfig.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.ComponentModel; - -namespace EasyTools.Configs -{ - public class CustomRoleConfig - { - [Description("开启3114?")] - public bool spawn_scp_3114 { get; set; } = false; - [Description("当有多少人时才会生成3114?")] - public int spawn_scp_3114_limit { get; set; } = 8; - } -} diff --git a/Configs/DataBaseConfig.cs b/Configs/DataBaseConfig.cs deleted file mode 100644 index 382d648..0000000 --- a/Configs/DataBaseConfig.cs +++ /dev/null @@ -1,15 +0,0 @@ -using LabApi.Loader.Features.Paths; -using System; -using System.ComponentModel; -using System.IO; - -namespace EasyTools.Configs -{ - public class DataBaseConfig - { - [Description("是否启用玩家数据储存系统")] - public bool database_enable { get; set; } = true; - [Description("数据库存储路径")] - public string database_path { get; set; } = Path.Combine(PathManager.Configs.FullName ?? Environment.CurrentDirectory, @"EasyTools.db"); - } -} diff --git a/Configs/LevelSystemConfig.cs b/Configs/LevelSystemConfig.cs new file mode 100644 index 0000000..4f75124 --- /dev/null +++ b/Configs/LevelSystemConfig.cs @@ -0,0 +1,24 @@ +using System.ComponentModel; + +namespace EasyTools.Configs +{ + public class LevelSystemConfig + { + [Description("是否启用等级系统")] + public bool EnableLevelSystem { get; set; } = true; + [Description("是否计入机器人")] + public bool CountBot { get; set; } = false; + [Description("经验值缩放系数")] + public double XpScaleFactor { get; set; } = 1.0; + [Description("人类阵营击杀SCP时奖励的经验")] + public double HumanKillSCPXp { get; set; } = 100.0; + [Description("人类阵营击杀SCP-049-2时奖励的经验")] + public double HumanKillSCP0492Xp { get; set; } = 30.0; + [Description("人类阵营击杀敌对人类阵营时奖励的经验")] + public double HumanKillHumanXp { get; set; } = 5.0; + [Description("SCP击杀人类阵营时奖励的经验")] + public double SCPKillHumanXp { get; set; } = 5.0; + [Description("人类阵营逃离设施时奖励的经验")] + public double HumanEscapeXp { get; set; } = 20.0; + } +} diff --git a/Configs/TranslateConfig.cs b/Configs/TranslateConfig.cs index caf0972..6f53c72 100644 --- a/Configs/TranslateConfig.cs +++ b/Configs/TranslateConfig.cs @@ -8,17 +8,17 @@ namespace EasyTools.Configs { public class TranslateConfig { - [Description("自救指令_错误")] - public string RescueCommandError { get; set; } = "执行指令时发生错误,请稍后再试"; - [Description("自救指令_失败")] - public string RescueCommandFailed { get; set; } = "失败,可能指令未启用或者身份不允许等"; - [Description("自救指令_成功")] - public string RescueCommandOk { get; set; } = "成功"; - [Description("聊天指令_错误")] - public string ChatCommandError { get; set; } = "发送消息时出现错误,请稍后重试"; - [Description("聊天指令_失败")] + [Description("命令未启用时的提示")] + public string CommandNotEnabled { get; set; } = "该命令未启用"; + [Description("当前身份不允许执行命令时的提示")] + public string CommandNotAllowed { get; set; } = "当前身份不允许执行该命令"; + [Description("命令执行失败时的提示")] + public string CommandFailed { get; set; } = "执行失败,可能是参数错误等"; + [Description("命令执行成功时的提示")] + public string CommandOk { get; set; } = "执行成功"; + [Description("聊天信息发送失败时提示")] public string ChatCommandFailed { get; set; } = "发送失败,你被禁言或者信息为空或者聊天系统未启用"; - [Description("聊天指令_成功")] + [Description("聊天信息发送成功时提示")] public string ChatCommandOk { get; set; } = "发送成功"; /// /// @@ -95,8 +95,6 @@ public class TranslateConfig /// [Description("等级系统_查询失败")] public string LevelCommandFailed { get; set; } = "查询失败,等级系统未启用"; - [Description("等级系统_查询成功")] - public string LevelCommandOk { get; set; } = "您当前的经验值为: "; /// /// /// @@ -104,5 +102,12 @@ public class TranslateConfig public string RewardFailedBroadcastTemplate { get; set; } = "\n你的背包空间不足,无法继续抽卡!"; [Description("使用硬币抽卡成功提示")] public string RewardOkBroadcastTemplate { get; set; } = "\n🎉 恭喜!玩家 {nickName} 通过抛硬币{result}!"; + /// + /// + /// + [Description("开局三分钟后使用交换指令的禁止提示")] + public string SwapCommandTimeLimitBroadcastTemplate { get; set; } = "交换指令只能在开局三分钟内使用"; + [Description("没有待处理交换请求时提示")] + public string SwapCommandNoRequestBroadcastTemplate { get; set; } = "没有待处理的交换请求"; } } diff --git a/EasyTools.csproj b/EasyTools.csproj index ae297d4..5cdac5a 100644 --- a/EasyTools.csproj +++ b/EasyTools.csproj @@ -136,8 +136,7 @@ - - + diff --git a/Events/CustomEventHandler.cs b/Events/CustomEventHandler.cs index 4faae8d..29b3f64 100644 --- a/Events/CustomEventHandler.cs +++ b/Events/CustomEventHandler.cs @@ -29,9 +29,7 @@ public class CustomEventHandler : CustomEventsHandler public static BadgeConfig BadgeConfig; - public static CustomRoleConfig CustomRoleConfig; - - public static DataBaseConfig DataBaseConfig; + public static LevelSystemConfig LevelSystemConfig; public static HUDInfoConfig HUDInfoConfig; @@ -88,7 +86,7 @@ public override void OnServerRoundStarted() PlayerHuds.Values.ToList().ForEach(h => h.Start()); }); - if (DataBaseConfig.database_enable) + if (Config.EnablePlayTime) { Timing.RunCoroutine(DataExtensions.CollectInfo()); } @@ -120,19 +118,28 @@ public override void OnPlayerJoined(PlayerJoinedEventArgs ev) player.InitChatHint(); - if (DataBaseConfig.database_enable) + DataExtensions.PlayerList.Add(player); + PlayerData data = player.GetData(); + data.NickName = player.Nickname; + data.LastJoinedTime = DateTime.Now; + data.UpdateData(); + + if (LevelSystemConfig.EnableLevelSystem) { - DataExtensions.PlayerList.Add(player); - PlayerData data = player.GetData(); - data.NickName = player.Nickname; - data.LastJoinedTime = DateTime.Now; - data.UpdateData(); player.UpdatePlayerNameWithLevelPrefix(); + } + + if (Config.EnableAdmin) + { player.ApplyPermission(); + } + + if (BadgeConfig.Enable) + { player.ApplyBadge(); } - if (Config.EnableLogger) + if (Config.EnablePlayerLogger) { string playerInfo = $"[JOIN] Date: {DateTime.Now} | Player: {ev.Player.Nickname} | IP: {ev.Player.IpAddress} | Steam64ID: {ev.Player.UserId}"; string path = Path.Combine(CustomEventHandler.Config.PlayerLogPath, $"{Server.Port}.log"); @@ -167,13 +174,10 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) if (player == null || string.IsNullOrEmpty(player.UserId)) return; - if (DataBaseConfig.database_enable) - { - DataExtensions.PlayerList.Remove(player); - PlayerData data = player.GetData(); - data.LastJoinedTime = DateTime.Now; - data.UpdateData(); - } + DataExtensions.PlayerList.Remove(player); + PlayerData data = player.GetData(); + data.LastJoinedTime = DateTime.Now; + data.UpdateData(); if (Config.EnablePlayerLogger) { @@ -197,20 +201,23 @@ public override void OnPlayerLeft(PlayerLeftEventArgs ev) PlayerHuds.Remove(player); } - // 清理该玩家在所有补位申请中的记录(防止幽灵申请) - foreach (var entry in Replacements.Values) - entry.Applicants.Remove(player); - - if (player.IsSCP && player.Health > 0) + if (Config.EnableSCPReplace) { - var role = player.Role; + // 清理该玩家在所有补位申请中的记录(防止幽灵申请) + foreach (var entry in Replacements.Values) + entry.Applicants.Remove(player); - Replacements[role] = new ReplacementEntry + if (player.IsSCP && player.Health > 0) { - ExpireTime = Time.time + 10f - }; + var role = player.Role; - Timing.CallDelayed(10f, () => ExecuteReplacement(role)); + Replacements[role] = new ReplacementEntry + { + ExpireTime = Time.time + Config.SCPReplaceTime + }; + + Timing.CallDelayed(Config.SCPReplaceTime, () => ExecuteReplacement(role)); + } } } @@ -236,28 +243,21 @@ private void ExecuteReplacement(RoleTypeId role) Log.Info($"{chosen.Nickname} 补位成为 {role}"); } - private static volatile bool allow_spawn_scp_3114 = true; //用以确保不会重复生成SCP-3114 + private static volatile bool AllowSpawnScp3114 = true; //用以确保不会重复生成 SCP-3114 public override void OnPlayerSpawning(PlayerSpawningEventArgs ev) { - if (CustomRoleConfig.spawn_scp_3114 && allow_spawn_scp_3114) + if (Config.EnableSCP3114 && AllowSpawnScp3114) { - if (Player.ReadyList.Count() >= CustomRoleConfig.spawn_scp_3114_limit) + if (Player.ReadyList.Count() >= Config.SCP3114Limit && UnityEngine.Random.value < Config.SCP3114Weight) { - foreach (Player p in Player.ReadyList) + AllowSpawnScp3114 = false; + Timing.CallDelayed(0.5f, () => { - if ((UnityEngine.Random.Range(0, 10) == 3)) - { - Timing.CallDelayed(0.5f, () => - { - ev.Player.Role = RoleTypeId.Scp3114; - ev.IsAllowed = true; - allow_spawn_scp_3114 = false; - }); - } - } + ev.Player.Role = RoleTypeId.Scp3114; + ev.IsAllowed = true; + }); } - allow_spawn_scp_3114 = false; } } @@ -313,34 +313,38 @@ public override void OnPlayerSpawned(PlayerSpawnedEventArgs ev) public override void OnPlayerDying(PlayerDyingEventArgs ev) { + if (!LevelSystemConfig.EnableLevelSystem) return; + // 避免处理非玩家击杀或无效情况 - //if (ev.Attacker == null || ev.Player == null) - // return; + if (ev.Attacker == null || ev.Player == null) + return; + + if (ev.Player.IsDummy && !LevelSystemConfig.CountBot) return; // 给击杀者添加经验 PlayerData data = ev.Attacker.GetData(); if (ev.Attacker.IsSCP) { - data.PlayerXp += 5.0; + data.PlayerXp += LevelSystemConfig.SCPKillHumanXp; } else if (ev.Player.IsSCP) { if (ev.Player.Role == RoleTypeId.Scp0492) { - data.PlayerXp += 30.0; + data.PlayerXp += LevelSystemConfig.HumanKillSCP0492Xp; } else { - data.PlayerXp += 50.0; + data.PlayerXp += LevelSystemConfig.HumanKillSCPXp; } } else { - data.PlayerXp += 5.0; + data.PlayerXp += LevelSystemConfig.HumanKillHumanXp; } - data.PlayerLevel = LevelExtensions.GetLevelFromXp(data.PlayerXp, 1); + data.PlayerLevel = LevelExtensions.GetLevelFromXp(data.PlayerXp, LevelSystemConfig.XpScaleFactor); ev.Attacker.UpdatePlayerNameWithLevelPrefix(); } @@ -392,14 +396,17 @@ public override void OnPlayerEscaping(PlayerEscapingEventArgs ev) } } - PlayerData data = ev.Player.GetData(); - data.PlayerXp += 20.0; + if (LevelSystemConfig.EnableLevelSystem) + { + PlayerData data = ev.Player.GetData(); + data.PlayerXp += LevelSystemConfig.HumanEscapeXp; - data.PlayerLevel = LevelExtensions.GetLevelFromXp(data.PlayerXp, 1); - ev.Player.UpdatePlayerNameWithLevelPrefix(); + data.PlayerLevel = LevelExtensions.GetLevelFromXp(data.PlayerXp, LevelSystemConfig.XpScaleFactor); + ev.Player.UpdatePlayerNameWithLevelPrefix(); - // 通知玩家 - ev.Player.SendBroadcast("\n逃脱成功,获得20经验值", 3); + // 通知玩家 + ev.Player.SendBroadcast("\n逃脱成功,获得20经验值", 3); + } } public override void OnPlayerInteractingScp330(PlayerInteractingScp330EventArgs ev) @@ -421,7 +428,7 @@ public override void OnServerCommandExecuted(CommandExecutedEventArgs ev) Player player = Player.Get(sender); - if (player != null && !string.IsNullOrEmpty(command) && Config.EnableLogger) + if (player != null && !string.IsNullOrEmpty(command) && Config.EnableAdminLogger) { if (!player.RemoteAdminAccess) return; diff --git a/Extensions/BadgeExtensions.cs b/Extensions/BadgeExtensions.cs index 0c2fc3b..e855441 100644 --- a/Extensions/BadgeExtensions.cs +++ b/Extensions/BadgeExtensions.cs @@ -109,7 +109,11 @@ public static void ApplyPermission(this Player player) }; Server.RunCommand($"/setgroup {player.PlayerId} {group}"); - Log.Info($"[AC] Date: {DateTime.Now} | Player: {player.Nickname} | Perm: {group} | Steam64ID: {player.UserId}"); + + if (CustomEventHandler.Config.EnableAdminLogger) + { + Log.Info($"[AC] Date: {DateTime.Now} | Player: {player.Nickname} | Perm: {group} | Steam64ID: {player.UserId}"); + } } } } diff --git a/Extensions/DataExtensions.cs b/Extensions/DataExtensions.cs index 559758a..427ba4d 100644 --- a/Extensions/DataExtensions.cs +++ b/Extensions/DataExtensions.cs @@ -39,7 +39,7 @@ public static PlayerData GetData(this Player ply) PlayerXp = 0.0, PlayerLevel = 0.0 }; - using LiteDatabase database = new(CustomEventHandler.DataBaseConfig.database_path); + using LiteDatabase database = new(CustomEventHandler.Config.DataBasePath); database.GetCollection("Players").Insert(toInsert); } @@ -69,7 +69,7 @@ public static PlayerData GetData(this ReferenceHub ply) RolePlayed = 0, PlayerShot = 0, }; - using LiteDatabase database = new(CustomEventHandler.DataBaseConfig.database_path); + using LiteDatabase database = new(CustomEventHandler.Config.DataBasePath); database.GetCollection("Players").Insert(toInsert); } @@ -80,7 +80,7 @@ public static PlayerData GetData(this ReferenceHub ply) public static void UpdateData(this PlayerData data) { - using LiteDatabase database = new(CustomEventHandler.DataBaseConfig.database_path); + using LiteDatabase database = new(CustomEventHandler.Config.DataBasePath); database.GetCollection("Players").Update(data); } diff --git a/Plugins.cs b/Plugins.cs index 6dd5e52..bf27e00 100644 --- a/Plugins.cs +++ b/Plugins.cs @@ -5,7 +5,6 @@ using LabApi.Features; using LabApi.Loader; using LabApi.Loader.Features.Plugins; -using System.IO; namespace EasyTools { @@ -19,8 +18,7 @@ public override void LoadConfigs() CustomEventHandler.Config = this.LoadConfig("config.yml"); CustomEventHandler.TranslateConfig = this.LoadConfig("translateConfig.yml"); CustomEventHandler.BadgeConfig = this.LoadConfig("badgeConfig.yml"); - CustomEventHandler.CustomRoleConfig = this.LoadConfig("customRoleConfig.yml"); - CustomEventHandler.DataBaseConfig = this.LoadConfig("dataBaseConfig.yml"); + CustomEventHandler.LevelSystemConfig = this.LoadConfig("dataBaseConfig.yml"); CustomEventHandler.HUDInfoConfig = this.LoadConfig("HUDInfoConfig.yml"); CustomEventHandler.CoinConfig = this.LoadConfig("coinConfig.yml"); @@ -37,11 +35,6 @@ public override void LoadConfigs() CustomEventHandler.HUDInfoConfig.ElevatorDisplayY, CustomEventHandler.HUDInfoConfig.ElevatorFontSize ); - - if (!Directory.Exists(CustomEventHandler.BadgeConfig.Pach)) - { - Directory.CreateDirectory(CustomEventHandler.BadgeConfig.Pach); - } } @@ -55,7 +48,7 @@ public override void LoadConfigs() public override string Author => "3cxc"; - public override System.Version Version => new(1, 0, 1); + public override System.Version Version => new(1, 1, 0); public override System.Version RequiredApiVersion => new(LabApiProperties.CompiledVersion);